From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([140.186.70.92]:42590) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QlAEZ-0004wd-1f for qemu-devel@nongnu.org; Sun, 24 Jul 2011 21:45:28 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1QlAEI-0005ZD-Fv for qemu-devel@nongnu.org; Sun, 24 Jul 2011 21:45:23 -0400 Received: from e4.ny.us.ibm.com ([32.97.182.144]:39439) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QlAEH-0005Xr-JG for qemu-devel@nongnu.org; Sun, 24 Jul 2011 21:45:09 -0400 Received: from d01relay02.pok.ibm.com (d01relay02.pok.ibm.com [9.56.227.234]) by e4.ny.us.ibm.com (8.14.4/8.13.1) with ESMTP id p6P1MeQ0007168 for ; Sun, 24 Jul 2011 21:22:40 -0400 Received: from d01av04.pok.ibm.com (d01av04.pok.ibm.com [9.56.224.64]) by d01relay02.pok.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id p6P1j7Xb286410 for ; Sun, 24 Jul 2011 21:45:07 -0400 Received: from d01av04.pok.ibm.com (loopback [127.0.0.1]) by d01av04.pok.ibm.com (8.14.4/8.13.1/NCO v10.0 AVout) with ESMTP id p6P1j7Eh007920 for ; Sun, 24 Jul 2011 21:45:07 -0400 From: Anthony Liguori Date: Sun, 24 Jul 2011 20:44:46 -0500 Message-Id: <1311558293-5855-15-git-send-email-aliguori@us.ibm.com> In-Reply-To: <1311558293-5855-1-git-send-email-aliguori@us.ibm.com> References: <1311558293-5855-1-git-send-email-aliguori@us.ibm.com> Subject: [Qemu-devel] [PATCH 14/21] qom: add example qsh command List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: Anthony Liguori This lets you explore the QEMU Object Model with a filesystem like interface. Signed-off-by: Anthony Liguori --- scripts/qsh | 178 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 178 insertions(+), 0 deletions(-) create mode 100755 scripts/qsh diff --git a/scripts/qsh b/scripts/qsh new file mode 100755 index 0000000..b4b5e94 --- /dev/null +++ b/scripts/qsh @@ -0,0 +1,178 @@ +#!/usr/bin/python + +import json, socket +import sys + +class QmpException(Exception): + def __init__(self, cls, desc): + Exception.__init__(self, desc) + +class QmpClient(object): + def __init__(self, host, port): + s = socket.socket(socket.AF_INET) + s.connect((host, port)) + + self.s = s + self.buffer = '' + self.readline() + + def readline(self): + while not self.buffer.find('\n') != -1: + self.buffer += self.s.recv(1024) + + line, self.buffer = self.buffer.split('\n', 1) + return line + + def _command(self, _command_name, **args): + req = { "execute": _command_name, "arguments": args } + self.s.sendall(json.dumps(req)) + + rsp = json.loads(self.readline()) + if rsp.has_key('error'): + raise QmpException(rsp['error']['class'], rsp['error']['desc']) + return rsp['return'] + + def qmp_capabilities(self): + return self._command('qmp_capabilities') + + def plug_create(self, typename, name, **args): + self._command('plug_create', id=name, type=typename, **args) + + def plug_list(self, typename=None): + if typename == None: + return self._command('plug_list') + else: + return self._command('plug_list', type=typename) + + def plug_get(self, name, propname): + return self._command('plug_get', id=name, name=propname) + + def plug_set(self, name, propname, value): + self._command('plug_set', id=name, name=propname, value=value) + + def plug_list_props(self, name): + return self._command('plug_list_props', id=name) + + def quit(self): + self._command('quit') + +from ConfigParser import SafeConfigParser +import re + +class GitConfigParser(SafeConfigParser): + SECTCRE = re.compile(r'\[(?P
[^\"]+"[^"]*")\]') + + +def resolve_property(qmp, value): + value = value[1:] + + components = value.split('/') + + name = components[0] + components = components[1:] + + prop = components[-1] + for component in components[:-1]: + if component.startswith('@'): + component = component[1:] + name = qmp.plug_get(name, component) + + if prop.startswith('@'): + prop = prop[1:] + + return name, prop + +def parse_property(srv, value): + if value == 'True': + value = True + elif value == 'False': + value = False + elif value[0] in '0123456789-': + value = int(value) + elif value[0] == '/': + name, prop = resolve_property(srv, value) + value = qmp.plug_get(name, prop) + elif value[0] == '"': + value = value[1:-1] + return value + +qmp = QmpClient('localhost', 8080) +qmp.qmp_capabilities() + +command = sys.argv[1] + +if command == 'import': + cp = GitConfigParser() + cp.read([sys.argv[2]]) + + for section in cp.sections(): + kind, name = section.split(' ', 1) + name = name[1:-1] + qmp.plug_create(kind, name) + + for section in cp.sections(): + kind, name = section.split(' ', 1) + name = name[1:-1] + + for key, value in cp.items(section): + value = parse_property(qmp, value) + qmp.plug_set(name, key, value) +elif command == 'create': + if len(sys.argv) != 4: + sys.exit(1) + qmp.plug_create(sys.argv[2], sys.argv[3]) +elif command == 'exit': + qmp.quit() +elif command == 'set': + if len(sys.argv) != 4: + sys.exit(1) + + name, prop = resolve_property(qmp, sys.argv[2]) + + value = parse_property(qmp, sys.argv[3]) + qmp.plug_set(name, prop, value) +elif command == 'get': + if len(sys.argv) != 3: + sys.exit(1) + + name, prop = resolve_property(qmp, sys.argv[2]) + print qmp.plug_get(name, prop) +elif command == 'plug_list': + if len(sys.argv) != 3: + sys.exit(1) + + items = qmp.plug_list(sys.argv[2]) + for i in items: + print i +elif command == 'ls': + if len(sys.argv) != 3: + sys.exit(1) + + path = sys.argv[2] + + while path.endswith('/'): + path = path[:-1] + + if path == '': + path = '/' + + if path == '/': + items = qmp.plug_list() + for item in items: + print '%s/' % item['id'] + else: + if path[1:].find('/') == -1: + items = qmp.plug_list_props(path[1:]) + else: + name, prop = resolve_property(qmp, path) + name = qmp.plug_get(name, prop) + items = qmp.plug_list_props(name) + + for item in items: + if item['type'].startswith('plug<'): + print '%s/' % item['name'] + elif item['type'].startswith('socket<'): + print '@%s/' % item['name'] + else: + print '%s' % item['name'] + -- 1.7.4.1