---
src/qemu/qemu_driver.c | 14 ++--
src/qemu/qemu_migration.c | 185 ++++++++++++++++++++++++++++++++--------------
src/qemu/qemu_migration.h | 2 +
3 files changed, 139 insertions(+), 62 deletions(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 29210a5..f7824b6 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -9778,7 +9778,7 @@ qemuDomainMigratePerform(virDomainPtr dom,
* Consume any cookie we were able to decode though
*/
ret = qemuMigrationPerform(driver, dom->conn, vm,
- NULL, dconnuri, uri, cookie, cookielen,
+ NULL, dconnuri, uri, NULL, cookie, cookielen,
NULL, NULL, /* No output cookies in v2 */
flags, dname, resource, false);
@@ -10044,7 +10044,7 @@ qemuDomainMigratePerform3(virDomainPtr dom,
return -1;
return qemuMigrationPerform(driver, dom->conn, vm, xmlin,
- dconnuri, uri, cookiein, cookieinlen,
+ dconnuri, uri, NULL, cookiein, cookieinlen,
cookieout, cookieoutlen,
flags, dname, resource, true);
}
@@ -10065,6 +10065,7 @@ qemuDomainMigratePerform3Params(virDomainPtr dom,
const char *dom_xml = NULL;
const char *dname = NULL;
const char *uri = NULL;
+ const char *graphicsuri = NULL;
unsigned long long bandwidth = 0;
virCheckFlags(QEMU_MIGRATION_FLAGS, -1);
@@ -10082,15 +10083,18 @@ qemuDomainMigratePerform3Params(virDomainPtr dom,
&uri) < 0 ||
virTypedParamsGetULLong(params, nparams,
VIR_MIGRATE_PARAM_BANDWIDTH,
- &bandwidth) < 0)
+ &bandwidth) < 0 ||
+ virTypedParamsGetString(params, nparams,
+ VIR_MIGRATE_PARAM_GRAPHICS_URI,
+ &graphicsuri) < 0)
return -1;
if (!(vm = qemuDomObjFromDomain(dom)))
return -1;
return qemuMigrationPerform(driver, dom->conn, vm, dom_xml,
- dconnuri, uri, cookiein, cookieinlen,
- cookieout, cookieoutlen,
+ dconnuri, uri, graphicsuri,
+ cookiein, cookieinlen, cookieout, cookieoutlen,
flags, dname, bandwidth, true);
}
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index a63af70..ce27c92 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -1785,44 +1785,87 @@ cancel:
static int
qemuDomainMigrateGraphicsRelocate(virQEMUDriverPtr driver,
virDomainObjPtr vm,
- qemuMigrationCookiePtr cookie)
+ qemuMigrationCookiePtr cookie,
+ const char *graphicsuri)
{
qemuDomainObjPrivatePtr priv = vm->privateData;
- int ret;
- char *listenAddress;
+ int ret = -1;
+ const char *listenAddress = NULL;
virSocketAddr addr;
+ virURIPtr uri = NULL;
+ int type = -1;
+ int port = -1;
+ int tlsPort = -1;
+ const char *tlsSubject = NULL;
- if (!cookie)
+ if (!cookie || (!cookie->graphics && !graphicsuri))
return 0;
- if (!cookie->graphics)
- return 0;
+ if (graphicsuri && !(uri = virURIParse(graphicsuri)))
+ goto cleanup;
+
+ if (cookie->graphics) {
+ type = cookie->graphics->type;
+
+ listenAddress = cookie->graphics->listen;
+
+ if (!listenAddress ||
+ (virSocketAddrParse(&addr, listenAddress, AF_UNSPEC) > 0 &&
+ virSocketAddrIsWildcard(&addr)))
+ listenAddress = cookie->remoteHostname;
+
+ port = cookie->graphics->port;
+ tlsPort = cookie->graphics->tlsPort;
+ tlsSubject = cookie->graphics->tlsSubject;
+ }
+
+ if (uri) {
+ int i;
+
+ if ((type = virDomainGraphicsTypeFromString(uri->scheme)) < 0) {
+ virReportError(VIR_ERR_INVALID_ARG,
+ _("unknown graphics type %s"), uri->scheme);
+ goto cleanup;
+ }
+
+ if (uri->server)
+ listenAddress = uri->server;
+ if (uri->port > 0)
+ port = uri->port;
+
+ for (i = 0; i < uri->paramsCount; i++) {
+ virURIParamPtr param = uri->params + i;
+
+ if (STRCASEEQ(param->name, "tlsPort")) {
+ if (virStrToLong_i(param->value, NULL, 10, &tlsPort) < 0) {
+ virReportError(VIR_ERR_INVALID_ARG,
+ _("invalid tlsPort number: %s"),
+ param->value);
+ goto cleanup;
+ }
+ } else if (STRCASEEQ(param->name, "tlsSubject")) {
+ tlsSubject = param->value;
+ }
+ }
+ }
/* 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;
-
- listenAddress = cookie->graphics->listen;
-
- if (!listenAddress ||
- (virSocketAddrParse(&addr, listenAddress, AF_UNSPEC) > 0 &&
- virSocketAddrIsWildcard(&addr)))
- listenAddress = cookie->remoteHostname;
+ if (type != VIR_DOMAIN_GRAPHICS_TYPE_SPICE) {
+ ret = 0;
+ goto cleanup;
+ }
- ret = qemuDomainObjEnterMonitorAsync(driver, vm,
- QEMU_ASYNC_JOB_MIGRATION_OUT);
- if (ret == 0) {
- ret = qemuMonitorGraphicsRelocate(priv->mon,
- cookie->graphics->type,
- listenAddress,
- cookie->graphics->port,
- cookie->graphics->tlsPort,
- cookie->graphics->tlsSubject);
+ if (qemuDomainObjEnterMonitorAsync(driver, vm,
+ QEMU_ASYNC_JOB_MIGRATION_OUT) == 0) {
+ ret = qemuMonitorGraphicsRelocate(priv->mon, type, listenAddress,
+ port, tlsPort, tlsSubject);
qemuDomainObjExitMonitor(driver, vm);
}
+cleanup:
+ virURIFree(uri);
return ret;
}
@@ -3068,7 +3111,8 @@ qemuMigrationRun(virQEMUDriverPtr driver,
unsigned long flags,
unsigned long resource,
qemuMigrationSpecPtr spec,
- virConnectPtr dconn)
+ virConnectPtr dconn,
+ const char *graphicsuri)
{
int ret = -1;
unsigned int migrate_flags = QEMU_MONITOR_MIGRATE_BACKGROUND;
@@ -3083,10 +3127,11 @@ qemuMigrationRun(virQEMUDriverPtr driver,
VIR_DEBUG("driver=%p, vm=%p, cookiein=%s, cookieinlen=%d, "
"cookieout=%p, cookieoutlen=%p, flags=%lx, resource=%lu, "
- "spec=%p (dest=%d, fwd=%d)",
+ "spec=%p (dest=%d, fwd=%d), dconn=%p, graphicsuri=%s",
driver, vm, NULLSTR(cookiein), cookieinlen,
cookieout, cookieoutlen, flags, resource,
- spec, spec->destType, spec->fwdType);
+ spec, spec->destType, spec->fwdType, dconn,
+ NULLSTR(graphicsuri));
if (flags & VIR_MIGRATE_NON_SHARED_DISK) {
migrate_flags |= QEMU_MONITOR_MIGRATE_NON_SHARED_DISK;
@@ -3112,7 +3157,7 @@ qemuMigrationRun(virQEMUDriverPtr driver,
if (!mig)
goto cleanup;
- if (qemuDomainMigrateGraphicsRelocate(driver, vm, mig) < 0)
+ if (qemuDomainMigrateGraphicsRelocate(driver, vm, mig, graphicsuri) < 0)
VIR_WARN("unable to provide data for graphics client relocation");
/* this will update migrate_flags on success */
@@ -3306,7 +3351,8 @@ static int doNativeMigrate(virQEMUDriverPtr driver,
int *cookieoutlen,
unsigned long flags,
unsigned long resource,
- virConnectPtr dconn)
+ virConnectPtr dconn,
+ const char *graphicsuri)
{
qemuDomainObjPrivatePtr priv = vm->privateData;
virURIPtr uribits = NULL;
@@ -3314,9 +3360,11 @@ static int doNativeMigrate(virQEMUDriverPtr driver,
qemuMigrationSpec spec;
VIR_DEBUG("driver=%p, vm=%p, uri=%s, cookiein=%s, cookieinlen=%d, "
- "cookieout=%p, cookieoutlen=%p, flags=%lx, resource=%lu",
+ "cookieout=%p, cookieoutlen=%p, flags=%lx, resource=%lu, "
+ "graphicsuri=%s",
driver, vm, uri, NULLSTR(cookiein), cookieinlen,
- cookieout, cookieoutlen, flags, resource);
+ cookieout, cookieoutlen, flags, resource,
+ NULLSTR(graphicsuri));
if (STRPREFIX(uri, "tcp:") && !STRPREFIX(uri, "tcp://"))
{
char *tmp;
@@ -3342,7 +3390,8 @@ static int doNativeMigrate(virQEMUDriverPtr driver,
spec.fwdType = MIGRATION_FWD_DIRECT;
ret = qemuMigrationRun(driver, vm, cookiein, cookieinlen, cookieout,
- cookieoutlen, flags, resource, &spec, dconn);
+ cookieoutlen, flags, resource, &spec, dconn,
+ graphicsuri);
if (spec.destType == MIGRATION_DEST_FD)
VIR_FORCE_CLOSE(spec.dest.fd.qemu);
@@ -3362,7 +3411,8 @@ static int doTunnelMigrate(virQEMUDriverPtr driver,
int *cookieoutlen,
unsigned long flags,
unsigned long resource,
- virConnectPtr dconn)
+ virConnectPtr dconn,
+ const char *graphicsuri)
{
qemuDomainObjPrivatePtr priv = vm->privateData;
virNetSocketPtr sock = NULL;
@@ -3371,9 +3421,11 @@ static int doTunnelMigrate(virQEMUDriverPtr driver,
virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
VIR_DEBUG("driver=%p, vm=%p, st=%p, cookiein=%s, cookieinlen=%d, "
- "cookieout=%p, cookieoutlen=%p, flags=%lx, resource=%lu",
+ "cookieout=%p, cookieoutlen=%p, flags=%lx, resource=%lu, "
+ "graphicsuri=%s",
driver, vm, st, NULLSTR(cookiein), cookieinlen,
- cookieout, cookieoutlen, flags, resource);
+ cookieout, cookieoutlen, flags, resource,
+ NULLSTR(graphicsuri));
if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_MIGRATE_QEMU_FD) &&
!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_MIGRATE_QEMU_UNIX) &&
@@ -3427,7 +3479,8 @@ static int doTunnelMigrate(virQEMUDriverPtr driver,
}
ret = qemuMigrationRun(driver, vm, cookiein, cookieinlen, cookieout,
- cookieoutlen, flags, resource, &spec, dconn);
+ cookieoutlen, flags, resource, &spec, dconn,
+ graphicsuri);
cleanup:
if (spec.destType == MIGRATION_DEST_FD) {
@@ -3533,12 +3586,12 @@ static int doPeer2PeerMigrate2(virQEMUDriverPtr driver,
if (flags & VIR_MIGRATE_TUNNELLED)
ret = doTunnelMigrate(driver, vm, st,
NULL, 0, NULL, NULL,
- flags, resource, dconn);
+ flags, resource, dconn, NULL);
else
ret = doNativeMigrate(driver, vm, uri_out,
cookie, cookielen,
NULL, NULL, /* No out cookie with v2 migration */
- flags, resource, dconn);
+ flags, resource, dconn, NULL);
/* Perform failed. Make sure Finish doesn't overwrite the error */
if (ret < 0)
@@ -3596,6 +3649,7 @@ doPeer2PeerMigrate3(virQEMUDriverPtr driver,
const char *xmlin,
const char *dname,
const char *uri,
+ const char *graphicsuri,
unsigned long long bandwidth,
bool useParams,
unsigned long flags)
@@ -3618,9 +3672,11 @@ doPeer2PeerMigrate3(virQEMUDriverPtr driver,
int maxparams = 0;
VIR_DEBUG("driver=%p, sconn=%p, dconn=%p, dconnuri=%s, vm=%p, xmlin=%s, "
- "dname=%s, uri=%s, bandwidth=%llu, useParams=%d, flags=%lx",
+ "dname=%s, uri=%s, graphicsuri=%s, bandwidth=%llu, "
+ "useParams=%d, flags=%lx",
driver, sconn, dconn, NULLSTR(dconnuri), vm, NULLSTR(xmlin),
- NULLSTR(dname), NULLSTR(uri), bandwidth, useParams, flags);
+ NULLSTR(dname), NULLSTR(uri), NULLSTR(graphicsuri), bandwidth,
+ useParams, flags);
/* Unlike the virDomainMigrateVersion3 counterpart, we don't need
* to worry about auto-setting the VIR_MIGRATE_CHANGE_PROTECTION
@@ -3652,6 +3708,12 @@ doPeer2PeerMigrate3(virQEMUDriverPtr driver,
VIR_MIGRATE_PARAM_BANDWIDTH,
bandwidth) < 0)
goto cleanup;
+
+ if (graphicsuri &&
+ virTypedParamsAddString(¶ms, &nparams, &maxparams,
+ VIR_MIGRATE_PARAM_GRAPHICS_URI,
+ graphicsuri) < 0)
+ goto cleanup;
}
if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_PAUSED)
@@ -3730,12 +3792,12 @@ doPeer2PeerMigrate3(virQEMUDriverPtr driver,
ret = doTunnelMigrate(driver, vm, st,
cookiein, cookieinlen,
&cookieout, &cookieoutlen,
- flags, bandwidth, dconn);
+ flags, bandwidth, dconn, graphicsuri);
} else {
ret = doNativeMigrate(driver, vm, uri,
cookiein, cookieinlen,
&cookieout, &cookieoutlen,
- flags, bandwidth, dconn);
+ flags, bandwidth, dconn, graphicsuri);
}
/* Perform failed. Make sure Finish doesn't overwrite the error */
@@ -3853,6 +3915,7 @@ static int doPeer2PeerMigrate(virQEMUDriverPtr driver,
const char *xmlin,
const char *dconnuri,
const char *uri,
+ const char *graphicsuri,
unsigned long flags,
const char *dname,
unsigned long resource,
@@ -3867,9 +3930,10 @@ static int doPeer2PeerMigrate(virQEMUDriverPtr driver,
bool useParams;
VIR_DEBUG("driver=%p, sconn=%p, vm=%p, xmlin=%s, dconnuri=%s, "
- "uri=%s, flags=%lx, dname=%s, resource=%lu",
+ "uri=%s, graphicsuri=%s, flags=%lx, dname=%s, resource=%lu",
driver, sconn, vm, NULLSTR(xmlin), NULLSTR(dconnuri),
- NULLSTR(uri), flags, NULLSTR(dname), resource);
+ NULLSTR(uri), NULLSTR(graphicsuri), flags, NULLSTR(dname),
+ resource);
/* the order of operations is important here; we make sure the
* destination side is completely setup before we touch the source
@@ -3946,7 +4010,8 @@ static int doPeer2PeerMigrate(virQEMUDriverPtr driver,
if (*v3proto) {
ret = doPeer2PeerMigrate3(driver, sconn, dconn, dconnuri, vm, xmlin,
- dname, uri, resource, useParams, flags);
+ dname, uri, graphicsuri, resource,
+ useParams, flags);
} else {
ret = doPeer2PeerMigrate2(driver, sconn, dconn, vm,
dconnuri, flags, dname, resource);
@@ -3978,6 +4043,7 @@ qemuMigrationPerformJob(virQEMUDriverPtr driver,
const char *xmlin,
const char *dconnuri,
const char *uri,
+ const char *graphicsuri,
const char *cookiein,
int cookieinlen,
char **cookieout,
@@ -4013,13 +4079,13 @@ qemuMigrationPerformJob(virQEMUDriverPtr driver,
if ((flags & (VIR_MIGRATE_TUNNELLED | VIR_MIGRATE_PEER2PEER))) {
ret = doPeer2PeerMigrate(driver, conn, vm, xmlin,
- dconnuri, uri, flags, dname,
+ dconnuri, uri, graphicsuri, flags, dname,
resource, &v3proto);
} else {
qemuMigrationJobSetPhase(driver, vm, QEMU_MIGRATION_PHASE_PERFORM2);
ret = doNativeMigrate(driver, vm, uri, cookiein, cookieinlen,
cookieout, cookieoutlen,
- flags, resource, NULL);
+ flags, resource, NULL, NULL);
}
if (ret < 0)
goto endjob;
@@ -4093,6 +4159,7 @@ qemuMigrationPerformPhase(virQEMUDriverPtr driver,
virConnectPtr conn,
virDomainObjPtr vm,
const char *uri,
+ const char *graphicsuri,
const char *cookiein,
int cookieinlen,
char **cookieout,
@@ -4120,7 +4187,7 @@ qemuMigrationPerformPhase(virQEMUDriverPtr driver,
resume = virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING;
ret = doNativeMigrate(driver, vm, uri, cookiein, cookieinlen,
cookieout, cookieoutlen,
- flags, resource, NULL);
+ flags, resource, NULL, graphicsuri);
if (ret < 0 && resume &&
virDomainObjGetState(vm, NULL) == VIR_DOMAIN_PAUSED) {
@@ -4177,6 +4244,7 @@ qemuMigrationPerform(virQEMUDriverPtr driver,
const char *xmlin,
const char *dconnuri,
const char *uri,
+ const char *graphicsuri,
const char *cookiein,
int cookieinlen,
char **cookieout,
@@ -4187,12 +4255,13 @@ qemuMigrationPerform(virQEMUDriverPtr driver,
bool v3proto)
{
VIR_DEBUG("driver=%p, conn=%p, vm=%p, xmlin=%s, dconnuri=%s, "
- "uri=%s, cookiein=%s, cookieinlen=%d, cookieout=%p, "
- "cookieoutlen=%p, flags=%lx, dname=%s, resource=%lu,
v3proto=%d",
+ "uri=%s, graphicsuri=%s, "
+ "cookiein=%s, cookieinlen=%d, cookieout=%p, cookieoutlen=%p, "
+ "flags=%lx, dname=%s, resource=%lu, v3proto=%d",
driver, conn, vm, NULLSTR(xmlin), NULLSTR(dconnuri),
- NULLSTR(uri), NULLSTR(cookiein), cookieinlen,
- cookieout, cookieoutlen, flags, NULLSTR(dname),
- resource, v3proto);
+ NULLSTR(uri), NULLSTR(graphicsuri),
+ NULLSTR(cookiein), cookieinlen, cookieout, cookieoutlen,
+ flags, NULLSTR(dname), resource, v3proto);
if ((flags & (VIR_MIGRATE_TUNNELLED | VIR_MIGRATE_PEER2PEER))) {
if (cookieinlen) {
@@ -4202,9 +4271,9 @@ qemuMigrationPerform(virQEMUDriverPtr driver,
}
return qemuMigrationPerformJob(driver, conn, vm, xmlin, dconnuri, uri,
- cookiein, cookieinlen, cookieout,
- cookieoutlen, flags, dname, resource,
- v3proto);
+ graphicsuri, cookiein, cookieinlen,
+ cookieout, cookieoutlen,
+ flags, dname, resource, v3proto);
} else {
if (dconnuri) {
virReportError(VIR_ERR_INTERNAL_ERROR,
@@ -4214,12 +4283,14 @@ qemuMigrationPerform(virQEMUDriverPtr driver,
if (v3proto) {
return qemuMigrationPerformPhase(driver, conn, vm, uri,
+ graphicsuri,
cookiein, cookieinlen,
cookieout, cookieoutlen,
flags, resource);
} else {
return qemuMigrationPerformJob(driver, conn, vm, xmlin, dconnuri,
- uri, cookiein, cookieinlen,
+ uri, graphicsuri,
+ cookiein, cookieinlen,
cookieout, cookieoutlen, flags,
dname, resource, v3proto);
}
diff --git a/src/qemu/qemu_migration.h b/src/qemu/qemu_migration.h
index 65663e9..a67a3fe 100644
--- a/src/qemu/qemu_migration.h
+++ b/src/qemu/qemu_migration.h
@@ -47,6 +47,7 @@
VIR_MIGRATE_PARAM_DEST_NAME, VIR_TYPED_PARAM_STRING, \
VIR_MIGRATE_PARAM_DEST_XML, VIR_TYPED_PARAM_STRING, \
VIR_MIGRATE_PARAM_BANDWIDTH, VIR_TYPED_PARAM_ULLONG, \
+ VIR_MIGRATE_PARAM_GRAPHICS_URI, VIR_TYPED_PARAM_STRING, \
NULL
@@ -120,6 +121,7 @@ int qemuMigrationPerform(virQEMUDriverPtr driver,
const char *xmlin,
const char *dconnuri,
const char *uri,
+ const char *graphicsuri,
const char *cookiein,
int cookieinlen,
char **cookieout,
--
1.8.2.1