Use the graphics information from the QEMU migration cookie to
issue a 'client_migrate_info' monitor command to QEMU. This causes
the SPICE client to automatically reconnect to the target host
when migration completes
* src/qemu/qemu_migration.c: Set data for SPICE client relocation
before starting migration on src
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h,
src/qemu/qemu_monitor_json.c, src/qemu/qemu_monitor_json.h,
src/qemu/qemu_monitor_text.c, src/qemu/qemu_monitor_text.h: Add
new qemuMonitorGraphicsRelocate() command
---
src/qemu/qemu_migration.c | 39 +++++++++++++++++++++++++++++++++++++++
src/qemu/qemu_monitor.c | 31 +++++++++++++++++++++++++++++++
src/qemu/qemu_monitor.h | 6 ++++++
src/qemu/qemu_monitor_json.c | 32 ++++++++++++++++++++++++++++++++
src/qemu/qemu_monitor_json.h | 7 +++++++
src/qemu/qemu_monitor_text.c | 31 +++++++++++++++++++++++++++++++
src/qemu/qemu_monitor_text.h | 7 +++++++
7 files changed, 153 insertions(+), 0 deletions(-)
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index dcc187e..5830077 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -740,6 +740,39 @@ cleanup:
}
+static int
+qemuDomainMigrateGraphicsRelocate(struct qemud_driver *driver,
+ virDomainObjPtr vm,
+ qemuMigrationCookiePtr cookie)
+{
+ qemuDomainObjPrivatePtr priv = vm->privateData;
+ int ret;
+
+ if (!cookie)
+ return 0;
+
+ if (!cookie->graphics)
+ return 0;
+
+ /* QEMU doesn't support VNC relocation yet, so
+ * skip it to avoid generating an error
+ */
+ if (cookie->graphics->type != VIR_DOMAIN_GRAPHICS_TYPE_SPICE)
+ return 0;
+
+ qemuDomainObjEnterMonitorWithDriver(driver, vm);
+ ret = qemuMonitorGraphicsRelocate(priv->mon,
+ cookie->graphics->type,
+ cookie->hostname,
+ cookie->graphics->port,
+ cookie->graphics->tlsPort,
+ cookie->graphics->tlsSubject);
+ qemuDomainObjExitMonitorWithDriver(driver, vm);
+
+ return ret;
+}
+
+
/* Prepare is the first step, and it runs on the destination host.
*
* This version starts an empty VM listening on a localhost TCP port, and
@@ -1127,6 +1160,9 @@ static int doNativeMigrate(struct qemud_driver *driver,
QEMU_MIGRATION_COOKIE_GRAPHICS)))
goto cleanup;
+ if (qemuDomainMigrateGraphicsRelocate(driver, vm, mig) < 0)
+ VIR_WARN("unable to provide data for graphics client relocation");
+
/* Issue the migrate command. */
if (STRPREFIX(uri, "tcp:") && !STRPREFIX(uri, "tcp://"))
{
/* HACK: source host generates bogus URIs, so fix them up */
@@ -1259,6 +1295,9 @@ static int doTunnelMigrate(struct qemud_driver *driver,
* 3. start migration on source
*/
+ /*
+ * XXX need to support migration cookies
+ */
/* Stage 1. setup local support infrastructure */
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index f031514..15c6cab 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -1620,6 +1620,37 @@ int qemuMonitorMigrateCancel(qemuMonitorPtr mon)
return ret;
}
+
+int qemuMonitorGraphicsRelocate(qemuMonitorPtr mon,
+ int type,
+ const char *hostname,
+ int port,
+ int tlsPort,
+ const char *tlsSubject)
+{
+ int ret;
+ VIR_DEBUG("mon=%p type=%d hostname=%s port=%d tlsPort=%d tlsSubject=%s",
+ mon, type, hostname, port, tlsPort, NULLSTR(tlsSubject));
+
+ if (mon->json)
+ ret = qemuMonitorJSONGraphicsRelocate(mon,
+ type,
+ hostname,
+ port,
+ tlsPort,
+ tlsSubject);
+ else
+ ret = qemuMonitorTextGraphicsRelocate(mon,
+ type,
+ hostname,
+ port,
+ tlsPort,
+ tlsSubject);
+
+ return ret;
+}
+
+
int qemuMonitorAddUSBDisk(qemuMonitorPtr mon,
const char *path)
{
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index b84e230..8f2baff 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -304,6 +304,12 @@ int qemuMonitorMigrateToUnix(qemuMonitorPtr mon,
int qemuMonitorMigrateCancel(qemuMonitorPtr mon);
+int qemuMonitorGraphicsRelocate(qemuMonitorPtr mon,
+ int type,
+ const char *hostname,
+ int port,
+ int tlsPort,
+ const char *tlsSubject);
/* XXX disk driver type eg, qcow/etc.
* XXX cache mode
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index 047a81f..e771090 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -1820,6 +1820,38 @@ int qemuMonitorJSONMigrateCancel(qemuMonitorPtr mon)
}
+int qemuMonitorJSONGraphicsRelocate(qemuMonitorPtr mon,
+ int type,
+ const char *hostname,
+ int port,
+ int tlsPort,
+ const char *tlsSubject)
+{
+ int ret = -1;
+ virJSONValuePtr cmd = qemuMonitorJSONMakeCommand("client_migrate_info",
+ "s:protocol",
+ (type ==
VIR_DOMAIN_GRAPHICS_TYPE_SPICE ? "spice" : "vnc"),
+ "s:hostname", hostname,
+ "i:port", port,
+ "i:tls-port", tlsPort,
+ (tlsSubject ?
"s:cert-subject" : NULL),
+ (tlsSubject ? tlsSubject : NULL),
+ NULL);
+ virJSONValuePtr reply = NULL;
+ if (!cmd)
+ return -1;
+
+ ret = qemuMonitorJSONCommand(mon, cmd, &reply);
+
+ if (ret == 0)
+ ret = qemuMonitorJSONCheckError(cmd, reply);
+
+ virJSONValueFree(cmd);
+ virJSONValueFree(reply);
+ return ret;
+}
+
+
int qemuMonitorJSONAddUSBDisk(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
const char *path ATTRIBUTE_UNUSED)
{
diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h
index f2dc4d2..98e3bed 100644
--- a/src/qemu/qemu_monitor_json.h
+++ b/src/qemu/qemu_monitor_json.h
@@ -117,6 +117,13 @@ int qemuMonitorJSONMigrate(qemuMonitorPtr mon,
int qemuMonitorJSONMigrateCancel(qemuMonitorPtr mon);
+int qemuMonitorJSONGraphicsRelocate(qemuMonitorPtr mon,
+ int type,
+ const char *hostname,
+ int port,
+ int tlsPort,
+ const char *tlsSubject);
+
int qemuMonitorJSONAddUSBDisk(qemuMonitorPtr mon,
const char *path);
diff --git a/src/qemu/qemu_monitor_text.c b/src/qemu/qemu_monitor_text.c
index 1d90c1b..33fc765 100644
--- a/src/qemu/qemu_monitor_text.c
+++ b/src/qemu/qemu_monitor_text.c
@@ -1282,6 +1282,37 @@ int qemuMonitorTextMigrateCancel(qemuMonitorPtr mon)
return 0;
}
+
+int qemuMonitorTextGraphicsRelocate(qemuMonitorPtr mon,
+ int type,
+ const char *hostname,
+ int port,
+ int tlsPort,
+ const char *tlsSubject)
+{
+ char *cmd;
+ char *info = NULL;
+
+ if (virAsprintf(&cmd, "client_migrate_info %s %s %d %d %s",
+ type == VIR_DOMAIN_GRAPHICS_TYPE_SPICE ? "spice" :
"vnc",
+ hostname, port, tlsPort, tlsSubject ? tlsSubject : "") <
0) {
+ virReportOOMError();
+ return -1;
+ }
+
+ if (qemuMonitorHMPCommand(mon, cmd, &info) < 0) {
+ VIR_FREE(cmd);
+ qemuReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s", _("cannot run monitor command to relocate
graphics client"));
+ return -1;
+ }
+ VIR_FREE(cmd);
+ VIR_FREE(info);
+
+ return 0;
+}
+
+
int qemuMonitorTextAddUSBDisk(qemuMonitorPtr mon,
const char *path)
{
diff --git a/src/qemu/qemu_monitor_text.h b/src/qemu/qemu_monitor_text.h
index dbae72b..c803c57 100644
--- a/src/qemu/qemu_monitor_text.h
+++ b/src/qemu/qemu_monitor_text.h
@@ -113,6 +113,13 @@ int qemuMonitorTextMigrate(qemuMonitorPtr mon,
int qemuMonitorTextMigrateCancel(qemuMonitorPtr mon);
+int qemuMonitorTextGraphicsRelocate(qemuMonitorPtr mon,
+ int type,
+ const char *hostname,
+ int port,
+ int tlsPort,
+ const char *tlsSubject);
+
int qemuMonitorTextAddUSBDisk(qemuMonitorPtr mon,
const char *path);
--
1.7.4.4