cephfs: add wrapper funcs for ceph_mds_command

Adding a wrapper for ceph_mds_command allows the client to make
queries against the mds server.

Signed-off-by: John Mulligan <jmulligan@redhat.com>
This commit is contained in:
John Mulligan 2020-01-28 13:09:29 -05:00 committed by Niels de Vos
parent dd041586ba
commit 34f1507992
2 changed files with 105 additions and 0 deletions

View File

@ -160,3 +160,76 @@ func (mount *MountInfo) IsMounted() bool {
ret := C.ceph_is_mounted(mount.mount)
return ret == 1
}
// MdsCommand sends commands to the specified MDS.
func (mount *MountInfo) MdsCommand(mdsSpec string, args [][]byte) ([]byte, string, error) {
return mount.mdsCommand(mdsSpec, args, nil)
}
// MdsCommandWithInputBuffer sends commands to the specified MDS, with an input
// buffer.
func (mount *MountInfo) MdsCommandWithInputBuffer(mdsSpec string, args [][]byte, inputBuffer []byte) ([]byte, string, error) {
return mount.mdsCommand(mdsSpec, args, inputBuffer)
}
// mdsCommand supports sending formatted commands to MDS.
//
// Implements:
// int ceph_mds_command(struct ceph_mount_info *cmount,
// const char *mds_spec,
// const char **cmd,
// size_t cmdlen,
// const char *inbuf, size_t inbuflen,
// char **outbuf, size_t *outbuflen,
// char **outs, size_t *outslen);
func (mount *MountInfo) mdsCommand(mdsSpec string, args [][]byte, inputBuffer []byte) (buffer []byte, info string, err error) {
spec := C.CString(mdsSpec)
defer C.free(unsafe.Pointer(spec))
argc := len(args)
argv := make([]*C.char, argc)
for i, arg := range args {
argv[i] = C.CString(string(arg))
}
// free all array elements in a single defer
defer func() {
for i := range argv {
C.free(unsafe.Pointer(argv[i]))
}
}()
var (
outs, outbuf *C.char
outslen, outbuflen C.size_t
)
inbuf := C.CString(string(inputBuffer))
inbufLen := len(inputBuffer)
defer C.free(unsafe.Pointer(inbuf))
ret := C.ceph_mds_command(
mount.mount, // cephfs mount ref
spec, // mds spec
&argv[0], // cmd array
C.size_t(argc), // cmd array length
inbuf, // bulk input
C.size_t(inbufLen), // length inbuf
&outbuf, // buffer
&outbuflen, // buffer length
&outs, // status string
&outslen)
if outslen > 0 {
info = C.GoStringN(outs, C.int(outslen))
C.free(unsafe.Pointer(outs))
}
if outbuflen > 0 {
buffer = C.GoBytes(unsafe.Pointer(outbuf), C.int(outbuflen))
C.free(unsafe.Pointer(outbuf))
}
if ret != 0 {
return nil, info, getError(ret)
}
return buffer, info, nil
}

View File

@ -1,6 +1,7 @@
package cephfs
import (
"encoding/json"
"fmt"
"os"
"syscall"
@ -236,3 +237,34 @@ func TestCreateMountWithId(t *testing.T) {
err = mount.Mount()
assert.NoError(t, err)
}
func TestMdsCommand(t *testing.T) {
mount := fsConnect(t)
cmd := []byte(`{"prefix": "client ls"}`)
buf, info, err := mount.MdsCommand(
"Z", // TODO: fix hard-coded name mds (from ci container script)
[][]byte{cmd})
assert.NoError(t, err)
assert.NotEqual(t, "", string(buf))
assert.Equal(t, "", string(info))
assert.Contains(t, string(buf), "ceph_version")
// response should also be valid json
var j []interface{}
err = json.Unmarshal(buf, &j)
assert.NoError(t, err)
assert.GreaterOrEqual(t, len(j), 1)
}
func TestMdsCommandError(t *testing.T) {
mount := fsConnect(t)
cmd := []byte("iAMinValId~~~")
buf, info, err := mount.MdsCommand(
"Z", // TODO: fix hard-coded name mds (from ci container script)
[][]byte{cmd})
assert.Error(t, err)
assert.Equal(t, "", string(buf))
assert.NotEqual(t, "", string(info))
assert.Contains(t, string(info), "unparseable JSON")
}