[libvirt] [PATCH 11/21] Implement extensible migration APIs in qemu driver

Jiri Denemark jdenemar at redhat.com
Tue Jun 18 14:05:53 UTC 2013


---
 src/qemu/qemu_driver.c    | 350 +++++++++++++++++++++++++++++++++++++++-------
 src/qemu/qemu_migration.c | 162 +++++++++++++++------
 src/qemu/qemu_migration.h |   9 ++
 3 files changed, 431 insertions(+), 90 deletions(-)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index a682e36..c040287 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -1086,6 +1086,7 @@ qemuConnectSupportsFeature(virConnectPtr conn ATTRIBUTE_UNUSED, 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;
@@ -9887,21 +9888,18 @@ cleanup:
  *******************************************************************/
 
 static char *
-qemuDomainMigrateBegin3(virDomainPtr domain,
-                        const char *xmlin,
-                        char **cookieout,
-                        int *cookieoutlen,
-                        unsigned long flags,
-                        const char *dname,
-                        unsigned long resource ATTRIBUTE_UNUSED)
+qemuDomainMigrateBegin3Internal(virDomainPtr domain,
+                                const char *xmlin,
+                                const char *dname,
+                                char **cookieout,
+                                int *cookieoutlen,
+                                unsigned long flags)
 {
     virQEMUDriverPtr driver = domain->conn->privateData;
     virDomainObjPtr vm;
     char *xml = NULL;
     enum qemuDomainAsyncJob asyncJob;
 
-    virCheckFlags(QEMU_MIGRATION_FLAGS, NULL);
-
     if (!(vm = qemuDomObjFromDomain(domain)))
         return NULL;
 
@@ -9969,26 +9967,66 @@ endjob:
     goto cleanup;
 }
 
+static char *
+qemuDomainMigrateBegin3(virDomainPtr domain,
+                        const char *xmlin,
+                        char **cookieout,
+                        int *cookieoutlen,
+                        unsigned long flags,
+                        const char *dname,
+                        unsigned long resource ATTRIBUTE_UNUSED)
+{
+    virCheckFlags(QEMU_MIGRATION_FLAGS, NULL);
+
+    return qemuDomainMigrateBegin3Internal(domain, xmlin, dname,
+                                           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;
+
+    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;
+
+    return qemuDomainMigrateBegin3Internal(domain, xmlin, dname,
+                                           cookieout, cookieoutlen, flags);
+}
+
+
 static int
-qemuDomainMigratePrepare3(virConnectPtr dconn,
-                          const char *cookiein,
-                          int cookieinlen,
-                          char **cookieout,
-                          int *cookieoutlen,
-                          const char *uri_in,
-                          char **uri_out,
-                          unsigned long flags,
-                          const char *dname,
-                          unsigned long resource ATTRIBUTE_UNUSED,
-                          const char *dom_xml)
+qemuDomainMigratePrepare3Internal(virConnectPtr dconn,
+                                  const char *dom_xml,
+                                  const char *dname,
+                                  const char *uri_in,
+                                  const char *cookiein,
+                                  int cookieinlen,
+                                  char **cookieout,
+                                  int *cookieoutlen,
+                                  char **uri_out,
+                                  unsigned long flags)
 {
     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) {
@@ -10032,26 +10070,78 @@ cleanup:
     return ret;
 }
 
+static int
+qemuDomainMigratePrepare3(virConnectPtr dconn,
+                          const char *cookiein,
+                          int cookieinlen,
+                          char **cookieout,
+                          int *cookieoutlen,
+                          const char *uri_in,
+                          char **uri_out,
+                          unsigned long flags,
+                          const char *dname,
+                          unsigned long resource ATTRIBUTE_UNUSED,
+                          const char *dom_xml)
+{
+    virCheckFlags(QEMU_MIGRATION_FLAGS, -1);
+
+    return qemuDomainMigratePrepare3Internal(dconn, dom_xml, dname, uri_in,
+                                             cookiein, cookieinlen, cookieout,
+                                             cookieoutlen, uri_out, flags);
+}
 
 static int
-qemuDomainMigratePrepareTunnel3(virConnectPtr dconn,
-                                virStreamPtr st,
+qemuDomainMigratePrepare3Params(virConnectPtr dconn,
+                                virTypedParameterPtr params,
+                                int nparams,
                                 const char *cookiein,
                                 int cookieinlen,
                                 char **cookieout,
                                 int *cookieoutlen,
-                                unsigned long flags,
-                                const char *dname,
-                                unsigned long resource ATTRIBUTE_UNUSED,
-                                const char *dom_xml)
+                                char **uri_out,
+                                unsigned int flags)
+{
+    const char *dom_xml = NULL;
+    const char *dname = NULL;
+    const char *uri_in = NULL;
+
+    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;
+
+    return qemuDomainMigratePrepare3Internal(dconn, dom_xml, dname, uri_in,
+                                             cookiein, cookieinlen, cookieout,
+                                             cookieoutlen, uri_out, flags);
+}
+
+
+static int
+qemuDomainMigratePrepareTunnel3Internal(virConnectPtr dconn,
+                                        virStreamPtr st,
+                                        const char *dom_xml,
+                                        const char *dname,
+                                        const char *cookiein,
+                                        int cookieinlen,
+                                        char **cookieout,
+                                        int *cookieoutlen,
+                                        unsigned long flags)
 {
     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"));
@@ -10093,6 +10183,58 @@ cleanup:
     return ret;
 }
 
+static int
+qemuDomainMigratePrepareTunnel3(virConnectPtr dconn,
+                                virStreamPtr st,
+                                const char *cookiein,
+                                int cookieinlen,
+                                char **cookieout,
+                                int *cookieoutlen,
+                                unsigned long flags,
+                                const char *dname,
+                                unsigned long resource ATTRIBUTE_UNUSED,
+                                const char *dom_xml)
+{
+    virCheckFlags(QEMU_MIGRATION_FLAGS, -1);
+
+    return qemuDomainMigratePrepareTunnel3Internal(dconn, st, dom_xml, dname,
+                                                   cookiein, cookieinlen,
+                                                   cookieout, cookieoutlen,
+                                                   flags);
+}
+
+static int
+qemuDomainMigratePrepareTunnel3Params(virConnectPtr dconn,
+                                      virStreamPtr st,
+                                      virTypedParameterPtr params,
+                                      int nparams,
+                                      const char *cookiein,
+                                      int cookieinlen,
+                                      char **cookieout,
+                                      int *cookieoutlen,
+                                      unsigned int flags)
+{
+    const char *dom_xml = NULL;
+    const char *dname = NULL;
+
+    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;
+
+    return qemuDomainMigratePrepareTunnel3Internal(dconn, st, dom_xml, dname,
+                                                   cookiein, cookieinlen,
+                                                   cookieout, cookieoutlen,
+                                                   flags);
+}
+
 
 static int
 qemuDomainMigratePerform3(virDomainPtr dom,
@@ -10121,6 +10263,51 @@ 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;
+
+    return qemuMigrationPerform(driver, dom->conn, vm, dom_xml,
+                                dconnuri, uri, cookiein, cookieinlen,
+                                cookieout, cookieoutlen,
+                                flags, dname, bandwidth, true);
+}
+
 
 static virDomainPtr
 qemuDomainMigrateFinish3(virConnectPtr dconn,
@@ -10136,32 +10323,66 @@ 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 (!(vm = virDomainObjListFindByName(driver->domains, dname))) {
         virReportError(VIR_ERR_NO_DOMAIN,
                        _("no domain with matching name '%s'"), dname);
-        goto cleanup;
+        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;
+    }
+
+    return qemuMigrationFinish(driver, dconn, vm,
+                               cookiein, cookieinlen,
+                               cookieout, cookieoutlen,
+                               flags, cancelled, true);
 }
 
+
 static int
-qemuDomainMigrateConfirm3(virDomainPtr domain,
-                          const char *cookiein,
-                          int cookieinlen,
-                          unsigned long flags,
-                          int cancelled)
+qemuDomainMigrateConfirm3Internal(virDomainPtr domain,
+                                  const char *cookiein,
+                                  int cookieinlen,
+                                  unsigned long flags,
+                                  int cancelled)
 {
     virQEMUDriverPtr driver = domain->conn->privateData;
     virDomainObjPtr vm;
@@ -10169,8 +10390,6 @@ qemuDomainMigrateConfirm3(virDomainPtr domain,
     enum qemuMigrationJobPhase phase;
     virQEMUDriverConfigPtr cfg = NULL;
 
-    virCheckFlags(QEMU_MIGRATION_FLAGS, -1);
-
     if (!(vm = qemuDomObjFromDomain(domain)))
         return -1;
 
@@ -10209,6 +10428,37 @@ cleanup:
     return ret;
 }
 
+static int
+qemuDomainMigrateConfirm3(virDomainPtr domain,
+                          const char *cookiein,
+                          int cookieinlen,
+                          unsigned long flags,
+                          int cancelled)
+{
+    virCheckFlags(QEMU_MIGRATION_FLAGS, -1);
+
+    return qemuDomainMigrateConfirm3Internal(domain, cookiein, cookieinlen,
+                                             flags, cancelled);
+}
+
+static int
+qemuDomainMigrateConfirm3Params(virDomainPtr domain,
+                                virTypedParameterPtr params,
+                                int nparams,
+                                const char *cookiein,
+                                int cookieinlen,
+                                unsigned int flags,
+                                int cancelled)
+{
+    virCheckFlags(QEMU_MIGRATION_FLAGS, -1);
+
+    if (virTypedParamsValidate(params, nparams, QEMU_MIGRATION_PARAMETERS) < 0)
+        return -1;
+
+    return qemuDomainMigrateConfirm3Internal(domain, cookiein, cookieinlen,
+                                             flags, cancelled);
+}
+
 
 static int
 qemuNodeDeviceGetPciInfo(virNodeDevicePtr dev,
@@ -15378,6 +15628,12 @@ static virDriver qemuDriver = {
     .nodeGetCPUMap = qemuNodeGetCPUMap, /* 1.0.0 */
     .domainFSTrim = qemuDomainFSTrim, /* 1.0.1 */
     .domainOpenChannel = qemuDomainOpenChannel, /* 1.0.2 */
+    .domainMigrateBegin3Params = qemuDomainMigrateBegin3Params, /* 1.0.7 */
+    .domainMigratePrepare3Params = qemuDomainMigratePrepare3Params, /* 1.0.7 */
+    .domainMigratePrepareTunnel3Params = qemuDomainMigratePrepareTunnel3Params, /* 1.0.7 */
+    .domainMigratePerform3Params = qemuDomainMigratePerform3Params, /* 1.0.7 */
+    .domainMigrateFinish3Params = qemuDomainMigrateFinish3Params, /* 1.0.7 */
+    .domainMigrateConfirm3Params = qemuDomainMigrateConfirm3Params, /* 1.0.7 */
 };
 
 
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index 8de38fe..6243d75 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -55,6 +55,7 @@
 #include "viruri.h"
 #include "virhook.h"
 #include "virstring.h"
+#include "virtypedparam.h"
 
 #define VIR_FROM_THIS VIR_FROM_QEMU
 
@@ -3306,16 +3307,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;
@@ -3326,15 +3329,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
@@ -3346,6 +3352,28 @@ static int doPeer2PeerMigrate3(virQEMUDriverPtr driver,
     if (!dom_xml)
         goto cleanup;
 
+    if (useParams) {
+        if (virTypedParamsAddString(&params, &nparams, &maxparams,
+                                    VIR_MIGRATE_PARAM_DEST_XML, dom_xml) < 0)
+            goto cleanup;
+
+        if (dname &&
+            virTypedParamsAddString(&params, &nparams, &maxparams,
+                                    VIR_MIGRATE_PARAM_DEST_NAME, dname) < 0)
+            goto cleanup;
+
+        if (uri &&
+            virTypedParamsAddString(&params, &nparams, &maxparams,
+                                    VIR_MIGRATE_PARAM_URI, uri) < 0)
+            goto cleanup;
+
+        if (bandwidth &&
+            virTypedParamsAddULLong(&params, &nparams, &maxparams,
+                                    VIR_MIGRATE_PARAM_BANDWIDTH,
+                                    bandwidth) < 0)
+            goto cleanup;
+    }
+
     if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_PAUSED)
         flags |= VIR_MIGRATE_PAUSED;
 
@@ -3359,16 +3387,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);
@@ -3383,11 +3422,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(&params, &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;
     }
 
@@ -3396,23 +3439,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) {
@@ -3440,12 +3484,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(&params, &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
@@ -3501,7 +3562,7 @@ finish:
     VIR_FREE(uri_out);
     VIR_FREE(cookiein);
     VIR_FREE(cookieout);
-
+    virTypedParamsFree(params, nparams);
     return ret;
 }
 
@@ -3523,6 +3584,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",
@@ -3557,6 +3619,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);
@@ -3568,6 +3632,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 "
@@ -3589,12 +3664,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 5b21ca2..e44cf3b 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




More information about the libvir-list mailing list