From e0d570f03e650a15cef49241561e56c8c57ca376 Mon Sep 17 00:00:00 2001 From: Luiz Capitulino Date: Tue, 4 Jan 2011 19:13:49 -0200 Subject: [PATCH 17/23] QMP/qmp-shell: Introduce HMP mode RH-Author: Luiz Capitulino Message-id: <1294168429-1120-17-git-send-email-lcapitulino@redhat.com> Patchwork-id: 15686 O-Subject: [PATCH 16/16] QMP/qmp-shell: Introduce HMP mode Bugzilla: 647447 RH-Acked-by: Alon Levy RH-Acked-by: Marcelo Tosatti RH-Acked-by: Markus Armbruster In which qmp-shell will exclusively use the HMP passthrough feature, this is useful for testing. Example: # ./qmp-shell -H qmp-sock Welcome to the HMP shell! Connected to QEMU 0.13.50 (QEMU) info network VLAN 0 devices: user.0: net=10.0.2.0, restricted=n e1000.0: model=e1000,macaddr=52:54:00:12:34:56 Devices not on any VLAN: (QEMU) Signed-off-by: Luiz Capitulino (cherry picked from commit 11217a757e7dda66fd2e78b10ea0cd8d6b290e42) --- QMP/qmp-shell | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 78 insertions(+), 1 deletions(-) Signed-off-by: Luiz Capitulino --- QMP/qmp-shell | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 78 insertions(+), 1 deletions(-) diff --git a/QMP/qmp-shell b/QMP/qmp-shell index 1fb7e76..42dabc8 100755 --- a/QMP/qmp-shell +++ b/QMP/qmp-shell @@ -145,6 +145,76 @@ class QMPShell(qmp.QEMUMonitorProtocol): else: return self._execute_cmd(cmdline) +class HMPShell(QMPShell): + def __init__(self, address): + QMPShell.__init__(self, address) + self.__cpu_index = 0 + + def __cmd_completion(self): + for cmd in self.__cmd_passthrough('help')['return'].split('\r\n'): + if cmd and cmd[0] != '[' and cmd[0] != '\t': + name = cmd.split()[0] # drop help text + if name == 'info': + continue + if name.find('|') != -1: + # Command in the form 'foobar|f' or 'f|foobar', take the + # full name + opt = name.split('|') + if len(opt[0]) == 1: + name = opt[1] + else: + name = opt[0] + self._completer.append(name) + self._completer.append('help ' + name) # help completion + + def __info_completion(self): + for cmd in self.__cmd_passthrough('info')['return'].split('\r\n'): + if cmd: + self._completer.append('info ' + cmd.split()[1]) + + def __other_completion(self): + # special cases + self._completer.append('help info') + + def _fill_completion(self): + self.__cmd_completion() + self.__info_completion() + 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 } }) + + def _execute_cmd(self, cmdline): + if cmdline.split()[0] == "cpu": + # trap the cpu command, it requires special setting + try: + idx = int(cmdline.split()[1]) + if not 'return' in self.__cmd_passthrough('info version', idx): + print 'bad CPU index' + return True + self.__cpu_index = idx + except ValueError: + print 'cpu command takes an integer argument' + return True + resp = self.__cmd_passthrough(cmdline, self.__cpu_index) + if resp is None: + print 'Disconnected' + return False + assert 'return' in resp or 'error' in resp + if 'return' in resp: + # Success + if len(resp['return']) > 0: + print resp['return'], + else: + # Error + print '%s: %s' % (resp['error']['class'], resp['error']['desc']) + return True + + def show_banner(self): + QMPShell.show_banner(self, msg='Welcome to the HMP shell!') + def die(msg): sys.stderr.write('ERROR: %s\n' % msg) sys.exit(1) @@ -156,9 +226,16 @@ def fail_cmdline(option=None): sys.exit(1) def main(): + addr = '' try: if len(sys.argv) == 2: qemu = QMPShell(sys.argv[1]) + addr = sys.argv[1] + elif len(sys.argv) == 3: + if sys.argv[1] != '-H': + fail_cmdline(sys.argv[1]) + qemu = HMPShell(sys.argv[2]) + addr = sys.argv[2] else: fail_cmdline() except QMPShellBadPort: @@ -171,7 +248,7 @@ def main(): except qmp.QMPCapabilitiesError: die('Could not negotiate capabilities') except qemu.error: - die('Could not connect to %s' % sys.argv[1]) + die('Could not connect to %s' % addr) qemu.show_banner() while qemu.read_exec_command('(QEMU) '): -- 1.7.4.rc1.16.gd2f15e