[libvirt] [PATCH v5 2/5] vz: add migration backbone code

Daniel P. Berrange berrange at redhat.com
Wed Sep 9 13:47:44 UTC 2015


On Fri, Sep 04, 2015 at 05:18:03PM +0300, Nikolay Shirokovskiy wrote:
> From: nshirokovskiy at virtuozzo.com <nshirokovskiy at virtuozzo.com>
> 
> This patch makes basic vz migration possible. For example by virsh:
> 
> virsh -c vz:///system migrate $NAME vz+ssh://$DST/system --p2p
> 
> Vz migration is implemented as p2p migration. The reason
> is that vz sdk do all the job. The question may arise then
> why don't implement it as a direct migration. The reason
> is that we want to leverage rich libvirt authentication abilities
> we lack in vz sdk. We can do it because vz sdk can use tokens to
> factor out authentication from migration command.
> 
> Signed-off-by: Nikolay Shirokovskiy <nshirokovskiy at virtuozzo.com>
> ---
>  src/vz/vz_driver.c |  257 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>  src/vz/vz_sdk.c    |   33 +++++++
>  src/vz/vz_sdk.h    |    2 +
>  3 files changed, 292 insertions(+), 0 deletions(-)
> 
> diff --git a/src/vz/vz_driver.c b/src/vz/vz_driver.c
> index 8fa7957..36c64e9 100644
> --- a/src/vz/vz_driver.c
> +++ b/src/vz/vz_driver.c

