mirror of https://github.com/ceph/go-ceph
rbd: Add mirror peer site API components
**Description:** Added some API components of mirror peer site Fixes: #486 Signed-off-by: Nikhil-Ladha <nikhilladha1999@gmail.com>
This commit is contained in:
parent
48afd419c4
commit
fcd2fcd6f6
|
@ -1816,6 +1816,54 @@
|
|||
"comment": "DescriptionReplayStatus parses a MirrorDescriptionReplayStatus result out of\nthe image status description field if available. If the embedded status JSON\nis not found or fails to parse and error will be returned.\n",
|
||||
"added_in_version": "$NEXT_RELEASE",
|
||||
"expected_stable_version": "$NEXT_RELEASE_STABLE"
|
||||
},
|
||||
{
|
||||
"name": "AddMirrorPeerSite",
|
||||
"comment": "AddMirrorPeerSite adds a peer site to the list of existing sites.\n",
|
||||
"added_in_version": "$NEXT_RELEASE",
|
||||
"expected_stable_version": "$NEXT_RELEASE_STABLE"
|
||||
},
|
||||
{
|
||||
"name": "RemoveMirrorPeerSite",
|
||||
"comment": "RemoveMirrorPeerSite removes the site with the provided uuid.\n",
|
||||
"added_in_version": "$NEXT_RELEASE",
|
||||
"expected_stable_version": "$NEXT_RELEASE_STABLE"
|
||||
},
|
||||
{
|
||||
"name": "GetAttributesMirrorPeerSite",
|
||||
"comment": "GetAttributesMirrorPeerSite fetches the list of key,value pair of attributes of a peer site.\n",
|
||||
"added_in_version": "$NEXT_RELEASE",
|
||||
"expected_stable_version": "$NEXT_RELEASE_STABLE"
|
||||
},
|
||||
{
|
||||
"name": "SetAttributesMirrorPeerSite",
|
||||
"comment": "SetAttributesMirrorPeerSite sets the attributes for the site with the given uuid.\n",
|
||||
"added_in_version": "$NEXT_RELEASE",
|
||||
"expected_stable_version": "$NEXT_RELEASE_STABLE"
|
||||
},
|
||||
{
|
||||
"name": "ListMirrorPeerSite",
|
||||
"comment": "ListMirrorPeerSite returns the list of peer sites.\n",
|
||||
"added_in_version": "$NEXT_RELEASE",
|
||||
"expected_stable_version": "$NEXT_RELEASE_STABLE"
|
||||
},
|
||||
{
|
||||
"name": "SetMirrorPeerSiteClientName",
|
||||
"comment": "SetMirrorPeerSiteClientName sets the client name of a mirror peer site.\n",
|
||||
"added_in_version": "$NEXT_RELEASE",
|
||||
"expected_stable_version": "$NEXT_RELEASE_STABLE"
|
||||
},
|
||||
{
|
||||
"name": "SetMirrorPeerSiteName",
|
||||
"comment": "SetMirrorPeerSiteName sets the site name of a mirror peer site.\n",
|
||||
"added_in_version": "$NEXT_RELEASE",
|
||||
"expected_stable_version": "$NEXT_RELEASE_STABLE"
|
||||
},
|
||||
{
|
||||
"name": "SetMirrorPeerSiteDirection",
|
||||
"comment": "SetMirrorPeerSiteDirection sets the direction of a mirror peer site.\n",
|
||||
"added_in_version": "$NEXT_RELEASE",
|
||||
"expected_stable_version": "$NEXT_RELEASE_STABLE"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
|
@ -49,6 +49,14 @@ MigrationAbort | v0.20.0 | v0.22.0 |
|
|||
MigrationStatus | v0.20.0 | v0.22.0 |
|
||||
SiteMirrorImageStatus.UnmarshalDescriptionJSON | $NEXT_RELEASE | $NEXT_RELEASE_STABLE |
|
||||
SiteMirrorImageStatus.DescriptionReplayStatus | $NEXT_RELEASE | $NEXT_RELEASE_STABLE |
|
||||
AddMirrorPeerSite | $NEXT_RELEASE | $NEXT_RELEASE_STABLE |
|
||||
RemoveMirrorPeerSite | $NEXT_RELEASE | $NEXT_RELEASE_STABLE |
|
||||
GetAttributesMirrorPeerSite | $NEXT_RELEASE | $NEXT_RELEASE_STABLE |
|
||||
SetAttributesMirrorPeerSite | $NEXT_RELEASE | $NEXT_RELEASE_STABLE |
|
||||
ListMirrorPeerSite | $NEXT_RELEASE | $NEXT_RELEASE_STABLE |
|
||||
SetMirrorPeerSiteClientName | $NEXT_RELEASE | $NEXT_RELEASE_STABLE |
|
||||
SetMirrorPeerSiteName | $NEXT_RELEASE | $NEXT_RELEASE_STABLE |
|
||||
SetMirrorPeerSiteDirection | $NEXT_RELEASE | $NEXT_RELEASE_STABLE |
|
||||
|
||||
### Deprecated APIs
|
||||
|
||||
|
|
|
@ -0,0 +1,255 @@
|
|||
//go:build !nautilus && ceph_preview
|
||||
// +build !nautilus,ceph_preview
|
||||
|
||||
package rbd
|
||||
|
||||
// #cgo LDFLAGS: -lrbd
|
||||
// #include <stdlib.h>
|
||||
// #include <rbd/librbd.h>
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"unsafe"
|
||||
|
||||
"github.com/ceph/go-ceph/internal/cutil"
|
||||
"github.com/ceph/go-ceph/internal/retry"
|
||||
"github.com/ceph/go-ceph/rados"
|
||||
)
|
||||
|
||||
// AddMirrorPeerSite adds a peer site to the list of existing sites
|
||||
//
|
||||
// Implements:
|
||||
//
|
||||
// int rbd_mirror_peer_site_add(rados_ioctx_t p, char *uuid, size_t uuid_max_length,
|
||||
// rbd_mirror_peer_direction_t direction,
|
||||
// const char *site_name,
|
||||
// const char *client_name);
|
||||
func AddMirrorPeerSite(ioctx *rados.IOContext, siteName string, clientName string,
|
||||
direction MirrorPeerDirection) (string, error) {
|
||||
|
||||
var (
|
||||
err error
|
||||
buf []byte
|
||||
cSize C.size_t
|
||||
)
|
||||
|
||||
cSiteName := C.CString(siteName)
|
||||
defer C.free(unsafe.Pointer(cSiteName))
|
||||
cClientName := C.CString(clientName)
|
||||
defer C.free(unsafe.Pointer(cClientName))
|
||||
|
||||
retry.WithSizes(512, 1<<16, func(size int) retry.Hint {
|
||||
cSize = C.size_t(size)
|
||||
buf = make([]byte, cSize)
|
||||
ret := C.rbd_mirror_peer_site_add(
|
||||
cephIoctx(ioctx),
|
||||
(*C.char)(unsafe.Pointer(&buf[0])),
|
||||
cSize, C.rbd_mirror_peer_direction_t(direction),
|
||||
cSiteName, cClientName)
|
||||
err = getError(ret)
|
||||
return retry.Size(int(cSize)).If(err != nil)
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return string(bytes.Trim(buf[:cSize], "\x00")), nil
|
||||
}
|
||||
|
||||
// RemoveMirrorPeerSite removes the site with the provided uuid
|
||||
//
|
||||
// Implements:
|
||||
//
|
||||
// int rbd_mirror_peer_site_remove(rados_ioctx_t p, const char *uuid)
|
||||
func RemoveMirrorPeerSite(ioctx *rados.IOContext, uuid string) error {
|
||||
cUUID := C.CString(uuid)
|
||||
defer C.free(unsafe.Pointer(cUUID))
|
||||
|
||||
ret := C.rbd_mirror_peer_site_remove(cephIoctx(ioctx), cUUID)
|
||||
|
||||
return getError(ret)
|
||||
}
|
||||
|
||||
// GetAttributesMirrorPeerSite fetches the list of key,value pair of attributes of a peer site
|
||||
//
|
||||
// Implements:
|
||||
//
|
||||
// int rbd_mirror_peer_site_get_attributes(rados_ioctx_t p, const char *uuid, char *keys,
|
||||
// size_t *max_key_len, char *values, size_t *max_val_len,
|
||||
// size_t *key_value_count);
|
||||
func GetAttributesMirrorPeerSite(ioctx *rados.IOContext, uuid string) (map[string]string, error) {
|
||||
|
||||
var (
|
||||
err error
|
||||
keys []byte
|
||||
vals []byte
|
||||
keySize C.size_t
|
||||
valSize C.size_t
|
||||
count = C.size_t(0)
|
||||
)
|
||||
|
||||
cUUID := C.CString(uuid)
|
||||
defer C.free(unsafe.Pointer(cUUID))
|
||||
|
||||
retry.WithSizes(1024, 1<<16, func(size int) retry.Hint {
|
||||
keySize = C.size_t(size)
|
||||
valSize = C.size_t(size)
|
||||
keys = make([]byte, keySize)
|
||||
vals = make([]byte, valSize)
|
||||
ret := C.rbd_mirror_peer_site_get_attributes(
|
||||
cephIoctx(ioctx), cUUID, (*C.char)(unsafe.Pointer(&keys[0])),
|
||||
&keySize, (*C.char)(unsafe.Pointer(&vals[0])), &valSize,
|
||||
&count)
|
||||
err = getErrorIfNegative(ret)
|
||||
return retry.Size(int(keySize)).If(err == errRange)
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
keyList := cutil.SplitBuffer(keys[:keySize])
|
||||
valList := cutil.SplitBuffer(vals[:valSize])
|
||||
attributes := map[string]string{}
|
||||
for i := 0; i < int(len(keyList)); i++ {
|
||||
attributes[keyList[i]] = valList[i]
|
||||
}
|
||||
return attributes, nil
|
||||
}
|
||||
|
||||
// SetAttributesMirrorPeerSite sets the attributes for the site with the given uuid
|
||||
//
|
||||
// Implements:
|
||||
//
|
||||
// int rbd_mirror_peer_site_set_attributes(rados_ioctx_t p, const char *uuid,
|
||||
// const char *keys, const char *values,
|
||||
// size_t count) ;
|
||||
func SetAttributesMirrorPeerSite(ioctx *rados.IOContext, uuid string, attributes map[string]string) error {
|
||||
cUUID := C.CString(uuid)
|
||||
defer C.free(unsafe.Pointer(cUUID))
|
||||
|
||||
var (
|
||||
key string
|
||||
val string
|
||||
count = C.size_t(len(attributes))
|
||||
)
|
||||
|
||||
for k, v := range attributes {
|
||||
key += k + "\000"
|
||||
val += v + "\000"
|
||||
}
|
||||
|
||||
cKey := C.CString(key)
|
||||
defer C.free(unsafe.Pointer(cKey))
|
||||
|
||||
cVal := C.CString(val)
|
||||
defer C.free(unsafe.Pointer(cVal))
|
||||
|
||||
ret := C.rbd_mirror_peer_site_set_attributes(cephIoctx(ioctx), cUUID, cKey, cVal, count)
|
||||
|
||||
return getError(ret)
|
||||
}
|
||||
|
||||
// MirrorPeerSite contains information about a mirroring peer site.
|
||||
type MirrorPeerSite struct {
|
||||
UUID string
|
||||
Direction MirrorPeerDirection
|
||||
SiteName string
|
||||
MirrorUUID string
|
||||
ClientName string
|
||||
LastSeen C.time_t
|
||||
}
|
||||
|
||||
// ListMirrorPeerSite returns the list of peer sites
|
||||
//
|
||||
// Implements:
|
||||
//
|
||||
// int rbd_mirror_peer_site_list(rados_ioctx_t p, rbd_mirror_peer_site_t *peers, int *max_peers)
|
||||
func ListMirrorPeerSite(ioctx *rados.IOContext) ([]*MirrorPeerSite, error) {
|
||||
var mps []*MirrorPeerSite
|
||||
cMaxPeers := C.int(10)
|
||||
|
||||
var cSites []C.rbd_mirror_peer_site_t
|
||||
for {
|
||||
cSites = make([]C.rbd_mirror_peer_site_t, cMaxPeers)
|
||||
ret := C.rbd_mirror_peer_site_list(cephIoctx(ioctx), &cSites[0], &cMaxPeers)
|
||||
err := getError(ret)
|
||||
if err == errRange {
|
||||
// There are too many peer sites to fit in the list, and the number of peer sites has been
|
||||
// returned in cMaxPeers. Try again with the returned value.
|
||||
continue
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// ret == 0
|
||||
break
|
||||
}
|
||||
|
||||
defer C.rbd_mirror_peer_site_list_cleanup(&cSites[0], cMaxPeers)
|
||||
cSites = cSites[:cMaxPeers]
|
||||
|
||||
for _, cSite := range cSites {
|
||||
mps = append(mps, &MirrorPeerSite{
|
||||
UUID: C.GoString(cSite.uuid),
|
||||
Direction: MirrorPeerDirection(cSite.direction),
|
||||
SiteName: C.GoString(cSite.site_name),
|
||||
MirrorUUID: C.GoString(cSite.mirror_uuid),
|
||||
ClientName: C.GoString(cSite.client_name),
|
||||
})
|
||||
}
|
||||
|
||||
return mps, nil
|
||||
}
|
||||
|
||||
// SetMirrorPeerSiteClientName sets the client name for a mirror peer site
|
||||
//
|
||||
// Implements:
|
||||
//
|
||||
// int rbd_mirror_peer_site_set_client_name(rados_ioctx_t p, const char *uuid,
|
||||
// const char *client_name);
|
||||
func SetMirrorPeerSiteClientName(ioctx *rados.IOContext, uuid string, clientName string) error {
|
||||
cUUID := C.CString(uuid)
|
||||
defer C.free(unsafe.Pointer(cUUID))
|
||||
|
||||
cClientName := C.CString(clientName)
|
||||
defer C.free(unsafe.Pointer(cClientName))
|
||||
|
||||
ret := C.rbd_mirror_peer_site_set_client_name(cephIoctx(ioctx), cUUID, cClientName)
|
||||
|
||||
return getError(ret)
|
||||
}
|
||||
|
||||
// SetMirrorPeerSiteDirection sets the direction of a mirror peer site
|
||||
//
|
||||
// Implements:
|
||||
//
|
||||
// int rbd_mirror_peer_site_set_direction(rados_ioctx_t p, const char *uuid,
|
||||
// rbd_mirror_peer_direction_t direction);
|
||||
func SetMirrorPeerSiteDirection(ioctx *rados.IOContext, uuid string, direction MirrorPeerDirection) error {
|
||||
cUUID := C.CString(uuid)
|
||||
defer C.free(unsafe.Pointer(cUUID))
|
||||
|
||||
ret := C.rbd_mirror_peer_site_set_direction(cephIoctx(ioctx), cUUID,
|
||||
C.rbd_mirror_peer_direction_t(direction))
|
||||
|
||||
return getError(ret)
|
||||
}
|
||||
|
||||
// SetMirrorPeerSiteName sets the name of a mirror peer site
|
||||
//
|
||||
// Implements:
|
||||
//
|
||||
// int rbd_mirror_peer_site_set_name(rados_ioctx_t p, const char *uuid,
|
||||
// const char *site_name);
|
||||
func SetMirrorPeerSiteName(ioctx *rados.IOContext, uuid string, siteName string) error {
|
||||
cUUID := C.CString(uuid)
|
||||
defer C.free(unsafe.Pointer(cUUID))
|
||||
|
||||
cSiteName := C.CString(siteName)
|
||||
defer C.free(unsafe.Pointer(cSiteName))
|
||||
|
||||
ret := C.rbd_mirror_peer_site_set_name(cephIoctx(ioctx), cUUID, cSiteName)
|
||||
|
||||
return getError(ret)
|
||||
}
|
|
@ -0,0 +1,103 @@
|
|||
//go:build !nautilus && ceph_preview
|
||||
// +build !nautilus,ceph_preview
|
||||
|
||||
package rbd
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestMirrorPeerSite(t *testing.T) {
|
||||
conn := radosConnect(t)
|
||||
poolName := GetUUID()
|
||||
err := conn.MakePool(poolName)
|
||||
require.NoError(t, err)
|
||||
defer func() {
|
||||
assert.NoError(t, conn.DeletePool(poolName))
|
||||
conn.Shutdown()
|
||||
}()
|
||||
|
||||
ioctx, err := conn.OpenIOContext(poolName)
|
||||
assert.NoError(t, err)
|
||||
defer func() {
|
||||
ioctx.Destroy()
|
||||
}()
|
||||
|
||||
err = SetMirrorMode(ioctx, MirrorModePool)
|
||||
assert.NoError(t, err)
|
||||
|
||||
t.Run("addRemovePeerSite", func(t *testing.T) {
|
||||
uuid, err := AddMirrorPeerSite(ioctx, "site_a", "client_a", MirrorPeerDirectionRxTx)
|
||||
assert.NoError(t, err)
|
||||
defer func() {
|
||||
assert.NoError(t, RemoveMirrorPeerSite(ioctx, uuid))
|
||||
}()
|
||||
})
|
||||
|
||||
t.Run("addPeerSiteInvalid", func(t *testing.T) {
|
||||
_, err := AddMirrorPeerSite(ioctx, "", "client_b", MirrorPeerDirectionRx)
|
||||
assert.Error(t, err)
|
||||
})
|
||||
|
||||
t.Run("listPeerSite", func(t *testing.T) {
|
||||
uuid, err := AddMirrorPeerSite(ioctx, "site_b", "client_b", MirrorPeerDirectionRxTx)
|
||||
assert.NoError(t, err)
|
||||
defer func() {
|
||||
assert.NoError(t, RemoveMirrorPeerSite(ioctx, uuid))
|
||||
}()
|
||||
|
||||
site, err := ListMirrorPeerSite(ioctx)
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, site, 1)
|
||||
assert.Equal(t, site[0].UUID, uuid)
|
||||
assert.Equal(t, site[0].SiteName, "site_b")
|
||||
assert.Equal(t, site[0].ClientName, "client_b")
|
||||
assert.Equal(t, site[0].Direction, MirrorPeerDirectionRxTx)
|
||||
})
|
||||
|
||||
t.Run("setGetAttributesPeerSite", func(t *testing.T) {
|
||||
uuid, err := AddMirrorPeerSite(ioctx, "site_c", "client_c", MirrorPeerDirectionRxTx)
|
||||
assert.NoError(t, err)
|
||||
defer func() {
|
||||
assert.NoError(t, RemoveMirrorPeerSite(ioctx, uuid))
|
||||
}()
|
||||
|
||||
attributes := map[string]string{
|
||||
"mon_host": "test_host",
|
||||
}
|
||||
err = SetAttributesMirrorPeerSite(ioctx, uuid, attributes)
|
||||
assert.NoError(t, err)
|
||||
|
||||
attributesList, err := GetAttributesMirrorPeerSite(ioctx, uuid)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, attributesList, attributes)
|
||||
})
|
||||
|
||||
t.Run("setPeerSite", func(t *testing.T) {
|
||||
uuid, err := AddMirrorPeerSite(ioctx, "site_d", "client_d", MirrorPeerDirectionRxTx)
|
||||
assert.NoError(t, err)
|
||||
defer func() {
|
||||
assert.NoError(t, RemoveMirrorPeerSite(ioctx, uuid))
|
||||
}()
|
||||
|
||||
err = SetMirrorPeerSiteClientName(ioctx, uuid, "client_e")
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = SetMirrorPeerSiteName(ioctx, uuid, "site_e")
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = SetMirrorPeerSiteDirection(ioctx, uuid, MirrorPeerDirectionRx)
|
||||
assert.NoError(t, err)
|
||||
|
||||
site, err := ListMirrorPeerSite(ioctx)
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, site, 1)
|
||||
assert.Equal(t, site[0].UUID, uuid)
|
||||
assert.Equal(t, site[0].SiteName, "site_e")
|
||||
assert.Equal(t, site[0].ClientName, "client_e")
|
||||
assert.Equal(t, site[0].Direction, MirrorPeerDirectionRx)
|
||||
})
|
||||
}
|
Loading…
Reference in New Issue