qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 1/6] QMP: add scripts/qmp
  2013-09-11 20:52 [Qemu-devel] [PATCH " Luiz Capitulino
@ 2013-09-11 20:52 ` Luiz Capitulino
  2013-09-11 22:08   ` Eric Blake
  0 siblings, 1 reply; 12+ messages in thread
From: Luiz Capitulino @ 2013-09-11 20:52 UTC (permalink / raw)
  To: qemu-devel; +Cc: armbru

Populate it with all scripts stored in QMP/.

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
 QMP/qemu-ga-client         | 299 ---------------------------------------------
 QMP/qmp                    | 126 -------------------
 QMP/qmp-shell              | 286 -------------------------------------------
 QMP/qmp.py                 | 190 ----------------------------
 QMP/qom-fuse               | 138 ---------------------
 QMP/qom-get                |  67 ----------
 QMP/qom-list               |  64 ----------
 QMP/qom-set                |  64 ----------
 scripts/qmp/qemu-ga-client | 299 +++++++++++++++++++++++++++++++++++++++++++++
 scripts/qmp/qmp            | 126 +++++++++++++++++++
 scripts/qmp/qmp-shell      | 286 +++++++++++++++++++++++++++++++++++++++++++
 scripts/qmp/qmp.py         | 190 ++++++++++++++++++++++++++++
 scripts/qmp/qom-fuse       | 138 +++++++++++++++++++++
 scripts/qmp/qom-get        |  67 ++++++++++
 scripts/qmp/qom-list       |  64 ++++++++++
 scripts/qmp/qom-set        |  64 ++++++++++
 16 files changed, 1234 insertions(+), 1234 deletions(-)
 delete mode 100755 QMP/qemu-ga-client
 delete mode 100755 QMP/qmp
 delete mode 100755 QMP/qmp-shell
 delete mode 100644 QMP/qmp.py
 delete mode 100755 QMP/qom-fuse
 delete mode 100755 QMP/qom-get
 delete mode 100755 QMP/qom-list
 delete mode 100755 QMP/qom-set
 create mode 100755 scripts/qmp/qemu-ga-client
 create mode 100755 scripts/qmp/qmp
 create mode 100755 scripts/qmp/qmp-shell
 create mode 100644 scripts/qmp/qmp.py
 create mode 100755 scripts/qmp/qom-fuse
 create mode 100755 scripts/qmp/qom-get
 create mode 100755 scripts/qmp/qom-list
 create mode 100755 scripts/qmp/qom-set

diff --git a/QMP/qemu-ga-client b/QMP/qemu-ga-client
deleted file mode 100755
index 46676c3..0000000
--- a/QMP/qemu-ga-client
+++ /dev/null
@@ -1,299 +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.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, e:
-        import errno
-
-        print(e)
-        if e.errno == errno.ECONNREFUSED:
-            print('Hint: qemu is not running?')
-        sys.exit(1)
-
-    if 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/QMP/qmp b/QMP/qmp
deleted file mode 100755
index 1db3c7f..0000000
--- a/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, (errno, msg):
-            if 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/QMP/qmp-shell b/QMP/qmp-shell
deleted file mode 100755
index 73cb3b6..0000000
--- a/QMP/qmp-shell
+++ /dev/null
@@ -1,286 +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)
-
-import qmp
-import readline
-import sys
-import pprint
-
-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
-
-# 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):
-        qmp.QEMUMonitorProtocol.__init__(self, self.__get_address(address))
-        self._greeting = None
-        self._completer = None
-        self._pp = pp
-
-    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 __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()
-        qmpcmd = { 'execute': cmdargs[0], 'arguments': {} }
-        for arg in cmdargs[1:]:
-            opt = arg.split('=')
-            try:
-                if(len(opt) > 2):
-                    opt[1] = '='.join(opt[1:])
-                value = int(opt[1])
-            except ValueError:
-                if opt[1] == 'true':
-                    value = True
-                elif opt[1] == 'false':
-                    value = False
-                else:
-                    value = opt[1]
-            qmpcmd['arguments'][opt[0]] = value
-        return qmpcmd
-
-    def _execute_cmd(self, cmdline):
-        try:
-            qmpcmd = self.__build_cmd(cmdline)
-        except:
-            print 'command format: <command-name> ',
-            print '[arg-name1=arg1] ... [arg-nameN=argN]'
-            return True
-        resp = self.cmd_obj(qmpcmd)
-        if resp is None:
-            print 'Disconnected'
-            return False
-
-        if self._pp is not None:
-            self._pp.pprint(resp)
-        else:
-            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 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)
-
-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 [ -p ] [ -H ] < UNIX socket path> | < TCP address:port >\n')
-    sys.exit(1)
-
-def main():
-    addr = ''
-    qemu = None
-    hmp = False
-    pp = None
-
-    try:
-        for arg in sys.argv[1:]:
-            if arg == "-H":
-                if qemu is not None:
-                    fail_cmdline(arg)
-                hmp = True
-            elif arg == "-p":
-                if pp is not None:
-                    fail_cmdline(arg)
-                pp = pprint.PrettyPrinter(indent=4)
-            else:
-                if qemu is not None:
-                    fail_cmdline(arg)
-                if hmp:
-                    qemu = HMPShell(arg)
-                else:
-                    qemu = QMPShell(arg, pp)
-                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()
-    while qemu.read_exec_command('(QEMU) '):
-        pass
-    qemu.close()
-
-if __name__ == '__main__':
-    main()
diff --git a/QMP/qmp.py b/QMP/qmp.py
deleted file mode 100644
index c551df1..0000000
--- a/QMP/qmp.py
+++ /dev/null
@@ -1,190 +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 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 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, 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: block until an event is available (bool)
-        """
-        self.__sock.setblocking(0)
-        try:
-            self.__json_read()
-        except socket.error, err:
-            if err[0] == errno.EAGAIN:
-                # No data available
-                pass
-        self.__sock.setblocking(1)
-        if not self.__events and wait:
-            self.__json_read(only_event=True)
-        event = self.__events[0]
-        del self.__events[0]
-        return event
-
-    def get_events(self, wait=False):
-        """
-        Get a list of available QMP events.
-
-        @param wait: block until an event is available (bool)
-        """
-        self.__sock.setblocking(0)
-        try:
-            self.__json_read()
-        except socket.error, err:
-            if err[0] == errno.EAGAIN:
-                # No data available
-                pass
-        self.__sock.setblocking(1)
-        if not self.__events and wait:
-            self.__json_read(only_event=True)
-        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)
diff --git a/QMP/qom-fuse b/QMP/qom-fuse
deleted file mode 100755
index 5c6754a..0000000
--- a/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/QMP/qom-get b/QMP/qom-get
deleted file mode 100755
index 0172c69..0000000
--- a/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/QMP/qom-list b/QMP/qom-list
deleted file mode 100755
index 1e7cc6c..0000000
--- a/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/QMP/qom-set b/QMP/qom-set
deleted file mode 100755
index 54ecfec..0000000
--- a/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/scripts/qmp/qemu-ga-client b/scripts/qmp/qemu-ga-client
new file mode 100755
index 0000000..46676c3
--- /dev/null
+++ b/scripts/qmp/qemu-ga-client
@@ -0,0 +1,299 @@
+#!/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.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, e:
+        import errno
+
+        print(e)
+        if e.errno == errno.ECONNREFUSED:
+            print('Hint: qemu is not running?')
+        sys.exit(1)
+
+    if 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/scripts/qmp/qmp b/scripts/qmp/qmp
new file mode 100755
index 0000000..1db3c7f
--- /dev/null
+++ b/scripts/qmp/qmp
@@ -0,0 +1,126 @@
+#!/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, (errno, msg):
+            if 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/scripts/qmp/qmp-shell b/scripts/qmp/qmp-shell
new file mode 100755
index 0000000..73cb3b6
--- /dev/null
+++ b/scripts/qmp/qmp-shell
@@ -0,0 +1,286 @@
+#!/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)
+
+import qmp
+import readline
+import sys
+import pprint
+
+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
+
+# 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):
+        qmp.QEMUMonitorProtocol.__init__(self, self.__get_address(address))
+        self._greeting = None
+        self._completer = None
+        self._pp = pp
+
+    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 __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()
+        qmpcmd = { 'execute': cmdargs[0], 'arguments': {} }
+        for arg in cmdargs[1:]:
+            opt = arg.split('=')
+            try:
+                if(len(opt) > 2):
+                    opt[1] = '='.join(opt[1:])
+                value = int(opt[1])
+            except ValueError:
+                if opt[1] == 'true':
+                    value = True
+                elif opt[1] == 'false':
+                    value = False
+                else:
+                    value = opt[1]
+            qmpcmd['arguments'][opt[0]] = value
+        return qmpcmd
+
+    def _execute_cmd(self, cmdline):
+        try:
+            qmpcmd = self.__build_cmd(cmdline)
+        except:
+            print 'command format: <command-name> ',
+            print '[arg-name1=arg1] ... [arg-nameN=argN]'
+            return True
+        resp = self.cmd_obj(qmpcmd)
+        if resp is None:
+            print 'Disconnected'
+            return False
+
+        if self._pp is not None:
+            self._pp.pprint(resp)
+        else:
+            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 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)
+
+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 [ -p ] [ -H ] < UNIX socket path> | < TCP address:port >\n')
+    sys.exit(1)
+
+def main():
+    addr = ''
+    qemu = None
+    hmp = False
+    pp = None
+
+    try:
+        for arg in sys.argv[1:]:
+            if arg == "-H":
+                if qemu is not None:
+                    fail_cmdline(arg)
+                hmp = True
+            elif arg == "-p":
+                if pp is not None:
+                    fail_cmdline(arg)
+                pp = pprint.PrettyPrinter(indent=4)
+            else:
+                if qemu is not None:
+                    fail_cmdline(arg)
+                if hmp:
+                    qemu = HMPShell(arg)
+                else:
+                    qemu = QMPShell(arg, pp)
+                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()
+    while qemu.read_exec_command('(QEMU) '):
+        pass
+    qemu.close()
+
+if __name__ == '__main__':
+    main()
diff --git a/scripts/qmp/qmp.py b/scripts/qmp/qmp.py
new file mode 100644
index 0000000..c551df1
--- /dev/null
+++ b/scripts/qmp/qmp.py
@@ -0,0 +1,190 @@
+# 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 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 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, 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: block until an event is available (bool)
+        """
+        self.__sock.setblocking(0)
+        try:
+            self.__json_read()
+        except socket.error, err:
+            if err[0] == errno.EAGAIN:
+                # No data available
+                pass
+        self.__sock.setblocking(1)
+        if not self.__events and wait:
+            self.__json_read(only_event=True)
+        event = self.__events[0]
+        del self.__events[0]
+        return event
+
+    def get_events(self, wait=False):
+        """
+        Get a list of available QMP events.
+
+        @param wait: block until an event is available (bool)
+        """
+        self.__sock.setblocking(0)
+        try:
+            self.__json_read()
+        except socket.error, err:
+            if err[0] == errno.EAGAIN:
+                # No data available
+                pass
+        self.__sock.setblocking(1)
+        if not self.__events and wait:
+            self.__json_read(only_event=True)
+        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)
diff --git a/scripts/qmp/qom-fuse b/scripts/qmp/qom-fuse
new file mode 100755
index 0000000..5c6754a
--- /dev/null
+++ b/scripts/qmp/qom-fuse
@@ -0,0 +1,138 @@
+#!/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/scripts/qmp/qom-get b/scripts/qmp/qom-get
new file mode 100755
index 0000000..0172c69
--- /dev/null
+++ b/scripts/qmp/qom-get
@@ -0,0 +1,67 @@
+#!/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/scripts/qmp/qom-list b/scripts/qmp/qom-list
new file mode 100755
index 0000000..1e7cc6c
--- /dev/null
+++ b/scripts/qmp/qom-list
@@ -0,0 +1,64 @@
+#!/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/scripts/qmp/qom-set b/scripts/qmp/qom-set
new file mode 100755
index 0000000..54ecfec
--- /dev/null
+++ b/scripts/qmp/qom-set
@@ -0,0 +1,64 @@
+#!/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])
-- 
1.8.1.4

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [Qemu-devel] [PATCH 1/6] QMP: add scripts/qmp
  2013-09-11 20:52 ` [Qemu-devel] [PATCH 1/6] QMP: add scripts/qmp Luiz Capitulino
@ 2013-09-11 22:08   ` Eric Blake
  2013-09-11 22:13     ` Eric Blake
  0 siblings, 1 reply; 12+ messages in thread
From: Eric Blake @ 2013-09-11 22:08 UTC (permalink / raw)
  To: Luiz Capitulino; +Cc: qemu-devel, armbru

[-- Attachment #1: Type: text/plain, Size: 4239 bytes --]

On 09/11/2013 02:52 PM, Luiz Capitulino wrote:
> Populate it with all scripts stored in QMP/.
> 
> Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
> ---
>  QMP/qemu-ga-client         | 299 ---------------------------------------------
>  QMP/qmp                    | 126 -------------------
>  QMP/qmp-shell              | 286 -------------------------------------------
>  QMP/qmp.py                 | 190 ----------------------------
>  QMP/qom-fuse               | 138 ---------------------
>  QMP/qom-get                |  67 ----------
>  QMP/qom-list               |  64 ----------
>  QMP/qom-set                |  64 ----------
>  scripts/qmp/qemu-ga-client | 299 +++++++++++++++++++++++++++++++++++++++++++++
>  scripts/qmp/qmp            | 126 +++++++++++++++++++
>  scripts/qmp/qmp-shell      | 286 +++++++++++++++++++++++++++++++++++++++++++
>  scripts/qmp/qmp.py         | 190 ++++++++++++++++++++++++++++
>  scripts/qmp/qom-fuse       | 138 +++++++++++++++++++++
>  scripts/qmp/qom-get        |  67 ++++++++++
>  scripts/qmp/qom-list       |  64 ++++++++++
>  scripts/qmp/qom-set        |  64 ++++++++++
>  16 files changed, 1234 insertions(+), 1234 deletions(-)
>  delete mode 100755 QMP/qemu-ga-client
>  delete mode 100755 QMP/qmp
>  delete mode 100755 QMP/qmp-shell
>  delete mode 100644 QMP/qmp.py
>  delete mode 100755 QMP/qom-fuse
>  delete mode 100755 QMP/qom-get
>  delete mode 100755 QMP/qom-list
>  delete mode 100755 QMP/qom-set
>  create mode 100755 scripts/qmp/qemu-ga-client
>  create mode 100755 scripts/qmp/qmp
>  create mode 100755 scripts/qmp/qmp-shell
>  create mode 100644 scripts/qmp/qmp.py
>  create mode 100755 scripts/qmp/qom-fuse
>  create mode 100755 scripts/qmp/qom-get
>  create mode 100755 scripts/qmp/qom-list
>  create mode 100755 scripts/qmp/qom-set

Reviewed-by: Eric Blake <eblake@redhat.com>

Repeat after me:
git config diff.renames true

at which point, this commit is much more compact and reviewable:

From c2957616df8bfa2066cbb375de106a45b5a80ae4 Mon Sep 17 00:00:00 2001
From: Luiz Capitulino <lcapitulino@redhat.com>
Date: Wed, 11 Sep 2013 16:52:12 -0400
Subject: [PATCH] QMP: add scripts/qmp

Populate it with all scripts stored in QMP/.

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
 {QMP => scripts/qmp}/qemu-ga-client | 0
 {QMP => scripts/qmp}/qmp            | 0
 {QMP => scripts/qmp}/qmp-shell      | 0
 {QMP => scripts/qmp}/qmp.py         | 0
 {QMP => scripts/qmp}/qom-fuse       | 0
 {QMP => scripts/qmp}/qom-get        | 0
 {QMP => scripts/qmp}/qom-list       | 0
 {QMP => scripts/qmp}/qom-set        | 0
 8 files changed, 0 insertions(+), 0 deletions(-)
 rename {QMP => scripts/qmp}/qemu-ga-client (100%)
 rename {QMP => scripts/qmp}/qmp (100%)
 rename {QMP => scripts/qmp}/qmp-shell (100%)
 rename {QMP => scripts/qmp}/qmp.py (100%)
 rename {QMP => scripts/qmp}/qom-fuse (100%)
 rename {QMP => scripts/qmp}/qom-get (100%)
 rename {QMP => scripts/qmp}/qom-list (100%)
 rename {QMP => scripts/qmp}/qom-set (100%)

diff --git a/QMP/qemu-ga-client b/scripts/qmp/qemu-ga-client
similarity index 100%
rename from QMP/qemu-ga-client
rename to scripts/qmp/qemu-ga-client
diff --git a/QMP/qmp b/scripts/qmp/qmp
similarity index 100%
rename from QMP/qmp
rename to scripts/qmp/qmp
diff --git a/QMP/qmp-shell b/scripts/qmp/qmp-shell
similarity index 100%
rename from QMP/qmp-shell
rename to scripts/qmp/qmp-shell
diff --git a/QMP/qmp.py b/scripts/qmp/qmp.py
similarity index 100%
rename from QMP/qmp.py
rename to scripts/qmp/qmp.py
diff --git a/QMP/qom-fuse b/scripts/qmp/qom-fuse
similarity index 100%
rename from QMP/qom-fuse
rename to scripts/qmp/qom-fuse
diff --git a/QMP/qom-get b/scripts/qmp/qom-get
similarity index 100%
rename from QMP/qom-get
rename to scripts/qmp/qom-get
diff --git a/QMP/qom-list b/scripts/qmp/qom-list
similarity index 100%
rename from QMP/qom-list
rename to scripts/qmp/qom-list
diff --git a/QMP/qom-set b/scripts/qmp/qom-set
similarity index 100%
rename from QMP/qom-set
rename to scripts/qmp/qom-set
-- 
1.8.3.1

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 621 bytes --]

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [Qemu-devel] [PATCH 1/6] QMP: add scripts/qmp
  2013-09-11 22:08   ` Eric Blake