> +static int
> +vzDomainMigratePerform3Params(virDomainPtr domain,
> +                              const char *dconnuri,
> +                              virTypedParameterPtr params,
> +                              int nparams,
> +                              const char *cookiein ATTRIBUTE_UNUSED,
> +                              int cookieinlen ATTRIBUTE_UNUSED,
> +                              char **cookieout ATTRIBUTE_UNUSED,
> +                              int *cookieoutlen ATTRIBUTE_UNUSED,
> +                              unsigned int flags)
> +{
> +    int ret = -1;
> +    virDomainObjPtr dom = NULL;
> +    virConnectPtr dconn = NULL;
> +    virURIPtr vzuri = NULL;
> +    unsigned char session_uuid[VIR_UUID_BUFLEN];
> +    vzConnPtr privconn = domain->conn->privateData;
> +    char *cookie = NULL;
> +    int cookielen = 0;
> +    const char *miguri = NULL;
> +
> +    virCheckFlags(VZ_MIGRATION_FLAGS, -1);
> +
> +    if (virTypedParamsValidate(params, nparams, VZ_MIGRATION_PARAMETERS) < 0)
> +        goto cleanup;
> +
> +    if (!(dom = vzDomObjFromDomain(domain)))
> +        goto cleanup;
> +
> +    dconn = virConnectOpen(dconnuri);
> +    if (dconn == NULL) {
> +        virReportError(VIR_ERR_OPERATION_FAILED,
> +                       _("Failed to connect to remote libvirt URI %s: %s"),
> +                       dconnuri, virGetLastErrorMessage());
> +        goto cleanup;
> +    }
> +
> +    if (virDomainMigratePrepare3Params(dconn, params, nparams, NULL, 0,
> +                                       &cookie, &cookielen,
> +                                       (char**)&miguri, flags) < 0)
> +        goto cleanup;
> +
> +    if (vzParseCookie(cookie, session_uuid) < 0)
> +        goto cleanup;
> +
> +    if (miguri == NULL &&
> +        virTypedParamsGetString(params, nparams,
> +                                VIR_MIGRATE_PARAM_URI, &miguri) < 0)
> +            goto cleanup;
> +
> +    if (miguri == NULL) {
> +        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> +                       _("domainMigratePrepare3Params did not set miguri"));
> +    }
> +
> +    if (!(vzuri = vzParseVzURI(miguri)))
> +        goto cleanup;
> +
> +    if (prlsdkMigrate(dom, vzuri, session_uuid) < 0)
> +        goto cleanup;
> +
> +    virDomainObjListRemove(privconn->domains, dom);
> +    dom = NULL;
> +
> +    ret = 0;
> +
> + cleanup:
> +    if (dom)
> +        virObjectUnlock(dom);
> +    virObjectUnref(dconn);
> +    virURIFree(vzuri);
> +    VIR_FREE(cookie);
> +
> +    return ret;
> +}
> +
>  static virHypervisorDriver vzDriver = {
>      .name = "vz",
>      .connectOpen = vzConnectOpen,            /* 0.10.0 */
> @@ -1396,6 +1650,9 @@ static virHypervisorDriver vzDriver = {
>      .domainBlockStatsFlags = vzDomainBlockStatsFlags, /* 1.2.17 */
>      .domainInterfaceStats = vzDomainInterfaceStats, /* 1.2.17 */
>      .domainMemoryStats = vzDomainMemoryStats, /* 1.2.17 */
> +    .connectSupportsFeature = vzConnectSupportsFeature, /* 1.2.20 */
> +    .domainMigratePrepare3Params = vzDomainMigratePrepare3Params, /* 1.2.20 */
> +    .domainMigratePerform3Params = vzDomainMigratePerform3Params, /* 1.2.20 */
>  };

As mentioned in the previous review, I really want to see VZ
provide the full set of drive callbacks required by the V3
migration protocol, not just those you happen to need to have
today. ie add Begin, Finish & Confirm.  This in turn makes it
quite easy to support non-P2P mode which is desirable because
in P2P mode there is no practical way todo interactive auth
for the destination connection, but in non-P2P mode the client
app opens the destination connection, so can do auth if needed.

I believe that the following changes to this patch should do
all that is required. NB, I have only compile tested this,
not actually run it, since I don't have an active VZ install,
only the SDK install.

This should work functionally identically with & without the
PEER2PEER flag being set by the caller.


diff --git a/src/vz/vz_driver.c b/src/vz/vz_driver.c
index 36c64e9..b160a3b 100644
--- a/src/vz/vz_driver.c
+++ b/src/vz/vz_driver.c
@@ -1398,6 +1398,7 @@ vzParseCookie(const char *xml, unsigned char *session_uuid)
 
 #define VZ_MIGRATION_PARAMETERS                                 \
     VIR_MIGRATE_PARAM_URI,              VIR_TYPED_PARAM_STRING, \
+    VIR_MIGRATE_PARAM_DEST_XML,         VIR_TYPED_PARAM_STRING, \
     NULL
 
 static char*
@@ -1425,49 +1426,6 @@ vzCreateMigrationURI(void)
 }
 
 static int
-vzDomainMigratePrepare3Params(virConnectPtr conn,
-                              virTypedParameterPtr params,
-                              int nparams,
-                              const char *cookiein ATTRIBUTE_UNUSED,
-                              int cookieinlen ATTRIBUTE_UNUSED,
-                              char **cookieout,
-                              int *cookieoutlen,
-                              char **uri_out,
-                              unsigned int flags)
-{
-    vzConnPtr privconn = conn->privateData;
-    const char *miguri = NULL;
-    int ret = -1;
-
-    virCheckFlags(VZ_MIGRATION_FLAGS, -1);
-
-    if (virTypedParamsValidate(params, nparams, VZ_MIGRATION_PARAMETERS) < 0)
-        goto cleanup;
-
-    if (virTypedParamsGetString(params, nparams,
-                                VIR_MIGRATE_PARAM_URI, &miguri) < 0)
-        goto cleanup;
-
-    /* This check is of par with direct managed imlementation */
-    if (miguri == NULL)
-        *uri_out = vzCreateMigrationURI();
-
-    if (!(*cookieout = vzFormatCookie(privconn->session_uuid)))
-        goto cleanup;
-    *cookieoutlen = strlen(*cookieout) + 1;
-    ret = 0;
-
- cleanup:
-    if (ret != 0) {
-        VIR_FREE(*cookieout);
-        *cookieoutlen = 0;
-        VIR_FREE(*uri_out);
-    }
-
-    return ret;
-}
-
-static int
 vzConnectSupportsFeature(virConnectPtr conn ATTRIBUTE_UNUSED, int feature)
 {
     switch (feature) {
@@ -1479,7 +1437,7 @@ vzConnectSupportsFeature(virConnectPtr conn ATTRIBUTE_UNUSED, int feature)
     }
 }
 
