mirror of https://github.com/ceph/go-ceph
rbd: add OpenImageById and OpenImageByIdReadOnly functions
Add OpenImageById and OpenImageByIdReadOnly that wrap rbd_open_by_id and rbd_open_by_id_read_only respectively. The added test case can not currently test trivial error conditions due to a known bug in ceph, these tests are skipped for meanwhile. Signed-off-by: John Mulligan <jmulligan@redhat.com>
This commit is contained in:
parent
a1f2aefcf9
commit
f72828c5b2
73
rbd/rbd.go
73
rbd/rbd.go
|
@ -1356,6 +1356,79 @@ func OpenImageReadOnly(ioctx *rados.IOContext, name, snapName string) (*Image, e
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// OpenImageById will open an existing rbd image by ID and snapshot name,
|
||||||
|
// returning a new opened image. Pass the NoSnapshot sentinel value as the
|
||||||
|
// snapName to explicitly indicate that no snapshot name is being provided.
|
||||||
|
// Error handling will fail & segfault unless compiled with a version of ceph
|
||||||
|
// that fixes https://tracker.ceph.com/issues/43178
|
||||||
|
//
|
||||||
|
// Implements:
|
||||||
|
// int rbd_open_by_id(rados_ioctx_t io, const char *id,
|
||||||
|
// rbd_image_t *image, const char *snap_name);
|
||||||
|
func OpenImageById(ioctx *rados.IOContext, id, snapName string) (*Image, error) {
|
||||||
|
cid := C.CString(id)
|
||||||
|
defer C.free(unsafe.Pointer(cid))
|
||||||
|
|
||||||
|
var cSnapName *C.char
|
||||||
|
if snapName != NoSnapshot {
|
||||||
|
cSnapName = C.CString(snapName)
|
||||||
|
defer C.free(unsafe.Pointer(cSnapName))
|
||||||
|
}
|
||||||
|
|
||||||
|
var cImage C.rbd_image_t
|
||||||
|
ret := C.rbd_open_by_id(
|
||||||
|
C.rados_ioctx_t(ioctx.Pointer()),
|
||||||
|
cid,
|
||||||
|
&cImage,
|
||||||
|
cSnapName)
|
||||||
|
|
||||||
|
if ret != 0 {
|
||||||
|
return nil, getError(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Image{
|
||||||
|
ioctx: ioctx,
|
||||||
|
image: cImage,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// OpenImageByIdReadOnly will open an existing rbd image by ID and snapshot
|
||||||
|
// name, returning a new opened-for-read image. Pass the NoSnapshot sentinel
|
||||||
|
// value as the snapName to explicitly indicate that no snapshot name is being
|
||||||
|
// provided.
|
||||||
|
// Error handling will fail & segfault unless compiled with a version of ceph
|
||||||
|
// that fixes https://tracker.ceph.com/issues/43178
|
||||||
|
//
|
||||||
|
// Implements:
|
||||||
|
// int rbd_open_by_id_read_only(rados_ioctx_t io, const char *id,
|
||||||
|
// rbd_image_t *image, const char *snap_name);
|
||||||
|
func OpenImageByIdReadOnly(ioctx *rados.IOContext, id, snapName string) (*Image, error) {
|
||||||
|
cid := C.CString(id)
|
||||||
|
defer C.free(unsafe.Pointer(cid))
|
||||||
|
|
||||||
|
var cSnapName *C.char
|
||||||
|
if snapName != NoSnapshot {
|
||||||
|
cSnapName = C.CString(snapName)
|
||||||
|
defer C.free(unsafe.Pointer(cSnapName))
|
||||||
|
}
|
||||||
|
|
||||||
|
var cImage C.rbd_image_t
|
||||||
|
ret := C.rbd_open_by_id_read_only(
|
||||||
|
C.rados_ioctx_t(ioctx.Pointer()),
|
||||||
|
cid,
|
||||||
|
&cImage,
|
||||||
|
cSnapName)
|
||||||
|
|
||||||
|
if ret != 0 {
|
||||||
|
return nil, getError(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Image{
|
||||||
|
ioctx: ioctx,
|
||||||
|
image: cImage,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
// CreateImage creates a new rbd image using provided image options.
|
// CreateImage creates a new rbd image using provided image options.
|
||||||
//
|
//
|
||||||
// Implements:
|
// Implements:
|
||||||
|
|
|
@ -1463,3 +1463,101 @@ func TestGetId(t *testing.T) {
|
||||||
conn.DeletePool(poolname)
|
conn.DeletePool(poolname)
|
||||||
conn.Shutdown()
|
conn.Shutdown()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestOpenImageById(t *testing.T) {
|
||||||
|
conn := radosConnect(t)
|
||||||
|
|
||||||
|
poolname := GetUUID()
|
||||||
|
err := conn.MakePool(poolname)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
ioctx, err := conn.OpenIOContext(poolname)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
name := GetUUID()
|
||||||
|
options := NewRbdImageOptions()
|
||||||
|
assert.NoError(t,
|
||||||
|
options.SetUint64(RbdImageOptionOrder, uint64(testImageOrder)))
|
||||||
|
err = CreateImage(ioctx, name, testImageSize, options)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
workingImage, err := OpenImage(ioctx, name, NoSnapshot)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
id, err := workingImage.GetId()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
err = workingImage.Close()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
t.Run("ReadWriteBadId", func(t *testing.T) {
|
||||||
|
t.Skip("segfaults due to https://tracker.ceph.com/issues/43178")
|
||||||
|
// phony id
|
||||||
|
img, err := OpenImageById(ioctx, "102f00aaabbbccd", NoSnapshot)
|
||||||
|
require.Error(t, err)
|
||||||
|
require.Nil(t, img)
|
||||||
|
})
|
||||||
|
t.Run("ReadOnlyBadId", func(t *testing.T) {
|
||||||
|
t.Skip("segfaults due to https://tracker.ceph.com/issues/43178")
|
||||||
|
// phony id
|
||||||
|
img, err := OpenImageByIdReadOnly(ioctx, "blubb", NoSnapshot)
|
||||||
|
require.Error(t, err)
|
||||||
|
require.Nil(t, img)
|
||||||
|
})
|
||||||
|
t.Run("ReadWrite", func(t *testing.T) {
|
||||||
|
img, err := OpenImageById(ioctx, id, NoSnapshot)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, img)
|
||||||
|
defer func() { assert.NoError(t, img.Close()) }()
|
||||||
|
|
||||||
|
data := []byte("input data")
|
||||||
|
_, err = img.Write(data)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
})
|
||||||
|
t.Run("ReadOnly", func(t *testing.T) {
|
||||||
|
img, err := OpenImageByIdReadOnly(ioctx, id, NoSnapshot)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, img)
|
||||||
|
defer func() { assert.NoError(t, img.Close()) }()
|
||||||
|
|
||||||
|
data := []byte("input data")
|
||||||
|
_, err = img.Write(data)
|
||||||
|
// writing should fail in read-only mode
|
||||||
|
assert.Error(t, err)
|
||||||
|
})
|
||||||
|
t.Run("Snapshot", func(t *testing.T) {
|
||||||
|
img, err := OpenImageById(ioctx, id, NoSnapshot)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, img)
|
||||||
|
defer func() { assert.NoError(t, img.Close()) }()
|
||||||
|
|
||||||
|
snapshot, err := img.CreateSnapshot("snerpshort")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
defer func() { assert.NoError(t, snapshot.Remove()) }()
|
||||||
|
|
||||||
|
snapImage, err := OpenImageById(ioctx, id, "snerpshort")
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, snapImage)
|
||||||
|
assert.NoError(t, snapImage.Close())
|
||||||
|
})
|
||||||
|
t.Run("ReadOnlySnapshot", func(t *testing.T) {
|
||||||
|
img, err := OpenImageById(ioctx, id, NoSnapshot)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, img)
|
||||||
|
defer func() { assert.NoError(t, img.Close()) }()
|
||||||
|
|
||||||
|
snapshot, err := img.CreateSnapshot("snerpshort2")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
defer func() { assert.NoError(t, snapshot.Remove()) }()
|
||||||
|
|
||||||
|
snapImage, err := OpenImageByIdReadOnly(ioctx, id, "snerpshort2")
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, snapImage)
|
||||||
|
assert.NoError(t, snapImage.Close())
|
||||||
|
})
|
||||||
|
|
||||||
|
err = workingImage.Remove()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
ioctx.Destroy()
|
||||||
|
conn.DeletePool(poolname)
|
||||||
|
conn.Shutdown()
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue