[Spice-devel] [PATCH 24/35] [wip] spice: client migration.

alexl at redhat.com alexl at redhat.com
Thu Sep 9 10:16:07 PDT 2010


From: Gerd Hoffmann <kraxel at redhat.com>

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.
---
 monitor.c       |    1 +
 qemu-monitor.hx |   11 +++++++
 ui/qemu-spice.h |    2 +
 ui/spice-core.c |   91 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 105 insertions(+), 0 deletions(-)

diff --git a/monitor.c b/monitor.c
index e27f8d8..61d12ec 100644
--- a/monitor.c
+++ b/monitor.c
@@ -56,6 +56,7 @@
 #include "json-parser.h"
 #include "osdep.h"
 #include "exec-all.h"
+#include "ui/qemu-spice.h"
 
 //#define DEBUG
 //#define DEBUG_COMPLETION
diff --git a/qemu-monitor.hx b/qemu-monitor.hx
index 5c1da33..dc7f407 100644
--- a/qemu-monitor.hx
+++ b/qemu-monitor.hx
@@ -2531,6 +2531,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/ui/qemu-spice.h b/ui/qemu-spice.h
index 0e3ad9b..79001cf 100644
--- a/ui/qemu-spice.h
+++ b/ui/qemu-spice.h
@@ -33,6 +33,8 @@ void qemu_spice_audio_init(void);
 void qemu_spice_display_init(DisplayState *ds);
 int qemu_spice_add_interface(SpiceBaseInstance *sin);
 
+int mon_spice_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data);
+
 #else  /* CONFIG_SPICE */
 
 #define using_spice 0
diff --git a/ui/spice-core.c b/ui/spice-core.c
index 7d43f7e..688a60c 100644
--- a/ui/spice-core.c
+++ b/ui/spice-core.c
@@ -24,6 +24,7 @@
 #include "qemu-queue.h"
 #include "qemu-x509.h"
 #include "monitor.h"
+#include "hw/hw.h"
 
 /* core bits */
 
@@ -202,8 +203,92 @@ static const char *wan_compression_names[] = {
     parse_name(_name, "wan compression",                                \
                wan_compression_names, ARRAY_SIZE(wan_compression_names))
 
+#if 0
+/* 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;
+}
+#endif
+
 /* 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);
+}
+
 static int add_channel(const char *name, const char *value, void *opaque)
 {
     int security = 0;
@@ -360,6 +445,12 @@ void qemu_spice_init(void)
     qemu_spice_input_init();
     qemu_spice_audio_init();
 
+#if 0
+    register_savevm_live(NULL, "spice", -1, 1, NULL,
+                         spice_live, spice_save, spice_load,
+                         spice_server);
+#endif
+
     qemu_free(x509_key_file);
     qemu_free(x509_cert_file);
     qemu_free(x509_cacert_file);
-- 
1.7.0.1



More information about the Spice-devel mailing list