-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathpool.go
119 lines (95 loc) · 3.3 KB
/
pool.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
// Package librbd provides functionality to interact with Ceph RADOS block device (RBD)
// subsystem and underlying kernel support. It requires the librados and librbd
// libraries to function.
//
// No operations are handled under lock; this is a deliberate design decision
// that allows you to implement the locks in the distributed fashion of your
// choice.
package librbd
// #cgo LDFLAGS: -lrbd -lrados
// #include <rados/librados.h>
// #include <rbd/librbd.h>
// #include <stdlib.h>
import "C"
import (
"runtime"
"strings"
"unsafe"
)
// Pool is a unit of storage composed of many images.
type Pool struct {
ioctx C.rados_ioctx_t
cluster C.rados_t
poolName string
rbdConfig RBDConfig
}
// GetPool instantiates a Pool object from librados. It must be able to
// authenticate to ceph through normal (e.g., CLI) means to perform this
// operation. The RBDConfig is used to supply parts of the configuration which
// cannot be necessarily parsed by the C versions of librados and librbd. This
// struct will need to be populated; if you want a way to fill it from JSON,
// see ReadConfig.
func GetPool(config RBDConfig, poolName string) (*Pool, error) {
if err := modprobeRBD(); err != nil {
return nil, err
}
var err error
pool := &Pool{poolName: poolName, rbdConfig: config}
str := C.CString(poolName)
defer C.free(unsafe.Pointer(str))
pool.cluster, err = getRados(config.UserName)
if err != nil {
return nil, err
}
if i := C.rados_ioctx_create(pool.cluster, str, &pool.ioctx); i < 0 {
return nil, strerror(i)
}
runtime.SetFinalizer(pool, freePool)
return pool, nil
}
// CreateImage creates a rbd image for the pool. Given a name and size in
// bytes, it will return any error if there was a problem creating the
// image.
func (p *Pool) CreateImage(name string, size uint64) error {
str := C.CString(name)
defer C.free(unsafe.Pointer(str))
order := C.int(0)
if i := C.rbd_create(p.ioctx, str, C.uint64_t(size), &order); i < 0 {
return strerror(i)
}
return nil
}
// RemoveImage removes an image named by the string. Returns an error on failure.
func (p *Pool) RemoveImage(name string) error {
str := C.CString(name)
defer C.free(unsafe.Pointer(str))
if i := C.rbd_remove(p.ioctx, str); i < 0 {
return strerror(i)
}
return nil
}
// List all the images for the pool.
func (p *Pool) List() ([]string, error) {
buf := make([]byte, 1024*1024)
// FIXME number of entries, but it's an undocumented call so I don't know for sure
sizeT := C.size_t(1024 * 1024)
var i C.int
if i = C.rbd_list(p.ioctx, (*C.char)(unsafe.Pointer(&buf[0])), &sizeT); i < 0 {
return nil, strerror(i)
}
// the returned string is multiple null terminated strings with a double null
// at the end. Hence GoStringN.
items := strings.Split(C.GoStringN((*C.char)(unsafe.Pointer(&buf[0])), i), string([]byte{0}))
return items[:len(items)-1], nil
}
// GetImage find and returns an Image struct for an existing image. If the
// image could not be fetched, or does not exist, this function will return
// error.
func (p *Pool) GetImage(imageName string) (*Image, error) {
// use this so we can exploit wrapOpen() to determine if the image exists
action := func(image *C.rbd_image_t) error { return nil }
if err := p.wrapOpen(imageName, action); err != nil {
return nil, err
}
return &Image{imageName: imageName, pool: p}, nil
}