QMP/qmp-shell: Introduce HMP mode
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 <lcapitulino@redhat.com>
			
			
This commit is contained in:
		
							parent
							
								
									0268d97c51
								
							
						
					
					
						commit
						11217a757e
					
				| @ -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) '): | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Luiz Capitulino
						Luiz Capitulino