Message ID | 1345471343-21497-1-git-send-email-berrange@redhat.com |
---|---|
State | New |
Headers | show |
On Mon, 20 Aug 2012 15:02:23 +0100 "Daniel P. Berrange" <berrange@redhat.com> wrote: > From: "Daniel P. Berrange" <berrange@redhat.com> > > By default, the JSON reply is parsed and the corresponding python > object printed on the console. When developing JSON client apps > for QEMU though, it is handy to see the raw JSON document instead. > Add a '-r' option that will cause the raw JSON to be printed, > instead of the parsed object. eg Looks good, but depends on the previous patch (which is being discussed). Btw, I wonder if we should make this the default, or add -v (instead of -r) which would allow for extra verbosity by printing both: the reply as read by qmp-shell and the parsed. > > $ qmp-shell -r /tmp/qemu > Welcome to the QMP low-level shell! > Connected to QEMU 1.1.50 > > (QEMU) stop > { > "return": { > } > } > > (QEMU) > { > "timestamp": { > "seconds": 1345471168, > "microseconds": 493463 > }, > "event": "STOP" > } > > Signed-off-by: Daniel P. Berrange <berrange@redhat.com> > --- > QMP/qmp-shell | 40 +++++++++++++++++++++++++++------------- > QMP/qmp.py | 12 ++++++------ > 2 files changed, 33 insertions(+), 19 deletions(-) > > diff --git a/QMP/qmp-shell b/QMP/qmp-shell > index 24b665c..6c7d8c3 100755 > --- a/QMP/qmp-shell > +++ b/QMP/qmp-shell > @@ -53,11 +53,12 @@ class QMPShellBadPort(QMPShellError): > # TODO: QMPShell's interface is a bit ugly (eg. _fill_completion() and > # _execute_cmd()). Let's design a better one. > class QMPShell(qmp.QEMUMonitorProtocol): > - def __init__(self, address, pp=None): > + def __init__(self, address, pp=None, raw=False): > qmp.QEMUMonitorProtocol.__init__(self, self.__get_address(address)) > self._greeting = None > self._completer = None > self._pp = pp > + self._raw = raw > > def __get_address(self, arg): > """ > @@ -75,7 +76,8 @@ class QMPShell(qmp.QEMUMonitorProtocol): > return arg > > def _fill_completion(self): > - for cmd in self.cmd('query-commands')['return']: > + cmds = self.cmd('query-commands') > + for cmd in cmds[0]['return']: > self._completer.append(cmd['name']) > > def __completer_setup(self): > @@ -105,6 +107,15 @@ class QMPShell(qmp.QEMUMonitorProtocol): > qmpcmd['arguments'][opt[0]] = value > return qmpcmd > > + def _print(self, data): > + if self._raw: > + print data[1] > + else: > + if self._pp is not None: > + self._pp.pprint(data[0]) > + else: > + print data[0] > + > def _execute_cmd(self, cmdline): > try: > qmpcmd = self.__build_cmd(cmdline) > @@ -113,14 +124,12 @@ class QMPShell(qmp.QEMUMonitorProtocol): > print '[arg-name1=arg1] ... [arg-nameN=argN]' > return True > resp = self.cmd_obj(qmpcmd) > - if resp is None: > + if resp[0] is None: > print 'Disconnected' > return False > > - if self._pp is not None: > - self._pp.pprint(resp) > - else: > - print resp > + self._print(resp) > + > return True > > def connect(self): > @@ -144,8 +153,9 @@ class QMPShell(qmp.QEMUMonitorProtocol): > print > return False > if cmdline == '': > - for ev in self.get_events(): > - print ev > + events = self.get_events() > + for ev in events: > + self._print(ev) > self.clear_events() > return True > else: > @@ -188,9 +198,10 @@ class HMPShell(QMPShell): > self.__other_completion() > > def __cmd_passthrough(self, cmdline, cpu_index = 0): > - return self.cmd_obj({ 'execute': 'human-monitor-command', 'arguments': > - { 'command-line': cmdline, > - 'cpu-index': cpu_index } }) > + resp = self.cmd_obj({ 'execute': 'human-monitor-command', 'arguments': > + { 'command-line': cmdline, > + 'cpu-index': cpu_index } }) > + return resp[0] > > def _execute_cmd(self, cmdline): > if cmdline.split()[0] == "cpu": > @@ -236,6 +247,7 @@ def main(): > qemu = None > hmp = False > pp = None > + raw = False > > try: > for arg in sys.argv[1:]: > @@ -247,13 +259,15 @@ def main(): > if pp is not None: > fail_cmdline(arg) > pp = pprint.PrettyPrinter(indent=4) > + elif arg == "-r": > + raw = True > else: > if qemu is not None: > fail_cmdline(arg) > if hmp: > qemu = HMPShell(arg) > else: > - qemu = QMPShell(arg, pp) > + qemu = QMPShell(arg, pp, raw) > addr = arg > > if qemu is None: > diff --git a/QMP/qmp.py b/QMP/qmp.py > index 464a01a..3a0efd8 100644 > --- a/QMP/qmp.py > +++ b/QMP/qmp.py > @@ -50,13 +50,13 @@ class QEMUMonitorProtocol: > > def __negotiate_capabilities(self): > self.__sockfile = self.__sock.makefile() > - greeting = self.__json_read() > - if greeting is None or not greeting.has_key('QMP'): > + greeting = self.__json_read() > + if greeting[0] is None or not greeting[0].has_key('QMP'): > raise QMPConnectError > # Greeting seems ok, negotiate capabilities > resp = self.cmd('qmp_capabilities') > - if "return" in resp: > - return greeting > + if "return" in resp[0]: > + return greeting[0] > raise QMPCapabilitiesError > > def __json_read(self, only_event=False): > @@ -74,10 +74,10 @@ class QEMUMonitorProtocol: > pass > > if 'event' in resp: > - self.__events.append(resp) > + self.__events.append((resp, data)) > if not only_event: > continue > - return resp > + return (resp, data) > > error = socket.error >
On Mon, Aug 20, 2012 at 03:22:35PM -0300, Luiz Capitulino wrote: > On Mon, 20 Aug 2012 15:02:23 +0100 > "Daniel P. Berrange" <berrange@redhat.com> wrote: > > > From: "Daniel P. Berrange" <berrange@redhat.com> > > > > By default, the JSON reply is parsed and the corresponding python > > object printed on the console. When developing JSON client apps > > for QEMU though, it is handy to see the raw JSON document instead. > > Add a '-r' option that will cause the raw JSON to be printed, > > instead of the parsed object. eg > > Looks good, but depends on the previous patch (which is being discussed). > > Btw, I wonder if we should make this the default, or add -v (instead of > -r) which would allow for extra verbosity by printing both: the reply > as read by qmp-shell and the parsed. I dunno, I feel the current default is reasonable and printing both would be a bit too verbose for commands with larger output. Daniel
diff --git a/QMP/qmp-shell b/QMP/qmp-shell index 24b665c..6c7d8c3 100755 --- a/QMP/qmp-shell +++ b/QMP/qmp-shell @@ -53,11 +53,12 @@ class QMPShellBadPort(QMPShellError): # TODO: QMPShell's interface is a bit ugly (eg. _fill_completion() and # _execute_cmd()). Let's design a better one. class QMPShell(qmp.QEMUMonitorProtocol): - def __init__(self, address, pp=None): + def __init__(self, address, pp=None, raw=False): qmp.QEMUMonitorProtocol.__init__(self, self.__get_address(address)) self._greeting = None self._completer = None self._pp = pp + self._raw = raw def __get_address(self, arg): """ @@ -75,7 +76,8 @@ class QMPShell(qmp.QEMUMonitorProtocol): return arg def _fill_completion(self): - for cmd in self.cmd('query-commands')['return']: + cmds = self.cmd('query-commands') + for cmd in cmds[0]['return']: self._completer.append(cmd['name']) def __completer_setup(self): @@ -105,6 +107,15 @@ class QMPShell(qmp.QEMUMonitorProtocol): qmpcmd['arguments'][opt[0]] = value return qmpcmd + def _print(self, data): + if self._raw: + print data[1] + else: + if self._pp is not None: + self._pp.pprint(data[0]) + else: + print data[0] + def _execute_cmd(self, cmdline): try: qmpcmd = self.__build_cmd(cmdline) @@ -113,14 +124,12 @@ class QMPShell(qmp.QEMUMonitorProtocol): print '[arg-name1=arg1] ... [arg-nameN=argN]' return True resp = self.cmd_obj(qmpcmd) - if resp is None: + if resp[0] is None: print 'Disconnected' return False - if self._pp is not None: - self._pp.pprint(resp) - else: - print resp + self._print(resp) + return True def connect(self): @@ -144,8 +153,9 @@ class QMPShell(qmp.QEMUMonitorProtocol): print return False if cmdline == '': - for ev in self.get_events(): - print ev + events = self.get_events() + for ev in events: + self._print(ev) self.clear_events() return True else: @@ -188,9 +198,10 @@ class HMPShell(QMPShell): self.__other_completion() def __cmd_passthrough(self, cmdline, cpu_index = 0): - return self.cmd_obj({ 'execute': 'human-monitor-command', 'arguments': - { 'command-line': cmdline, - 'cpu-index': cpu_index } }) + resp = self.cmd_obj({ 'execute': 'human-monitor-command', 'arguments': + { 'command-line': cmdline, + 'cpu-index': cpu_index } }) + return resp[0] def _execute_cmd(self, cmdline): if cmdline.split()[0] == "cpu": @@ -236,6 +247,7 @@ def main(): qemu = None hmp = False pp = None + raw = False try: for arg in sys.argv[1:]: @@ -247,13 +259,15 @@ def main(): if pp is not None: fail_cmdline(arg) pp = pprint.PrettyPrinter(indent=4) + elif arg == "-r": + raw = True else: if qemu is not None: fail_cmdline(arg) if hmp: qemu = HMPShell(arg) else: - qemu = QMPShell(arg, pp) + qemu = QMPShell(arg, pp, raw) addr = arg if qemu is None: diff --git a/QMP/qmp.py b/QMP/qmp.py index 464a01a..3a0efd8 100644 --- a/QMP/qmp.py +++ b/QMP/qmp.py @@ -50,13 +50,13 @@ class QEMUMonitorProtocol: def __negotiate_capabilities(self): self.__sockfile = self.__sock.makefile() - greeting = self.__json_read() - if greeting is None or not greeting.has_key('QMP'): + greeting = self.__json_read() + if greeting[0] is None or not greeting[0].has_key('QMP'): raise QMPConnectError # Greeting seems ok, negotiate capabilities resp = self.cmd('qmp_capabilities') - if "return" in resp: - return greeting + if "return" in resp[0]: + return greeting[0] raise QMPCapabilitiesError def __json_read(self, only_event=False): @@ -74,10 +74,10 @@ class QEMUMonitorProtocol: pass if 'event' in resp: - self.__events.append(resp) + self.__events.append((resp, data)) if not only_event: continue - return resp + return (resp, data) error = socket.error