summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Mick <dan.mick@inktank.com>2013-07-18 14:43:37 -0700
committerDan Mick <dan.mick@inktank.com>2013-07-26 13:51:09 -0700
commitcb38762bca942e8e8c1a89bca6d3c6362182385f (patch)
treeb35ce840663139071de8ac9ff69479e6274456a7
parent67eb7de42f40eb080438a2f22303265c987a4b27 (diff)
downloadceph-cb38762bca942e8e8c1a89bca6d3c6362182385f.tar.gz
ceph.in: admin_socket() now validates command and passes format
Signed-off-by: Dan Mick <dan.mick@inktank.com>
-rwxr-xr-xsrc/ceph.in70
1 files changed, 52 insertions, 18 deletions
diff --git a/src/ceph.in b/src/ceph.in
index 90795058127..a72761216bd 100755
--- a/src/ceph.in
+++ b/src/ceph.in
@@ -285,26 +285,57 @@ def format_help(cmddict, partial=None):
return fullusage
-def admin_socket(asok_path, cmd):
- sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+def admin_socket(asok_path, cmd, format=''):
+ """
+ Send a daemon (--admin-daemon) command 'cmd'. asok_path is the
+ path to the admin socket; cmd is a list of strings; format may be
+ set to one of the formatted forms to get output in that form
+ (daemon commands don't support 'plain' output).
+ """
+
+ def do_sockio(path, cmd):
+ """ helper: do all the actual low-level stream I/O """
+ sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+ sock.connect(path)
+ try:
+ sock.sendall(cmd + '\0')
+ len_str = sock.recv(4)
+ if len(len_str) < 4:
+ raise RuntimeError("no data returned from admin socket")
+ l, = struct.unpack(">I", len_str)
+ ret = ''
+
+ got = 0
+ while got < l:
+ bit = sock.recv(l - got)
+ ret += bit
+ got += len(bit)
+
+ except Exception as e:
+ raise RuntimeError('exception: ' + str(e))
+ return ret
+
try:
- sock.connect(asok_path)
- sock.sendall(' '.join(cmd) + '\0')
+ cmd_json = do_sockio(asok_path,
+ json.dumps({"prefix":"get_command_descriptions"}))
+ except Exception as e:
+ raise RuntimeError('exception getting command descriptions: ' + str(e))
+
+ if cmd[0] == 'get_command_descriptions':
+ return cmd_json
- len_str = sock.recv(4)
- if len(len_str) < 4:
- raise RuntimeError("no data returned from admin socket")
- l, = struct.unpack(">I", len_str)
- ret = ''
+ sigdict = parse_json_funcsigs(cmd_json, 'cli')
+ valid_dict = validate_command(sigdict, cmd)
+ if not valid_dict:
+ return -errno.EINVAL
- got = 0
- while got < l:
- bit = sock.recv(l - got)
- ret += bit
- got += len(bit)
+ if format:
+ valid_dict['format'] = format
+ try:
+ ret = do_sockio(asok_path, json.dumps(valid_dict))
except Exception as e:
- raise RuntimeError('exception: {0}'.format(e))
+ raise RuntimeError('exception: ' + str(e))
return ret
@@ -473,9 +504,12 @@ def main():
conffile = parsed_args.cephconf
# For now, --admin-daemon is handled as usual. Try it
# first in case we can't connect() to the cluster
+
+ format = parsed_args.output_format
+
if parsed_args.admin_socket:
try:
- print admin_socket(parsed_args.admin_socket, childargs)
+ print admin_socket(parsed_args.admin_socket, childargs, format)
except Exception as e:
print >> sys.stderr, 'admin_socket: {0}'.format(e)
return 0
@@ -484,7 +518,7 @@ def main():
if len(childargs) > 2:
if childargs[1].find('/') >= 0:
try:
- print admin_socket(childargs[1], childargs[2:])
+ print admin_socket(childargs[1], childargs[2:], format)
except Exception as e:
print >> sys.stderr, 'admin_socket: {0}'.format(e)
return 0
@@ -492,7 +526,7 @@ def main():
# try resolve daemon name
path = ceph_conf('admin_socket', childargs[1])
try:
- print admin_socket(path, childargs[2:])
+ print admin_socket(path, childargs[2:], format)
except Exception as e:
print >> sys.stderr, 'admin_socket: {0}'.format(e)
return 0