rbd: add new more idomatic functions for opening rbd images

Create new OpenImage & OpenImageReadOnly functions to replace the use of
Open() on image types. This function more closely matches the underlying
of the librbd function calls.

The third argument to the functions is a snapshot name but we also
create a new constant to clearly indicate that an image should be opened
w/o a snapshot. Internally, this also ensures that a null string is
passed to the C api.

Signed-off-by: John Mulligan <jmulligan@redhat.com>
This commit is contained in:
John Mulligan 2019-12-29 14:44:41 -05:00 committed by John Mulligan
parent 09813739ed
commit 20a458a614
2 changed files with 121 additions and 0 deletions

View File

@ -61,6 +61,9 @@ const (
imageNeedsIOContext
imageIsOpen
snapshotNeedsName
// NoSnapshot indicates that no snapshot name is in use (see OpenImage)
NoSnapshot = ""
)
//
@ -1286,3 +1289,74 @@ func TrashRestore(ioctx *rados.IOContext, id, name string) error {
return GetError(C.rbd_trash_restore(C.rados_ioctx_t(ioctx.Pointer()), c_id, c_name))
}
// OpenImage will open an existing rbd image by name 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.
//
// Implements:
// int rbd_open(rados_ioctx_t io, const char *name,
// rbd_image_t *image, const char *snap_name);
func OpenImage(ioctx *rados.IOContext, name, snapName string) (*Image, error) {
cName := C.CString(name)
defer C.free(unsafe.Pointer(cName))
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(
C.rados_ioctx_t(ioctx.Pointer()),
cName,
&cImage,
cSnapName)
if ret != 0 {
return nil, GetError(ret)
}
return &Image{
ioctx: ioctx,
name: name,
image: cImage,
}, nil
}
// OpenImageReadOnly will open an existing rbd image by name 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.
//
// Implements:
// int rbd_open_read_only(rados_ioctx_t io, const char *name,
// rbd_image_t *image, const char *snap_name);
func OpenImageReadOnly(ioctx *rados.IOContext, name, snapName string) (*Image, error) {
cName := C.CString(name)
defer C.free(unsafe.Pointer(cName))
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_read_only(
C.rados_ioctx_t(ioctx.Pointer()),
cName,
&cImage,
cSnapName)
if ret != 0 {
return nil, GetError(ret)
}
return &Image{
ioctx: ioctx,
name: name,
image: cImage,
}, nil
}

View File

@ -1259,3 +1259,50 @@ func TestClosedImage(t *testing.T) {
conn.DeletePool(poolname)
conn.Shutdown()
}
func TestOpenImage(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()
_, err = OpenImage(ioctx, name, NoSnapshot)
assert.Error(t, err)
image, err := Create(ioctx, name, 1<<22, 22)
assert.NoError(t, err)
oImage, err := OpenImage(ioctx, name, NoSnapshot)
assert.NoError(t, err)
assert.Equal(t, name, oImage.name)
err = oImage.Close()
assert.NoError(t, err)
// open read-only
oImage, err = OpenImageReadOnly(ioctx, name, NoSnapshot)
assert.NoError(t, err)
bytes_in := []byte("input data")
_, err = image.Write(bytes_in)
// writing should fail in read-only mode
assert.Error(t, err)
err = oImage.Close()
assert.NoError(t, err)
err = oImage.Remove()
assert.NoError(t, err)
_, err = OpenImageReadOnly(ioctx, name, NoSnapshot)
assert.Error(t, err)
ioctx.Destroy()
conn.DeletePool(poolname)
conn.Shutdown()
}