-virURIPtr
+static virURIPtr
 vzParseVzURI(const char *uri_str)
 {
     virURIPtr uri = NULL;
@@ -1521,64 +1479,128 @@ vzParseVzURI(const char *uri_str)
     return uri;
 }
 
+static char *
+vzDomainMigrateBegin3Params(virDomainPtr domain,
+                            virTypedParameterPtr params,
+                            int nparams,
+                            char **cookieout ATTRIBUTE_UNUSED,
+                            int *cookieoutlen ATTRIBUTE_UNUSED,
+                            unsigned int flags ATTRIBUTE_UNUSED)
+{
+    virDomainObjPtr privdom;
+    char *ret = NULL;
+
+    if (!(privdom = vzDomObjFromDomain(domain)))
+        goto cleanup;
+
+    if (virTypedParamsValidate(params, nparams, VZ_MIGRATION_PARAMETERS) < 0)
+        goto cleanup;
+
+    if (virTypedParamsGet(params, nparams, VIR_MIGRATE_PARAM_DEST_XML)) {
+        virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
+                       _("Changing destination XML is not supported"));
+        goto cleanup;
+    }
+
+    /* We don't really need the XML, but the Begin API requires it
+     * be returned anyway
+     */
+    ret = virDomainDefFormat(privdom->def, VIR_DOMAIN_XML_MIGRATABLE);
+
+ cleanup:
+    if (privdom)
+        virObjectUnlock(privdom);
+    return ret;
+
+}
+
 static int
