diff options
Diffstat (limited to 'qemu/scripts/qmp')
-rwxr-xr-x | qemu/scripts/qmp/qemu-ga-client | 301 | ||||
-rwxr-xr-x | qemu/scripts/qmp/qmp | 126 | ||||
-rwxr-xr-x | qemu/scripts/qmp/qmp-shell | 422 | ||||
-rw-r--r-- | qemu/scripts/qmp/qmp.py | 236 | ||||
-rwxr-xr-x | qemu/scripts/qmp/qom-fuse | 138 | ||||
-rwxr-xr-x | qemu/scripts/qmp/qom-get | 67 | ||||
-rwxr-xr-x | qemu/scripts/qmp/qom-list | 64 | ||||
-rwxr-xr-x | qemu/scripts/qmp/qom-set | 64 | ||||
-rwxr-xr-x | qemu/scripts/qmp/qom-tree | 75 |
9 files changed, 0 insertions, 1493 deletions
diff --git a/qemu/scripts/qmp/qemu-ga-client b/qemu/scripts/qmp/qemu-ga-client deleted file mode 100755 index fd056056f..000000000 --- a/qemu/scripts/qmp/qemu-ga-client +++ /dev/null @@ -1,301 +0,0 @@ -#!/usr/bin/python - -# QEMU Guest Agent Client -# -# Copyright (C) 2012 Ryota Ozaki <ozaki.ryota@gmail.com> -# -# This work is licensed under the terms of the GNU GPL, version 2. See -# the COPYING file in the top-level directory. -# -# Usage: -# -# Start QEMU with: -# -# # qemu [...] -chardev socket,path=/tmp/qga.sock,server,nowait,id=qga0 \ -# -device virtio-serial -device virtserialport,chardev=qga0,name=org.qemu.guest_agent.0 -# -# Run the script: -# -# $ qemu-ga-client --address=/tmp/qga.sock <command> [args...] -# -# or -# -# $ export QGA_CLIENT_ADDRESS=/tmp/qga.sock -# $ qemu-ga-client <command> [args...] -# -# For example: -# -# $ qemu-ga-client cat /etc/resolv.conf -# # Generated by NetworkManager -# nameserver 10.0.2.3 -# $ qemu-ga-client fsfreeze status -# thawed -# $ qemu-ga-client fsfreeze freeze -# 2 filesystems frozen -# -# See also: http://wiki.qemu-project.org/Features/QAPI/GuestAgent -# - -import base64 -import random - -import qmp - - -class QemuGuestAgent(qmp.QEMUMonitorProtocol): - def __getattr__(self, name): - def wrapper(**kwds): - return self.command('guest-' + name.replace('_', '-'), **kwds) - return wrapper - - -class QemuGuestAgentClient: - error = QemuGuestAgent.error - - def __init__(self, address): - self.qga = QemuGuestAgent(address) - self.qga.connect(negotiate=False) - - def sync(self, timeout=3): - # Avoid being blocked forever - if not self.ping(timeout): - raise EnvironmentError('Agent seems not alive') - uid = random.randint(0, (1 << 32) - 1) - while True: - ret = self.qga.sync(id=uid) - if isinstance(ret, int) and int(ret) == uid: - break - - def __file_read_all(self, handle): - eof = False - data = '' - while not eof: - ret = self.qga.file_read(handle=handle, count=1024) - _data = base64.b64decode(ret['buf-b64']) - data += _data - eof = ret['eof'] - return data - - def read(self, path): - handle = self.qga.file_open(path=path) - try: - data = self.__file_read_all(handle) - finally: - self.qga.file_close(handle=handle) - return data - - def info(self): - info = self.qga.info() - - msgs = [] - msgs.append('version: ' + info['version']) - msgs.append('supported_commands:') - enabled = [c['name'] for c in info['supported_commands'] if c['enabled']] - msgs.append('\tenabled: ' + ', '.join(enabled)) - disabled = [c['name'] for c in info['supported_commands'] if not c['enabled']] - msgs.append('\tdisabled: ' + ', '.join(disabled)) - - return '\n'.join(msgs) - - def __gen_ipv4_netmask(self, prefixlen): - mask = int('1' * prefixlen + '0' * (32 - prefixlen), 2) - return '.'.join([str(mask >> 24), - str((mask >> 16) & 0xff), - str((mask >> 8) & 0xff), - str(mask & 0xff)]) - - def ifconfig(self): - nifs = self.qga.network_get_interfaces() - - msgs = [] - for nif in nifs: - msgs.append(nif['name'] + ':') - if 'ip-addresses' in nif: - for ipaddr in nif['ip-addresses']: - if ipaddr['ip-address-type'] == 'ipv4': - addr = ipaddr['ip-address'] - mask = self.__gen_ipv4_netmask(int(ipaddr['prefix'])) - msgs.append("\tinet %s netmask %s" % (addr, mask)) - elif ipaddr['ip-address-type'] == 'ipv6': - addr = ipaddr['ip-address'] - prefix = ipaddr['prefix'] - msgs.append("\tinet6 %s prefixlen %s" % (addr, prefix)) - if nif['hardware-address'] != '00:00:00:00:00:00': - msgs.append("\tether " + nif['hardware-address']) - - return '\n'.join(msgs) - - def ping(self, timeout): - self.qga.settimeout(timeout) - try: - self.qga.ping() - except self.qga.timeout: - return False - return True - - def fsfreeze(self, cmd): - if cmd not in ['status', 'freeze', 'thaw']: - raise StandardError('Invalid command: ' + cmd) - - return getattr(self.qga, 'fsfreeze' + '_' + cmd)() - - def fstrim(self, minimum=0): - return getattr(self.qga, 'fstrim')(minimum=minimum) - - def suspend(self, mode): - if mode not in ['disk', 'ram', 'hybrid']: - raise StandardError('Invalid mode: ' + mode) - - try: - getattr(self.qga, 'suspend' + '_' + mode)() - # On error exception will raise - except self.qga.timeout: - # On success command will timed out - return - - def shutdown(self, mode='powerdown'): - if mode not in ['powerdown', 'halt', 'reboot']: - raise StandardError('Invalid mode: ' + mode) - - try: - self.qga.shutdown(mode=mode) - except self.qga.timeout: - return - - -def _cmd_cat(client, args): - if len(args) != 1: - print('Invalid argument') - print('Usage: cat <file>') - sys.exit(1) - print(client.read(args[0])) - - -def _cmd_fsfreeze(client, args): - usage = 'Usage: fsfreeze status|freeze|thaw' - if len(args) != 1: - print('Invalid argument') - print(usage) - sys.exit(1) - if args[0] not in ['status', 'freeze', 'thaw']: - print('Invalid command: ' + args[0]) - print(usage) - sys.exit(1) - cmd = args[0] - ret = client.fsfreeze(cmd) - if cmd == 'status': - print(ret) - elif cmd == 'freeze': - print("%d filesystems frozen" % ret) - else: - print("%d filesystems thawed" % ret) - - -def _cmd_fstrim(client, args): - if len(args) == 0: - minimum = 0 - else: - minimum = int(args[0]) - print(client.fstrim(minimum)) - - -def _cmd_ifconfig(client, args): - print(client.ifconfig()) - - -def _cmd_info(client, args): - print(client.info()) - - -def _cmd_ping(client, args): - if len(args) == 0: - timeout = 3 - else: - timeout = float(args[0]) - alive = client.ping(timeout) - if not alive: - print("Not responded in %s sec" % args[0]) - sys.exit(1) - - -def _cmd_suspend(client, args): - usage = 'Usage: suspend disk|ram|hybrid' - if len(args) != 1: - print('Less argument') - print(usage) - sys.exit(1) - if args[0] not in ['disk', 'ram', 'hybrid']: - print('Invalid command: ' + args[0]) - print(usage) - sys.exit(1) - client.suspend(args[0]) - - -def _cmd_shutdown(client, args): - client.shutdown() -_cmd_powerdown = _cmd_shutdown - - -def _cmd_halt(client, args): - client.shutdown('halt') - - -def _cmd_reboot(client, args): - client.shutdown('reboot') - - -commands = [m.replace('_cmd_', '') for m in dir() if '_cmd_' in m] - - -def main(address, cmd, args): - if not os.path.exists(address): - print('%s not found' % address) - sys.exit(1) - - if cmd not in commands: - print('Invalid command: ' + cmd) - print('Available commands: ' + ', '.join(commands)) - sys.exit(1) - - try: - client = QemuGuestAgentClient(address) - except QemuGuestAgent.error as e: - import errno - - print(e) - if e.errno == errno.ECONNREFUSED: - print('Hint: qemu is not running?') - sys.exit(1) - - if cmd == 'fsfreeze' and args[0] == 'freeze': - client.sync(60) - elif cmd != 'ping': - client.sync() - - globals()['_cmd_' + cmd](client, args) - - -if __name__ == '__main__': - import sys - import os - import optparse - - address = os.environ['QGA_CLIENT_ADDRESS'] if 'QGA_CLIENT_ADDRESS' in os.environ else None - - usage = "%prog [--address=<unix_path>|<ipv4_address>] <command> [args...]\n" - usage += '<command>: ' + ', '.join(commands) - parser = optparse.OptionParser(usage=usage) - parser.add_option('--address', action='store', type='string', - default=address, help='Specify a ip:port pair or a unix socket path') - options, args = parser.parse_args() - - address = options.address - if address is None: - parser.error('address is not specified') - sys.exit(1) - - if len(args) == 0: - parser.error('Less argument') - sys.exit(1) - - main(address, args[0], args[1:]) diff --git a/qemu/scripts/qmp/qmp b/qemu/scripts/qmp/qmp deleted file mode 100755 index 514b539a6..000000000 --- a/qemu/scripts/qmp/qmp +++ /dev/null @@ -1,126 +0,0 @@ -#!/usr/bin/python -# -# QMP command line tool -# -# Copyright IBM, Corp. 2011 -# -# Authors: -# Anthony Liguori <aliguori@us.ibm.com> -# -# This work is licensed under the terms of the GNU GPLv2 or later. -# See the COPYING file in the top-level directory. - -import sys, os -from qmp import QEMUMonitorProtocol - -def print_response(rsp, prefix=[]): - if type(rsp) == list: - i = 0 - for item in rsp: - if prefix == []: - prefix = ['item'] - print_response(item, prefix[:-1] + ['%s[%d]' % (prefix[-1], i)]) - i += 1 - elif type(rsp) == dict: - for key in rsp.keys(): - print_response(rsp[key], prefix + [key]) - else: - if len(prefix): - print '%s: %s' % ('.'.join(prefix), rsp) - else: - print '%s' % (rsp) - -def main(args): - path = None - - # Use QMP_PATH if it's set - if os.environ.has_key('QMP_PATH'): - path = os.environ['QMP_PATH'] - - while len(args): - arg = args[0] - - if arg.startswith('--'): - arg = arg[2:] - if arg.find('=') == -1: - value = True - else: - arg, value = arg.split('=', 1) - - if arg in ['path']: - if type(value) == str: - path = value - elif arg in ['help']: - os.execlp('man', 'man', 'qmp') - else: - print 'Unknown argument "%s"' % arg - - args = args[1:] - else: - break - - if not path: - print "QMP path isn't set, use --path=qmp-monitor-address or set QMP_PATH" - return 1 - - if len(args): - command, args = args[0], args[1:] - else: - print 'No command found' - print 'Usage: "qmp [--path=qmp-monitor-address] qmp-cmd arguments"' - return 1 - - if command in ['help']: - os.execlp('man', 'man', 'qmp') - - srv = QEMUMonitorProtocol(path) - srv.connect() - - def do_command(srv, cmd, **kwds): - rsp = srv.cmd(cmd, kwds) - if rsp.has_key('error'): - raise Exception(rsp['error']['desc']) - return rsp['return'] - - commands = map(lambda x: x['name'], do_command(srv, 'query-commands')) - - srv.close() - - if command not in commands: - fullcmd = 'qmp-%s' % command - try: - os.environ['QMP_PATH'] = path - os.execvp(fullcmd, [fullcmd] + args) - except OSError as exc: - if exc.errno == 2: - print 'Command "%s" not found.' % (fullcmd) - return 1 - raise - return 0 - - srv = QEMUMonitorProtocol(path) - srv.connect() - - arguments = {} - for arg in args: - if not arg.startswith('--'): - print 'Unknown argument "%s"' % arg - return 1 - - arg = arg[2:] - if arg.find('=') == -1: - value = True - else: - arg, value = arg.split('=', 1) - - if arg in ['help']: - os.execlp('man', 'man', 'qmp-%s' % command) - return 1 - - arguments[arg] = value - - rsp = do_command(srv, command, **arguments) - print_response(rsp) - -if __name__ == '__main__': - sys.exit(main(sys.argv[1:])) diff --git a/qemu/scripts/qmp/qmp-shell b/qemu/scripts/qmp/qmp-shell deleted file mode 100755 index 0373b24b2..000000000 --- a/qemu/scripts/qmp/qmp-shell +++ /dev/null @@ -1,422 +0,0 @@ -#!/usr/bin/python -# -# Low-level QEMU shell on top of QMP. -# -# Copyright (C) 2009, 2010 Red Hat Inc. -# -# Authors: -# Luiz Capitulino <lcapitulino@redhat.com> -# -# This work is licensed under the terms of the GNU GPL, version 2. See -# the COPYING file in the top-level directory. -# -# Usage: -# -# Start QEMU with: -# -# # qemu [...] -qmp unix:./qmp-sock,server -# -# Run the shell: -# -# $ qmp-shell ./qmp-sock -# -# Commands have the following format: -# -# < command-name > [ arg-name1=arg1 ] ... [ arg-nameN=argN ] -# -# For example: -# -# (QEMU) device_add driver=e1000 id=net1 -# {u'return': {}} -# (QEMU) -# -# key=value pairs also support Python or JSON object literal subset notations, -# without spaces. Dictionaries/objects {} are supported as are arrays []. -# -# example-command arg-name1={'key':'value','obj'={'prop':"value"}} -# -# Both JSON and Python formatting should work, including both styles of -# string literal quotes. Both paradigms of literal values should work, -# including null/true/false for JSON and None/True/False for Python. -# -# -# Transactions have the following multi-line format: -# -# transaction( -# action-name1 [ arg-name1=arg1 ] ... [arg-nameN=argN ] -# ... -# action-nameN [ arg-name1=arg1 ] ... [arg-nameN=argN ] -# ) -# -# One line transactions are also supported: -# -# transaction( action-name1 ... ) -# -# For example: -# -# (QEMU) transaction( -# TRANS> block-dirty-bitmap-add node=drive0 name=bitmap1 -# TRANS> block-dirty-bitmap-clear node=drive0 name=bitmap0 -# TRANS> ) -# {"return": {}} -# (QEMU) -# -# Use the -v and -p options to activate the verbose and pretty-print options, -# which will echo back the properly formatted JSON-compliant QMP that is being -# sent to QEMU, which is useful for debugging and documentation generation. - -import qmp -import json -import ast -import readline -import sys - -class QMPCompleter(list): - def complete(self, text, state): - for cmd in self: - if cmd.startswith(text): - if not state: - return cmd - else: - state -= 1 - -class QMPShellError(Exception): - pass - -class QMPShellBadPort(QMPShellError): - pass - -class FuzzyJSON(ast.NodeTransformer): - '''This extension of ast.NodeTransformer filters literal "true/false/null" - values in an AST and replaces them by proper "True/False/None" values that - Python can properly evaluate.''' - def visit_Name(self, node): - if node.id == 'true': - node.id = 'True' - if node.id == 'false': - node.id = 'False' - if node.id == 'null': - node.id = 'None' - return node - -# 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, pretty=False): - qmp.QEMUMonitorProtocol.__init__(self, self.__get_address(address)) - self._greeting = None - self._completer = None - self._pretty = pretty - self._transmode = False - self._actions = list() - - def __get_address(self, arg): - """ - Figure out if the argument is in the port:host form, if it's not it's - probably a file path. - """ - addr = arg.split(':') - if len(addr) == 2: - try: - port = int(addr[1]) - except ValueError: - raise QMPShellBadPort - return ( addr[0], port ) - # socket path - return arg - - def _fill_completion(self): - for cmd in self.cmd('query-commands')['return']: - self._completer.append(cmd['name']) - - def __completer_setup(self): - self._completer = QMPCompleter() - self._fill_completion() - readline.set_completer(self._completer.complete) - readline.parse_and_bind("tab: complete") - # XXX: default delimiters conflict with some command names (eg. query-), - # clearing everything as it doesn't seem to matter - readline.set_completer_delims('') - - def __parse_value(self, val): - try: - return int(val) - except ValueError: - pass - - if val.lower() == 'true': - return True - if val.lower() == 'false': - return False - if val.startswith(('{', '[')): - # Try first as pure JSON: - try: - return json.loads(val) - except ValueError: - pass - # Try once again as FuzzyJSON: - try: - st = ast.parse(val, mode='eval') - return ast.literal_eval(FuzzyJSON().visit(st)) - except SyntaxError: - pass - except ValueError: - pass - return val - - def __cli_expr(self, tokens, parent): - for arg in tokens: - (key, _, val) = arg.partition('=') - if not val: - raise QMPShellError("Expected a key=value pair, got '%s'" % arg) - - value = self.__parse_value(val) - optpath = key.split('.') - curpath = [] - for p in optpath[:-1]: - curpath.append(p) - d = parent.get(p, {}) - if type(d) is not dict: - raise QMPShellError('Cannot use "%s" as both leaf and non-leaf key' % '.'.join(curpath)) - parent[p] = d - parent = d - if optpath[-1] in parent: - if type(parent[optpath[-1]]) is dict: - raise QMPShellError('Cannot use "%s" as both leaf and non-leaf key' % '.'.join(curpath)) - else: - raise QMPShellError('Cannot set "%s" multiple times' % key) - parent[optpath[-1]] = value - - def __build_cmd(self, cmdline): - """ - Build a QMP input object from a user provided command-line in the - following format: - - < command-name > [ arg-name1=arg1 ] ... [ arg-nameN=argN ] - """ - cmdargs = cmdline.split() - - # Transactional CLI entry/exit: - if cmdargs[0] == 'transaction(': - self._transmode = True - cmdargs.pop(0) - elif cmdargs[0] == ')' and self._transmode: - self._transmode = False - if len(cmdargs) > 1: - raise QMPShellError("Unexpected input after close of Transaction sub-shell") - qmpcmd = { 'execute': 'transaction', - 'arguments': { 'actions': self._actions } } - self._actions = list() - return qmpcmd - - # Nothing to process? - if not cmdargs: - return None - - # Parse and then cache this Transactional Action - if self._transmode: - finalize = False - action = { 'type': cmdargs[0], 'data': {} } - if cmdargs[-1] == ')': - cmdargs.pop(-1) - finalize = True - self.__cli_expr(cmdargs[1:], action['data']) - self._actions.append(action) - return self.__build_cmd(')') if finalize else None - - # Standard command: parse and return it to be executed. - qmpcmd = { 'execute': cmdargs[0], 'arguments': {} } - self.__cli_expr(cmdargs[1:], qmpcmd['arguments']) - return qmpcmd - - def _print(self, qmp): - indent = None - if self._pretty: - indent = 4 - jsobj = json.dumps(qmp, indent=indent) - print str(jsobj) - - def _execute_cmd(self, cmdline): - try: - qmpcmd = self.__build_cmd(cmdline) - except Exception as e: - print 'Error while parsing command line: %s' % e - print 'command format: <command-name> ', - print '[arg-name1=arg1] ... [arg-nameN=argN]' - return True - # For transaction mode, we may have just cached the action: - if qmpcmd is None: - return True - if self._verbose: - self._print(qmpcmd) - resp = self.cmd_obj(qmpcmd) - if resp is None: - print 'Disconnected' - return False - self._print(resp) - return True - - def connect(self): - self._greeting = qmp.QEMUMonitorProtocol.connect(self) - self.__completer_setup() - - def show_banner(self, msg='Welcome to the QMP low-level shell!'): - print msg - version = self._greeting['QMP']['version']['qemu'] - print 'Connected to QEMU %d.%d.%d\n' % (version['major'],version['minor'],version['micro']) - - def get_prompt(self): - if self._transmode: - return "TRANS> " - return "(QEMU) " - - def read_exec_command(self, prompt): - """ - Read and execute a command. - - @return True if execution was ok, return False if disconnected. - """ - try: - cmdline = raw_input(prompt) - except EOFError: - print - return False - if cmdline == '': - for ev in self.get_events(): - print ev - self.clear_events() - return True - else: - return self._execute_cmd(cmdline) - - def set_verbosity(self, verbose): - self._verbose = verbose - -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) - -def fail_cmdline(option=None): - if option: - sys.stderr.write('ERROR: bad command-line option \'%s\'\n' % option) - sys.stderr.write('qemu-shell [ -v ] [ -p ] [ -H ] < UNIX socket path> | < TCP address:port >\n') - sys.exit(1) - -def main(): - addr = '' - qemu = None - hmp = False - pretty = False - verbose = False - - try: - for arg in sys.argv[1:]: - if arg == "-H": - if qemu is not None: - fail_cmdline(arg) - hmp = True - elif arg == "-p": - pretty = True - elif arg == "-v": - verbose = True - else: - if qemu is not None: - fail_cmdline(arg) - if hmp: - qemu = HMPShell(arg) - else: - qemu = QMPShell(arg, pretty) - addr = arg - - if qemu is None: - fail_cmdline() - except QMPShellBadPort: - die('bad port number in command-line') - - try: - qemu.connect() - except qmp.QMPConnectError: - die('Didn\'t get QMP greeting message') - except qmp.QMPCapabilitiesError: - die('Could not negotiate capabilities') - except qemu.error: - die('Could not connect to %s' % addr) - - qemu.show_banner() - qemu.set_verbosity(verbose) - while qemu.read_exec_command(qemu.get_prompt()): - pass - qemu.close() - -if __name__ == '__main__': - main() diff --git a/qemu/scripts/qmp/qmp.py b/qemu/scripts/qmp/qmp.py deleted file mode 100644 index 779332f32..000000000 --- a/qemu/scripts/qmp/qmp.py +++ /dev/null @@ -1,236 +0,0 @@ -# QEMU Monitor Protocol Python class -# -# Copyright (C) 2009, 2010 Red Hat Inc. -# -# Authors: -# Luiz Capitulino <lcapitulino@redhat.com> -# -# This work is licensed under the terms of the GNU GPL, version 2. See -# the COPYING file in the top-level directory. - -import json -import errno -import socket - -class QMPError(Exception): - pass - -class QMPConnectError(QMPError): - pass - -class QMPCapabilitiesError(QMPError): - pass - -class QMPTimeoutError(QMPError): - pass - -class QEMUMonitorProtocol: - def __init__(self, address, server=False): - """ - Create a QEMUMonitorProtocol class. - - @param address: QEMU address, can be either a unix socket path (string) - or a tuple in the form ( address, port ) for a TCP - connection - @param server: server mode listens on the socket (bool) - @raise socket.error on socket connection errors - @note No connection is established, this is done by the connect() or - accept() methods - """ - self.__events = [] - self.__address = address - self.__sock = self.__get_sock() - if server: - self.__sock.bind(self.__address) - self.__sock.listen(1) - - def __get_sock(self): - if isinstance(self.__address, tuple): - family = socket.AF_INET - else: - family = socket.AF_UNIX - return socket.socket(family, socket.SOCK_STREAM) - - def __negotiate_capabilities(self): - greeting = self.__json_read() - if greeting is None or not greeting.has_key('QMP'): - raise QMPConnectError - # Greeting seems ok, negotiate capabilities - resp = self.cmd('qmp_capabilities') - if "return" in resp: - return greeting - raise QMPCapabilitiesError - - def __json_read(self, only_event=False): - while True: - data = self.__sockfile.readline() - if not data: - return - resp = json.loads(data) - if 'event' in resp: - self.__events.append(resp) - if not only_event: - continue - return resp - - error = socket.error - - def __get_events(self, wait=False): - """ - Check for new events in the stream and cache them in __events. - - @param wait (bool): block until an event is available. - @param wait (float): If wait is a float, treat it as a timeout value. - - @raise QMPTimeoutError: If a timeout float is provided and the timeout - period elapses. - @raise QMPConnectError: If wait is True but no events could be retrieved - or if some other error occurred. - """ - - # Check for new events regardless and pull them into the cache: - self.__sock.setblocking(0) - try: - self.__json_read() - except socket.error as err: - if err[0] == errno.EAGAIN: - # No data available - pass - self.__sock.setblocking(1) - - # Wait for new events, if needed. - # if wait is 0.0, this means "no wait" and is also implicitly false. - if not self.__events and wait: - if isinstance(wait, float): - self.__sock.settimeout(wait) - try: - ret = self.__json_read(only_event=True) - except socket.timeout: - raise QMPTimeoutError("Timeout waiting for event") - except: - raise QMPConnectError("Error while reading from socket") - if ret is None: - raise QMPConnectError("Error while reading from socket") - self.__sock.settimeout(None) - - def connect(self, negotiate=True): - """ - Connect to the QMP Monitor and perform capabilities negotiation. - - @return QMP greeting dict - @raise socket.error on socket connection errors - @raise QMPConnectError if the greeting is not received - @raise QMPCapabilitiesError if fails to negotiate capabilities - """ - self.__sock.connect(self.__address) - self.__sockfile = self.__sock.makefile() - if negotiate: - return self.__negotiate_capabilities() - - def accept(self): - """ - Await connection from QMP Monitor and perform capabilities negotiation. - - @return QMP greeting dict - @raise socket.error on socket connection errors - @raise QMPConnectError if the greeting is not received - @raise QMPCapabilitiesError if fails to negotiate capabilities - """ - self.__sock, _ = self.__sock.accept() - self.__sockfile = self.__sock.makefile() - return self.__negotiate_capabilities() - - def cmd_obj(self, qmp_cmd): - """ - Send a QMP command to the QMP Monitor. - - @param qmp_cmd: QMP command to be sent as a Python dict - @return QMP response as a Python dict or None if the connection has - been closed - """ - try: - self.__sock.sendall(json.dumps(qmp_cmd)) - except socket.error as err: - if err[0] == errno.EPIPE: - return - raise socket.error(err) - return self.__json_read() - - def cmd(self, name, args=None, id=None): - """ - Build a QMP command and send it to the QMP Monitor. - - @param name: command name (string) - @param args: command arguments (dict) - @param id: command id (dict, list, string or int) - """ - qmp_cmd = { 'execute': name } - if args: - qmp_cmd['arguments'] = args - if id: - qmp_cmd['id'] = id - return self.cmd_obj(qmp_cmd) - - def command(self, cmd, **kwds): - ret = self.cmd(cmd, kwds) - if ret.has_key('error'): - raise Exception(ret['error']['desc']) - return ret['return'] - - def pull_event(self, wait=False): - """ - Get and delete the first available QMP event. - - @param wait (bool): block until an event is available. - @param wait (float): If wait is a float, treat it as a timeout value. - - @raise QMPTimeoutError: If a timeout float is provided and the timeout - period elapses. - @raise QMPConnectError: If wait is True but no events could be retrieved - or if some other error occurred. - - @return The first available QMP event, or None. - """ - self.__get_events(wait) - - if self.__events: - return self.__events.pop(0) - return None - - def get_events(self, wait=False): - """ - Get a list of available QMP events. - - @param wait (bool): block until an event is available. - @param wait (float): If wait is a float, treat it as a timeout value. - - @raise QMPTimeoutError: If a timeout float is provided and the timeout - period elapses. - @raise QMPConnectError: If wait is True but no events could be retrieved - or if some other error occurred. - - @return The list of available QMP events. - """ - self.__get_events(wait) - return self.__events - - def clear_events(self): - """ - Clear current list of pending events. - """ - self.__events = [] - - def close(self): - self.__sock.close() - self.__sockfile.close() - - timeout = socket.timeout - - def settimeout(self, timeout): - self.__sock.settimeout(timeout) - - def get_sock_fd(self): - return self.__sock.fileno() - - def is_scm_available(self): - return self.__sock.family == socket.AF_UNIX diff --git a/qemu/scripts/qmp/qom-fuse b/qemu/scripts/qmp/qom-fuse deleted file mode 100755 index 5c6754aa6..000000000 --- a/qemu/scripts/qmp/qom-fuse +++ /dev/null @@ -1,138 +0,0 @@ -#!/usr/bin/python -## -# QEMU Object Model test tools -# -# Copyright IBM, Corp. 2012 -# -# Authors: -# Anthony Liguori <aliguori@us.ibm.com> -# -# This work is licensed under the terms of the GNU GPL, version 2 or later. See -# the COPYING file in the top-level directory. -## - -import fuse, stat -from fuse import Fuse -import os, posix -from errno import * -from qmp import QEMUMonitorProtocol - -fuse.fuse_python_api = (0, 2) - -class QOMFS(Fuse): - def __init__(self, qmp, *args, **kwds): - Fuse.__init__(self, *args, **kwds) - self.qmp = qmp - self.qmp.connect() - self.ino_map = {} - self.ino_count = 1 - - def get_ino(self, path): - if self.ino_map.has_key(path): - return self.ino_map[path] - self.ino_map[path] = self.ino_count - self.ino_count += 1 - return self.ino_map[path] - - def is_object(self, path): - try: - items = self.qmp.command('qom-list', path=path) - return True - except: - return False - - def is_property(self, path): - try: - path, prop = path.rsplit('/', 1) - for item in self.qmp.command('qom-list', path=path): - if item['name'] == prop: - return True - return False - except: - return False - - def is_link(self, path): - try: - path, prop = path.rsplit('/', 1) - for item in self.qmp.command('qom-list', path=path): - if item['name'] == prop: - if item['type'].startswith('link<'): - return True - return False - return False - except: - return False - - def read(self, path, length, offset): - if not self.is_property(path): - return -ENOENT - - path, prop = path.rsplit('/', 1) - try: - data = str(self.qmp.command('qom-get', path=path, property=prop)) - data += '\n' # make values shell friendly - except: - return -EPERM - - if offset > len(data): - return '' - - return str(data[offset:][:length]) - - def readlink(self, path): - if not self.is_link(path): - return False - path, prop = path.rsplit('/', 1) - prefix = '/'.join(['..'] * (len(path.split('/')) - 1)) - return prefix + str(self.qmp.command('qom-get', path=path, - property=prop)) - - def getattr(self, path): - if self.is_link(path): - value = posix.stat_result((0755 | stat.S_IFLNK, - self.get_ino(path), - 0, - 2, - 1000, - 1000, - 4096, - 0, - 0, - 0)) - elif self.is_object(path): - value = posix.stat_result((0755 | stat.S_IFDIR, - self.get_ino(path), - 0, - 2, - 1000, - 1000, - 4096, - 0, - 0, - 0)) - elif self.is_property(path): - value = posix.stat_result((0644 | stat.S_IFREG, - self.get_ino(path), - 0, - 1, - 1000, - 1000, - 4096, - 0, - 0, - 0)) - else: - value = -ENOENT - return value - - def readdir(self, path, offset): - yield fuse.Direntry('.') - yield fuse.Direntry('..') - for item in self.qmp.command('qom-list', path=path): - yield fuse.Direntry(str(item['name'])) - -if __name__ == '__main__': - import sys, os - - fs = QOMFS(QEMUMonitorProtocol(os.environ['QMP_SOCKET'])) - fs.main(sys.argv) diff --git a/qemu/scripts/qmp/qom-get b/qemu/scripts/qmp/qom-get deleted file mode 100755 index 0172c6944..000000000 --- a/qemu/scripts/qmp/qom-get +++ /dev/null @@ -1,67 +0,0 @@ -#!/usr/bin/python -## -# QEMU Object Model test tools -# -# Copyright IBM, Corp. 2011 -# -# Authors: -# Anthony Liguori <aliguori@us.ibm.com> -# -# This work is licensed under the terms of the GNU GPL, version 2 or later. See -# the COPYING file in the top-level directory. -## - -import sys -import os -from qmp import QEMUMonitorProtocol - -cmd, args = sys.argv[0], sys.argv[1:] -socket_path = None -path = None -prop = None - -def usage(): - return '''environment variables: - QMP_SOCKET=<path | addr:port> -usage: - %s [-h] [-s <QMP socket path | addr:port>] <path>.<property> -''' % cmd - -def usage_error(error_msg = "unspecified error"): - sys.stderr.write('%s\nERROR: %s\n' % (usage(), error_msg)) - exit(1) - -if len(args) > 0: - if args[0] == "-h": - print usage() - exit(0); - elif args[0] == "-s": - try: - socket_path = args[1] - except: - usage_error("missing argument: QMP socket path or address"); - args = args[2:] - -if not socket_path: - if os.environ.has_key('QMP_SOCKET'): - socket_path = os.environ['QMP_SOCKET'] - else: - usage_error("no QMP socket path or address given"); - -if len(args) > 0: - try: - path, prop = args[0].rsplit('.', 1) - except: - usage_error("invalid format for path/property/value") -else: - usage_error("not enough arguments") - -srv = QEMUMonitorProtocol(socket_path) -srv.connect() - -rsp = srv.command('qom-get', path=path, property=prop) -if type(rsp) == dict: - for i in rsp.keys(): - print '%s: %s' % (i, rsp[i]) -else: - print rsp diff --git a/qemu/scripts/qmp/qom-list b/qemu/scripts/qmp/qom-list deleted file mode 100755 index 1e7cc6cb2..000000000 --- a/qemu/scripts/qmp/qom-list +++ /dev/null @@ -1,64 +0,0 @@ -#!/usr/bin/python -## -# QEMU Object Model test tools -# -# Copyright IBM, Corp. 2011 -# -# Authors: -# Anthony Liguori <aliguori@us.ibm.com> -# -# This work is licensed under the terms of the GNU GPL, version 2 or later. See -# the COPYING file in the top-level directory. -## - -import sys -import os -from qmp import QEMUMonitorProtocol - -cmd, args = sys.argv[0], sys.argv[1:] -socket_path = None -path = None -prop = None - -def usage(): - return '''environment variables: - QMP_SOCKET=<path | addr:port> -usage: - %s [-h] [-s <QMP socket path | addr:port>] [<path>] -''' % cmd - -def usage_error(error_msg = "unspecified error"): - sys.stderr.write('%s\nERROR: %s\n' % (usage(), error_msg)) - exit(1) - -if len(args) > 0: - if args[0] == "-h": - print usage() - exit(0); - elif args[0] == "-s": - try: - socket_path = args[1] - except: - usage_error("missing argument: QMP socket path or address"); - args = args[2:] - -if not socket_path: - if os.environ.has_key('QMP_SOCKET'): - socket_path = os.environ['QMP_SOCKET'] - else: - usage_error("no QMP socket path or address given"); - -srv = QEMUMonitorProtocol(socket_path) -srv.connect() - -if len(args) == 0: - print '/' - sys.exit(0) - -for item in srv.command('qom-list', path=args[0]): - if item['type'].startswith('child<'): - print '%s/' % item['name'] - elif item['type'].startswith('link<'): - print '@%s/' % item['name'] - else: - print '%s' % item['name'] diff --git a/qemu/scripts/qmp/qom-set b/qemu/scripts/qmp/qom-set deleted file mode 100755 index 54ecfecc5..000000000 --- a/qemu/scripts/qmp/qom-set +++ /dev/null @@ -1,64 +0,0 @@ -#!/usr/bin/python -## -# QEMU Object Model test tools -# -# Copyright IBM, Corp. 2011 -# -# Authors: -# Anthony Liguori <aliguori@us.ibm.com> -# -# This work is licensed under the terms of the GNU GPL, version 2 or later. See -# the COPYING file in the top-level directory. -## - -import sys -import os -from qmp import QEMUMonitorProtocol - -cmd, args = sys.argv[0], sys.argv[1:] -socket_path = None -path = None -prop = None -value = None - -def usage(): - return '''environment variables: - QMP_SOCKET=<path | addr:port> -usage: - %s [-h] [-s <QMP socket path | addr:port>] <path>.<property> <value> -''' % cmd - -def usage_error(error_msg = "unspecified error"): - sys.stderr.write('%s\nERROR: %s\n' % (usage(), error_msg)) - exit(1) - -if len(args) > 0: - if args[0] == "-h": - print usage() - exit(0); - elif args[0] == "-s": - try: - socket_path = args[1] - except: - usage_error("missing argument: QMP socket path or address"); - args = args[2:] - -if not socket_path: - if os.environ.has_key('QMP_SOCKET'): - socket_path = os.environ['QMP_SOCKET'] - else: - usage_error("no QMP socket path or address given"); - -if len(args) > 1: - try: - path, prop = args[0].rsplit('.', 1) - except: - usage_error("invalid format for path/property/value") - value = args[1] -else: - usage_error("not enough arguments") - -srv = QEMUMonitorProtocol(socket_path) -srv.connect() - -print srv.command('qom-set', path=path, property=prop, value=sys.argv[2]) diff --git a/qemu/scripts/qmp/qom-tree b/qemu/scripts/qmp/qom-tree deleted file mode 100755 index 906fcd264..000000000 --- a/qemu/scripts/qmp/qom-tree +++ /dev/null @@ -1,75 +0,0 @@ -#!/usr/bin/python -## -# QEMU Object Model test tools -# -# Copyright IBM, Corp. 2011 -# Copyright (c) 2013 SUSE LINUX Products GmbH -# -# Authors: -# Anthony Liguori <aliguori@amazon.com> -# Andreas Faerber <afaerber@suse.de> -# -# This work is licensed under the terms of the GNU GPL, version 2 or later. See -# the COPYING file in the top-level directory. -## - -import sys -import os -from qmp import QEMUMonitorProtocol - -cmd, args = sys.argv[0], sys.argv[1:] -socket_path = None -path = None -prop = None - -def usage(): - return '''environment variables: - QMP_SOCKET=<path | addr:port> -usage: - %s [-h] [-s <QMP socket path | addr:port>] [<path>] -''' % cmd - -def usage_error(error_msg = "unspecified error"): - sys.stderr.write('%s\nERROR: %s\n' % (usage(), error_msg)) - exit(1) - -if len(args) > 0: - if args[0] == "-h": - print usage() - exit(0); - elif args[0] == "-s": - try: - socket_path = args[1] - except: - usage_error("missing argument: QMP socket path or address"); - args = args[2:] - -if not socket_path: - if os.environ.has_key('QMP_SOCKET'): - socket_path = os.environ['QMP_SOCKET'] - else: - usage_error("no QMP socket path or address given"); - -srv = QEMUMonitorProtocol(socket_path) -srv.connect() - -def list_node(path): - print '%s' % path - items = srv.command('qom-list', path=path) - for item in items: - if not item['type'].startswith('child<'): - try: - print ' %s: %s (%s)' % (item['name'], srv.command('qom-get', path=path, property=item['name']), item['type']) - except: - print ' %s: <EXCEPTION> (%s)' % (item['name'], item['type']) - print '' - for item in items: - if item['type'].startswith('child<'): - list_node((path if (path != '/') else '') + '/' + item['name']) - -if len(args) == 0: - path = '/' -else: - path = args[0] - -list_node(path) |