@ 2013-09-11 22:13     ` Eric Blake
  2013-09-13 17:52       ` Luiz Capitulino
  0 siblings, 1 reply; 12+ messages in thread
From: Eric Blake @ 2013-09-11 22:13 UTC (permalink / raw)
  Cc: armbru, qemu-devel, Luiz Capitulino

[-- Attachment #1: Type: text/plain, Size: 902 bytes --]

On 09/11/2013 04:08 PM, Eric Blake wrote:
> On 09/11/2013 02:52 PM, Luiz Capitulino wrote:
>> Populate it with all scripts stored in QMP/.
>>
>> Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>

> Reviewed-by: Eric Blake <eblake@redhat.com>
> 
> Repeat after me:
> git config diff.renames true
> 
> at which point, this commit is much more compact and reviewable:
> 

Oh, and while testing your patch:

<stdin>:1854: trailing whitespace.

<stdin>:2054: trailing whitespace.
#
warning: 2 lines add whitespace errors.

One instance from qmp-shell; the other from qmp.py.  It's okay if you
touch those up as part of this rename (again, the diff.renames true bit
will highlight those two changes, rather than showing the complete file
as a delete and addition).

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 621 bytes --]

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [Qemu-devel] [PATCH 1/6] QMP: add scripts/qmp
  2013-09-11 22:13     ` Eric Blake
@ 2013-09-13 17:52       ` Luiz Capitulino
  0 siblings, 0 replies; 12+ messages in thread