-vzDomainMigratePerform3Params(virDomainPtr domain,
-                              const char *dconnuri,
+vzDomainMigratePrepare3Params(virConnectPtr conn,
                               virTypedParameterPtr params,
                               int nparams,
                               const char *cookiein ATTRIBUTE_UNUSED,
                               int cookieinlen ATTRIBUTE_UNUSED,
-                              char **cookieout ATTRIBUTE_UNUSED,
-                              int *cookieoutlen ATTRIBUTE_UNUSED,
+                              char **cookieout,
+                              int *cookieoutlen,
+                              char **uri_out,
                               unsigned int flags)
 {
-    int ret = -1;
-    virDomainObjPtr dom = NULL;
-    virConnectPtr dconn = NULL;
-    virURIPtr vzuri = NULL;
-    unsigned char session_uuid[VIR_UUID_BUFLEN];
-    vzConnPtr privconn = domain->conn->privateData;
-    char *cookie = NULL;
-    int cookielen = 0;
+    vzConnPtr privconn = conn->privateData;
     const char *miguri = NULL;
+    int ret = -1;
 
     virCheckFlags(VZ_MIGRATION_FLAGS, -1);
 
     if (virTypedParamsValidate(params, nparams, VZ_MIGRATION_PARAMETERS) < 0)
         goto cleanup;
 
-    if (!(dom = vzDomObjFromDomain(domain)))
+    if (virTypedParamsGetString(params, nparams,
+                                VIR_MIGRATE_PARAM_URI, &miguri) < 0)
         goto cleanup;
 
-    dconn = virConnectOpen(dconnuri);
-    if (dconn == NULL) {
-        virReportError(VIR_ERR_OPERATION_FAILED,
-                       _("Failed to connect to remote libvirt URI %s: %s"),
-                       dconnuri, virGetLastErrorMessage());
+    /* This check is of par with direct managed imlementation */
+    if (miguri == NULL)
+        *uri_out = vzCreateMigrationURI();
+
+    if (!(*cookieout = vzFormatCookie(privconn->session_uuid)))
         goto cleanup;
+    *cookieoutlen = strlen(*cookieout) + 1;
+    ret = 0;
+
+ cleanup:
+    if (ret != 0) {
+        VIR_FREE(*cookieout);
+        *cookieoutlen = 0;
+        VIR_FREE(*uri_out);
     }
 
-    if (virDomainMigratePrepare3Params(dconn, params, nparams, NULL, 0,
-                                       &cookie, &cookielen,
-                                       (char**)&miguri, flags) < 0)
+    return ret;
+}
+
+
+static int
+vzDomainMigratePerform3DirectParams(virDomainPtr domain,
+                                    virTypedParameterPtr params,
+                                    int nparams,
+                                    const char *cookiein,
+                                    int cookieinlen ATTRIBUTE_UNUSED,
+                                    char **cookieout ATTRIBUTE_UNUSED,
+                                    int *cookieoutlen ATTRIBUTE_UNUSED,
+                                    unsigned int flags)
+{
+    int ret = -1;
+    virDomainObjPtr dom = NULL;
+    virConnectPtr dconn = NULL;
+    virURIPtr vzuri = NULL;
+    unsigned char session_uuid[VIR_UUID_BUFLEN];
+    vzConnPtr privconn = domain->conn->privateData;
+    char *defmiguri = NULL;
+    const char *miguri = NULL;
+
+    virCheckFlags(VZ_MIGRATION_FLAGS, -1);
+
+    if (virTypedParamsValidate(params, nparams, VZ_MIGRATION_PARAMETERS) < 0)
         goto cleanup;
 
-    if (vzParseCookie(cookie, session_uuid) < 0)
+    if (!(dom = vzDomObjFromDomain(domain)))
         goto cleanup;
 
-    if (miguri == NULL &&
-        virTypedParamsGetString(params, nparams,
+    if (virTypedParamsGetString(params, nparams,
                                 VIR_MIGRATE_PARAM_URI, &miguri) < 0)
-            goto cleanup;
+        goto cleanup;
 
     if (miguri == NULL) {
         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                        _("domainMigratePrepare3Params did not set miguri"));
+        goto cleanup;
     }
 
     if (!(vzuri = vzParseVzURI(miguri)))
         goto cleanup;
 
+    if (vzParseCookie(cookiein, session_uuid) < 0)
+        goto cleanup;
+
     if (prlsdkMigrate(dom, vzuri, session_uuid) < 0)
         goto cleanup;
 
@@ -1592,11 +1614,336 @@ vzDomainMigratePerform3Params(virDomainPtr domain,
         virObjectUnlock(dom);
     virObjectUnref(dconn);
     virURIFree(vzuri);
-    VIR_FREE(cookie);
+    VIR_FREE(defmiguri);
+
+    return ret;
+}
+
+static int
+vzDomainMigratePerform3P2PParams(virDomainPtr domain,
+                                 const char *dconnuri,
+                                 virTypedParameterPtr params,
+                                 int nparams,
+                                 unsigned int flags)
+{
+    virDomainPtr ddomain = NULL;
+    char *uri_out = NULL;
+    char *cookiein = NULL;
+    char *cookieout = NULL;
+    char *dom_xml = NULL;
+    int cookieinlen = 0;
+    int cookieoutlen = 0;
+    int ret;
+    virErrorPtr orig_err = NULL;
+    int cancelled = 1;
+    bool notify_source = true;
+    unsigned int destflags;
+    int state;
+    virTypedParameterPtr tmp;
+    const char *uri = NULL;
+    virConnectPtr dconn = NULL;
+
+    VIR_DOMAIN_DEBUG(domain,
+                     "params=%p, nparams=%d, flags=%x",
+                     params, nparams, flags);
+    VIR_TYPED_PARAMS_DEBUG(params, nparams);
+
+    if (virTypedParamsCopy(&tmp, params, nparams) < 0)
+        return NULL;
+    params = tmp;
+
+    if ((dconn = virConnectOpen(dconnuri)) == NULL)
+        goto done;
+
+    VIR_DEBUG("Begin3 %p", domain->conn);
+    dom_xml = domain->conn->driver->domainMigrateBegin3Params
+        (domain, params, nparams, &cookieout, &cookieoutlen,
+         flags);
+    if (!dom_xml)
+        goto done;
+
+    ret = virDomainGetState(domain, &state, NULL, 0);
+    if (ret == 0 && state == VIR_DOMAIN_PAUSED)
+        flags |= VIR_MIGRATE_PAUSED;
+
+    destflags = flags & ~(VIR_MIGRATE_ABORT_ON_ERROR |
+                          VIR_MIGRATE_AUTO_CONVERGE);
+
+    VIR_DEBUG("Prepare3 %p flags=%x", dconn, destflags);
+    cookiein = cookieout;
+    cookieinlen = cookieoutlen;
+    cookieout = NULL;
+    cookieoutlen = 0;
+    if (virTypedParamsReplaceString(&params, &nparams,
+                                    VIR_MIGRATE_PARAM_DEST_XML,
+                                    dom_xml) < 0)
+        goto done;
+    ret = dconn->driver->domainMigratePrepare3Params
+        (dconn, params, nparams, cookiein, cookieinlen,
+         &cookieout, &cookieoutlen, &uri_out, destflags);
+    if (ret == -1) {
+        goto done;
+    }
+
+    /* Did domainMigratePrepare3 change URI? */
+    if (uri_out) {
+        uri = uri_out;
+        if (virTypedParamsReplaceString(&params, &nparams,
+                                        VIR_MIGRATE_PARAM_URI,
+                                        uri_out) < 0) {
+            cancelled = 1;
+            orig_err = virSaveLastError();
+            goto finish;
+        }
+    } else if (virTypedParamsGetString(params, nparams,
+                                       VIR_MIGRATE_PARAM_URI, &uri) <= 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("domainMigratePrepare3 did not set uri"));
+        cancelled = 1;
+        orig_err = virSaveLastError();
+        goto finish;
+    }
+
+    if (flags & VIR_MIGRATE_OFFLINE) {
+        VIR_DEBUG("Offline migration, skipping Perform phase");
+        VIR_FREE(cookieout);
+        cookieoutlen = 0;
+        cancelled = 0;
+        goto finish;
+    }
+
+    /* Perform the migration.  The driver isn't supposed to return
+     * until the migration is complete. The src VM should remain
+     * running, but in paused state until the destination can
+     * confirm migration completion.
+     */
+    VIR_DEBUG("Perform3 %p uri=%s", domain->conn, uri);
+    VIR_FREE(cookiein);
+    cookiein = cookieout;
+    cookieinlen = cookieoutlen;
+    cookieout = NULL;
+    cookieoutlen = 0;
+    /* dconnuri not relevant in non-P2P modes, so left NULL here */
+    ret = domain->conn->driver->domainMigratePerform3Params
+        (domain, NULL, params, nparams, cookiein, cookieinlen,
+         &cookieout, &cookieoutlen, flags & ~(VIR_MIGRATE_PEER2PEER));
+
+    /* Perform failed. Make sure Finish doesn't overwrite the error */
+    if (ret < 0) {
+        orig_err = virSaveLastError();
+        /* Perform failed so we don't need to call confirm to let source know
+         * about the failure.
+         */
+        notify_source = false;
+    }
+
+    /* If Perform returns < 0, then we need to cancel the VM
+     * startup on the destination
+     */
+    cancelled = ret < 0 ? 1 : 0;
+
+ finish:
+    /*
+     * The status code from the source is passed to the destination.
+     * The dest can cleanup if the source indicated it failed to
+     * send all migration data. Returns NULL for ddomain if
+     * the dest was unable to complete migration.
+     */
+    VIR_DEBUG("Finish3 %p ret=%d", dconn, ret);
+    VIR_FREE(cookiein);
+    cookiein = cookieout;
+    cookieinlen = cookieoutlen;
+    cookieout = NULL;
+    cookieoutlen = 0;
+    if (virTypedParamsGetString(params, nparams,
+                                VIR_MIGRATE_PARAM_DEST_NAME, NULL) <= 0 &&
+        virTypedParamsReplaceString(&params, &nparams,
+                                    VIR_MIGRATE_PARAM_DEST_NAME,
+                                    domain->name) < 0) {
+        ddomain = NULL;
+    } else {
+        ddomain = dconn->driver->domainMigrateFinish3Params
+            (dconn, params, nparams, cookiein, cookieinlen,
+             &cookieout, &cookieoutlen, destflags, cancelled);
+    }
+
+    if (cancelled) {
+        if (ddomain) {
+            VIR_ERROR(_("finish step ignored that migration was cancelled"));
+        } else {
+            /* If Finish reported a useful error, use it instead of the
+             * original "migration unexpectedly failed" error.
+             *
+             * This is ugly but we can't do better with the APIs we have. We
+             * only replace the error if Finish was called with cancelled == 1
+             * and reported a real error (old libvirt would report an error
+             * from RPC instead of MIGRATE_FINISH_OK), which only happens when
+             * the domain died on destination. To further reduce a possibility
+             * of false positives we also check that Perform returned
+             * VIR_ERR_OPERATION_FAILED.
+             */
+            if (orig_err &&
+                orig_err->domain == VIR_FROM_QEMU &&
+                orig_err->code == VIR_ERR_OPERATION_FAILED) {
+                virErrorPtr err = virGetLastError();
+                if (err &&
+                    err->domain == VIR_FROM_QEMU &&
+                    err->code != VIR_ERR_MIGRATE_FINISH_OK) {
+                    virFreeError(orig_err);
+                    orig_err = NULL;
+                }
+            }
+        }
+    }
+
+    /* If ddomain is NULL, then we were unable to start
+     * the guest on the target, and must restart on the
+     * source. There is a small chance that the ddomain
+     * is NULL due to an RPC failure, in which case
+     * ddomain could in fact be running on the dest.
+     * The lock manager plugins should take care of
+     * safety in this scenario.
+     */
+    cancelled = ddomain == NULL ? 1 : 0;
+
+    /* If finish3 set an error, and we don't have an earlier
+     * one we need to preserve it in case confirm3 overwrites
+     */
+    if (!orig_err)
+        orig_err = virSaveLastError();
+
+    /*
+     * If cancelled, then src VM will be restarted, else it will be killed.
+     * Don't do this if migration failed on source and thus it was already
+     * cancelled there.
+     */
+    if (notify_source) {
+        VIR_DEBUG("Confirm3 %p ret=%d domain=%p", domain->conn, ret, domain);
+        VIR_FREE(cookiein);
+        cookiein = cookieout;
+        cookieinlen = cookieoutlen;
+        cookieout = NULL;
+        cookieoutlen = 0;
+        ret = domain->conn->driver->domainMigrateConfirm3Params
+            (domain, params, nparams, 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.
+         */
+        if (ret < 0) {
+            VIR_WARN("Guest %s probably left in 'paused' state on source",
+                     domain->name);
+        }
+    }
+
+ done:
+    if (orig_err) {
+        virSetError(orig_err);
+        virFreeError(orig_err);
+    }
+    VIR_FREE(dom_xml);
+    VIR_FREE(uri_out);
+    VIR_FREE(cookiein);
+    VIR_FREE(cookieout);
+    virTypedParamsFree(params, nparams);
+    virObjectUnref(dconn);
+    ret = ddomain ? 0 : -1;
+    virObjectUnref(ddomain);
+    return ret;
+}
 
+
+static int
+vzDomainMigratePerform3Params(virDomainPtr domain,
+                              const char *dconnuri,
+                              virTypedParameterPtr params,
+                              int nparams,
+                              const char *cookiein,
+                              int cookieinlen,
+                              char **cookieout,
+                              int *cookieoutlen,
+                              unsigned int flags)
+{
+    virCheckFlags(VZ_MIGRATION_FLAGS, -1);
+
+    if (virTypedParamsValidate(params, nparams, VZ_MIGRATION_PARAMETERS) < 0)
+        return -1;
+
+    if (flags & VIR_MIGRATE_PEER2PEER) {
+        return vzDomainMigratePerform3P2PParams(domain,
+                                                dconnuri,
+                                                params,
+                                                nparams,
+                                                flags);
+    } else {
+        return vzDomainMigratePerform3DirectParams(domain,
+                                                   params,
+                                                   nparams,
+                                                   cookiein,
+                                                   cookieinlen,
+                                                   cookieout,
+                                                   cookieoutlen,
+                                                   flags);
+    }
+}
+
+
+static virDomainPtr
+vzDomainMigrateFinish3Params(virConnectPtr dconn,
+                             virTypedParameterPtr params,
+                             int nparams,
+                             const char *cookiein ATTRIBUTE_UNUSED,
+                             int cookieinlen ATTRIBUTE_UNUSED,
+                             char **cookieout ATTRIBUTE_UNUSED,
+                             int *cookieoutlen ATTRIBUTE_UNUSED,
+                             unsigned int flags ATTRIBUTE_UNUSED,
+                             int cancelled ATTRIBUTE_UNUSED)
+{
+    vzConnPtr privconn = dconn->privateData;
+    virDomainPtr ret = NULL;
+    virDomainObjPtr dom;
+    const char *name;
+
+    if (virTypedParamsGetString(params, nparams,
+                                VIR_MIGRATE_PARAM_DEST_NAME,
+                                &name) < 0)
+        return NULL;
+
+    vzDriverLock(privconn);
+    dom = virDomainObjListFindByName(privconn->domains, name);
+    vzDriverUnlock(privconn);
+
+    if (dom == NULL) {
+        virReportError(VIR_ERR_NO_DOMAIN,
+                       _("no domain with matching name '%s'"), name);
+        goto cleanup;
+    }
+
+    ret = virGetDomain(dconn, dom->def->name, dom->def->uuid);
+    if (ret)
+        ret->id = dom->def->id;
+
+ cleanup:
+    virDomainObjEndAPI(&dom);
     return ret;
+
 }
 
+
+static int
+vzDomainMigrateConfirm3Params(virDomainPtr domain ATTRIBUTE_UNUSED,
+                              virTypedParameterPtr params ATTRIBUTE_UNUSED,
+                              int nparams ATTRIBUTE_UNUSED,
+                              const char *cookiein ATTRIBUTE_UNUSED,
+                              int cookieinlen ATTRIBUTE_UNUSED,
+                              unsigned int flags ATTRIBUTE_UNUSED,
+                              int cancelled ATTRIBUTE_UNUSED)
+{
+    return 0;
+}
+
+
 static virHypervisorDriver vzDriver = {
     .name = "vz",
     .connectOpen = vzConnectOpen,            /* 0.10.0 */
@@ -1651,8 +1998,11 @@ static virHypervisorDriver vzDriver = {
     .domainInterfaceStats = vzDomainInterfaceStats, /* 1.2.17 */
     .domainMemoryStats = vzDomainMemoryStats, /* 1.2.17 */
     .connectSupportsFeature = vzConnectSupportsFeature, /* 1.2.20 */
+    .domainMigrateBegin3Params = vzDomainMigrateBegin3Params, /* 1.2.20 */
     .domainMigratePrepare3Params = vzDomainMigratePrepare3Params, /* 1.2.20 */
     .domainMigratePerform3Params = vzDomainMigratePerform3Params, /* 1.2.20 */
+    .domainMigrateFinish3Params = vzDomainMigrateFinish3Params, /* 1.2.20 */
+    .domainMigrateConfirm3Params = vzDomainMigrateConfirm3Params, /* 1.2.20 */
 };
 
 static virConnectDriver vzConnectDriver = {



Regards,
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 :|




More information about the libvir-list mailing list