//go:build !luminous && !mimic // +build !luminous,!mimic // // Ceph Nautilus is the first release that includes rbd_pool_metadata_get(), // rbd_pool_metadata_set() and rbd_pool_metadata_remove(). package rbd // #cgo LDFLAGS: -lrbd // #include // #include // #include import "C" import ( "unsafe" "github.com/ceph/go-ceph/internal/retry" "github.com/ceph/go-ceph/rados" ) // GetPoolMetadata returns pool metadata associated with the given key. // // Implements: // int rbd_pool_metadata_get(rados_ioctx_t io_ctx, const char *key, char *value, size_t *val_len); func GetPoolMetadata(ioctx *rados.IOContext, key string) (string, error) { if ioctx == nil { return "", ErrNoIOContext } cKey := C.CString(key) defer C.free(unsafe.Pointer(cKey)) var ( buf []byte err error ) retry.WithSizes(4096, 262144, func(size int) retry.Hint { cSize := C.size_t(size) buf = make([]byte, cSize) ret := C.rbd_pool_metadata_get(cephIoctx(ioctx), cKey, (*C.char)(unsafe.Pointer(&buf[0])), &cSize) err = getError(ret) return retry.Size(int(cSize)).If(err == errRange) }) if err != nil { return "", err } return C.GoString((*C.char)(unsafe.Pointer(&buf[0]))), nil } // SetPoolMetadata updates the pool metadata string associated with the given key. // // Implements: // int rbd_pool_metadata_set(rados_ioctx_t io_ctx, const char *key, const char *value); func SetPoolMetadata(ioctx *rados.IOContext, key, value string) error { if ioctx == nil { return ErrNoIOContext } cKey := C.CString(key) defer C.free(unsafe.Pointer(cKey)) cValue := C.CString(value) defer C.free(unsafe.Pointer(cValue)) ret := C.rbd_pool_metadata_set(cephIoctx(ioctx), cKey, cValue) return getError(ret) } // RemovePoolMetadata removes the pool metadata value for a given pool metadata key. // // Implements: // int rbd_pool_metadata_remove(rados_ioctx_t io_ctx, const char *key) func RemovePoolMetadata(ioctx *rados.IOContext, key string) error { if ioctx == nil { return ErrNoIOContext } cKey := C.CString(key) defer C.free(unsafe.Pointer(cKey)) ret := C.rbd_pool_metadata_remove(cephIoctx(ioctx), cKey) return getError(ret) } // PoolInit initializes a pool for use by rbd. // This function does not create new pools, rather it prepares the pool // to host rbd images. // // Implements: // int rbd_pool_init(rados_ioctx_t io, bool force) func PoolInit(ioctx *rados.IOContext, force bool) error { if ioctx == nil { return ErrNoIOContext } ret := C.rbd_pool_init(cephIoctx(ioctx), C.bool(force)) return getError(ret) } // poolStats represents RBD pool stats variable. type poolStats struct { stats C.rbd_pool_stats_t } // poolStatsCreate creates a new poolStats struct. // // Implements: // void rbd_pool_stats_create(rbd_pool_stats_t *stats) func poolStatsCreate() *poolStats { poolstats := &poolStats{} C.rbd_pool_stats_create(&poolstats.stats) return poolstats } // destroy a poolStats struct and free the associated resources. // // Implements: // void rbd_pool_stats_destroy(rbd_pool_stats_t stats) func (poolstats *poolStats) destroy() { C.rbd_pool_stats_destroy(poolstats.stats) if poolstats.stats != nil { poolstats.stats = nil } } // PoolStatOption represents a group of configurable pool stat options. type PoolStatOption C.rbd_pool_stat_option_t const ( // PoolStatOptionImages is the representation of // RBD_POOL_STAT_OPTION_IMAGES from librbd. PoolStatOptionImages = PoolStatOption(C.RBD_POOL_STAT_OPTION_IMAGES) // PoolStatOptionImageProvisionedBytes is the representation of // RBD_POOL_STAT_OPTION_IMAGE_PROVISIONED_BYTES from librbd. PoolStatOptionImageProvisionedBytes = PoolStatOption(C.RBD_POOL_STAT_OPTION_IMAGE_PROVISIONED_BYTES) // PoolStatOptionImageMaxProvisionedBytes is the representation of // RBD_POOL_STAT_OPTION_IMAGE_MAX_PROVISIONED_BYTES from librbd. PoolStatOptionImageMaxProvisionedBytes = PoolStatOption(C.RBD_POOL_STAT_OPTION_IMAGE_MAX_PROVISIONED_BYTES) // PoolStatOptionImageSnapshots is the representation of // RBD_POOL_STAT_OPTION_IMAGE_SNAPSHOTS from librbd. PoolStatOptionImageSnapshots = PoolStatOption(C.RBD_POOL_STAT_OPTION_IMAGE_SNAPSHOTS) // PoolStatOptionTrashImages is the representation of // RBD_POOL_STAT_OPTION_TRASH_IMAGES from librbd. PoolStatOptionTrashImages = PoolStatOption(C.RBD_POOL_STAT_OPTION_TRASH_IMAGES) // PoolStatOptionTrashProvisionedBytes is the representation of // RBD_POOL_STAT_OPTION_TRASH_PROVISIONED_BYTES from librbd. PoolStatOptionTrashProvisionedBytes = PoolStatOption(C.RBD_POOL_STAT_OPTION_TRASH_PROVISIONED_BYTES) // PoolStatOptionTrashMaxProvisionedBytes is the representation of // RBD_POOL_STAT_OPTION_TRASH_MAX_PROVISIONED_BYTES from librbd. PoolStatOptionTrashMaxProvisionedBytes = PoolStatOption(C.RBD_POOL_STAT_OPTION_TRASH_MAX_PROVISIONED_BYTES) // PoolStatOptionTrashSnapshots is the representation of // RBD_POOL_STAT_OPTION_TRASH_SNAPSHOTS from librbd. PoolStatOptionTrashSnapshots = PoolStatOption(C.RBD_POOL_STAT_OPTION_TRASH_SNAPSHOTS) ) // addPoolStatOption adds the given PoolStatOption to PoolStats. // // Implements: // int rbd_pool_stats_option_add_uint64(rbd_pool_stats_t stats, int stat_option, uint64_t* stat_val) func (poolstats *poolStats) addPoolStatOption(option PoolStatOption, val *uint64) error { ret := C.rbd_pool_stats_option_add_uint64( poolstats.stats, C.int(option), (*C.uint64_t)(val)) return getError(ret) } // GetAllPoolStats returns a map of all PoolStatOption(s) to their respective values. // // Implements: // int rbd_pool_stats_get(rados_ioctx_t io, rbd_pool_stats_t stats); func GetAllPoolStats(ioctx *rados.IOContext) (map[PoolStatOption]uint64, error) { var omap = make(map[PoolStatOption]uint64) if ioctx == nil { return omap, ErrNoIOContext } poolstats := poolStatsCreate() defer func() { poolstats.destroy() }() var keys [8]PoolStatOption keys[0] = PoolStatOptionImages keys[1] = PoolStatOptionImageProvisionedBytes keys[2] = PoolStatOptionImageMaxProvisionedBytes keys[3] = PoolStatOptionImageSnapshots keys[4] = PoolStatOptionTrashImages keys[5] = PoolStatOptionTrashProvisionedBytes keys[6] = PoolStatOptionTrashMaxProvisionedBytes keys[7] = PoolStatOptionTrashSnapshots ovalArray := make([]uint64, len(keys)) // add option with the address where the respective value would be stored. for i, key := range keys { err := poolstats.addPoolStatOption(key, &ovalArray[i]) if err != nil { return omap, err } } ret := C.rbd_pool_stats_get(cephIoctx(ioctx), poolstats.stats) if ret < 0 { return omap, getError(ret) } for j, key := range keys { omap[key] = ovalArray[j] } return omap, nil }