From: Luiz Capitulino @ 2013-09-13 17:52 UTC (permalink / raw)
  To: Eric Blake; +Cc: qemu-devel, armbru

On Wed, 11 Sep 2013 16:13:32 -0600
Eric Blake <eblake@redhat.com> wrote:

> On 09/11/2013 04:08 PM, Eric Blake wrote:
> > On 09/11/2013 02:52 PM, Luiz Capitulino wrote:
> >> Populate it with all scripts stored in QMP/.
> >>
> >> Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
> 
> > Reviewed-by: Eric Blake <eblake@redhat.com>
> > 
> > Repeat after me:
> > git config diff.renames true
> > 
> > at which point, this commit is much more compact and reviewable:

Done.

> Oh, and while testing your patch:
> 
> <stdin>:1854: trailing whitespace.
> 
> <stdin>:2054: trailing whitespace.
> #
> warning: 2 lines add whitespace errors.
> 
> One instance from qmp-shell; the other from qmp.py.  It's okay if you
> touch those up as part of this rename (again, the diff.renames true bit
> will highlight those two changes, rather than showing the complete file
> as a delete and addition).

Fixed.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [Qemu-devel] [PATCH v2 0/6] QMP: re-organize documentation
@ 2013-09-13 18:11 Luiz Capitulino
  2013-09-13 18:11 ` [Qemu-devel] [PATCH 1/6] QMP: add scripts/qmp Luiz Capitulino
                   ` (6 more replies)
  0 siblings, 7 replies; 12+ messages in thread
