mirror of https://github.com/ceph/go-ceph
rados: move *Command functions into a separate file
Organize the rados package a bit more by moving functions that wrap rados_xyz_command functions into a dedicated file. Move related test to a separate file as well. Signed-off-by: John Mulligan <jmulligan@redhat.com>
This commit is contained in:
parent
301d8e427f
commit
79dfe8e631
|
@ -0,0 +1,128 @@
|
|||
package rados
|
||||
|
||||
// #cgo LDFLAGS: -lrados
|
||||
// #include <stdlib.h>
|
||||
// #include <rados/librados.h>
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// MonCommand sends a command to one of the monitors
|
||||
func (c *Conn) MonCommand(args []byte) (buffer []byte, info string, err error) {
|
||||
return c.monCommand(args, nil)
|
||||
}
|
||||
|
||||
// MonCommandWithInputBuffer sends a command to one of the monitors, with an input buffer
|
||||
func (c *Conn) MonCommandWithInputBuffer(args, inputBuffer []byte) (buffer []byte, info string, err error) {
|
||||
return c.monCommand(args, inputBuffer)
|
||||
}
|
||||
|
||||
func (c *Conn) monCommand(args, inputBuffer []byte) (buffer []byte, info string, err error) {
|
||||
argv := C.CString(string(args))
|
||||
defer C.free(unsafe.Pointer(argv))
|
||||
|
||||
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.rados_mon_command(c.cluster,
|
||||
&argv, 1,
|
||||
inbuf, // bulk input (e.g. crush map)
|
||||
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 {
|
||||
err = getError(ret)
|
||||
return nil, info, err
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// PGCommand sends a command to one of the PGs
|
||||
//
|
||||
// Implements:
|
||||
// int rados_pg_command(rados_t cluster, const char *pgstr,
|
||||
// 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) PGCommand(pgid []byte, args [][]byte) (buffer []byte, info string, err error) {
|
||||
return c.pgCommand(pgid, args, nil)
|
||||
}
|
||||
|
||||
// PGCommandWithInputBuffer sends a command to one of the PGs, with an input buffer
|
||||
//
|
||||
// Implements:
|
||||
// int rados_pg_command(rados_t cluster, const char *pgstr,
|
||||
// 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) PGCommandWithInputBuffer(pgid []byte, args [][]byte, inputBuffer []byte) (buffer []byte, info string, err error) {
|
||||
return c.pgCommand(pgid, args, inputBuffer)
|
||||
}
|
||||
|
||||
func (c *Conn) pgCommand(pgid []byte, args [][]byte, inputBuffer []byte) (buffer []byte, info string, err error) {
|
||||
name := C.CString(string(pgid))
|
||||
defer C.free(unsafe.Pointer(name))
|
||||
|
||||
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 (
|
||||
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_pg_command(c.cluster,
|
||||
name,
|
||||
&argv[0],
|
||||
C.size_t(argc),
|
||||
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 {
|
||||
err = getError(ret)
|
||||
return nil, info, err
|
||||
}
|
||||
|
||||
return
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
package rados
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func (suite *RadosTestSuite) TestMonCommand() {
|
||||
suite.SetupConnection()
|
||||
|
||||
command, err := json.Marshal(
|
||||
map[string]string{"prefix": "df", "format": "json"})
|
||||
assert.NoError(suite.T(), err)
|
||||
|
||||
buf, info, err := suite.conn.MonCommand(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)
|
||||
}
|
||||
|
||||
// NB: ceph octopus appears to be stricter about the formatting of the keyring
|
||||
// and now rejects whitespace that older versions did not have a problem with.
|
||||
const clientKeyFormat = `
|
||||
[%s]
|
||||
key = AQD4PGNXBZJNHhAA582iUgxe9DsN+MqFN4Z6Jw==
|
||||
`
|
||||
|
||||
func (suite *RadosTestSuite) TestMonCommandWithInputBuffer() {
|
||||
suite.SetupConnection()
|
||||
|
||||
entity := fmt.Sprintf("client.testMonCmdUser%d", time.Now().UnixNano())
|
||||
|
||||
// first add the new test user, specifying its key in the input buffer
|
||||
command, err := json.Marshal(map[string]interface{}{
|
||||
"prefix": "auth add",
|
||||
"format": "json",
|
||||
"entity": entity,
|
||||
})
|
||||
assert.NoError(suite.T(), err)
|
||||
|
||||
client_key := fmt.Sprintf(clientKeyFormat, entity)
|
||||
|
||||
inbuf := []byte(client_key)
|
||||
|
||||
buf, info, err := suite.conn.MonCommandWithInputBuffer(command, inbuf)
|
||||
assert.NoError(suite.T(), err)
|
||||
expected_info := fmt.Sprintf("added key for %s", entity)
|
||||
assert.Equal(suite.T(), expected_info, info)
|
||||
assert.Equal(suite.T(), "", string(buf[:]))
|
||||
|
||||
// get the key and verify that it's what we previously set
|
||||
command, err = json.Marshal(map[string]interface{}{
|
||||
"prefix": "auth get-key",
|
||||
"format": "json",
|
||||
"entity": entity,
|
||||
})
|
||||
assert.NoError(suite.T(), err)
|
||||
|
||||
buf, info, err = suite.conn.MonCommand(command)
|
||||
assert.NoError(suite.T(), err)
|
||||
assert.Equal(suite.T(), "", info)
|
||||
assert.Equal(suite.T(),
|
||||
`{"key":"AQD4PGNXBZJNHhAA582iUgxe9DsN+MqFN4Z6Jw=="}`,
|
||||
string(buf[:]))
|
||||
}
|
||||
|
||||
func (suite *RadosTestSuite) TestPGCommand() {
|
||||
suite.SetupConnection()
|
||||
|
||||
pgid := "1.2"
|
||||
|
||||
command, err := json.Marshal(
|
||||
map[string]string{"prefix": "query", "pgid": pgid, "format": "json"})
|
||||
assert.NoError(suite.T(), err)
|
||||
|
||||
buf, info, err := suite.conn.PGCommand([]byte(pgid), [][]byte{[]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)
|
||||
}
|
118
rados/conn.go
118
rados/conn.go
|
@ -291,121 +291,3 @@ func (c *Conn) GetPoolByID(id int64) (string, error) {
|
|||
}
|
||||
return C.GoString((*C.char)(unsafe.Pointer(&buf[0]))), nil
|
||||
}
|
||||
|
||||
// MonCommand sends a command to one of the monitors
|
||||
func (c *Conn) MonCommand(args []byte) (buffer []byte, info string, err error) {
|
||||
return c.monCommand(args, nil)
|
||||
}
|
||||
|
||||
// MonCommandWithInputBuffer sends a command to one of the monitors, with an input buffer
|
||||
func (c *Conn) MonCommandWithInputBuffer(args, inputBuffer []byte) (buffer []byte, info string, err error) {
|
||||
return c.monCommand(args, inputBuffer)
|
||||
}
|
||||
|
||||
func (c *Conn) monCommand(args, inputBuffer []byte) (buffer []byte, info string, err error) {
|
||||
argv := C.CString(string(args))
|
||||
defer C.free(unsafe.Pointer(argv))
|
||||
|
||||
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.rados_mon_command(c.cluster,
|
||||
&argv, 1,
|
||||
inbuf, // bulk input (e.g. crush map)
|
||||
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 {
|
||||
err = getError(ret)
|
||||
return nil, info, err
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// PGCommand sends a command to one of the PGs
|
||||
//
|
||||
// Implements:
|
||||
// int rados_pg_command(rados_t cluster, const char *pgstr,
|
||||
// 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) PGCommand(pgid []byte, args [][]byte) (buffer []byte, info string, err error) {
|
||||
return c.pgCommand(pgid, args, nil)
|
||||
}
|
||||
|
||||
// PGCommandWithInputBuffer sends a command to one of the PGs, with an input buffer
|
||||
//
|
||||
// Implements:
|
||||
// int rados_pg_command(rados_t cluster, const char *pgstr,
|
||||
// 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) PGCommandWithInputBuffer(pgid []byte, args [][]byte, inputBuffer []byte) (buffer []byte, info string, err error) {
|
||||
return c.pgCommand(pgid, args, inputBuffer)
|
||||
}
|
||||
|
||||
func (c *Conn) pgCommand(pgid []byte, args [][]byte, inputBuffer []byte) (buffer []byte, info string, err error) {
|
||||
name := C.CString(string(pgid))
|
||||
defer C.free(unsafe.Pointer(name))
|
||||
|
||||
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 (
|
||||
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_pg_command(c.cluster,
|
||||
name,
|
||||
&argv[0],
|
||||
C.size_t(argc),
|
||||
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 {
|
||||
err = getError(ret)
|
||||
return nil, info, err
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package rados
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
|
@ -595,86 +594,6 @@ func (suite *RadosTestSuite) TestGetPoolName() {
|
|||
assert.Equal(suite.T(), name, suite.pool)
|
||||
}
|
||||
|
||||
func (suite *RadosTestSuite) TestMonCommand() {
|
||||
suite.SetupConnection()
|
||||
|
||||
command, err := json.Marshal(
|
||||
map[string]string{"prefix": "df", "format": "json"})
|
||||
assert.NoError(suite.T(), err)
|
||||
|
||||
buf, info, err := suite.conn.MonCommand(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)
|
||||
}
|
||||
|
||||
// NB: ceph octopus appears to be stricter about the formatting of the keyring
|
||||
// and now rejects whitespace that older versions did not have a problem with.
|
||||
const clientKeyFormat = `
|
||||
[%s]
|
||||
key = AQD4PGNXBZJNHhAA582iUgxe9DsN+MqFN4Z6Jw==
|
||||
`
|
||||
|
||||
func (suite *RadosTestSuite) TestMonCommandWithInputBuffer() {
|
||||
suite.SetupConnection()
|
||||
|
||||
entity := fmt.Sprintf("client.testMonCmdUser%d", time.Now().UnixNano())
|
||||
|
||||
// first add the new test user, specifying its key in the input buffer
|
||||
command, err := json.Marshal(map[string]interface{}{
|
||||
"prefix": "auth add",
|
||||
"format": "json",
|
||||
"entity": entity,
|
||||
})
|
||||
assert.NoError(suite.T(), err)
|
||||
|
||||
client_key := fmt.Sprintf(clientKeyFormat, entity)
|
||||
|
||||
inbuf := []byte(client_key)
|
||||
|
||||
buf, info, err := suite.conn.MonCommandWithInputBuffer(command, inbuf)
|
||||
assert.NoError(suite.T(), err)
|
||||
expected_info := fmt.Sprintf("added key for %s", entity)
|
||||
assert.Equal(suite.T(), expected_info, info)
|
||||
assert.Equal(suite.T(), "", string(buf[:]))
|
||||
|
||||
// get the key and verify that it's what we previously set
|
||||
command, err = json.Marshal(map[string]interface{}{
|
||||
"prefix": "auth get-key",
|
||||
"format": "json",
|
||||
"entity": entity,
|
||||
})
|
||||
assert.NoError(suite.T(), err)
|
||||
|
||||
buf, info, err = suite.conn.MonCommand(command)
|
||||
assert.NoError(suite.T(), err)
|
||||
assert.Equal(suite.T(), "", info)
|
||||
assert.Equal(suite.T(),
|
||||
`{"key":"AQD4PGNXBZJNHhAA582iUgxe9DsN+MqFN4Z6Jw=="}`,
|
||||
string(buf[:]))
|
||||
}
|
||||
|
||||
func (suite *RadosTestSuite) TestPGCommand() {
|
||||
suite.SetupConnection()
|
||||
|
||||
pgid := "1.2"
|
||||
|
||||
command, err := json.Marshal(
|
||||
map[string]string{"prefix": "query", "pgid": pgid, "format": "json"})
|
||||
assert.NoError(suite.T(), err)
|
||||
|
||||
buf, info, err := suite.conn.PGCommand([]byte(pgid), [][]byte{[]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) TestObjectListObjects() {
|
||||
suite.SetupConnection()
|
||||
|
||||
|
|
Loading…
Reference in New Issue