From 1d00a07de980ecf643c7d7699dfc48e94bec15ae Mon Sep 17 00:00:00 2001 From: Luiz Capitulino Date: Wed, 27 Oct 2010 17:43:34 -0200 Subject: [PATCH 1/7] QMP: Revamp the Python class example This commit simplifies and fixes a number of problems in the Python QEMUMonitorProtocol example class. It's almost a rewrite and it DOES BREAK the qmp-shell script (which is going to be fixed in the next commit). However, I'm not going to split this in different commits because it could get up to 10 commits, it's really not worth it for a simple demo class. Highlights: o TCP sockets support o QMP events support o Add documentation o Fix a number of unhandled errors o Simplify methods that send commands to the Monitor Signed-off-by: Luiz Capitulino --- QMP/qmp.py | 161 +++++++++++++++++++++++++++++++++++------------------ 1 file changed, 108 insertions(+), 53 deletions(-) diff --git a/QMP/qmp.py b/QMP/qmp.py index 4062f84f36..14ce8b0d05 100644 --- a/QMP/qmp.py +++ b/QMP/qmp.py @@ -1,6 +1,6 @@ # QEMU Monitor Protocol Python class # -# Copyright (C) 2009 Red Hat Inc. +# Copyright (C) 2009, 2010 Red Hat Inc. # # Authors: # Luiz Capitulino @@ -8,7 +8,9 @@ # This work is licensed under the terms of the GNU GPL, version 2. See # the COPYING file in the top-level directory. -import socket, json +import json +import errno +import socket class QMPError(Exception): pass @@ -16,61 +18,114 @@ class QMPError(Exception): class QMPConnectError(QMPError): pass +class QMPCapabilitiesError(QMPError): + pass + class QEMUMonitorProtocol: - def connect(self): - self.sock.connect(self.filename) - data = self.__json_read() - if data == None: - raise QMPConnectError - if not data.has_key('QMP'): - raise QMPConnectError - return data['QMP']['capabilities'] + def __init__(self, address): + """ + Create a QEMUMonitorProtocol class. - def close(self): - self.sock.close() + @param address: QEMU address, can be either a unix socket path (string) + or a tuple in the form ( address, port ) for a TCP + connection + @note No connection is established, this is done by the connect() method + """ + self.__events = [] + self.__address = address + self.__sock = self.__get_sock() + self.__sockfile = self.__sock.makefile() - def send_raw(self, line): - self.sock.send(str(line)) - return self.__json_read() - - def send(self, cmdline): - cmd = self.__build_cmd(cmdline) - self.__json_send(cmd) - resp = self.__json_read() - if resp == None: - return - elif resp.has_key('error'): - return resp['error'] + def __get_sock(self): + if isinstance(self.__address, tuple): + family = socket.AF_INET else: - return resp['return'] - - def __build_cmd(self, cmdline): - cmdargs = cmdline.split() - qmpcmd = { 'execute': cmdargs[0], 'arguments': {} } - for arg in cmdargs[1:]: - opt = arg.split('=') - try: - value = int(opt[1]) - except ValueError: - value = opt[1] - qmpcmd['arguments'][opt[0]] = value - return qmpcmd - - def __json_send(self, cmd): - # XXX: We have to send any additional char, otherwise - # the Server won't read our input - self.sock.send(json.dumps(cmd) + ' ') + family = socket.AF_UNIX + return socket.socket(family, socket.SOCK_STREAM) def __json_read(self): - try: - while True: - line = json.loads(self.sockfile.readline()) - if not 'event' in line: - return line - except ValueError: - return + while True: + data = self.__sockfile.readline() + if not data: + return + resp = json.loads(data) + if 'event' in resp: + self.__events.append(resp) + continue + return resp - def __init__(self, filename): - self.filename = filename - self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) - self.sockfile = self.sock.makefile() + error = socket.error + + def connect(self): + """ + 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) + 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 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 get_events(self): + """ + Get a list of available QMP events. + """ + 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) + return self.__events + + def clear_events(self): + """ + Clear current list of pending events. + """ + self.__events = [] + + def close(self): + self.__sock.close() + self.__sockfile.close() From 9bed0d0d1c5667a2e1124c8e44d31ac254ca2efb Mon Sep 17 00:00:00 2001 From: Luiz Capitulino Date: Wed, 27 Oct 2010 17:57:51 -0200 Subject: [PATCH 2/7] QMP: Revamp the qmp-shell script This commit updates the qmp-shell script to use the new interface introduced by the last commit. Additionally, the following fixes/features are also introduced: o TCP sockets support o Update/add documentation o Simple command-line completion o Fix a number of unhandled errors Signed-off-by: Luiz Capitulino --- QMP/qmp-shell | 179 ++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 144 insertions(+), 35 deletions(-) diff --git a/QMP/qmp-shell b/QMP/qmp-shell index a5b72d15d1..1fb7e767b0 100755 --- a/QMP/qmp-shell +++ b/QMP/qmp-shell @@ -1,8 +1,8 @@ #!/usr/bin/python # -# Simple QEMU shell on top of QMP +# Low-level QEMU shell on top of QMP. # -# Copyright (C) 2009 Red Hat Inc. +# Copyright (C) 2009, 2010 Red Hat Inc. # # Authors: # Luiz Capitulino @@ -14,60 +14,169 @@ # # Start QEMU with: # -# $ qemu [...] -monitor control,unix:./qmp,server +# # qemu [...] -qmp unix:./qmp-sock,server # # Run the shell: # -# $ qmp-shell ./qmp +# $ qmp-shell ./qmp-sock # # Commands have the following format: # -# < command-name > [ arg-name1=arg1 ] ... [ arg-nameN=argN ] +# < command-name > [ arg-name1=arg1 ] ... [ arg-nameN=argN ] # # For example: # -# (QEMU) info item=network +# (QEMU) device_add driver=e1000 id=net1 +# {u'return': {}} +# (QEMU) import qmp import readline -from sys import argv,exit +import sys -def shell_help(): - print 'bye exit from the shell' +class QMPCompleter(list): + def complete(self, text, state): + for cmd in self: + if cmd.startswith(text): + if not state: + return cmd + else: + state -= 1 -def main(): - if len(argv) != 2: - print 'qemu-shell ' - exit(1) +class QMPShellError(Exception): + pass - qemu = qmp.QEMUMonitorProtocol(argv[1]) - qemu.connect() - qemu.send("qmp_capabilities") +class QMPShellBadPort(QMPShellError): + pass - print 'Connected!' +# 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): + qmp.QEMUMonitorProtocol.__init__(self, self.__get_address(address)) + self._greeting = None + self._completer = None - while True: + 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: + value = int(opt[1]) + except ValueError: + value = opt[1] + qmpcmd['arguments'][opt[0]] = value + return qmpcmd + + def _execute_cmd(self, cmdline): try: - cmd = raw_input('(QEMU) ') + qmpcmd = self.__build_cmd(cmdline) + except: + print 'command format: ', + print '[arg-name1=arg1] ... [arg-nameN=argN]' + return True + resp = self.cmd_obj(qmpcmd) + if resp is None: + print 'Disconnected' + return False + 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 - break - if cmd == '': - continue - elif cmd == 'bye': - break - elif cmd == 'help': - shell_help() + return False + if cmdline == '': + for ev in self.get_events(): + print ev + self.clear_events() + return True else: - try: - resp = qemu.send(cmd) - if resp == None: - print 'Disconnected' - break - print resp - except IndexError: - print '-> command format: ', - print '[arg-name1=arg1] ... [arg-nameN=argN]' + return self._execute_cmd(cmdline) + +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 [ -H ] < UNIX socket path> | < TCP address:port >\n') + sys.exit(1) + +def main(): + try: + if len(sys.argv) == 2: + qemu = QMPShell(sys.argv[1]) + else: + 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' % sys.argv[1]) + + qemu.show_banner() + while qemu.read_exec_command('(QEMU) '): + pass + qemu.close() if __name__ == '__main__': main() From 4cdbc094ca3865696c1456f1586818766bf9aae6 Mon Sep 17 00:00:00 2001 From: Luiz Capitulino Date: Wed, 27 Oct 2010 18:03:01 -0200 Subject: [PATCH 3/7] QMP: Drop vm-info example script It's broken and not really useful, let's just drop it. Signed-off-by: Luiz Capitulino --- QMP/README | 5 +---- QMP/vm-info | 33 --------------------------------- 2 files changed, 1 insertion(+), 37 deletions(-) delete mode 100755 QMP/vm-info diff --git a/QMP/README b/QMP/README index 80503f2d7a..c95a08c234 100644 --- a/QMP/README +++ b/QMP/README @@ -19,10 +19,7 @@ o qmp-spec.txt QEMU Monitor 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 are also two simple Python scripts available: - -o qmp-shell A shell -o vm-info Show some information about the Virtual Machine +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. diff --git a/QMP/vm-info b/QMP/vm-info deleted file mode 100755 index be5b03843c..0000000000 --- a/QMP/vm-info +++ /dev/null @@ -1,33 +0,0 @@ -#!/usr/bin/python -# -# Print Virtual Machine information -# -# Usage: -# -# Start QEMU with: -# -# $ qemu [...] -monitor control,unix:./qmp,server -# -# Run vm-info: -# -# $ vm-info ./qmp -# -# Luiz Capitulino - -import qmp -from sys import argv,exit - -def main(): - if len(argv) != 2: - print 'vm-info ' - exit(1) - - qemu = qmp.QEMUMonitorProtocol(argv[1]) - qemu.connect() - qemu.send("qmp_capabilities") - - for cmd in [ 'version', 'kvm', 'status', 'uuid', 'balloon' ]: - print cmd + ': ' + str(qemu.send('query-' + cmd)) - -if __name__ == '__main__': - main() From 999bd67c879cbd8bf0fe2b4ff0fb308a9a48ec72 Mon Sep 17 00:00:00 2001 From: Luiz Capitulino Date: Fri, 22 Oct 2010 16:09:05 -0200 Subject: [PATCH 4/7] qemu-char: Introduce Memory driver This driver handles in-memory chardev operations. That's, all writes to this driver are stored in an internal buffer and it doesn't talk to the external world in any way. Right now it's very simple: it supports only writes. But it can be easily extended to support more operations. This is going to be used by the monitor's "HMP passthrough via QMP" feature, which needs to run monitor handlers without a backing device. Signed-off-by: Luiz Capitulino --- qemu-char.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++++ qemu-char.h | 7 ++++++ 2 files changed, 71 insertions(+) diff --git a/qemu-char.c b/qemu-char.c index 88997f9d5a..edc9ad6851 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -2275,6 +2275,70 @@ static CharDriverState *qemu_chr_open_socket(QemuOpts *opts) return NULL; } +/***********************************************************/ +/* Memory chardev */ +typedef struct { + size_t outbuf_size; + size_t outbuf_capacity; + uint8_t *outbuf; +} MemoryDriver; + +static int mem_chr_write(CharDriverState *chr, const uint8_t *buf, int len) +{ + MemoryDriver *d = chr->opaque; + + /* TODO: the QString implementation has the same code, we should + * introduce a generic way to do this in cutils.c */ + if (d->outbuf_capacity < d->outbuf_size + len) { + /* grow outbuf */ + d->outbuf_capacity += len; + d->outbuf_capacity *= 2; + d->outbuf = qemu_realloc(d->outbuf, d->outbuf_capacity); + } + + memcpy(d->outbuf + d->outbuf_size, buf, len); + d->outbuf_size += len; + + return len; +} + +void qemu_chr_init_mem(CharDriverState *chr) +{ + MemoryDriver *d; + + d = qemu_malloc(sizeof(*d)); + d->outbuf_size = 0; + d->outbuf_capacity = 4096; + d->outbuf = qemu_mallocz(d->outbuf_capacity); + + memset(chr, 0, sizeof(*chr)); + chr->opaque = d; + chr->chr_write = mem_chr_write; +} + +QString *qemu_chr_mem_to_qs(CharDriverState *chr) +{ + MemoryDriver *d = chr->opaque; + return qstring_from_substr((char *) d->outbuf, 0, d->outbuf_size - 1); +} + +/* NOTE: this driver can not be closed with qemu_chr_close()! */ +void qemu_chr_close_mem(CharDriverState *chr) +{ + MemoryDriver *d = chr->opaque; + + qemu_free(d->outbuf); + qemu_free(chr->opaque); + chr->opaque = NULL; + chr->chr_write = NULL; +} + +size_t qemu_chr_mem_osize(const CharDriverState *chr) +{ + const MemoryDriver *d = chr->opaque; + return d->outbuf_size; +} + QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename) { char host[65], port[33], width[8], height[8]; diff --git a/qemu-char.h b/qemu-char.h index 18ad12bb5d..e6ee6c4bc9 100644 --- a/qemu-char.h +++ b/qemu-char.h @@ -6,6 +6,7 @@ #include "qemu-option.h" #include "qemu-config.h" #include "qobject.h" +#include "qstring.h" /* character device */ @@ -100,6 +101,12 @@ CharDriverState *qemu_chr_open_eventfd(int eventfd); extern int term_escape_char; +/* memory chardev */ +void qemu_chr_init_mem(CharDriverState *chr); +void qemu_chr_close_mem(CharDriverState *chr); +QString *qemu_chr_mem_to_qs(CharDriverState *chr); +size_t qemu_chr_mem_osize(const CharDriverState *chr); + /* async I/O support */ int qemu_set_fd_handler2(int fd, From 0268d97c51207f35a5a01239ad92ef2c35dcd5ba Mon Sep 17 00:00:00 2001 From: Luiz Capitulino Date: Fri, 22 Oct 2010 10:08:02 -0200 Subject: [PATCH 5/7] QMP: Introduce Human Monitor passthrough command This command allows QMP clients to execute HMP commands. Please, check the documentation added to the qmp-commands.hx file for additional details about the interface and its limitations. Signed-off-by: Luiz Capitulino --- monitor.c | 38 ++++++++++++++++++++++++++++++++++++++ qmp-commands.hx | 45 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+) diff --git a/monitor.c b/monitor.c index 8cee35d77a..ec31eac8c1 100644 --- a/monitor.c +++ b/monitor.c @@ -491,6 +491,44 @@ static int do_qmp_capabilities(Monitor *mon, const QDict *params, return 0; } +static int mon_set_cpu(int cpu_index); +static void handle_user_command(Monitor *mon, const char *cmdline); + +static int do_hmp_passthrough(Monitor *mon, const QDict *params, + QObject **ret_data) +{ + int ret = 0; + Monitor *old_mon, hmp; + CharDriverState mchar; + + memset(&hmp, 0, sizeof(hmp)); + qemu_chr_init_mem(&mchar); + hmp.chr = &mchar; + + old_mon = cur_mon; + cur_mon = &hmp; + + if (qdict_haskey(params, "cpu-index")) { + ret = mon_set_cpu(qdict_get_int(params, "cpu-index")); + if (ret < 0) { + cur_mon = old_mon; + qerror_report(QERR_INVALID_PARAMETER_VALUE, "cpu-index", "a CPU number"); + goto out; + } + } + + handle_user_command(&hmp, qdict_get_str(params, "command-line")); + cur_mon = old_mon; + + if (qemu_chr_mem_osize(hmp.chr) > 0) { + *ret_data = QOBJECT(qemu_chr_mem_to_qs(hmp.chr)); + } + +out: + qemu_chr_close_mem(hmp.chr); + return ret; +} + static int compare_cmd(const char *name, const char *list) { const char *p, *pstart; diff --git a/qmp-commands.hx b/qmp-commands.hx index 793cf1c0f9..e5f157fe10 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -761,6 +761,51 @@ Example: Note: This command must be issued before issuing any other command. +EQMP + + { + .name = "human-monitor-command", + .args_type = "command-line:s,cpu-index:i?", + .params = "", + .help = "", + .user_print = monitor_user_noop, + .mhandler.cmd_new = do_hmp_passthrough, + }, + +SQMP +human-monitor-command +--------------------- + +Execute a Human Monitor command. + +Arguments: + +- command-line: the command name and its arguments, just like the + Human Monitor's shell (json-string) +- cpu-index: select the CPU number to be used by commands which access CPU + data, like 'info registers'. The Monitor selects CPU 0 if this + argument is not provided (json-int, optional) + +Example: + +-> { "execute": "human-monitor-command", "arguments": { "command-line": "info kvm" } } +<- { "return": "kvm support: enabled\r\n" } + +Notes: + +(1) The Human Monitor is NOT an stable interface, this means that command + names, arguments and responses can change or be removed at ANY time. + Applications that rely on long term stability guarantees should NOT + use this command + +(2) Limitations: + + o This command is stateless, this means that commands that depend + on state information (such as getfd) might not work + + o Commands that prompt the user for data (eg. 'cont' when the block + device is encrypted) don't currently work + 3. Query Commands ================= From 11217a757e7dda66fd2e78b10ea0cd8d6b290e42 Mon Sep 17 00:00:00 2001 From: Luiz Capitulino Date: Thu, 28 Oct 2010 13:28:37 -0200 Subject: [PATCH 6/7] QMP/qmp-shell: Introduce HMP mode In which qmp-shell will exclusively use the HMP passthrough feature, this is useful for testing. Example: # ./qmp-shell -H qmp-sock Welcome to the HMP shell! Connected to QEMU 0.13.50 (QEMU) info network VLAN 0 devices: user.0: net=10.0.2.0, restricted=n e1000.0: model=e1000,macaddr=52:54:00:12:34:56 Devices not on any VLAN: (QEMU) Signed-off-by: Luiz Capitulino --- QMP/qmp-shell | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 78 insertions(+), 1 deletion(-) diff --git a/QMP/qmp-shell b/QMP/qmp-shell index 1fb7e767b0..42dabc8c6d 100755 --- a/QMP/qmp-shell +++ b/QMP/qmp-shell @@ -145,6 +145,76 @@ class QMPShell(qmp.QEMUMonitorProtocol): else: return self._execute_cmd(cmdline) +class HMPShell(QMPShell): + def __init__(self, address): + QMPShell.__init__(self, address) + self.__cpu_index = 0 + + def __cmd_completion(self): + for cmd in self.__cmd_passthrough('help')['return'].split('\r\n'): + if cmd and cmd[0] != '[' and cmd[0] != '\t': + name = cmd.split()[0] # drop help text + if name == 'info': + continue + if name.find('|') != -1: + # Command in the form 'foobar|f' or 'f|foobar', take the + # full name + opt = name.split('|') + if len(opt[0]) == 1: + name = opt[1] + else: + name = opt[0] + self._completer.append(name) + self._completer.append('help ' + name) # help completion + + def __info_completion(self): + for cmd in self.__cmd_passthrough('info')['return'].split('\r\n'): + if cmd: + self._completer.append('info ' + cmd.split()[1]) + + def __other_completion(self): + # special cases + self._completer.append('help info') + + def _fill_completion(self): + self.__cmd_completion() + self.__info_completion() + self.__other_completion() + + def __cmd_passthrough(self, cmdline, cpu_index = 0): + return self.cmd_obj({ 'execute': 'human-monitor-command', 'arguments': + { 'command-line': cmdline, + 'cpu-index': cpu_index } }) + + def _execute_cmd(self, cmdline): + if cmdline.split()[0] == "cpu": + # trap the cpu command, it requires special setting + try: + idx = int(cmdline.split()[1]) + if not 'return' in self.__cmd_passthrough('info version', idx): + print 'bad CPU index' + return True + self.__cpu_index = idx + except ValueError: + print 'cpu command takes an integer argument' + return True + resp = self.__cmd_passthrough(cmdline, self.__cpu_index) + if resp is None: + print 'Disconnected' + return False + assert 'return' in resp or 'error' in resp + if 'return' in resp: + # Success + if len(resp['return']) > 0: + print resp['return'], + else: + # Error + print '%s: %s' % (resp['error']['class'], resp['error']['desc']) + return True + + def show_banner(self): + QMPShell.show_banner(self, msg='Welcome to the HMP shell!') + def die(msg): sys.stderr.write('ERROR: %s\n' % msg) sys.exit(1) @@ -156,9 +226,16 @@ def fail_cmdline(option=None): sys.exit(1) def main(): + addr = '' try: if len(sys.argv) == 2: qemu = QMPShell(sys.argv[1]) + addr = sys.argv[1] + elif len(sys.argv) == 3: + if sys.argv[1] != '-H': + fail_cmdline(sys.argv[1]) + qemu = HMPShell(sys.argv[2]) + addr = sys.argv[2] else: fail_cmdline() except QMPShellBadPort: @@ -171,7 +248,7 @@ def main(): except qmp.QMPCapabilitiesError: die('Could not negotiate capabilities') except qemu.error: - die('Could not connect to %s' % sys.argv[1]) + die('Could not connect to %s' % addr) qemu.show_banner() while qemu.read_exec_command('(QEMU) '): From a6f9dd02f75685934ca52f038b6fcb38b661c283 Mon Sep 17 00:00:00 2001 From: Luiz Capitulino Date: Wed, 10 Nov 2010 15:59:57 -0200 Subject: [PATCH 7/7] Makefile: Fix check dependency breakage Commit b152aa84d52882bb1846485a89baf13aa07c86bc broke the unit-tests build, fix it. Signed-off-by: Luiz Capitulino --- Makefile | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index 747e47c834..4e120a2d3a 100644 --- a/Makefile +++ b/Makefile @@ -163,12 +163,14 @@ qemu-img-cmds.h: $(SRC_PATH)/qemu-img-cmds.hx check-qint.o check-qstring.o check-qdict.o check-qlist.o check-qfloat.o check-qjson.o: $(GENERATED_HEADERS) -check-qint: check-qint.o qint.o qemu-malloc.o $(trace-obj-y) -check-qstring: check-qstring.o qstring.o qemu-malloc.o $(trace-obj-y) -check-qdict: check-qdict.o qdict.o qfloat.o qint.o qstring.o qbool.o qemu-malloc.o qlist.o $(trace-obj-y) -check-qlist: check-qlist.o qlist.o qint.o qemu-malloc.o $(trace-obj-y) -check-qfloat: check-qfloat.o qfloat.o qemu-malloc.o $(trace-obj-y) -check-qjson: check-qjson.o qfloat.o qint.o qdict.o qstring.o qlist.o qbool.o qjson.o json-streamer.o json-lexer.o json-parser.o qemu-malloc.o $(trace-obj-y) +CHECK_PROG_DEPS = qemu-malloc.o $(oslib-obj-y) $(trace-obj-y) + +check-qint: check-qint.o qint.o $(CHECK_PROG_DEPS) +check-qstring: check-qstring.o qstring.o $(CHECK_PROG_DEPS) +check-qdict: check-qdict.o qdict.o qfloat.o qint.o qstring.o qbool.o qlist.o $(CHECK_PROG_DEPS) +check-qlist: check-qlist.o qlist.o qint.o $(CHECK_PROG_DEPS) +check-qfloat: check-qfloat.o qfloat.o $(CHECK_PROG_DEPS) +check-qjson: check-qjson.o qfloat.o qint.o qdict.o qstring.o qlist.o qbool.o qjson.o json-streamer.o json-lexer.o json-parser.o $(CHECK_PROG_DEPS) clean: # avoid old build problems by removing potentially incorrect old files