mirror of https://github.com/ceph/go-ceph
rbd: implement binding for rbd_mirror_image_instance_id_list
This commit adds MirrorImageInstanceIDList and MirrorImageInstanceIDIter with necessary helper functions and tests. Fixes: #483 Signed-off-by: Rakshith R <rar@redhat.com>
This commit is contained in:
parent
1d2ef78c2f
commit
a32355cba2
129
rbd/mirror.go
129
rbd/mirror.go
|
@ -908,3 +908,132 @@ func (iter *MirrorImageInfoIter) fetch() error {
|
|||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// MirrorImageInstanceIDItem contains an ID string for a RBD image and
|
||||
// its corresponding mirrored image's Instance ID.
|
||||
type MirrorImageInstanceIDItem struct {
|
||||
ID string
|
||||
InstanceID string
|
||||
}
|
||||
|
||||
// MirrorImageInstanceIDList returns a slice of MirrorImageInstanceIDItem. If
|
||||
// the length of the returned slice equals max, the next chunk of the list can
|
||||
// be obtained by setting start to the ID of the last item of the returned slice.
|
||||
// If max is 0 a slice of all items is returned.
|
||||
//
|
||||
// Implements:
|
||||
// int rbd_mirror_image_instance_id_list(
|
||||
// rados_ioctx_t io_ctx,
|
||||
// const char *start_id,
|
||||
// size_t max, char **image_ids,
|
||||
// char **instance_ids,
|
||||
// size_t *len)
|
||||
func MirrorImageInstanceIDList(
|
||||
ioctx *rados.IOContext, start string,
|
||||
max int) ([]MirrorImageInstanceIDItem, error) {
|
||||
var (
|
||||
result []MirrorImageInstanceIDItem
|
||||
fetchAll bool
|
||||
)
|
||||
if max <= 0 {
|
||||
max = iterBufSize
|
||||
fetchAll = true
|
||||
}
|
||||
chunk := make([]MirrorImageInstanceIDItem, max)
|
||||
for {
|
||||
length, err := mirrorImageInstanceIDList(ioctx, start, chunk)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result = append(result, chunk[:length]...)
|
||||
if !fetchAll || length < max {
|
||||
break
|
||||
}
|
||||
start = chunk[length-1].ID
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func mirrorImageInstanceIDList(ioctx *rados.IOContext, start string,
|
||||
results []MirrorImageInstanceIDItem) (int, error) {
|
||||
|
||||
cStart := C.CString(start)
|
||||
defer C.free(unsafe.Pointer(cStart))
|
||||
|
||||
var (
|
||||
max = C.size_t(len(results))
|
||||
length = C.size_t(0)
|
||||
ids = make([]*C.char, len(results))
|
||||
instance_ids = make([]*C.char, len(results))
|
||||
)
|
||||
ret := C.rbd_mirror_image_instance_id_list(
|
||||
cephIoctx(ioctx),
|
||||
cStart,
|
||||
max,
|
||||
&ids[0],
|
||||
&instance_ids[0],
|
||||
&length,
|
||||
)
|
||||
if err := getError(ret); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
for i := 0; i < int(length); i++ {
|
||||
results[i].ID = C.GoString(ids[i])
|
||||
results[i].InstanceID = C.GoString(instance_ids[i])
|
||||
}
|
||||
C.rbd_mirror_image_instance_id_list_cleanup(
|
||||
&ids[0],
|
||||
&instance_ids[0],
|
||||
length)
|
||||
return int(length), getError(ret)
|
||||
}
|
||||
|
||||
// MirrorImageInstanceIDIter provide methods for iterating over all
|
||||
// the MirrorImageInstanceIDItem values in a pool.
|
||||
type MirrorImageInstanceIDIter struct {
|
||||
ioctx *rados.IOContext
|
||||
|
||||
buf []MirrorImageInstanceIDItem
|
||||
lastID string
|
||||
}
|
||||
|
||||
// NewMirrorImageInstanceIDIter creates a new iterator ready for use.
|
||||
func NewMirrorImageInstanceIDIter(ioctx *rados.IOContext) *MirrorImageInstanceIDIter {
|
||||
return &MirrorImageInstanceIDIter{
|
||||
ioctx: ioctx,
|
||||
}
|
||||
}
|
||||
|
||||
// Next fetches one MirrorImageInstanceIDItem value or a nil value if iteration is
|
||||
// exhausted. The error return will be non-nil if an underlying error fetching
|
||||
// more values occurred.
|
||||
func (iter *MirrorImageInstanceIDIter) Next() (*MirrorImageInstanceIDItem, error) {
|
||||
if len(iter.buf) == 0 {
|
||||
if err := iter.fetch(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(iter.buf) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
iter.lastID = iter.buf[len(iter.buf)-1].ID
|
||||
}
|
||||
item := iter.buf[0]
|
||||
iter.buf = iter.buf[1:]
|
||||
return &item, nil
|
||||
}
|
||||
|
||||
func (iter *MirrorImageInstanceIDIter) fetch() error {
|
||||
iter.buf = nil
|
||||
items := make([]MirrorImageInstanceIDItem, iterBufSize)
|
||||
n, err := mirrorImageInstanceIDList(
|
||||
iter.ioctx,
|
||||
iter.lastID,
|
||||
items)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if n > 0 {
|
||||
iter.buf = items[:n]
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -971,3 +971,130 @@ func TestMirrorImageLists(t *testing.T) {
|
|||
assert.Len(t, lst, 7)
|
||||
})
|
||||
}
|
||||
|
||||
func TestMirrorImageInstanceIDLists(t *testing.T) {
|
||||
defer func(x int) {
|
||||
iterBufSize = x
|
||||
}(iterBufSize)
|
||||
// shrink the buffer size in order to trigger more of the
|
||||
// retry logic in the iter type
|
||||
iterBufSize = 4
|
||||
|
||||
t.Run("instanceIDIterIoctxNil", func(t *testing.T) {
|
||||
iter := NewMirrorImageInstanceIDIter(nil)
|
||||
assert.Panics(t, func() {
|
||||
iter.Next() //nolint:errcheck
|
||||
})
|
||||
})
|
||||
|
||||
mconfig := mirrorConfig()
|
||||
if mconfig == "" {
|
||||
t.Skip("no mirror config env var set")
|
||||
}
|
||||
|
||||
conn := radosConnect(t)
|
||||
defer conn.Shutdown()
|
||||
|
||||
poolName := GetUUID()
|
||||
err := conn.MakePool(poolName)
|
||||
require.NoError(t, err)
|
||||
defer func() {
|
||||
assert.NoError(t, conn.DeletePool(poolName))
|
||||
}()
|
||||
|
||||
ioctx, err := conn.OpenIOContext(poolName)
|
||||
assert.NoError(t, err)
|
||||
defer func() {
|
||||
ioctx.Destroy()
|
||||
}()
|
||||
|
||||
err = SetMirrorMode(ioctx, MirrorModeImage)
|
||||
require.NoError(t, err)
|
||||
|
||||
token, err := CreateMirrorPeerBootstrapToken(ioctx)
|
||||
assert.NoError(t, err)
|
||||
assert.GreaterOrEqual(t, len(token), 4)
|
||||
|
||||
conn2 := radosConnectConfig(t, mconfig)
|
||||
defer conn2.Shutdown()
|
||||
|
||||
err = conn2.MakePool(poolName)
|
||||
require.NoError(t, err)
|
||||
defer func() {
|
||||
assert.NoError(t, conn2.DeletePool(poolName))
|
||||
}()
|
||||
|
||||
ioctx2, err := conn2.OpenIOContext(poolName)
|
||||
assert.NoError(t, err)
|
||||
defer func() {
|
||||
ioctx2.Destroy()
|
||||
}()
|
||||
|
||||
err = SetMirrorMode(ioctx2, MirrorModeImage)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = ImportMirrorPeerBootstrapToken(
|
||||
ioctx2, MirrorPeerDirectionRxTx, token)
|
||||
assert.NoError(t, err)
|
||||
|
||||
imgName := GetUUID()
|
||||
options := NewRbdImageOptions()
|
||||
assert.NoError(t, options.SetUint64(ImageOptionOrder, uint64(testImageOrder)))
|
||||
|
||||
for i := 0; i < 5; i++ {
|
||||
name := fmt.Sprintf("%s%d", imgName, i)
|
||||
err = CreateImage(ioctx, name, testImageSize, options)
|
||||
require.NoError(t, err)
|
||||
img, err := OpenImage(ioctx, name, NoSnapshot)
|
||||
assert.NoError(t, err)
|
||||
err = img.MirrorEnable(ImageMirrorModeSnapshot)
|
||||
assert.NoError(t, err)
|
||||
require.NoError(t, img.Close())
|
||||
}
|
||||
|
||||
// wait for all the images to be mirrored
|
||||
for i := 0; i < 30; i++ {
|
||||
lst, err := MirrorImageInstanceIDList(ioctx, "", 0)
|
||||
assert.NoError(t, err)
|
||||
if len(lst) == 5 {
|
||||
break
|
||||
}
|
||||
time.Sleep(time.Second)
|
||||
}
|
||||
|
||||
t.Run("getInstanceID", func(t *testing.T) {
|
||||
lst := []*MirrorImageInstanceIDItem{}
|
||||
iter := NewMirrorImageInstanceIDIter(ioctx)
|
||||
for {
|
||||
istatus, err := iter.Next()
|
||||
assert.NoError(t, err)
|
||||
if istatus == nil {
|
||||
break
|
||||
}
|
||||
lst = append(lst, istatus)
|
||||
}
|
||||
assert.Len(t, lst, 5)
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
|
||||
t.Run("getInstanceIDSlice", func(t *testing.T) {
|
||||
lst, err := MirrorImageInstanceIDList(ioctx, "", 0)
|
||||
fmt.Print(lst)
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, lst, 5)
|
||||
for i := 1; i < len(lst); i++ {
|
||||
assert.NotEqual(t, lst[i-1].ID, lst[i].ID)
|
||||
}
|
||||
for i := 1; i <= iterBufSize; i++ {
|
||||
lst, err := MirrorImageInstanceIDList(ioctx, "", i)
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, lst, i)
|
||||
}
|
||||
lst, err = MirrorImageInstanceIDList(ioctx, "", 3)
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, lst, 3)
|
||||
lst, err = MirrorImageInstanceIDList(ioctx, lst[2].ID, 0)
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, lst, 2)
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue