mirror of https://github.com/ceph/go-ceph
rados: add MgrCommand and MgrCommandWithInputBuffer functions
Add functions for issuing commands to ceph mgrs with MgrCommand and MgrCommandWithInputBuffer, implemented simliarly to the other *Command style functions. Signed-off-by: John Mulligan <jmulligan@redhat.com>
This commit is contained in:
parent
ff805ee1e1
commit
fb2736dd0a
|
@ -130,3 +130,65 @@ func (c *Conn) pgCommand(pgid []byte, args [][]byte, inputBuffer []byte) ([]byte
|
||||||
|
|
||||||
return buffer, info, nil
|
return buffer, info, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MgrCommand sends a command to a ceph-mgr.
|
||||||
|
func (c *Conn) MgrCommand(args [][]byte) ([]byte, string, error) {
|
||||||
|
return c.mgrCommand(args, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MgrCommandWithInputBuffer sends a command, with an input buffer, to a ceph-mgr.
|
||||||
|
func (c *Conn) MgrCommandWithInputBuffer(args [][]byte, inputBuffer []byte) ([]byte, string, error) {
|
||||||
|
return c.mgrCommand(args, inputBuffer)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implements:
|
||||||
|
// int rados_mgr_command(rados_t cluster, const char **cmd,
|
||||||
|
// size_t cmdlen, const char *inbuf,
|
||||||
|
// size_t inbuflen, char **outbuf,
|
||||||
|
// size_t *outbuflen, char **outs,
|
||||||
|
// size_t *outslen);
|
||||||
|
func (c *Conn) mgrCommand(args [][]byte, inputBuffer []byte) ([]byte, string, error) {
|
||||||
|
argc := len(args)
|
||||||
|
argv := make([]*C.char, argc)
|
||||||
|
|
||||||
|
for i, arg := range args {
|
||||||
|
argv[i] = C.CString(string(arg))
|
||||||
|
defer C.free(unsafe.Pointer(argv[i]))
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
info string
|
||||||
|
buffer []byte
|
||||||
|
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.rados_mgr_command(
|
||||||
|
c.cluster,
|
||||||
|
&argv[0],
|
||||||
|
C.size_t(argc),
|
||||||
|
inbuf,
|
||||||
|
C.size_t(inbufLen),
|
||||||
|
&outbuf,
|
||||||
|
&outbuflen,
|
||||||
|
&outs,
|
||||||
|
&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 {
|
||||||
|
err := getError(ret)
|
||||||
|
return nil, info, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer, info, nil
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
// +build !luminous
|
||||||
|
|
||||||
|
package rados
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
// A real test using input buffer is hard to find for mgr.
|
||||||
|
// The simplest does not work on luminous, so we simply don't
|
||||||
|
// provide the test for luminous.
|
||||||
|
|
||||||
|
func (suite *RadosTestSuite) TestMgrCommandWithInputBuffer() {
|
||||||
|
suite.SetupConnection()
|
||||||
|
|
||||||
|
command, err := json.Marshal(
|
||||||
|
map[string]string{"prefix": "crash post", "format": "json"})
|
||||||
|
assert.NoError(suite.T(), err)
|
||||||
|
|
||||||
|
buf, info, err := suite.conn.MgrCommandWithInputBuffer(
|
||||||
|
[][]byte{command}, []byte(`{"crash_id": "foobar", "timestamp": "2020-04-10 15:08:34.659679Z"}`))
|
||||||
|
assert.NoError(suite.T(), err)
|
||||||
|
assert.Equal(suite.T(), info, "")
|
||||||
|
assert.Len(suite.T(), buf, 0)
|
||||||
|
|
||||||
|
command, err = json.Marshal(
|
||||||
|
map[string]string{"prefix": "crash rm", "id": "foobar", "format": "json"})
|
||||||
|
assert.NoError(suite.T(), err)
|
||||||
|
|
||||||
|
buf, info, err = suite.conn.MgrCommandWithInputBuffer(
|
||||||
|
[][]byte{command}, nil)
|
||||||
|
assert.NoError(suite.T(), err)
|
||||||
|
assert.Equal(suite.T(), info, "")
|
||||||
|
assert.Len(suite.T(), buf, 0)
|
||||||
|
}
|
|
@ -87,3 +87,45 @@ func (suite *RadosTestSuite) TestPGCommand() {
|
||||||
err = json.Unmarshal(buf, &message)
|
err = json.Unmarshal(buf, &message)
|
||||||
assert.NoError(suite.T(), err)
|
assert.NoError(suite.T(), err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (suite *RadosTestSuite) TestMgrCommandDescrptions() {
|
||||||
|
suite.SetupConnection()
|
||||||
|
|
||||||
|
command, err := json.Marshal(
|
||||||
|
map[string]string{"prefix": "get_command_descriptions", "format": "json"})
|
||||||
|
assert.NoError(suite.T(), err)
|
||||||
|
|
||||||
|
buf, info, err := suite.conn.MgrCommand([][]byte{command})
|
||||||
|
assert.NoError(suite.T(), err)
|
||||||
|
assert.Equal(suite.T(), info, "")
|
||||||
|
|
||||||
|
var message map[string]interface{}
|
||||||
|
err = json.Unmarshal(buf, &message)
|
||||||
|
assert.NoError(suite.T(), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *RadosTestSuite) TestMgrCommand() {
|
||||||
|
suite.SetupConnection()
|
||||||
|
|
||||||
|
command, err := json.Marshal(
|
||||||
|
map[string]string{"prefix": "balancer status", "format": "json"})
|
||||||
|
assert.NoError(suite.T(), err)
|
||||||
|
|
||||||
|
buf, info, err := suite.conn.MgrCommand([][]byte{command})
|
||||||
|
assert.NoError(suite.T(), err)
|
||||||
|
assert.Equal(suite.T(), info, "")
|
||||||
|
|
||||||
|
var message map[string]interface{}
|
||||||
|
err = json.Unmarshal(buf, &message)
|
||||||
|
assert.NoError(suite.T(), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *RadosTestSuite) TestMgrCommandMalformedCommand() {
|
||||||
|
suite.SetupConnection()
|
||||||
|
|
||||||
|
command := []byte("JUNK!")
|
||||||
|
buf, info, err := suite.conn.MgrCommand([][]byte{command})
|
||||||
|
assert.Error(suite.T(), err)
|
||||||
|
assert.NotEqual(suite.T(), info, "")
|
||||||
|
assert.Len(suite.T(), buf, 0)
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue