[libvirt] [PATCH v2 0/5] Make migration APIs more extensible -- qemu patches

These are the patches for qemu driver that were already acked but had to be reworked due to the introduction of ACL checks. Jiri Denemark (5): qemu: Move internals of Begin phase to qemu_migration.c qemu: Move common parts of Prepare phase to qemu_migration.c qemu: Move internals of Confirm phase to qemu_migration.c Implement extensible migration APIs in qemu driver qemu: Implement support for VIR_MIGRATE_PARAM_GRAPHICS_URI src/qemu/qemu_driver.c | 506 ++++++++++++++++++++-------------- src/qemu/qemu_migration.c | 690 +++++++++++++++++++++++++++++++++------------- src/qemu/qemu_migration.h | 22 +- 3 files changed, 825 insertions(+), 393 deletions(-) -- 1.8.2.1

--- src/qemu/qemu_driver.c | 71 +++----------------------------------- src/qemu/qemu_migration.c | 86 +++++++++++++++++++++++++++++++++++++++++++++-- src/qemu/qemu_migration.h | 2 +- 3 files changed, 89 insertions(+), 70 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index dbe344c..863923d 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -10200,81 +10200,20 @@ qemuDomainMigrateBegin3(virDomainPtr domain, const char *dname, unsigned long resource ATTRIBUTE_UNUSED) { - virQEMUDriverPtr driver = domain->conn->privateData; virDomainObjPtr vm; - char *xml = NULL; - enum qemuDomainAsyncJob asyncJob; virCheckFlags(QEMU_MIGRATION_FLAGS, NULL); if (!(vm = qemuDomObjFromDomain(domain))) return NULL; - if (virDomainMigrateBegin3EnsureACL(domain->conn, vm->def) < 0) - goto cleanup; - - if ((flags & VIR_MIGRATE_CHANGE_PROTECTION)) { - if (qemuMigrationJobStart(driver, vm, QEMU_ASYNC_JOB_MIGRATION_OUT) < 0) - goto cleanup; - asyncJob = QEMU_ASYNC_JOB_MIGRATION_OUT; - } else { - if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0) - goto cleanup; - asyncJob = QEMU_ASYNC_JOB_NONE; - } - - if (!virDomainObjIsActive(vm) && !(flags & VIR_MIGRATE_OFFLINE)) { - virReportError(VIR_ERR_OPERATION_INVALID, - "%s", _("domain is not running")); - goto endjob; - } - - /* Check if there is any ejected media. - * We don't want to require them on the destination. - */ - if (!(flags & VIR_MIGRATE_OFFLINE) && - qemuDomainCheckEjectableMedia(driver, vm, asyncJob) < 0) - goto endjob; - - if (!(xml = qemuMigrationBegin(driver, vm, xmlin, dname, - cookieout, cookieoutlen, - flags))) - goto endjob; - - if ((flags & VIR_MIGRATE_CHANGE_PROTECTION)) { - /* We keep the job active across API calls until the confirm() call. - * This prevents any other APIs being invoked while migration is taking - * place. - */ - if (virQEMUCloseCallbacksSet(driver->closeCallbacks, vm, domain->conn, - qemuMigrationCleanup) < 0) - goto endjob; - if (qemuMigrationJobContinue(vm) == 0) { - vm = NULL; - virReportError(VIR_ERR_OPERATION_FAILED, - "%s", _("domain disappeared")); - VIR_FREE(xml); - if (cookieout) - VIR_FREE(*cookieout); - } - } else { - goto endjob; - } - -cleanup: - if (vm) + if (virDomainMigrateBegin3EnsureACL(domain->conn, vm->def) < 0) { virObjectUnlock(vm); - return xml; - -endjob: - if ((flags & VIR_MIGRATE_CHANGE_PROTECTION)) { - if (qemuMigrationJobFinish(driver, vm) == 0) - vm = NULL; - } else { - if (qemuDomainObjEndJob(driver, vm) == 0) - vm = NULL; + return NULL; } - goto cleanup; + + return qemuMigrationBegin(domain->conn, vm, xmlin, dname, + cookieout, cookieoutlen, flags); } static int diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index 8de38fe..9e2d043 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -39,6 +39,7 @@ #include "qemu_capabilities.h" #include "qemu_command.h" #include "qemu_cgroup.h" +#include "qemu_hotplug.h" #include "domain_audit.h" #include "virlog.h" @@ -1923,8 +1924,10 @@ cleanup: return vm; } + /* The caller is supposed to lock the vm and start a migration job. */ -char *qemuMigrationBegin(virQEMUDriverPtr driver, +static char +*qemuMigrationBeginPhase(virQEMUDriverPtr driver, virDomainObjPtr vm, const char *xmlin, const char *dname, @@ -2024,6 +2027,83 @@ cleanup: return rv; } +char * +qemuMigrationBegin(virConnectPtr conn, + virDomainObjPtr vm, + const char *xmlin, + const char *dname, + char **cookieout, + int *cookieoutlen, + unsigned long flags) +{ + virQEMUDriverPtr driver = conn->privateData; + char *xml = NULL; + enum qemuDomainAsyncJob asyncJob; + + if ((flags & VIR_MIGRATE_CHANGE_PROTECTION)) { + if (qemuMigrationJobStart(driver, vm, QEMU_ASYNC_JOB_MIGRATION_OUT) < 0) + goto cleanup; + asyncJob = QEMU_ASYNC_JOB_MIGRATION_OUT; + } else { + if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0) + goto cleanup; + asyncJob = QEMU_ASYNC_JOB_NONE; + } + + if (!virDomainObjIsActive(vm) && !(flags & VIR_MIGRATE_OFFLINE)) { + virReportError(VIR_ERR_OPERATION_INVALID, + "%s", _("domain is not running")); + goto endjob; + } + + /* Check if there is any ejected media. + * We don't want to require them on the destination. + */ + if (!(flags & VIR_MIGRATE_OFFLINE) && + qemuDomainCheckEjectableMedia(driver, vm, asyncJob) < 0) + goto endjob; + + if (!(xml = qemuMigrationBeginPhase(driver, vm, xmlin, dname, + cookieout, cookieoutlen, + flags))) + goto endjob; + + if ((flags & VIR_MIGRATE_CHANGE_PROTECTION)) { + /* We keep the job active across API calls until the confirm() call. + * This prevents any other APIs being invoked while migration is taking + * place. + */ + if (virQEMUCloseCallbacksSet(driver->closeCallbacks, vm, conn, + qemuMigrationCleanup) < 0) + goto endjob; + if (qemuMigrationJobContinue(vm) == 0) { + vm = NULL; + virReportError(VIR_ERR_OPERATION_FAILED, + "%s", _("domain disappeared")); + VIR_FREE(xml); + if (cookieout) + VIR_FREE(*cookieout); + } + } else { + goto endjob; + } + +cleanup: + if (vm) + virObjectUnlock(vm); + return xml; + +endjob: + if ((flags & VIR_MIGRATE_CHANGE_PROTECTION)) { + if (qemuMigrationJobFinish(driver, vm) == 0) + vm = NULL; + } else { + if (qemuDomainObjEndJob(driver, vm) == 0) + vm = NULL; + } + goto cleanup; +} + /* Prepare is the first step, and it runs on the destination host. */ @@ -3341,8 +3421,8 @@ static int doPeer2PeerMigrate3(virQEMUDriverPtr driver, * bit here, because we are already running inside the context of * a single job. */ - dom_xml = qemuMigrationBegin(driver, vm, xmlin, dname, - &cookieout, &cookieoutlen, flags); + dom_xml = qemuMigrationBeginPhase(driver, vm, xmlin, dname, + &cookieout, &cookieoutlen, flags); if (!dom_xml) goto cleanup; diff --git a/src/qemu/qemu_migration.h b/src/qemu/qemu_migration.h index 5b21ca2..09b5b1a 100644 --- a/src/qemu/qemu_migration.h +++ b/src/qemu/qemu_migration.h @@ -84,7 +84,7 @@ virDomainObjPtr qemuMigrationCleanup(virQEMUDriverPtr driver, virDomainObjPtr vm, virConnectPtr conn); -char *qemuMigrationBegin(virQEMUDriverPtr driver, +char *qemuMigrationBegin(virConnectPtr conn, virDomainObjPtr vm, const char *xmlin, const char *dname, -- 1.8.2.1

