package rbd /* #cgo LDFLAGS: -lrbd #include <stdlib.h> #include <rbd/librbd.h> */ import "C" import ( "unsafe" "github.com/ceph/go-ceph/internal/cutil" "github.com/ceph/go-ceph/internal/retry" "github.com/ceph/go-ceph/rados" ) // GroupCreate is used to create an image group. // // Implements: // // int rbd_group_create(rados_ioctx_t p, const char *name); func GroupCreate(ioctx *rados.IOContext, name string) error { cName := C.CString(name) defer C.free(unsafe.Pointer(cName)) ret := C.rbd_group_create(cephIoctx(ioctx), cName) return getError(ret) } // GroupRemove is used to remove an image group. // // Implements: // // int rbd_group_remove(rados_ioctx_t p, const char *name); func GroupRemove(ioctx *rados.IOContext, name string) error { cName := C.CString(name) defer C.free(unsafe.Pointer(cName)) ret := C.rbd_group_remove(cephIoctx(ioctx), cName) return getError(ret) } // GroupRename will rename an existing image group. // // Implements: // // int rbd_group_rename(rados_ioctx_t p, const char *src_name, // const char *dest_name); func GroupRename(ioctx *rados.IOContext, src, dest string) error { cSrc := C.CString(src) defer C.free(unsafe.Pointer(cSrc)) cDest := C.CString(dest) defer C.free(unsafe.Pointer(cDest)) ret := C.rbd_group_rename(cephIoctx(ioctx), cSrc, cDest) return getError(ret) } // GroupList returns a slice of image group names. // // Implements: // // int rbd_group_list(rados_ioctx_t p, char *names, size_t *size); func GroupList(ioctx *rados.IOContext) ([]string, error) { var ( buf []byte err error ret C.int ) retry.WithSizes(1024, 262144, func(size int) retry.Hint { cSize := C.size_t(size) buf = make([]byte, cSize) ret = C.rbd_group_list( cephIoctx(ioctx), (*C.char)(unsafe.Pointer(&buf[0])), &cSize) err = getErrorIfNegative(ret) return retry.Size(int(cSize)).If(err == errRange) }) if err != nil { return nil, err } // cSize is not set to the expected size when it is sufficiently large // but ret will be set to the size in a non-error condition. groups := cutil.SplitBuffer(buf[:ret]) return groups, nil } // GroupImageAdd will add the specified image to the named group. // An io context must be supplied for both the group and image. // // Implements: // // int rbd_group_image_add(rados_ioctx_t group_p, // const char *group_name, // rados_ioctx_t image_p, // const char *image_name); func GroupImageAdd(groupIoctx *rados.IOContext, groupName string, imageIoctx *rados.IOContext, imageName string) error { cGroupName := C.CString(groupName) defer C.free(unsafe.Pointer(cGroupName)) cImageName := C.CString(imageName) defer C.free(unsafe.Pointer(cImageName)) ret := C.rbd_group_image_add( cephIoctx(groupIoctx), cGroupName, cephIoctx(imageIoctx), cImageName) return getError(ret) } // GroupImageRemove will remove the specified image from the named group. // An io context must be supplied for both the group and image. // // Implements: // // int rbd_group_image_remove(rados_ioctx_t group_p, // const char *group_name, // rados_ioctx_t image_p, // const char *image_name); func GroupImageRemove(groupIoctx *rados.IOContext, groupName string, imageIoctx *rados.IOContext, imageName string) error { cGroupName := C.CString(groupName) defer C.free(unsafe.Pointer(cGroupName)) cImageName := C.CString(imageName) defer C.free(unsafe.Pointer(cImageName)) ret := C.rbd_group_image_remove( cephIoctx(groupIoctx), cGroupName, cephIoctx(imageIoctx), cImageName) return getError(ret) } // GroupImageRemoveByID will remove the specified image from the named group. // An io context must be supplied for both the group and image. // // Implements: // // CEPH_RBD_API int rbd_group_image_remove_by_id(rados_ioctx_t group_p, // const char *group_name, // rados_ioctx_t image_p, // const char *image_id); func GroupImageRemoveByID(groupIoctx *rados.IOContext, groupName string, imageIoctx *rados.IOContext, imageID string) error { cGroupName := C.CString(groupName) defer C.free(unsafe.Pointer(cGroupName)) cid := C.CString(imageID) defer C.free(unsafe.Pointer(cid)) ret := C.rbd_group_image_remove_by_id( cephIoctx(groupIoctx), cGroupName, cephIoctx(imageIoctx), cid) return getError(ret) } // GroupImageState indicates an image's state in a group. type GroupImageState int const ( // GroupImageStateAttached is equivalent to RBD_GROUP_IMAGE_STATE_ATTACHED GroupImageStateAttached = GroupImageState(C.RBD_GROUP_IMAGE_STATE_ATTACHED) // GroupImageStateIncomplete is equivalent to RBD_GROUP_IMAGE_STATE_INCOMPLETE GroupImageStateIncomplete = GroupImageState(C.RBD_GROUP_IMAGE_STATE_INCOMPLETE) ) // GroupImageInfo reports on images within a group. type GroupImageInfo struct { Name string PoolID int64 State GroupImageState } // GroupImageList returns a slice of GroupImageInfo types based on the // images that are part of the named group. // // Implements: // // int rbd_group_image_list(rados_ioctx_t group_p, // const char *group_name, // rbd_group_image_info_t *images, // size_t group_image_info_size, // size_t *num_entries); func GroupImageList(ioctx *rados.IOContext, name string) ([]GroupImageInfo, error) { cName := C.CString(name) defer C.free(unsafe.Pointer(cName)) var ( cImages []C.rbd_group_image_info_t cSize C.size_t err error ) retry.WithSizes(1024, 262144, func(size int) retry.Hint { cSize = C.size_t(size) cImages = make([]C.rbd_group_image_info_t, cSize) ret := C.rbd_group_image_list( cephIoctx(ioctx), cName, (*C.rbd_group_image_info_t)(unsafe.Pointer(&cImages[0])), C.sizeof_rbd_group_image_info_t, &cSize) err = getErrorIfNegative(ret) return retry.Size(int(cSize)).If(err == errRange) }) if err != nil { return nil, err } images := make([]GroupImageInfo, cSize) for i := range images { images[i].Name = C.GoString(cImages[i].name) images[i].PoolID = int64(cImages[i].pool) images[i].State = GroupImageState(cImages[i].state) } // free C memory allocated by C.rbd_group_image_list call ret := C.rbd_group_image_list_cleanup( (*C.rbd_group_image_info_t)(unsafe.Pointer(&cImages[0])), C.sizeof_rbd_group_image_info_t, cSize) return images, getError(ret) } // GroupInfo contains the name and pool id of a RBD group. type GroupInfo struct { Name string PoolID int64 } // GetGroup returns group info for the group this image is part of. // // Implements: // // int rbd_get_group(rbd_image_t image, rbd_group_info_t *group_info, // size_t group_info_size); func (image *Image) GetGroup() (GroupInfo, error) { if err := image.validate(imageIsOpen); err != nil { return GroupInfo{}, err } var cgi C.rbd_group_info_t ret := C.rbd_get_group( image.image, &cgi, C.sizeof_rbd_group_info_t) if err := getErrorIfNegative(ret); err != nil { return GroupInfo{}, err } gi := GroupInfo{ Name: C.GoString(cgi.name), PoolID: int64(cgi.pool), } ret = C.rbd_group_info_cleanup(&cgi, C.sizeof_rbd_group_info_t) return gi, getError(ret) }