From: Luiz Capitulino @ 2013-09-13 18:11 UTC (permalink / raw)
  To: qemu-devel; +Cc: armbru

The QMP dir is storing QMP docs and scripts. This series moves the scripts to
scripts/qmp/ and the docs to docs/qmp/. Also, the docs are updated.

v2

 - Set git diff.renames to true
 - Fix trailing whitespaces
 - Other minor fixes

Luiz Capitulino (6):
  QMP: add scripts/qmp
  QMP: fix qmp-commands.txt generation path
  QMP: QMP/ -> docs/qmp/
  QMP: Update README file
  QMP: Update qmp-spec.txt
  QMP: qmp-events.txt: alphabetical order fix and other minor changes

 Makefile                            |  6 +--
 QMP/README                          | 88 -------------------------------------
 docs/qmp/README                     | 87 ++++++++++++++++++++++++++++++++++++
 {QMP => docs/qmp}/qmp-events.txt    | 34 +++++++-------
 {QMP => docs/qmp}/qmp-spec.txt      | 65 ++++++++++++---------------
 {QMP => scripts/qmp}/qemu-ga-client |  0
 {QMP => scripts/qmp}/qmp            |  0
 {QMP => scripts/qmp}/qmp-shell      |  2 +-
 {QMP => scripts/qmp}/qmp.py         |  2 +-
 {QMP => scripts/qmp}/qom-fuse       |  0
 {QMP => scripts/qmp}/qom-get        |  0
 {QMP => scripts/qmp}/qom-list       |  0
 {QMP => scripts/qmp}/qom-set        |  0
 13 files changed, 137 insertions(+), 147 deletions(-)
 delete mode 100644 QMP/README
 create mode 100644 docs/qmp/README
 rename {QMP => docs/qmp}/qmp-events.txt (99%)
 rename {QMP => docs/qmp}/qmp-spec.txt (82%)
 rename {QMP => scripts/qmp}/qemu-ga-client (100%)
 rename {QMP => scripts/qmp}/qmp (100%)
 rename {QMP => scripts/qmp}/qmp-shell (99%)
 rename {QMP => scripts/qmp}/qmp.py (99%)
 rename {QMP => scripts/qmp}/qom-fuse (100%)
 rename {QMP => scripts/qmp}/qom-get (100%)
 rename {QMP => scripts/qmp}/qom-list (100%)
 rename {QMP => scripts/qmp}/qom-set (100%)

-- 
1.8.1.4

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [Qemu-devel] [PATCH 1/6] QMP: add scripts/qmp
  2013-09-13 18:11 [Qemu-devel] [PATCH v2 0/6] QMP: re-organize documentation Luiz Capitulino
@ 2013-09-13 18:11 ` Luiz Capitulino
  2013-09-13 18:11 ` [Qemu-devel] [PATCH 2/6] QMP: fix qmp-commands.txt generation path Luiz Capitulino
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 12+ messages in thread
From: Luiz Capitulino @ 2013-09-13 18:11 UTC (permalink / raw)
  To: qemu-devel; +Cc: armbru

Populate it with all scripts stored in QMP/. Also fixes trailing
whitespaces in qmp-shell and qmp.py.

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
 {QMP => scripts/qmp}/qemu-ga-client | 0
 {QMP => scripts/qmp}/qmp            | 0
 {QMP => scripts/qmp}/qmp-shell      | 2 +-
 {QMP => scripts/qmp}/qmp.py         | 2 +-
 {QMP => scripts/qmp}/qom-fuse       | 0
 {QMP => scripts/qmp}/qom-get        | 0
 {QMP => scripts/qmp}/qom-list       | 0
 {QMP => scripts/qmp}/qom-set        | 0
 8 files changed, 2 insertions(+), 2 deletions(-)
 rename {QMP => scripts/qmp}/qemu-ga-client (100%)
 rename {QMP => scripts/qmp}/qmp (100%)
 rename {QMP => scripts/qmp}/qmp-shell (99%)
 rename {QMP => scripts/qmp}/qmp.py (99%)
 rename {QMP => scripts/qmp}/qom-fuse (100%)
 rename {QMP => scripts/qmp}/qom-get (100%)
 rename {QMP => scripts/qmp}/qom-list (100%)
 rename {QMP => scripts/qmp}/qom-set (100%)

