diff options
author | Gerd Hoffmann <kraxel@redhat.com> | 2010-04-23 13:28:21 +0200 |
---|---|---|
committer | Gerd Hoffmann <kraxel@redhat.com> | 2010-08-04 17:15:52 +0200 |
commit | 91db0417ac64255a297d88543bc91b439a48c013 (patch) | |
tree | 115e51cc207bf6bb74debfce0d89cb0632b21ddf | |
parent | 1b4ac7632a8337526555b91a9148ebfa5928c88a (diff) |
spice: live migration (wip).
Handle spice client migration, i.e. inform a spice client connected
about the new host and connection parameters, so it can move over the
connection automatically.
-rw-r--r-- | monitor.c | 1 | ||||
-rw-r--r-- | qemu-monitor.hx | 11 | ||||
-rw-r--r-- | qemu-spice.h | 2 | ||||
-rw-r--r-- | spice.c | 87 |
4 files changed, 101 insertions, 0 deletions
@@ -56,6 +56,7 @@ #include "json-parser.h" #include "osdep.h" #include "exec-all.h" +#include "qemu-spice.h" //#define DEBUG //#define DEBUG_COMPLETION diff --git a/qemu-monitor.hx b/qemu-monitor.hx index 2af3de6c2..f8c38a9f6 100644 --- a/qemu-monitor.hx +++ b/qemu-monitor.hx @@ -2497,6 +2497,17 @@ ETEXI HXCOMM DO NOT add new commands after 'info', move your addition before it! +#if defined(CONFIG_SPICE) + { + .name = "spice_migrate_info", + .args_type = "hostname:s,port:i?,tls-port:i?,cert-subject:s?", + .params = "hostname port tls-port cert-subject", + .help = "send migration info to spice client", + .user_print = monitor_user_noop, + .mhandler.cmd_new = mon_spice_migrate, + }, +#endif + STEXI @end table ETEXI diff --git a/qemu-spice.h b/qemu-spice.h index 6f19ba731..3c8e959bf 100644 --- a/qemu-spice.h +++ b/qemu-spice.h @@ -16,6 +16,8 @@ void qemu_spice_input_init(void); void qemu_spice_audio_init(void); void qemu_spice_display_init(DisplayState *ds); +int mon_spice_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data); + #else /* CONFIG_SPICE */ #define using_spice 0 @@ -11,6 +11,7 @@ #include "qemu-queue.h" #include "qemu-x509.h" #include "monitor.h" +#include "hw/hw.h" /* core bits */ @@ -172,8 +173,90 @@ static const char *wan_compression_names[] = { parse_name(_name, "wan compression", \ wan_compression_names, ARRAY_SIZE(wan_compression_names)) +/* handle client migration */ + +static int spice_live(Monitor *mon, QEMUFile *f, int stage, void *opaque) +{ + static int last_stage; + static int migrate_client, client_connected; + int ret = 1; + + if (last_stage != stage) { + last_stage = stage; + fprintf(stderr, "%s: stage %d\n", __FUNCTION__, stage); + } else { + fprintf(stderr, "."); + } + + switch (stage) { + case 1: + migrate_client = 1; + client_connected = 0; + fprintf(stderr, "%s: start client migration\n", __FUNCTION__); + if (spice_server_migrate_start(spice_server) != 0) { + fprintf(stderr, "%s: fail -> no client migration\n", __FUNCTION__); + migrate_client = 0; + } + break; + case 2: + if (!migrate_client) + break; + switch (spice_server_migrate_client_state(spice_server)) { + case SPICE_MIGRATE_CLIENT_NONE: + fprintf(stderr, "%s: no client connected\n", __FUNCTION__); + migrate_client = 0; + break; + case SPICE_MIGRATE_CLIENT_WAITING: + ret = 0; + break; + case SPICE_MIGRATE_CLIENT_READY: + if (!client_connected) { + fprintf(stderr, "%s: client connected to target\n", __FUNCTION__); + client_connected = 1; + } + break; + } + break; + case 3: + if (migrate_client && client_connected) { + fprintf(stderr, "%s: finish client migration\n", __FUNCTION__); + spice_server_migrate_end(spice_server, 1); + } + break; + } + return ret; +} + +static void spice_save(QEMUFile *f, void *opaque) +{ + fprintf(stderr, "%s:\n", __FUNCTION__); +} + +static int spice_load(QEMUFile *f, void *opaque, int version_id) +{ + fprintf(stderr, "%s:\n", __FUNCTION__); + return 0; +} + /* functions for the rest of qemu */ +int mon_spice_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data) +{ + const char *hostname = qdict_get_str(qdict, "hostname"); + const char *subject = qdict_get_try_str(qdict, "cert-subject"); + int port = qdict_get_try_int(qdict, "port", -1); + int tls_port = qdict_get_try_int(qdict, "tls-port", -1); + + if (!spice_server) { + qerror_report(QERR_DEVICE_NOT_ACTIVE, "spice"); + return -1; + } + + /* TODO: Convert to QError */ + return spice_server_migrate_info(spice_server, hostname, + port, tls_port, subject); +} + void qemu_spice_init(void) { QemuOpts *opts = QTAILQ_FIRST(&qemu_spice_opts.head); @@ -276,6 +359,10 @@ void qemu_spice_init(void) qemu_spice_input_init(); qemu_spice_audio_init(); + register_savevm_live(NULL, "spice", -1, 1, NULL, + spice_live, spice_save, spice_load, + spice_server); + qemu_free(x509_key_file); qemu_free(x509_cert_file); qemu_free(x509_cacert_file); |