On Tue, Jun 25, 2013 at 03:59:44PM +0200, Jiri Denemark wrote:
--- src/qemu/qemu_driver.c | 71 +++----------------------------------- src/qemu/qemu_migration.c | 86 +++++++++++++++++++++++++++++++++++++++++++++-- src/qemu/qemu_migration.h | 2 +- 3 files changed, 89 insertions(+), 70 deletions(-)
ACK Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

--- src/qemu/qemu_driver.c | 120 +++++++--------------------------------------- src/qemu/qemu_migration.c | 44 +++++++++++++++++ src/qemu/qemu_migration.h | 4 ++ 3 files changed, 65 insertions(+), 103 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 863923d..4a17b64 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -9962,25 +9962,14 @@ qemuDomainMigratePrepareTunnel(virConnectPtr dconn, const char *dom_xml) { virQEMUDriverPtr driver = dconn->privateData; - virCapsPtr caps = NULL; virDomainDefPtr def = NULL; int ret = -1; virCheckFlags(QEMU_MIGRATION_FLAGS, -1); - if (!dom_xml) { - virReportError(VIR_ERR_INTERNAL_ERROR, - "%s", _("no domain XML passed")); - goto cleanup; - } if (!(flags & VIR_MIGRATE_TUNNELLED)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - "%s", _("PrepareTunnel called but no TUNNELLED flag set")); - goto cleanup; - } - if (st == NULL) { - virReportError(VIR_ERR_INTERNAL_ERROR, - "%s", _("tunnelled migration requested but NULL stream passed")); + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("PrepareTunnel called but no TUNNELLED flag set")); goto cleanup; } @@ -9991,20 +9980,9 @@ qemuDomainMigratePrepareTunnel(virConnectPtr dconn, goto cleanup; } - if (!(caps = virQEMUDriverGetCapabilities(driver, false))) + if (!(def = qemuMigrationPrepareDef(driver, dom_xml, dname))) goto cleanup; - if (!(def = virDomainDefParseString(dom_xml, caps, driver->xmlopt, - QEMU_EXPECTED_VIRT_TYPES, - VIR_DOMAIN_XML_INACTIVE))) - goto cleanup; - - if (dname) { - VIR_FREE(def->name); - if (VIR_STRDUP(def->name, dname) < 0) - goto cleanup; - } - if (virDomainMigratePrepareTunnelEnsureACL(dconn, def) < 0) goto cleanup; @@ -10014,7 +9992,6 @@ qemuDomainMigratePrepareTunnel(virConnectPtr dconn, cleanup: virDomainDefFree(def); - virObjectUnref(caps); return ret; } @@ -10034,50 +10011,31 @@ qemuDomainMigratePrepare2(virConnectPtr dconn, const char *dom_xml) { virQEMUDriverPtr driver = dconn->privateData; - virCapsPtr caps = NULL; virDomainDefPtr def = NULL; int ret = -1; virCheckFlags(QEMU_MIGRATION_FLAGS, -1); - *uri_out = NULL; - - if (virLockManagerPluginUsesState(driver->lockManager)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Cannot use migrate v2 protocol with lock manager %s"), - virLockManagerPluginGetName(driver->lockManager)); - goto cleanup; - } - if (flags & VIR_MIGRATE_TUNNELLED) { /* this is a logical error; we never should have gotten here with * VIR_MIGRATE_TUNNELLED set */ - virReportError(VIR_ERR_INTERNAL_ERROR, - "%s", _("Tunnelled migration requested but invalid RPC method called")); + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Tunnelled migration requested but invalid " + "RPC method called")); goto cleanup; } - if (!dom_xml) { + if (virLockManagerPluginUsesState(driver->lockManager)) { virReportError(VIR_ERR_INTERNAL_ERROR, - "%s", _("no domain XML passed")); + _("Cannot use migrate v2 protocol with lock manager %s"), + virLockManagerPluginGetName(driver->lockManager)); goto cleanup; } - if (!(caps = virQEMUDriverGetCapabilities(driver, false))) + if (!(def = qemuMigrationPrepareDef(driver, dom_xml, dname))) goto cleanup; - if (!(def = virDomainDefParseString(dom_xml, caps, driver->xmlopt, - QEMU_EXPECTED_VIRT_TYPES, - VIR_DOMAIN_XML_INACTIVE))) - goto cleanup; - - if (dname) { - VIR_FREE(def->name); - if (VIR_STRDUP(def->name, dname) < 0) - goto cleanup; - } - if (virDomainMigratePrepare2EnsureACL(dconn, def) < 0) goto cleanup; @@ -10092,7 +10050,6 @@ qemuDomainMigratePrepare2(virConnectPtr dconn, cleanup: virDomainDefFree(def); - virObjectUnref(caps); return ret; } @@ -10230,43 +10187,24 @@ qemuDomainMigratePrepare3(virConnectPtr dconn, const char *dom_xml) { virQEMUDriverPtr driver = dconn->privateData; - virCapsPtr caps = NULL; virDomainDefPtr def = NULL; int ret = -1; virCheckFlags(QEMU_MIGRATION_FLAGS, -1); - *uri_out = NULL; - if (flags & VIR_MIGRATE_TUNNELLED) { /* this is a logical error; we never should have gotten here with * VIR_MIGRATE_TUNNELLED set */ - virReportError(VIR_ERR_INTERNAL_ERROR, - "%s", _("Tunnelled migration requested but invalid RPC method called")); - goto cleanup; - } - - if (!dom_xml) { - virReportError(VIR_ERR_INTERNAL_ERROR, - "%s", _("no domain XML passed")); + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Tunnelled migration requested but invalid " + "RPC method called")); goto cleanup; } - if (!(caps = virQEMUDriverGetCapabilities(driver, false))) + if (!(def = qemuMigrationPrepareDef(driver, dom_xml, dname))) goto cleanup; - if (!(def = virDomainDefParseString(dom_xml, caps, driver->xmlopt, - QEMU_EXPECTED_VIRT_TYPES, - VIR_DOMAIN_XML_INACTIVE))) - goto cleanup; - - if (dname) { - VIR_FREE(def->name); - if (VIR_STRDUP(def->name, dname) < 0) - goto cleanup; - } - if (virDomainMigratePrepare3EnsureACL(dconn, def) < 0) goto cleanup; @@ -10278,7 +10216,6 @@ qemuDomainMigratePrepare3(virConnectPtr dconn, cleanup: virDomainDefFree(def); - virObjectUnref(caps); return ret; } @@ -10296,42 +10233,20 @@ qemuDomainMigratePrepareTunnel3(virConnectPtr dconn, const char *dom_xml) { virQEMUDriverPtr driver = dconn->privateData; - virCapsPtr caps = NULL; virDomainDefPtr def = NULL; int ret = -1; virCheckFlags(QEMU_MIGRATION_FLAGS, -1); - if (!dom_xml) { - virReportError(VIR_ERR_INTERNAL_ERROR, - "%s", _("no domain XML passed")); - goto cleanup; - } if (!(flags & VIR_MIGRATE_TUNNELLED)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - "%s", _("PrepareTunnel called but no TUNNELLED flag set")); - goto cleanup; - } - if (st == NULL) { - virReportError(VIR_ERR_INTERNAL_ERROR, - "%s", _("tunnelled migration requested but NULL stream passed")); + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("PrepareTunnel called but no TUNNELLED flag set")); goto cleanup; } - if (!(caps = virQEMUDriverGetCapabilities(driver, false))) - goto cleanup; - - if (!(def = virDomainDefParseString(dom_xml, caps, driver->xmlopt, - QEMU_EXPECTED_VIRT_TYPES, - VIR_DOMAIN_XML_INACTIVE))) + if (!(def = qemuMigrationPrepareDef(driver, dom_xml, dname))) goto cleanup; - if (dname) { - VIR_FREE(def->name); - if (VIR_STRDUP(def->name, dname) < 0) - goto cleanup; - } - if (virDomainMigratePrepareTunnel3EnsureACL(dconn, def) < 0) goto cleanup; @@ -10342,7 +10257,6 @@ qemuDomainMigratePrepareTunnel3(virConnectPtr dconn, cleanup: virDomainDefFree(def); - virObjectUnref(caps); return ret; } diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index 9e2d043..5d3b3c9 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -2442,6 +2442,12 @@ qemuMigrationPrepareTunnel(virQEMUDriverPtr driver, driver, dconn, NULLSTR(cookiein), cookieinlen, cookieout, cookieoutlen, st, *def, flags); + if (st == NULL) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("tunnelled migration requested but NULL stream passed")); + return -1; + } + ret = qemuMigrationPrepareAny(driver, dconn, cookiein, cookieinlen, cookieout, cookieoutlen, def, st, 0, flags); @@ -2476,6 +2482,8 @@ qemuMigrationPrepareDirect(virQEMUDriverPtr driver, cookieout, cookieoutlen, NULLSTR(uri_in), uri_out, *def, flags); + *uri_out = NULL; + /* The URI passed in may be NULL or a string "tcp://somehostname:port". * * If the URI passed in is NULL then we allocate a port number @@ -2580,6 +2588,42 @@ cleanup: } +virDomainDefPtr +qemuMigrationPrepareDef(virQEMUDriverPtr driver, + const char *dom_xml, + const char *dname) +{ + virCapsPtr caps = NULL; + virDomainDefPtr def; + + if (!dom_xml) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("no domain XML passed")); + return NULL; + } + + if (!(caps = virQEMUDriverGetCapabilities(driver, false))) + return NULL; + + if (!(def = virDomainDefParseString(dom_xml, caps, driver->xmlopt, + QEMU_EXPECTED_VIRT_TYPES, + VIR_DOMAIN_XML_INACTIVE))) + goto cleanup; + + if (dname) { + VIR_FREE(def->name); + if (VIR_STRDUP(def->name, dname) < 0) { + virDomainDefFree(def); + def = NULL; + } + } + +cleanup: + virObjectUnref(caps); + return def; +} + + enum qemuMigrationDestinationType { MIGRATION_DEST_HOST, MIGRATION_DEST_CONNECT_HOST, diff --git a/src/qemu/qemu_migration.h b/src/qemu/qemu_migration.h index 09b5b1a..fdca583 100644 --- a/src/qemu/qemu_migration.h +++ b/src/qemu/qemu_migration.h @@ -92,6 +92,10 @@ char *qemuMigrationBegin(virConnectPtr conn, int *cookieoutlen, unsigned long flags); +virDomainDefPtr qemuMigrationPrepareDef(virQEMUDriverPtr driver, + const char *dom_xml, + const char *dname); + int qemuMigrationPrepareTunnel(virQEMUDriverPtr driver, virConnectPtr dconn, const char *cookiein, -- 1.8.2.1

On Tue, Jun 25, 2013 at 03:59:45PM +0200, Jiri Denemark wrote:
--- src/qemu/qemu_driver.c | 120 +++++++--------------------------------------- src/qemu/qemu_migration.c | 44 +++++++++++++++++ src/qemu/qemu_migration.h | 4 ++ 3 files changed, 65 insertions(+), 103 deletions(-)
ACK Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

--- src/qemu/qemu_driver.c | 43 ++------- src/qemu/qemu_migration.c | 225 ++++++++++++++++++++++++++++------------------ src/qemu/qemu_migration.h | 5 +- 3 files changed, 144 insertions(+), 129 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 4a17b64..e2b85c0 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -10338,53 +10338,20 @@ qemuDomainMigrateConfirm3(virDomainPtr domain, unsigned long flags, int cancelled) { - virQEMUDriverPtr driver = domain->conn->privateData; virDomainObjPtr vm; - int ret = -1; - enum qemuMigrationJobPhase phase; - virQEMUDriverConfigPtr cfg = NULL; virCheckFlags(QEMU_MIGRATION_FLAGS, -1); if (!(vm = qemuDomObjFromDomain(domain))) return -1; - cfg = virQEMUDriverGetConfig(driver); - - if (virDomainMigrateConfirm3EnsureACL(domain->conn, vm->def) < 0) - goto cleanup; - - if (!qemuMigrationJobIsActive(vm, QEMU_ASYNC_JOB_MIGRATION_OUT)) - goto cleanup; - - if (cancelled) - phase = QEMU_MIGRATION_PHASE_CONFIRM3_CANCELLED; - else - phase = QEMU_MIGRATION_PHASE_CONFIRM3; - - qemuMigrationJobStartPhase(driver, vm, phase); - virQEMUCloseCallbacksUnset(driver->closeCallbacks, vm, - qemuMigrationCleanup); - - ret = qemuMigrationConfirm(driver, domain->conn, vm, - cookiein, cookieinlen, - flags, cancelled); - - if (qemuMigrationJobFinish(driver, vm) == 0) { - vm = NULL; - } else if (!virDomainObjIsActive(vm) && - (!vm->persistent || (flags & VIR_MIGRATE_UNDEFINE_SOURCE))) { - if (flags & VIR_MIGRATE_UNDEFINE_SOURCE) - virDomainDeleteConfig(cfg->configDir, cfg->autostartDir, vm); - qemuDomainRemoveInactive(driver, vm); - vm = NULL; + if (virDomainMigrateConfirm3EnsureACL(domain->conn, vm->def) < 0) { + virObjectUnlock(vm); + return -1; } -cleanup: - if (vm) - virObjectUnlock(vm); - virObjectUnref(cfg); - return ret; + return qemuMigrationConfirm(domain->conn, vm, cookiein, cookieinlen, + flags, cancelled); } diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index 5d3b3c9..66d62fe 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -2624,6 +2624,140 @@ cleanup: } +static int +qemuMigrationConfirmPhase(virQEMUDriverPtr driver, + virConnectPtr conn, + virDomainObjPtr vm, + const char *cookiein, + int cookieinlen, + unsigned int flags, + int retcode) +{ + qemuMigrationCookiePtr mig; + virDomainEventPtr event = NULL; + int rv = -1; + virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver); + + VIR_DEBUG("driver=%p, conn=%p, vm=%p, cookiein=%s, cookieinlen=%d, " + "flags=%x, retcode=%d", + driver, conn, vm, NULLSTR(cookiein), cookieinlen, + flags, retcode); + + virCheckFlags(QEMU_MIGRATION_FLAGS, -1); + + qemuMigrationJobSetPhase(driver, vm, + retcode == 0 + ? QEMU_MIGRATION_PHASE_CONFIRM3 + : QEMU_MIGRATION_PHASE_CONFIRM3_CANCELLED); + + if (!(mig = qemuMigrationEatCookie(driver, vm, cookiein, cookieinlen, 0))) + goto cleanup; + + if (flags & VIR_MIGRATE_OFFLINE) + goto done; + + /* Did the migration go as planned? If yes, kill off the + * domain object, but if no, resume CPUs + */ + if (retcode == 0) { + /* If guest uses SPICE and supports seamless migration we have to hold + * up domain shutdown until SPICE server transfers its data */ + qemuMigrationWaitForSpice(driver, vm); + + qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_MIGRATED, + VIR_QEMU_PROCESS_STOP_MIGRATED); + virDomainAuditStop(vm, "migrated"); + + event = virDomainEventNewFromObj(vm, + VIR_DOMAIN_EVENT_STOPPED, + VIR_DOMAIN_EVENT_STOPPED_MIGRATED); + } else { + + /* cancel any outstanding NBD jobs */ + qemuMigrationCancelDriveMirror(mig, driver, vm); + + /* run 'cont' on the destination, which allows migration on qemu + * >= 0.10.6 to work properly. This isn't strictly necessary on + * older qemu's, but it also doesn't hurt anything there + */ + if (qemuProcessStartCPUs(driver, vm, conn, + VIR_DOMAIN_RUNNING_MIGRATED, + QEMU_ASYNC_JOB_MIGRATION_OUT) < 0) { + if (virGetLastError() == NULL) + virReportError(VIR_ERR_INTERNAL_ERROR, + "%s", _("resume operation failed")); + goto cleanup; + } + + event = virDomainEventNewFromObj(vm, + VIR_DOMAIN_EVENT_RESUMED, + VIR_DOMAIN_EVENT_RESUMED_MIGRATED); + if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0) { + VIR_WARN("Failed to save status on vm %s", vm->def->name); + goto cleanup; + } + } + +done: + qemuMigrationCookieFree(mig); + rv = 0; + +cleanup: + if (event) + qemuDomainEventQueue(driver, event); + virObjectUnref(cfg); + return rv; +} + +int +qemuMigrationConfirm(virConnectPtr conn, + virDomainObjPtr vm, + const char *cookiein, + int cookieinlen, + unsigned int flags, + int cancelled) +{ + virQEMUDriverPtr driver = conn->privateData; + enum qemuMigrationJobPhase phase; + virQEMUDriverConfigPtr cfg = NULL; + int ret = -1; + + cfg = virQEMUDriverGetConfig(driver); + + if (!qemuMigrationJobIsActive(vm, QEMU_ASYNC_JOB_MIGRATION_OUT)) + goto cleanup; + + if (cancelled) + phase = QEMU_MIGRATION_PHASE_CONFIRM3_CANCELLED; + else + phase = QEMU_MIGRATION_PHASE_CONFIRM3; + + qemuMigrationJobStartPhase(driver, vm, phase); + virQEMUCloseCallbacksUnset(driver->closeCallbacks, vm, + qemuMigrationCleanup); + + ret = qemuMigrationConfirmPhase(driver, conn, vm, + cookiein, cookieinlen, + flags, cancelled); + + if (qemuMigrationJobFinish(driver, vm) == 0) { + vm = NULL; + } else if (!virDomainObjIsActive(vm) && + (!vm->persistent || (flags & VIR_MIGRATE_UNDEFINE_SOURCE))) { + if (flags & VIR_MIGRATE_UNDEFINE_SOURCE) + virDomainDeleteConfig(cfg->configDir, cfg->autostartDir, vm); + qemuDomainRemoveInactive(driver, vm); + vm = NULL; + } + +cleanup: + if (vm) + virObjectUnlock(vm); + virObjectUnref(cfg); + return ret; +} + + enum qemuMigrationDestinationType { MIGRATION_DEST_HOST, MIGRATION_DEST_CONNECT_HOST, @@ -3597,9 +3731,9 @@ finish: cookieinlen = cookieoutlen; cookieout = NULL; cookieoutlen = 0; - ret = qemuMigrationConfirm(driver, sconn, vm, - cookiein, cookieinlen, - flags, cancelled); + ret = qemuMigrationConfirmPhase(driver, sconn, vm, + cookiein, cookieinlen, + flags, cancelled); /* If Confirm3 returns -1, there's nothing more we can * do, but fortunately worst case is that there is a * domain left in 'paused' state on source. @@ -4267,91 +4401,6 @@ cleanup: } -int qemuMigrationConfirm(virQEMUDriverPtr driver, - virConnectPtr conn, - virDomainObjPtr vm, - const char *cookiein, - int cookieinlen, - unsigned int flags, - int retcode) -{ - qemuMigrationCookiePtr mig; - virDomainEventPtr event = NULL; - int rv = -1; - virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver); - - VIR_DEBUG("driver=%p, conn=%p, vm=%p, cookiein=%s, cookieinlen=%d, " - "flags=%x, retcode=%d", - driver, conn, vm, NULLSTR(cookiein), cookieinlen, - flags, retcode); - - virCheckFlags(QEMU_MIGRATION_FLAGS, -1); - - qemuMigrationJobSetPhase(driver, vm, - retcode == 0 - ? QEMU_MIGRATION_PHASE_CONFIRM3 - : QEMU_MIGRATION_PHASE_CONFIRM3_CANCELLED); - - if (!(mig = qemuMigrationEatCookie(driver, vm, cookiein, cookieinlen, 0))) - goto cleanup; - - if (flags & VIR_MIGRATE_OFFLINE) - goto done; - - /* Did the migration go as planned? If yes, kill off the - * domain object, but if no, resume CPUs - */ - if (retcode == 0) { - /* If guest uses SPICE and supports seamless migration we have to hold - * up domain shutdown until SPICE server transfers its data */ - qemuMigrationWaitForSpice(driver, vm); - - qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_MIGRATED, - VIR_QEMU_PROCESS_STOP_MIGRATED); - virDomainAuditStop(vm, "migrated"); - - event = virDomainEventNewFromObj(vm, - VIR_DOMAIN_EVENT_STOPPED, - VIR_DOMAIN_EVENT_STOPPED_MIGRATED); - } else { - - /* cancel any outstanding NBD jobs */ - qemuMigrationCancelDriveMirror(mig, driver, vm); - - /* run 'cont' on the destination, which allows migration on qemu - * >= 0.10.6 to work properly. This isn't strictly necessary on - * older qemu's, but it also doesn't hurt anything there - */ - if (qemuProcessStartCPUs(driver, vm, conn, - VIR_DOMAIN_RUNNING_MIGRATED, - QEMU_ASYNC_JOB_MIGRATION_OUT) < 0) { - if (virGetLastError() == NULL) - virReportError(VIR_ERR_INTERNAL_ERROR, - "%s", _("resume operation failed")); - goto cleanup; - } - - event = virDomainEventNewFromObj(vm, - VIR_DOMAIN_EVENT_RESUMED, - VIR_DOMAIN_EVENT_RESUMED_MIGRATED); - if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0) { - VIR_WARN("Failed to save status on vm %s", vm->def->name); - goto cleanup; - } - } - -done: - qemuMigrationCookieFree(mig); - rv = 0; - -cleanup: - if (event) - qemuDomainEventQueue(driver, event); - virObjectUnref(cfg); - return rv; -} - - /* Helper function called while vm is active. */ int qemuMigrationToFile(virQEMUDriverPtr driver, virDomainObjPtr vm, diff --git a/src/qemu/qemu_migration.h b/src/qemu/qemu_migration.h index fdca583..dd1d0a1 100644 --- a/src/qemu/qemu_migration.h +++ b/src/qemu/qemu_migration.h @@ -143,13 +143,12 @@ virDomainPtr qemuMigrationFinish(virQEMUDriverPtr driver, int retcode, bool v3proto); -int qemuMigrationConfirm(virQEMUDriverPtr driver, - virConnectPtr conn, +int qemuMigrationConfirm(virConnectPtr conn, virDomainObjPtr vm, const char *cookiein, int cookieinlen, unsigned int flags, - int retcode); + int cancelled); bool qemuMigrationIsAllowed(virQEMUDriverPtr driver, virDomainObjPtr vm, virDomainDefPtr def, bool remote, -- 1.8.2.1

On Tue, Jun 25, 2013 at 03:59:46PM +0200, Jiri Denemark wrote:
--- src/qemu/qemu_driver.c | 43 ++------- src/qemu/qemu_migration.c | 225 ++++++++++++++++++++++++++++------------------ src/qemu/qemu_migration.h | 5 +- 3 files changed, 144 insertions(+), 129 deletions(-)
ACK Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

--- src/qemu/qemu_driver.c | 302 ++++++++++++++++++++++++++++++++++++++++++++-- src/qemu/qemu_migration.c | 162 ++++++++++++++++++------- src/qemu/qemu_migration.h | 9 ++ 3 files changed, 417 insertions(+), 56 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index e2b85c0..cedec91 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -1095,6 +1095,7 @@ qemuConnectSupportsFeature(virConnectPtr conn, int feature) case VIR_DRV_FEATURE_TYPED_PARAM_STRING: case VIR_DRV_FEATURE_XML_MIGRATABLE: case VIR_DRV_FEATURE_MIGRATION_OFFLINE: + case VIR_DRV_FEATURE_MIGRATION_PARAMS: return 1; default: return 0; @@ -10173,6 +10174,43 @@ qemuDomainMigrateBegin3(virDomainPtr domain, cookieout, cookieoutlen, flags); } +static char * +qemuDomainMigrateBegin3Params(virDomainPtr domain, + virTypedParameterPtr params, + int nparams, + char **cookieout, + int *cookieoutlen, + unsigned int flags) +{ + const char *xmlin = NULL; + const char *dname = NULL; + virDomainObjPtr vm; + + virCheckFlags(QEMU_MIGRATION_FLAGS, NULL); + if (virTypedParamsValidate(params, nparams, QEMU_MIGRATION_PARAMETERS) < 0) + return NULL; + + if (virTypedParamsGetString(params, nparams, + VIR_MIGRATE_PARAM_DEST_XML, + &xmlin) < 0 || + virTypedParamsGetString(params, nparams, + VIR_MIGRATE_PARAM_DEST_NAME, + &dname) < 0) + return NULL; + + if (!(vm = qemuDomObjFromDomain(domain))) + return NULL; + + if (virDomainMigrateBegin3ParamsEnsureACL(domain->conn, vm->def) < 0) { + virObjectUnlock(vm); + return NULL; + } + + return qemuMigrationBegin(domain->conn, vm, xmlin, dname, + cookieout, cookieoutlen, flags); +} + + static int qemuDomainMigratePrepare3(virConnectPtr dconn, const char *cookiein, @@ -10219,6 +10257,66 @@ cleanup: return ret; } +static int +qemuDomainMigratePrepare3Params(virConnectPtr dconn, + virTypedParameterPtr params, + int nparams, + const char *cookiein, + int cookieinlen, + char **cookieout, + int *cookieoutlen, + char **uri_out, + unsigned int flags) +{ + virQEMUDriverPtr driver = dconn->privateData; + virDomainDefPtr def = NULL; + const char *dom_xml = NULL; + const char *dname = NULL; + const char *uri_in = NULL; + int ret = -1; + + virCheckFlags(QEMU_MIGRATION_FLAGS, -1); + if (virTypedParamsValidate(params, nparams, QEMU_MIGRATION_PARAMETERS) < 0) + return -1; + + if (virTypedParamsGetString(params, nparams, + VIR_MIGRATE_PARAM_DEST_XML, + &dom_xml) < 0 || + virTypedParamsGetString(params, nparams, + VIR_MIGRATE_PARAM_DEST_NAME, + &dname) < 0 || + virTypedParamsGetString(params, nparams, + VIR_MIGRATE_PARAM_URI, + &uri_in) < 0) + return -1; + + if (flags & VIR_MIGRATE_TUNNELLED) { + /* this is a logical error; we never should have gotten here with + * VIR_MIGRATE_TUNNELLED set + */ + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Tunnelled migration requested but invalid " + "RPC method called")); + goto cleanup; + } + + if (!(def = qemuMigrationPrepareDef(driver, dom_xml, dname))) + goto cleanup; + + if (virDomainMigratePrepare3ParamsEnsureACL(dconn, def) < 0) + goto cleanup; + + ret = qemuMigrationPrepareDirect(driver, dconn, + cookiein, cookieinlen, + cookieout, cookieoutlen, + uri_in, uri_out, + &def, flags); + +cleanup: + virDomainDefFree(def); + return ret; +} + static int qemuDomainMigratePrepareTunnel3(virConnectPtr dconn, @@ -10260,6 +10358,57 @@ cleanup: return ret; } +static int +qemuDomainMigratePrepareTunnel3Params(virConnectPtr dconn, + virStreamPtr st, + virTypedParameterPtr params, + int nparams, + const char *cookiein, + int cookieinlen, + char **cookieout, + int *cookieoutlen, + unsigned int flags) +{ + virQEMUDriverPtr driver = dconn->privateData; + virDomainDefPtr def = NULL; + const char *dom_xml = NULL; + const char *dname = NULL; + int ret = -1; + + virCheckFlags(QEMU_MIGRATION_FLAGS, -1); + if (virTypedParamsValidate(params, nparams, QEMU_MIGRATION_PARAMETERS) < 0) + return -1; + + if (virTypedParamsGetString(params, nparams, + VIR_MIGRATE_PARAM_DEST_XML, + &dom_xml) < 0 || + virTypedParamsGetString(params, nparams, + VIR_MIGRATE_PARAM_DEST_NAME, + &dname) < 0) + return -1; + + if (!(flags & VIR_MIGRATE_TUNNELLED)) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("PrepareTunnel called but no TUNNELLED flag set")); + goto cleanup; + } + + if (!(def = qemuMigrationPrepareDef(driver, dom_xml, dname))) + goto cleanup; + + if (virDomainMigratePrepareTunnel3ParamsEnsureACL(dconn, def) < 0) + goto cleanup; + + ret = qemuMigrationPrepareTunnel(driver, dconn, + cookiein, cookieinlen, + cookieout, cookieoutlen, + st, &def, flags); + +cleanup: + virDomainDefFree(def); + return ret; +} + static int qemuDomainMigratePerform3(virDomainPtr dom, @@ -10293,6 +10442,56 @@ qemuDomainMigratePerform3(virDomainPtr dom, flags, dname, resource, true); } +static int +qemuDomainMigratePerform3Params(virDomainPtr dom, + const char *dconnuri, + virTypedParameterPtr params, + int nparams, + const char *cookiein, + int cookieinlen, + char **cookieout, + int *cookieoutlen, + unsigned int flags) +{ + virQEMUDriverPtr driver = dom->conn->privateData; + virDomainObjPtr vm; + const char *dom_xml = NULL; + const char *dname = NULL; + const char *uri = NULL; + unsigned long long bandwidth = 0; + + virCheckFlags(QEMU_MIGRATION_FLAGS, -1); + if (virTypedParamsValidate(params, nparams, QEMU_MIGRATION_PARAMETERS) < 0) + return -1; + + if (virTypedParamsGetString(params, nparams, + VIR_MIGRATE_PARAM_DEST_XML, + &dom_xml) < 0 || + virTypedParamsGetString(params, nparams, + VIR_MIGRATE_PARAM_DEST_NAME, + &dname) < 0 || + virTypedParamsGetString(params, nparams, + VIR_MIGRATE_PARAM_URI, + &uri) < 0 || + virTypedParamsGetULLong(params, nparams, + VIR_MIGRATE_PARAM_BANDWIDTH, + &bandwidth) < 0) + return -1; + + if (!(vm = qemuDomObjFromDomain(dom))) + return -1; + + if (virDomainMigratePerform3ParamsEnsureACL(dom->conn, vm->def) < 0) { + virObjectUnlock(vm); + return -1; + } + + return qemuMigrationPerform(driver, dom->conn, vm, dom_xml, + dconnuri, uri, cookiein, cookieinlen, + cookieout, cookieoutlen, + flags, dname, bandwidth, true); +} + static virDomainPtr qemuDomainMigrateFinish3(virConnectPtr dconn, @@ -10308,29 +10507,72 @@ qemuDomainMigrateFinish3(virConnectPtr dconn, { virQEMUDriverPtr driver = dconn->privateData; virDomainObjPtr vm; - virDomainPtr dom = NULL; virCheckFlags(QEMU_MIGRATION_FLAGS, NULL); - vm = virDomainObjListFindByName(driver->domains, dname); - if (!vm) { + if (!dname || + !(vm = virDomainObjListFindByName(driver->domains, dname))) { virReportError(VIR_ERR_NO_DOMAIN, - _("no domain with matching name '%s'"), dname); - goto cleanup; + _("no domain with matching name '%s'"), + NULLSTR(dname)); + return NULL; } - if (virDomainMigrateFinish3EnsureACL(dconn, vm->def) < 0) - goto cleanup; + if (virDomainMigrateFinish3EnsureACL(dconn, vm->def) < 0) { + virObjectUnlock(vm); + return NULL; + } - dom = qemuMigrationFinish(driver, dconn, vm, - cookiein, cookieinlen, - cookieout, cookieoutlen, - flags, cancelled, true); + return qemuMigrationFinish(driver, dconn, vm, + cookiein, cookieinlen, + cookieout, cookieoutlen, + flags, cancelled, true); +} -cleanup: - return dom; +static virDomainPtr +qemuDomainMigrateFinish3Params(virConnectPtr dconn, + virTypedParameterPtr params, + int nparams, + const char *cookiein, + int cookieinlen, + char **cookieout, + int *cookieoutlen, + unsigned int flags, + int cancelled) +{ + virQEMUDriverPtr driver = dconn->privateData; + virDomainObjPtr vm; + const char *dname = NULL; + + virCheckFlags(QEMU_MIGRATION_FLAGS, NULL); + if (virTypedParamsValidate(params, nparams, QEMU_MIGRATION_PARAMETERS) < 0) + return NULL; + + if (virTypedParamsGetString(params, nparams, + VIR_MIGRATE_PARAM_DEST_NAME, + &dname) < 0) + return NULL; + + if (!dname || + !(vm = virDomainObjListFindByName(driver->domains, dname))) { + virReportError(VIR_ERR_NO_DOMAIN, + _("no domain with matching name '%s'"), + NULLSTR(dname)); + return NULL; + } + + if (virDomainMigrateFinish3ParamsEnsureACL(dconn, vm->def) < 0) { + virObjectUnlock(vm); + return NULL; + } + + return qemuMigrationFinish(driver, dconn, vm, + cookiein, cookieinlen, + cookieout, cookieoutlen, + flags, cancelled, true); } + static int qemuDomainMigrateConfirm3(virDomainPtr domain, const char *cookiein, @@ -10354,6 +10596,34 @@ qemuDomainMigrateConfirm3(virDomainPtr domain, flags, cancelled); } +static int +qemuDomainMigrateConfirm3Params(virDomainPtr domain, + virTypedParameterPtr params, + int nparams, + const char *cookiein, + int cookieinlen, + unsigned int flags, + int cancelled) +{ + virDomainObjPtr vm; + + virCheckFlags(QEMU_MIGRATION_FLAGS, -1); + + if (virTypedParamsValidate(params, nparams, QEMU_MIGRATION_PARAMETERS) < 0) + return -1; + + if (!(vm = qemuDomObjFromDomain(domain))) + return -1; + + if (virDomainMigrateConfirm3ParamsEnsureACL(domain->conn, vm->def) < 0) { + virObjectUnlock(vm); + return -1; + } + + return qemuMigrationConfirm(domain->conn, vm, cookiein, cookieinlen, + flags, cancelled); +} + static int qemuNodeDeviceGetPciInfo(virNodeDeviceDefPtr def, @@ -15776,6 +16046,12 @@ static virDriver qemuDriver = { .nodeGetCPUMap = qemuNodeGetCPUMap, /* 1.0.0 */ .domainFSTrim = qemuDomainFSTrim, /* 1.0.1 */ .domainOpenChannel = qemuDomainOpenChannel, /* 1.0.2 */ + .domainMigrateBegin3Params = qemuDomainMigrateBegin3Params, /* 1.1.0 */ + .domainMigratePrepare3Params = qemuDomainMigratePrepare3Params, /* 1.1.0 */ + .domainMigratePrepareTunnel3Params = qemuDomainMigratePrepareTunnel3Params, /* 1.1.0 */ + .domainMigratePerform3Params = qemuDomainMigratePerform3Params, /* 1.1.0 */ + .domainMigrateFinish3Params = qemuDomainMigrateFinish3Params, /* 1.1.0 */ + .domainMigrateConfirm3Params = qemuDomainMigrateConfirm3Params, /* 1.1.0 */ }; diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index 66d62fe..d4a169e 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -56,6 +56,7 @@ #include "viruri.h" #include "virhook.h" #include "virstring.h" +#include "virtypedparam.h" #define VIR_FROM_THIS VIR_FROM_QEMU @@ -3564,16 +3565,18 @@ cleanup: * from libvirt.c, but running in source libvirtd context, * instead of client app context & also adding in tunnel * handling */ -static int doPeer2PeerMigrate3(virQEMUDriverPtr driver, - virConnectPtr sconn, - virConnectPtr dconn, - virDomainObjPtr vm, - const char *xmlin, - const char *dconnuri, - const char *uri, - unsigned long flags, - const char *dname, - unsigned long resource) +static int +doPeer2PeerMigrate3(virQEMUDriverPtr driver, + virConnectPtr sconn, + virConnectPtr dconn, + const char *dconnuri, + virDomainObjPtr vm, + const char *xmlin, + const char *dname, + const char *uri, + unsigned long long bandwidth, + bool useParams, + unsigned long flags) { virDomainPtr ddomain = NULL; char *uri_out = NULL; @@ -3584,15 +3587,18 @@ static int doPeer2PeerMigrate3(virQEMUDriverPtr driver, int cookieoutlen = 0; int ret = -1; virErrorPtr orig_err = NULL; - bool cancelled; + bool cancelled = true; virStreamPtr st = NULL; unsigned int destflags = flags & ~VIR_MIGRATE_ABORT_ON_ERROR; - VIR_DEBUG("driver=%p, sconn=%p, dconn=%p, vm=%p, xmlin=%s, " - "dconnuri=%s, uri=%s, flags=%lx, dname=%s, resource=%lu", - driver, sconn, dconn, vm, NULLSTR(xmlin), - NULLSTR(dconnuri), NULLSTR(uri), flags, - NULLSTR(dname), resource); + virTypedParameterPtr params = NULL; + int nparams = 0; + 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", + driver, sconn, dconn, NULLSTR(dconnuri), vm, NULLSTR(xmlin), + NULLSTR(dname), NULLSTR(uri), bandwidth, useParams, flags); /* Unlike the virDomainMigrateVersion3 counterpart, we don't need * to worry about auto-setting the VIR_MIGRATE_CHANGE_PROTECTION @@ -3604,6 +3610,28 @@ static int doPeer2PeerMigrate3(virQEMUDriverPtr driver, if (!dom_xml) goto cleanup; + if (useParams) { + if (virTypedParamsAddString(¶ms, &nparams, &maxparams, + VIR_MIGRATE_PARAM_DEST_XML, dom_xml) < 0) + goto cleanup; + + if (dname && + virTypedParamsAddString(¶ms, &nparams, &maxparams, + VIR_MIGRATE_PARAM_DEST_NAME, dname) < 0) + goto cleanup; + + if (uri && + virTypedParamsAddString(¶ms, &nparams, &maxparams, + VIR_MIGRATE_PARAM_URI, uri) < 0) + goto cleanup; + + if (bandwidth && + virTypedParamsAddULLong(¶ms, &nparams, &maxparams, + VIR_MIGRATE_PARAM_BANDWIDTH, + bandwidth) < 0) + goto cleanup; + } + if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_PAUSED) flags |= VIR_MIGRATE_PAUSED; @@ -3617,16 +3645,27 @@ static int doPeer2PeerMigrate3(virQEMUDriverPtr driver, goto cleanup; qemuDomainObjEnterRemote(vm); - ret = dconn->driver->domainMigratePrepareTunnel3 - (dconn, st, cookiein, cookieinlen, - &cookieout, &cookieoutlen, - destflags, dname, resource, dom_xml); + if (useParams) { + ret = dconn->driver->domainMigratePrepareTunnel3Params + (dconn, st, params, nparams, cookiein, cookieinlen, + &cookieout, &cookieoutlen, destflags); + } else { + ret = dconn->driver->domainMigratePrepareTunnel3 + (dconn, st, cookiein, cookieinlen, &cookieout, &cookieoutlen, + destflags, dname, bandwidth, dom_xml); + } qemuDomainObjExitRemote(vm); } else { qemuDomainObjEnterRemote(vm); - ret = dconn->driver->domainMigratePrepare3 - (dconn, cookiein, cookieinlen, &cookieout, &cookieoutlen, - uri, &uri_out, destflags, dname, resource, dom_xml); + if (useParams) { + ret = dconn->driver->domainMigratePrepare3Params + (dconn, params, nparams, cookiein, cookieinlen, + &cookieout, &cookieoutlen, &uri_out, destflags); + } else { + ret = dconn->driver->domainMigratePrepare3 + (dconn, cookiein, cookieinlen, &cookieout, &cookieoutlen, + uri, &uri_out, destflags, dname, bandwidth, dom_xml); + } qemuDomainObjExitRemote(vm); } VIR_FREE(dom_xml); @@ -3641,11 +3680,15 @@ static int doPeer2PeerMigrate3(virQEMUDriverPtr driver, goto finish; } - if (!(flags & VIR_MIGRATE_TUNNELLED) && - (uri_out == NULL)) { + if (uri_out) { + uri = uri_out; + if (useParams && + virTypedParamsReplaceString(¶ms, &nparams, + VIR_MIGRATE_PARAM_URI, uri_out) < 0) + goto finish; + } else if (!uri && !(flags & VIR_MIGRATE_TUNNELLED)) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("domainMigratePrepare3 did not set uri")); - cancelled = true; goto finish; } @@ -3654,23 +3697,24 @@ static int doPeer2PeerMigrate3(virQEMUDriverPtr driver, * running, but in paused state until the destination can * confirm migration completion. */ - VIR_DEBUG("Perform3 %p uri=%s uri_out=%s", sconn, uri, uri_out); + VIR_DEBUG("Perform3 %p uri=%s", sconn, NULLSTR(uri)); qemuMigrationJobSetPhase(driver, vm, QEMU_MIGRATION_PHASE_PERFORM3); VIR_FREE(cookiein); cookiein = cookieout; cookieinlen = cookieoutlen; cookieout = NULL; cookieoutlen = 0; - if (flags & VIR_MIGRATE_TUNNELLED) + if (flags & VIR_MIGRATE_TUNNELLED) { ret = doTunnelMigrate(driver, vm, st, cookiein, cookieinlen, &cookieout, &cookieoutlen, - flags, resource, dconn); - else - ret = doNativeMigrate(driver, vm, uri_out, + flags, bandwidth, dconn); + } else { + ret = doNativeMigrate(driver, vm, uri, cookiein, cookieinlen, &cookieout, &cookieoutlen, - flags, resource, dconn); + flags, bandwidth, dconn); + } /* Perform failed. Make sure Finish doesn't overwrite the error */ if (ret < 0) { @@ -3698,12 +3742,29 @@ finish: cookieinlen = cookieoutlen; cookieout = NULL; cookieoutlen = 0; - dname = dname ? dname : vm->def->name; - qemuDomainObjEnterRemote(vm); - ddomain = dconn->driver->domainMigrateFinish3 - (dconn, dname, cookiein, cookieinlen, &cookieout, &cookieoutlen, - dconnuri, uri_out ? uri_out : uri, destflags, cancelled); - qemuDomainObjExitRemote(vm); + + if (useParams) { + if (virTypedParamsGetString(params, nparams, + VIR_MIGRATE_PARAM_DEST_NAME, NULL) <= 0 && + virTypedParamsReplaceString(¶ms, &nparams, + VIR_MIGRATE_PARAM_DEST_NAME, + vm->def->name) < 0) { + ddomain = NULL; + } else { + qemuDomainObjEnterRemote(vm); + ddomain = dconn->driver->domainMigrateFinish3Params + (dconn, params, nparams, cookiein, cookieinlen, + &cookieout, &cookieoutlen, destflags, cancelled); + qemuDomainObjExitRemote(vm); + } + } else { + dname = dname ? dname : vm->def->name; + qemuDomainObjEnterRemote(vm); + ddomain = dconn->driver->domainMigrateFinish3 + (dconn, dname, cookiein, cookieinlen, &cookieout, &cookieoutlen, + dconnuri, uri, destflags, cancelled); + qemuDomainObjExitRemote(vm); + } /* If ddomain is NULL, then we were unable to start * the guest on the target, and must restart on the @@ -3759,7 +3820,7 @@ finish: VIR_FREE(uri_out); VIR_FREE(cookiein); VIR_FREE(cookieout); - + virTypedParamsFree(params, nparams); return ret; } @@ -3781,6 +3842,7 @@ static int doPeer2PeerMigrate(virQEMUDriverPtr driver, virErrorPtr orig_err = NULL; bool offline = false; virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver); + bool useParams; VIR_DEBUG("driver=%p, sconn=%p, vm=%p, xmlin=%s, dconnuri=%s, " "uri=%s, flags=%lx, dname=%s, resource=%lu", @@ -3815,6 +3877,8 @@ static int doPeer2PeerMigrate(virQEMUDriverPtr driver, */ *v3proto = VIR_DRV_SUPPORTS_FEATURE(dconn->driver, dconn, VIR_DRV_FEATURE_MIGRATION_V3); + useParams = VIR_DRV_SUPPORTS_FEATURE(dconn->driver, dconn, + VIR_DRV_FEATURE_MIGRATION_PARAMS); if (flags & VIR_MIGRATE_OFFLINE) offline = VIR_DRV_SUPPORTS_FEATURE(dconn->driver, dconn, VIR_DRV_FEATURE_MIGRATION_OFFLINE); @@ -3826,6 +3890,17 @@ static int doPeer2PeerMigrate(virQEMUDriverPtr driver, goto cleanup; } + /* Only xmlin, dname, uri, and bandwidth parameters can be used with + * old-style APIs. */ +#if 0 + if (!useParams && /* any new parameter */) { + virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s", + _("Migration APIs with extensible parameters are not " + "supported but extended parameters were passed")); + goto cleanup; + } +#endif + if (flags & VIR_MIGRATE_OFFLINE && !offline) { virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s", _("offline migration is not supported by " @@ -3847,12 +3922,13 @@ static int doPeer2PeerMigrate(virQEMUDriverPtr driver, * Therefore it is safe to clear the bit here. */ flags &= ~VIR_MIGRATE_CHANGE_PROTECTION; - if (*v3proto) - ret = doPeer2PeerMigrate3(driver, sconn, dconn, vm, xmlin, - dconnuri, uri, flags, dname, resource); - else + if (*v3proto) { + ret = doPeer2PeerMigrate3(driver, sconn, dconn, dconnuri, vm, xmlin, + dname, uri, resource, useParams, flags); + } else { ret = doPeer2PeerMigrate2(driver, sconn, dconn, vm, dconnuri, flags, dname, resource); + } cleanup: orig_err = virSaveLastError(); diff --git a/src/qemu/qemu_migration.h b/src/qemu/qemu_migration.h index dd1d0a1..469c948 100644 --- a/src/qemu/qemu_migration.h +++ b/src/qemu/qemu_migration.h @@ -41,6 +41,15 @@ VIR_MIGRATE_COMPRESSED | \ VIR_MIGRATE_ABORT_ON_ERROR) +/* All supported migration parameters and their types. */ +# define QEMU_MIGRATION_PARAMETERS \ + VIR_MIGRATE_PARAM_URI, VIR_TYPED_PARAM_STRING, \ + 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, \ + NULL + + enum qemuMigrationJobPhase { QEMU_MIGRATION_PHASE_NONE = 0, QEMU_MIGRATION_PHASE_PERFORM2, -- 1.8.2.1

On Tue, Jun 25, 2013 at 03:59:47PM +0200, Jiri Denemark wrote:
--- src/qemu/qemu_driver.c | 302 ++++++++++++++++++++++++++++++++++++++++++++-- src/qemu/qemu_migration.c | 162 ++++++++++++++++++------- src/qemu/qemu_migration.h | 9 ++ 3 files changed, 417 insertions(+), 56 deletions(-)
ACK Danielx -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

--- src/qemu/qemu_driver.c | 14 ++-- src/qemu/qemu_migration.c | 189 +++++++++++++++++++++++++++++++--------------- src/qemu/qemu_migration.h | 2 + 3 files changed, 140 insertions(+), 65 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index cedec91..127abfe 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -10097,7 +10097,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); @@ -10437,7 +10437,7 @@ qemuDomainMigratePerform3(virDomainPtr dom, } return qemuMigrationPerform(driver, dom->conn, vm, xmlin, - dconnuri, uri, cookiein, cookieinlen, + dconnuri, uri, NULL, cookiein, cookieinlen, cookieout, cookieoutlen, flags, dname, resource, true); } @@ -10458,6 +10458,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); @@ -10475,7 +10476,10 @@ 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))) @@ -10487,8 +10491,8 @@ qemuDomainMigratePerform3Params(virDomainPtr dom, } 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 d4a169e..69d5398 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; } @@ -3046,7 +3089,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; @@ -3061,10 +3105,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; @@ -3090,7 +3135,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 */ @@ -3284,7 +3329,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; @@ -3292,9 +3338,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; @@ -3320,7 +3368,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); @@ -3340,7 +3389,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; @@ -3349,9 +3399,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) && @@ -3405,7 +3457,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) { @@ -3511,12 +3564,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) @@ -3574,6 +3627,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) @@ -3596,9 +3650,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 @@ -3630,6 +3686,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) @@ -3708,12 +3770,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 */ @@ -3831,6 +3893,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, @@ -3845,9 +3908,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 @@ -3892,14 +3956,12 @@ static int doPeer2PeerMigrate(virQEMUDriverPtr driver, /* Only xmlin, dname, uri, and bandwidth parameters can be used with * old-style APIs. */ -#if 0 - if (!useParams && /* any new parameter */) { + if (!useParams && graphicsuri) { virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s", _("Migration APIs with extensible parameters are not " "supported but extended parameters were passed")); goto cleanup; } -#endif if (flags & VIR_MIGRATE_OFFLINE && !offline) { virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s", @@ -3924,7 +3986,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); @@ -3956,6 +4019,7 @@ qemuMigrationPerformJob(virQEMUDriverPtr driver, const char *xmlin, const char *dconnuri, const char *uri, + const char *graphicsuri, const char *cookiein, int cookieinlen, char **cookieout, @@ -3991,13 +4055,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; @@ -4071,6 +4135,7 @@ qemuMigrationPerformPhase(virQEMUDriverPtr driver, virConnectPtr conn, virDomainObjPtr vm, const char *uri, + const char *graphicsuri, const char *cookiein, int cookieinlen, char **cookieout, @@ -4098,7 +4163,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) { @@ -4155,6 +4220,7 @@ qemuMigrationPerform(virQEMUDriverPtr driver, const char *xmlin, const char *dconnuri, const char *uri, + const char *graphicsuri, const char *cookiein, int cookieinlen, char **cookieout, @@ -4165,12 +4231,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) { @@ -4180,9 +4247,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, @@ -4192,12 +4259,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 469c948..43b26de 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 @@ -132,6 +133,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

On Tue, Jun 25, 2013 at 03:59:48PM +0200, Jiri Denemark wrote:
--- src/qemu/qemu_driver.c | 14 ++-- src/qemu/qemu_migration.c | 189 +++++++++++++++++++++++++++++++--------------- src/qemu/qemu_migration.h | 2 + 3 files changed, 140 insertions(+), 65 deletions(-)
ACK Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

On Tue, Jun 25, 2013 at 15:59:43 +0200, Jiri Denemark wrote:
These are the patches for qemu driver that were already acked but had to be reworked due to the introduction of ACL checks.
Jiri Denemark (5): qemu: Move internals of Begin phase to qemu_migration.c qemu: Move common parts of Prepare phase to qemu_migration.c qemu: Move internals of Confirm phase to qemu_migration.c Implement extensible migration APIs in qemu driver qemu: Implement support for VIR_MIGRATE_PARAM_GRAPHICS_URI
src/qemu/qemu_driver.c | 506 ++++++++++++++++++++-------------- src/qemu/qemu_migration.c | 690 +++++++++++++++++++++++++++++++++------------- src/qemu/qemu_migration.h | 22 +- 3 files changed, 825 insertions(+), 393 deletions(-)
I pushed these remaining patches, thanks for the quick review. Jirka
participants (2)
-
Daniel P. Berrange
-
Jiri Denemark