diff options
author | Dan Mick <dan.mick@inktank.com> | 2013-07-18 14:43:37 -0700 |
---|---|---|
committer | Dan Mick <dan.mick@inktank.com> | 2013-07-26 13:51:09 -0700 |
commit | cb38762bca942e8e8c1a89bca6d3c6362182385f (patch) | |
tree | b35ce840663139071de8ac9ff69479e6274456a7 | |
parent | 67eb7de42f40eb080438a2f22303265c987a4b27 (diff) | |
download | ceph-cb38762bca942e8e8c1a89bca6d3c6362182385f.tar.gz |
ceph.in: admin_socket() now validates command and passes format
Signed-off-by: Dan Mick <dan.mick@inktank.com>
-rwxr-xr-x | src/ceph.in | 70 |
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 |