diff options
author | Anthony Liguori <aliguori@us.ibm.com> | 2010-10-11 19:01:41 -0500 |
---|---|---|
committer | Anthony Liguori <aliguori@us.ibm.com> | 2010-10-11 19:01:41 -0500 |
commit | a62e5f41204e71f375a5ba0f93f06b699003f694 (patch) | |
tree | 978d47f0488c63699a972888c6e6bb754871fe8b | |
parent | c2ccc98ceb07c009d64b7ee801f8966194510021 (diff) | |
parent | a0a90b92c94607c04a915d2a47c19e2cc5e85f85 (diff) | |
download | qemu-a62e5f41204e71f375a5ba0f93f06b699003f694.zip qemu-a62e5f41204e71f375a5ba0f93f06b699003f694.tar.gz qemu-a62e5f41204e71f375a5ba0f93f06b699003f694.tar.bz2 |
Merge remote branch 'qmp/for-stable-0.13' into stable-0.13
-rw-r--r-- | QMP/README | 73 | ||||
-rw-r--r-- | arch_init.c | 7 | ||||
-rw-r--r-- | buffered_file.c | 4 | ||||
-rw-r--r-- | migration.c | 10 | ||||
-rw-r--r-- | monitor.c | 27 | ||||
-rw-r--r-- | qemu-monitor.hx | 42 | ||||
-rw-r--r-- | qerror.c | 4 | ||||
-rw-r--r-- | qerror.h | 3 | ||||
-rw-r--r-- | sysemu.h | 1 | ||||
-rw-r--r-- | vl.c | 2 |
10 files changed, 137 insertions, 36 deletions
@@ -7,60 +7,85 @@ Introduction The QEMU Monitor Protocol (QMP) allows applications to communicate with QEMU's Monitor. -QMP is JSON[1] based and has the following features: +QMP is JSON[1] based and currently has the following features: - Lightweight, text-based, easy to parse data format -- Asynchronous events support -- Stability +- Asynchronous messages support (ie. events) +- Capabilities Negotiation -For more information, please, refer to the following files: +For detailed information on QMP's usage, please, refer to the following files: o qmp-spec.txt QEMU Monitor Protocol current specification -o qmp-commands.txt QMP supported commands +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 +o qmp-shell A shell +o vm-info Show some information about the Virtual Machine + +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, QEMU has to be started in "control mode". There are -two ways of doing this, the simplest one is using the the '-qmp' -command-line option. +To enable QMP, you need a QEMU monitor instance in "control mode". There are +two ways of doing this. + +The simplest one is using the '-qmp' command-line option. The following +example makes QMP available on localhost port 4444: -For example: + $ qemu [...] -qmp tcp:localhost:4444,server -$ qemu [...] -qmp tcp:localhost:4444,server +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. -Will start QEMU in control mode, waiting for a client TCP connection -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 -It is also possible to use the '-mon' command-line option to have -more complex combinations. Please, refer to the QEMU's manpage for -more information. +Please, refer to QEMU's manpage for more information. Simple Testing -------------- -To manually test QMP one can connect with telnet and issue commands: +To manually test QMP one can connect with telnet and issue commands by hand: $ telnet localhost 4444 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. -{"QMP": {"version": {"qemu": "0.12.50", "package": ""}, "capabilities": []}} +{"QMP": {"version": {"qemu": {"micro": 50, "minor": 13, "major": 0}, "package": ""}, "capabilities": []}} { "execute": "qmp_capabilities" } {"return": {}} { "execute": "query-version" } -{"return": {"qemu": "0.12.50", "package": ""}} +{"return": {"qemu": {"micro": 50, "minor": 13, "major": 0}, "package": ""}} + +Development Process +------------------- + +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 qemu-monitor.hx one, which + is the file that should be edited. -Contact -------- +Homepage +-------- -http://www.linux-kvm.org/page/MonitorProtocol -Luiz Fernando N. Capitulino <lcapitulino@redhat.com> +http://wiki.qemu.org/QMP diff --git a/arch_init.c b/arch_init.c index 47bb4b2..e0bd18c 100644 --- a/arch_init.c +++ b/arch_init.c @@ -104,10 +104,11 @@ static int is_dup_page(uint8_t *page, uint8_t ch) return 1; } +static RAMBlock *last_block; +static ram_addr_t last_offset; + static int ram_save_block(QEMUFile *f) { - static RAMBlock *last_block = NULL; - static ram_addr_t last_offset = 0; RAMBlock *block = last_block; ram_addr_t offset = last_offset; ram_addr_t current_addr; @@ -231,6 +232,8 @@ int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque) if (stage == 1) { RAMBlock *block; bytes_transferred = 0; + last_block = NULL; + last_offset = 0; /* Make sure all dirty bits are set */ QLIST_FOREACH(block, &ram_list.blocks, next) { diff --git a/buffered_file.c b/buffered_file.c index a79264f..1836e7e 100644 --- a/buffered_file.c +++ b/buffered_file.c @@ -230,8 +230,10 @@ static void buffered_rate_tick(void *opaque) { QEMUFileBuffered *s = opaque; - if (s->has_error) + if (s->has_error) { + buffered_close(s); return; + } qemu_mod_timer(s->timer, qemu_get_clock(rt_clock) + 100); diff --git a/migration.c b/migration.c index 650eb78..468d517 100644 --- a/migration.c +++ b/migration.c @@ -67,6 +67,8 @@ void process_incoming_migration(QEMUFile *f) qemu_announce_self(); DPRINTF("successfully loaded vm state\n"); + incoming_expected = false; + if (autostart) vm_start(); } @@ -314,8 +316,14 @@ ssize_t migrate_fd_put_buffer(void *opaque, const void *data, size_t size) if (ret == -1) ret = -(s->get_error(s)); - if (ret == -EAGAIN) + if (ret == -EAGAIN) { qemu_set_fd_handler2(s->fd, NULL, NULL, migrate_fd_put_notify, s); + } else if (ret < 0) { + if (s->mon) { + monitor_resume(s->mon); + } + s->state = MIG_STATE_ERROR; + } return ret; } @@ -669,17 +669,32 @@ help: static void do_info_version_print(Monitor *mon, const QObject *data) { QDict *qdict; + QDict *qemu; qdict = qobject_to_qdict(data); + qemu = qdict_get_qdict(qdict, "qemu"); - monitor_printf(mon, "%s%s\n", qdict_get_str(qdict, "qemu"), - qdict_get_str(qdict, "package")); + monitor_printf(mon, "%" PRId64 ".%" PRId64 ".%" PRId64 "%s\n", + qdict_get_int(qemu, "major"), + qdict_get_int(qemu, "minor"), + qdict_get_int(qemu, "micro"), + qdict_get_str(qdict, "package")); } static void do_info_version(Monitor *mon, QObject **ret_data) { - *ret_data = qobject_from_jsonf("{ 'qemu': %s, 'package': %s }", - QEMU_VERSION, QEMU_PKGVERSION); + const char *version = QEMU_VERSION; + int major = 0, minor = 0, micro = 0; + char *tmp; + + major = strtol(version, &tmp, 10); + tmp++; + minor = strtol(tmp, &tmp, 10); + tmp++; + micro = strtol(tmp, &tmp, 10); + + *ret_data = qobject_from_jsonf("{ 'qemu': { 'major': %d, 'minor': %d, \ + 'micro': %d }, 'package': %s }", major, minor, micro, QEMU_PKGVERSION); } static void do_info_name_print(Monitor *mon, const QObject *data) @@ -1056,6 +1071,10 @@ static int do_cont(Monitor *mon, const QDict *qdict, QObject **ret_data) { struct bdrv_iterate_context context = { mon, 0 }; + if (incoming_expected) { + qerror_report(QERR_MIGRATION_EXPECTED); + return -1; + } bdrv_iterate(encrypted_bdrv_it, &context); /* only resume the vm if all keys are set and valid */ if (!context.err) { diff --git a/qemu-monitor.hx b/qemu-monitor.hx index 2af3de6..5c1da33 100644 --- a/qemu-monitor.hx +++ b/qemu-monitor.hx @@ -35,7 +35,29 @@ information on the Server command and response formats. NOTE: This document is temporary and will be replaced soon. -1. Regular Commands +1. Stability Considerations +=========================== + +The current QMP command set (described in this file) may be useful for a +number of use cases, however it's limited and several commands have bad +defined semantics, specially with regard to command completion. + +These problems are going to be solved incrementally in the next QEMU releases +and we're going to establish a deprecation policy for badly defined commands. + +If you're planning to adopt QMP, please observe the following: + + 1. The deprecation policy will take efect and be documented soon, please + check the documentation of each used command as soon as a new release of + QEMU is available + + 2. DO NOT rely on anything which is not explicit documented + + 3. Errors, in special, are not documented. Applications should NOT check + for specific errors classes or data (it's strongly recommended to only + check for the "error" key) + +2. Regular Commands =================== Server's responses in the examples below are always a success response, please @@ -1592,7 +1614,7 @@ HXCOMM This is required for the QMP documentation layout. SQMP -2. Query Commands +3. Query Commands ================= EQMP @@ -1623,13 +1645,25 @@ Show QEMU version. Return a json-object with the following information: -- "qemu": QEMU's version (json-string) +- "qemu": A json-object containing three integer values: + - "major": QEMU's major version (json-int) + - "minor": QEMU's minor version (json-int) + - "micro": QEMU's micro version (json-int) - "package": package's version (json-string) Example: -> { "execute": "query-version" } -<- { "return": { "qemu": "0.11.50", "package": "" } } +<- { + "return":{ + "qemu":{ + "major":0, + "minor":11, + "micro":5 + }, + "package":"" + } + } EQMP @@ -141,6 +141,10 @@ static const QErrorStringTable qerror_table[] = { .desc = "Using KVM without %(capability), %(feature) unavailable", }, { + .error_fmt = QERR_MIGRATION_EXPECTED, + .desc = "An incoming migration is expected before this command can be executed", + }, + { .error_fmt = QERR_MISSING_PARAMETER, .desc = "Parameter '%(name)' is missing", }, @@ -121,6 +121,9 @@ QError *qobject_to_qerror(const QObject *obj); #define QERR_KVM_MISSING_CAP \ "{ 'class': 'KVMMissingCap', 'data': { 'capability': %s, 'feature': %s } }" +#define QERR_MIGRATION_EXPECTED \ + "{ 'class': 'MigrationExpected', 'data': {} }" + #define QERR_MISSING_PARAMETER \ "{ 'class': 'MissingParameter', 'data': { 'name': %s } }" @@ -99,6 +99,7 @@ typedef enum DisplayType } DisplayType; extern int autostart; +extern int incoming_expected; extern int bios_size; typedef enum { @@ -182,6 +182,7 @@ int nb_nics; NICInfo nd_table[MAX_NICS]; int vm_running; int autostart; +int incoming_expected; /* Started with -incoming and waiting for incoming */ static int rtc_utc = 1; static int rtc_date_offset = -1; /* -1 means no change */ QEMUClock *rtc_clock; @@ -2557,6 +2558,7 @@ int main(int argc, char **argv, char **envp) break; case QEMU_OPTION_incoming: incoming = optarg; + incoming_expected = true; break; case QEMU_OPTION_nodefaults: default_serial = 0; |