Patchwork [14/21] qom: add example qsh command

login
register
mail settings
Submitter Anthony Liguori
Date July 25, 2011, 1:44 a.m.
Message ID <1311558293-5855-15-git-send-email-aliguori@us.ibm.com>
Download mbox | patch
Permalink /patch/106588/
State New
Headers show

Comments

Anthony Liguori - July 25, 2011, 1:44 a.m.
This lets you explore the QEMU Object Model with a filesystem like interface.

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
---
 scripts/qsh |  178 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 178 insertions(+), 0 deletions(-)
 create mode 100755 scripts/qsh

Patch

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<header>[^\"]+"[^"]*")\]')
+
+
+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']
+