diff --git a/QMP/qemu-ga-client b/scripts/qmp/qemu-ga-client
similarity index 100%
rename from QMP/qemu-ga-client
rename to scripts/qmp/qemu-ga-client
diff --git a/QMP/qmp b/scripts/qmp/qmp
similarity index 100%
rename from QMP/qmp
rename to scripts/qmp/qmp
diff --git a/QMP/qmp-shell b/scripts/qmp/qmp-shell
similarity index 99%
rename from QMP/qmp-shell
rename to scripts/qmp/qmp-shell
index 73cb3b6..d6b420f 100755
--- a/QMP/qmp-shell
+++ b/scripts/qmp/qmp-shell
@@ -91,7 +91,7 @@ class QMPShell(qmp.QEMUMonitorProtocol):
         """
         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()
diff --git a/QMP/qmp.py b/scripts/qmp/qmp.py
similarity index 99%
rename from QMP/qmp.py
rename to scripts/qmp/qmp.py
index c551df1..21804f4 100644
--- a/QMP/qmp.py
+++ b/scripts/qmp/qmp.py
@@ -1,5 +1,5 @@
 # QEMU Monitor Protocol Python class
-# 
+#
 # Copyright (C) 2009, 2010 Red Hat Inc.
 #
 # Authors:
diff --git a/QMP/qom-fuse b/scripts/qmp/qom-fuse
similarity index 100%
rename from QMP/qom-fuse
rename to scripts/qmp/qom-fuse
diff --git a/QMP/qom-get b/scripts/qmp/qom-get
similarity index 100%
rename from QMP/qom-get
rename to scripts/qmp/qom-get
diff --git a/QMP/qom-list b/scripts/qmp/qom-list
similarity index 100%
rename from QMP/qom-list
rename to scripts/qmp/qom-list
diff --git a/QMP/qom-set b/scripts/qmp/qom-set
similarity index 100%
rename from QMP/qom-set
rename to scripts/qmp/qom-set
-- 
1.8.1.4

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [Qemu-devel] [PATCH 2/6] QMP: fix qmp-commands.txt generation path
  2013-09-13 18:11 [Qemu-devel] [PATCH v2 0/6] QMP: re-organize documentation Luiz Capitulino
  2013-09-13 18:11 ` [Qemu-devel] [PATCH 1/6] QMP: add scripts/qmp Luiz Capitulino
@ 2013-09-13 18:11 ` Luiz Capitulino
  2013-09-13 18:11 ` [Qemu-devel] [PATCH 3/6] QMP: QMP/ -> docs/qmp/ Luiz Capitulino
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 12+ messages in thread
From: Luiz Capitulino @ 2013-09-13 18:11 UTC (permalink / raw)
  To: qemu-devel; +Cc: armbru

This file should be generated in the BUILD_DIR, as all other docs.

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
---
 Makefile | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/Makefile b/Makefile
index 362fe3e..aca548d 100644
--- a/Makefile
+++ b/Makefile
@@ -65,7 +65,7 @@ LIBS+=-lz $(LIBS_TOOLS)
 HELPERS-$(CONFIG_LINUX) = qemu-bridge-helper$(EXESUF)
 
 ifdef BUILD_DOCS
-DOCS=qemu-doc.html qemu-tech.html qemu.1 qemu-img.1 qemu-nbd.8 QMP/qmp-commands.txt
+DOCS=qemu-doc.html qemu-tech.html qemu.1 qemu-img.1 qemu-nbd.8 qmp-commands.txt
 ifdef CONFIG_VIRTFS
 DOCS+=fsdev/virtfs-proxy-helper.1
 endif
@@ -304,7 +304,7 @@ endif
 install-doc: $(DOCS)
 	$(INSTALL_DIR) "$(DESTDIR)$(qemu_docdir)"
 	$(INSTALL_DATA) qemu-doc.html  qemu-tech.html "$(DESTDIR)$(qemu_docdir)"
-	$(INSTALL_DATA) QMP/qmp-commands.txt "$(DESTDIR)$(qemu_docdir)"
+	$(INSTALL_DATA) qmp-commands.txt "$(DESTDIR)$(qemu_docdir)"
 ifdef CONFIG_POSIX
 	$(INSTALL_DIR) "$(DESTDIR)$(mandir)/man1"
 	$(INSTALL_DATA) qemu.1 "$(DESTDIR)$(mandir)/man1"
@@ -398,7 +398,7 @@ qemu-options.texi: $(SRC_PATH)/qemu-options.hx
 qemu-monitor.texi: $(SRC_PATH)/hmp-commands.hx
 	$(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -t < $< > $@,"  GEN   $@")
 
-QMP/qmp-commands.txt: $(SRC_PATH)/qmp-commands.hx
+qmp-commands.txt: $(SRC_PATH)/qmp-commands.hx
 	$(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -q < $< > $@,"  GEN   $@")
 
 qemu-img-cmds.texi: $(SRC_PATH)/qemu-img-cmds.hx
-- 
1.8.1.4

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [Qemu-devel] [PATCH 3/6] QMP: QMP/ -> docs/qmp/
  2013-09-13 18:11 [Qemu-devel] [PATCH v2 0/6] QMP: re-organize documentation Luiz Capitulino
  2013-09-13 18:11 ` [Qemu-devel] [PATCH 1/6] QMP: add scripts/qmp Luiz Capitulino
  2013-09-13 18:11 ` [Qemu-devel] [PATCH 2/6] QMP: fix qmp-commands.txt generation path Luiz Capitulino
@ 2013-09-13 18:11 ` Luiz Capitulino
  2013-09-13 18:11 ` [Qemu-devel] [PATCH 4/6] QMP: Update README file Luiz Capitulino
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 12+ messages in thread
From: Luiz Capitulino @ 2013-09-13 18:11 UTC (permalink / raw)
  To: qemu-devel; +Cc: armbru

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
 {QMP => docs/qmp}/README         | 0
 {QMP => docs/qmp}/qmp-events.txt | 0
 {QMP => docs/qmp}/qmp-spec.txt   | 0
 3 files changed, 0 insertions(+), 0 deletions(-)
 rename {QMP => docs/qmp}/README (100%)
 rename {QMP => docs/qmp}/qmp-events.txt (100%)
 rename {QMP => docs/qmp}/qmp-spec.txt (100%)

diff --git a/QMP/README b/docs/qmp/README
similarity index 100%
rename from QMP/README
rename to docs/qmp/README
diff --git a/QMP/qmp-events.txt b/docs/qmp/qmp-events.txt
similarity index 100%
rename from QMP/qmp-events.txt
rename to docs/qmp/qmp-events.txt
diff --git a/QMP/qmp-spec.txt b/docs/qmp/qmp-spec.txt
similarity index 100%
rename from QMP/qmp-spec.txt
rename to docs/qmp/qmp-spec.txt
-- 
1.8.1.4

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [Qemu-devel] [PATCH 4/6] QMP: Update README file
  2013-09-13 18:11 [Qemu-devel] [PATCH v2 0/6] QMP: re-organize documentation Luiz Capitulino
                   ` (2 preceding siblings ...)
  2013-09-13 18:11 ` [Qemu-devel] [PATCH 3/6] QMP: QMP/ -> docs/qmp/ Luiz Capitulino
@ 2013-09-13 18:11 ` Luiz Capitulino
  2013-09-13 18:11 ` [Qemu-devel] [PATCH 5/6] QMP: Update qmp-spec.txt Luiz Capitulino
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 12+ messages in thread
From: Luiz Capitulino @ 2013-09-13 18:11 UTC (permalink / raw)
  To: qemu-devel; +Cc: armbru

Drop unneeded info, fix some of the examples and rename QEMU Monitor
Protocol to QEMU Machine Protocol.

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
---
 docs/qmp/README | 99 ++++++++++++++++++++++++++++-----------------------------
 1 file changed, 49 insertions(+), 50 deletions(-)

diff --git a/docs/qmp/README b/docs/qmp/README
index c95a08c..85c4bc1 100644
--- a/docs/qmp/README
+++ b/docs/qmp/README
@@ -1,13 +1,13 @@
-                          QEMU Monitor Protocol
+                          QEMU Machine Protocol
                           =====================
 
 Introduction
--------------
+------------
 
-The QEMU Monitor Protocol (QMP) allows applications to communicate with
-QEMU's Monitor.
+The QEMU Machine Protocol (QMP) allows applications to operate a
+QEMU instance.
 
-QMP is JSON[1] based and currently has the following features:
+QMP is JSON[1] based and features the following:
 
 - Lightweight, text-based, easy to parse data format
 - Asynchronous messages support (ie. events)
@@ -15,37 +15,28 @@ QMP is JSON[1] based and currently has the following features:
 
 For detailed information on QMP's usage, please, refer to the following files:
 
-o qmp-spec.txt      QEMU Monitor Protocol current specification
+o qmp-spec.txt      QEMU Machine Protocol current specification
 o qmp-commands.txt  QMP supported commands (auto-generated at build-time)
 o qmp-events.txt    List of available asynchronous events
 
-There is also a simple Python script called 'qmp-shell' available.
-
-IMPORTANT: It's strongly recommended to read the 'Stability Considerations'
-section in the qmp-commands.txt file before making any serious use of QMP.
-
-
 [1] http://www.json.org
 
 Usage
 -----
 
-To enable QMP, you need a QEMU monitor instance in "control mode". There are
-two ways of doing this.
+You can use the -qmp option to enable QMP. For example, the following
+makes QMP available on localhost port 4444:
 
-The simplest one is using the '-qmp' command-line option. The following
-example makes QMP available on localhost port 4444:
+$ qemu [...] -qmp tcp:localhost:4444,server,nowait
 
-  $ qemu [...] -qmp tcp:localhost:4444,server
+However, for more flexibility and to make use of more options, the -mon
+command-line option should be used. For instance, the following example
+creates one HMP instance (human monitor) on stdio and one QMP instance
+on localhost port 4444:
 
-However, in order to have more complex combinations, like multiple monitors,
-the '-mon' command-line option should be used along with the '-chardev' one.
-For instance, the following example creates one user monitor on stdio and one
-QMP monitor on localhost port 4444.
-
-   $ qemu [...] -chardev stdio,id=mon0 -mon chardev=mon0,mode=readline \
-                -chardev socket,id=mon1,host=localhost,port=4444,server \
-                -mon chardev=mon1,mode=control
+$ qemu [...] -chardev stdio,id=mon0 -mon chardev=mon0,mode=readline \
+             -chardev socket,id=mon1,host=localhost,port=4444,server,nowait \
+             -mon chardev=mon1,mode=control,pretty=on
 
 Please, refer to QEMU's manpage for more information.
 
@@ -58,31 +49,39 @@ $ telnet localhost 4444
 Trying 127.0.0.1...
 Connected to localhost.
 Escape character is '^]'.
-{"QMP": {"version": {"qemu": {"micro": 50, "minor": 13, "major": 0}, "package": ""}, "capabilities": []}}
-{ "execute": "qmp_capabilities" }
-{"return": {}}
-{ "execute": "query-version" }
-{"return": {"qemu": {"micro": 50, "minor": 13, "major": 0}, "package": ""}}
-
-Development Process
--------------------
+{
+    "QMP": {
+        "version": {
+            "qemu": {
+                "micro": 50, 
+                "minor": 6, 
+                "major": 1
+            }, 
+            "package": ""
+        }, 
+        "capabilities": [
+        ]
+    }
+}
 
-When changing QMP's interface (by adding new commands, events or modifying
-existing ones) it's mandatory to update the relevant documentation, which is
-one (or more) of the files listed in the 'Introduction' section*.
-
-Also, it's strongly recommended to send the documentation patch first, before
-doing any code change. This is so because:
-
-  1. Avoids the code dictating the interface
-
-  2. Review can improve your interface.  Letting that happen before
-     you implement it can save you work.
-
-* The qmp-commands.txt file is generated from the qmp-commands.hx one, which
-  is the file that should be edited.
-
-Homepage
---------
+{ "execute": "qmp_capabilities" }
+{
+    "return": {
+    }
+}
+
+{ "execute": "query-status" }
+{
+    "return": {
+        "status": "prelaunch", 
+        "singlestep": false, 
+        "running": false
+    }
+}
+
+Please, refer to the qapi-schema.json file for a complete command reference.
+
+QMP wiki page
+-------------
 
 http://wiki.qemu.org/QMP
-- 
1.8.1.4

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [Qemu-devel] [PATCH 5/6] QMP: Update qmp-spec.txt
  2013-09-13 18:11 [Qemu-devel] [PATCH v2 0/6] QMP: re-organize documentation Luiz Capitulino
                   ` (3 preceding siblings ...)
  2013-09-13 18:11 ` [Qemu-devel] [PATCH 4/6] QMP: Update README file Luiz Capitulino
@ 2013-09-13 18:11 ` Luiz Capitulino
  2013-09-13 18:11 ` [Qemu-devel] [PATCH 6/6] QMP: qmp-events.txt: alphabetical order fix and other minor changes Luiz Capitulino
  2013-09-13 18:15 ` [Qemu-devel] [PATCH v2 0/6] QMP: re-organize documentation Eric Blake
  6 siblings, 0 replies; 12+ messages in thread
From: Luiz Capitulino @ 2013-09-13 18:11 UTC (permalink / raw)
  To: qemu-devel; +Cc: armbru

Simplify the text, fix some of the examples.

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
---
 docs/qmp/qmp-spec.txt | 65 ++++++++++++++++++++++-----------------------------
 1 file changed, 28 insertions(+), 37 deletions(-)

diff --git a/docs/qmp/qmp-spec.txt b/docs/qmp/qmp-spec.txt
index a277896..22568c6 100644
--- a/docs/qmp/qmp-spec.txt
+++ b/docs/qmp/qmp-spec.txt
@@ -1,21 +1,17 @@
-           QEMU Monitor Protocol Specification - Version 0.1
+                      QEMU Machine Protocol Specification
 
 1. Introduction
 ===============
 
-This document specifies the QEMU Monitor Protocol (QMP), a JSON-based protocol
-which is available for applications to control QEMU at the machine-level.
-
-To enable QMP support, QEMU has to be run in "control mode". This is done by
-starting QEMU with the appropriate command-line options. Please, refer to the
-QEMU manual page for more information.
+This document specifies the QEMU Machine Protocol (QMP), a JSON-based protocol
+which is available for applications to operate QEMU at the machine-level.
 
 2. Protocol Specification
 =========================
 
 This section details the protocol format. For the purpose of this document
-"Client" is any application which is communicating with QEMU in control mode,
-and "Server" is QEMU itself.
+"Client" is any application which is using QMP to communicate with QEMU and
+"Server" is QEMU itself.
 
 JSON data structures, when mentioned in this document, are always in the
 following format:
@@ -47,14 +43,14 @@ that the connection has been successfully established and that the Server is
 ready for capabilities negotiation (for more information refer to section
 '4. Capabilities Negotiation').
 
-The format is:
+The greeting message format is:
 
 { "QMP": { "version": json-object, "capabilities": json-array } }
 
  Where,
 
 - The "version" member contains the Server's version information (the format
-  is the same of the 'query-version' command)
+  is the same of the query-version command)
 - The "capabilities" member specify the availability of features beyond the
   baseline specification
 
@@ -83,10 +79,7 @@ of a command execution: success or error.
 2.4.1 success
 -------------
 
-The success response is issued when the command execution has finished
-without errors.
-
-The format is:
+The format of a success response is:
 
 { "return": json-object, "id": json-value }
 
@@ -96,15 +89,12 @@ The format is:
   in a per-command basis or an empty json-object if the command does not
   return data
 - The "id" member contains the transaction identification associated
-  with the command execution (if issued by the Client)
+  with the command execution if issued by the Client
 
 2.4.2 error
 -----------
 
-The error response is issued when the command execution could not be
-completed because of an error condition.
-
-The format is:
+The format of an error response is:
 
 { "error": { "class": json-string, "desc": json-string }, "id": json-value }
 
@@ -114,7 +104,7 @@ The format is:
 - The "desc" member is a human-readable error message. Clients should
   not attempt to parse this message.
 - The "id" member contains the transaction identification associated with
-  the command execution (if issued by the Client)
+  the command execution if issued by the Client
 
 NOTE: Some errors can occur before the Server is able to read the "id" member,
 in these cases the "id" member will not be part of the error response, even
@@ -124,9 +114,9 @@ if provided by the client.
 -----------------------
 
 As a result of state changes, the Server may send messages unilaterally
-to the Client at any time. They are called 'asynchronous events'.
+to the Client at any time. They are called "asynchronous events".
 
-The format is:
+The format of asynchronous events is:
 
 { "event": json-string, "data": json-object,
   "timestamp": { "seconds": json-number, "microseconds": json-number } }
@@ -147,36 +137,37 @@ qmp-events.txt file.
 ===============
 
 This section provides some examples of real QMP usage, in all of them
-'C' stands for 'Client' and 'S' stands for 'Server'.
+"C" stands for "Client" and "S" stands for "Server".
 
 3.1 Server greeting
 -------------------
 
-S: {"QMP": {"version": {"qemu": "0.12.50", "package": ""}, "capabilities": []}}
+S: { "QMP": { "version": { "qemu": { "micro": 50, "minor": 6, "major": 1 },
+     "package": ""}, "capabilities": []}}
 
 3.2 Simple 'stop' execution
 ---------------------------
 
 C: { "execute": "stop" }
-S: {"return": {}}
+S: { "return": {} }
 
 3.3 KVM information
 -------------------
 
 C: { "execute": "query-kvm", "id": "example" }
-S: {"return": {"enabled": true, "present": true}, "id": "example"}
+S: { "return": { "enabled": true, "present": true }, "id": "example"}
 
 3.4 Parsing error
 ------------------
 
 C: { "execute": }
-S: {"error": {"class": "GenericError", "desc": "Invalid JSON syntax" } }
+S: { "error": { "class": "GenericError", "desc": "Invalid JSON syntax" } }
 
 3.5 Powerdown event
 -------------------
 
-S: {"timestamp": {"seconds": 1258551470, "microseconds": 802384}, "event":
-"POWERDOWN"}
+S: { "timestamp": { "seconds": 1258551470, "microseconds": 802384 },
+    "event": "POWERDOWN" }
 
 4. Capabilities Negotiation
 ----------------------------
@@ -184,17 +175,17 @@ S: {"timestamp": {"seconds": 1258551470, "microseconds": 802384}, "event":
 When a Client successfully establishes a connection, the Server is in
 Capabilities Negotiation mode.
 
-In this mode only the 'qmp_capabilities' command is allowed to run, all
-other commands will return the CommandNotFound error. Asynchronous messages
-are not delivered either.
+In this mode only the qmp_capabilities command is allowed to run, all
+other commands will return the CommandNotFound error. Asynchronous
+messages are not delivered either.
 
-Clients should use the 'qmp_capabilities' command to enable capabilities
+Clients should use the qmp_capabilities command to enable capabilities
 advertised in the Server's greeting (section '2.2 Server Greeting') they
 support.
 
-When the 'qmp_capabilities' command is issued, and if it does not return an
+When the qmp_capabilities command is issued, and if it does not return an
 error, the Server enters in Command mode where capabilities changes take
-effect, all commands (except 'qmp_capabilities') are allowed and asynchronous
+effect, all commands (except qmp_capabilities) are allowed and asynchronous
 messages are delivered.
 
 5 Compatibility Considerations
@@ -245,7 +236,7 @@ arguments, errors, asynchronous events, and so forth.
 
 Any new names downstream wishes to add must begin with '__'.  To
 ensure compatibility with other downstreams, it is strongly
-recommended that you prefix your downstram names with '__RFQDN_' where
+recommended that you prefix your downstream names with '__RFQDN_' where
 RFQDN is a valid, reverse fully qualified domain name which you
 control.  For example, a qemu-kvm specific monitor command would be:
 
-- 
1.8.1.4

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [Qemu-devel] [PATCH 6/6] QMP: qmp-events.txt: alphabetical order fix and other minor changes
  2013-09-13 18:11 [Qemu-devel] [PATCH v2 0/6] QMP: re-organize documentation Luiz Capitulino
                   ` (4 preceding siblings ...)
  2013-09-13 18:11 ` [Qemu-devel] [PATCH 5/6] QMP: Update qmp-spec.txt Luiz Capitulino
@ 2013-09-13 18:11 ` Luiz Capitulino
  2013-09-13 18:15 ` [Qemu-devel] [PATCH v2 0/6] QMP: re-organize documentation Eric Blake
  6 siblings, 0 replies; 12+ messages in thread
From: Luiz Capitulino @ 2013-09-13 18:11 UTC (permalink / raw)
  To: qemu-devel; +Cc: armbru

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
 docs/qmp/qmp-events.txt | 34 +++++++++++++++++-----------------
 1 file changed, 17 insertions(+), 17 deletions(-)

diff --git a/docs/qmp/qmp-events.txt b/docs/qmp/qmp-events.txt
index 4b24ec9..6b87e97 100644
--- a/docs/qmp/qmp-events.txt
+++ b/docs/qmp/qmp-events.txt
@@ -1,4 +1,4 @@
-                   QEMU Monitor Protocol Events
+                   QEMU Machine Protocol Events
                    ============================
 
 BALLOON_CHANGE
@@ -159,7 +159,7 @@ Note: The "ready to complete" status is always reset by a BLOCK_JOB_ERROR
 event.
 
 DEVICE_DELETED
------------------
+--------------
 
 Emitted whenever the device removal completion is acknowledged
 by the guest.
@@ -194,8 +194,22 @@ Data:
   },
   "timestamp": { "seconds": 1265044230, "microseconds": 450486 } }
 
+GUEST_PANICKED
+--------------
+
+Emitted when guest OS panic is detected.
+
+Data:
+
+- "action": Action that has been taken (json-string, currently always "pause").
+
+Example:
+
+{ "event": "GUEST_PANICKED",
+     "data": { "action": "pause" } }
+
 NIC_RX_FILTER_CHANGED
------------------
+---------------------
 
 The event is emitted once until the query command is executed,
 the first event will always be emitted.
@@ -486,17 +500,3 @@ Example:
 
 Note: If action is "reset", "shutdown", or "pause" the WATCHDOG event is
 followed respectively by the RESET, SHUTDOWN, or STOP events.
-
-GUEST_PANICKED
---------------
-
-Emitted when guest OS panic is detected.
-
-Data:
-
-- "action": Action that has been taken (json-string, currently always "pause").
-
-Example:
-
-{ "event": "GUEST_PANICKED",
-     "data": { "action": "pause" } }
-- 
1.8.1.4

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [Qemu-devel] [PATCH v2 0/6] QMP: re-organize documentation
  2013-09-13 18:11 [Qemu-devel] [PATCH v2 0/6] QMP: re-organize documentation Luiz Capitulino
                   ` (5 preceding siblings ...)
  2013-09-13 18:11 ` [Qemu-devel] [PATCH 6/6] QMP: qmp-events.txt: alphabetical order fix and other minor changes Luiz Capitulino
@ 2013-09-13 18:15 ` Eric Blake
  6 siblings, 0 replies; 12+ messages in thread
From: Eric Blake @ 2013-09-13 18:15 UTC (permalink / raw)
  To: Luiz Capitulino; +Cc: qemu-devel, armbru

[-- Attachment #1: Type: text/plain, Size: 731 bytes --]

On 09/13/2013 12:11 PM, Luiz Capitulino wrote:
> The QMP dir is storing QMP docs and scripts. This series moves the scripts to
> scripts/qmp/ and the docs to docs/qmp/. Also, the docs are updated.
> 
> v2
> 
>  - Set git diff.renames to true
>  - Fix trailing whitespaces
>  - Other minor fixes
> 
> Luiz Capitulino (6):
>   QMP: add scripts/qmp
>   QMP: fix qmp-commands.txt generation path
>   QMP: QMP/ -> docs/qmp/
>   QMP: Update README file
>   QMP: Update qmp-spec.txt
>   QMP: qmp-events.txt: alphabetical order fix and other minor changes

Series: Reviewed-by: Eric Blake <eblake@redhat.com>

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 621 bytes --]

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2013-09-13 18:15 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-09-13 18:11 [Qemu-devel] [PATCH v2 0/6] QMP: re-organize documentation Luiz Capitulino
2013-09-13 18:11 ` [Qemu-devel] [PATCH 1/6] QMP: add scripts/qmp Luiz Capitulino
2013-09-13 18:11 ` [Qemu-devel] [PATCH 2/6] QMP: fix qmp-commands.txt generation path Luiz Capitulino
2013-09-13 18:11 ` [Qemu-devel] [PATCH 3/6] QMP: QMP/ -> docs/qmp/ Luiz Capitulino
2013-09-13 18:11 ` [Qemu-devel] [PATCH 4/6] QMP: Update README file Luiz Capitulino
2013-09-13 18:11 ` [Qemu-devel] [PATCH 5/6] QMP: Update qmp-spec.txt Luiz Capitulino
2013-09-13 18:11 ` [Qemu-devel] [PATCH 6/6] QMP: qmp-events.txt: alphabetical order fix and other minor changes Luiz Capitulino
2013-09-13 18:15 ` [Qemu-devel] [PATCH v2 0/6] QMP: re-organize documentation Eric Blake
  -- strict thread matches above, loose matches on Subject: below --
2013-09-11 20:52 [Qemu-devel] [PATCH " Luiz Capitulino
2013-09-11 20:52 ` [Qemu-devel] [PATCH 1/6] QMP: add scripts/qmp Luiz Capitulino
2013-09-11 22:08   ` Eric Blake
2013-09-11 22:13     ` Eric Blake
2013-09-13 17:52       ` Luiz Capitulino

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).