[libvirt] [PATCH] Split virDomainMigrate into functions.

Daniel P. Berrange berrange at redhat.com
Tue Aug 11 10:01:37 UTC 2009


On Fri, Aug 07, 2009 at 11:06:34AM +0200, Chris Lalancette wrote:
> Re-factor virDomainMigrate to split out the version 1 and version 2
> protocols into their own functions.  In reality, the two versions share
> very little in common, so forcing them together in the same function was
> just confusing.  This will also make adding tunnelled migration easier.
> 
> Signed-off-by: Chris Lalancette <clalance at redhat.com>
> ---
>  src/libvirt.c |  258 ++++++++++++++++++++++++++++++++++-----------------------
>  1 files changed, 155 insertions(+), 103 deletions(-)
> 
> diff --git a/src/libvirt.c b/src/libvirt.c
> index 9fd864d..6c1cc3d 100644
> --- a/src/libvirt.c
> +++ b/src/libvirt.c
> @@ -2874,6 +2874,146 @@ error:
>  }
>  
>  
> +static virDomainPtr
> +virDomainMigrateVersion1 (virDomainPtr domain,
> +                          virConnectPtr dconn,
> +                          unsigned long flags,
> +                          const char *dname,
> +                          const char *uri,
> +                          unsigned long bandwidth)
> +{
> +    virDomainPtr ddomain = NULL;
> +    char *uri_out = NULL;
> +    char *cookie = NULL;
> +    int cookielen = 0;
> +
> +    /* Prepare the migration.
> +     *
> +     * The destination host may return a cookie, or leave cookie as
> +     * NULL.
> +     *
> +     * The destination host MUST set uri_out if uri_in is NULL.
> +     *
> +     * If uri_in is non-NULL, then the destination host may modify
> +     * the URI by setting uri_out.  If it does not wish to modify
> +     * the URI, it should leave uri_out as NULL.
> +     */
> +    if (dconn->driver->domainMigratePrepare
> +        (dconn, &cookie, &cookielen, uri, &uri_out, flags, dname,
> +         bandwidth) == -1)
> +        goto done;
> +
> +    if (uri == NULL && uri_out == NULL) {
> +        virLibConnError (domain->conn, VIR_ERR_INTERNAL_ERROR,
> +                         _("domainMigratePrepare did not set uri"));
> +        goto done;
> +    }
> +    if (uri_out)
> +        uri = uri_out; /* Did domainMigratePrepare change URI? */
> +    assert (uri != NULL);
> +
> +    /* Perform the migration.  The driver isn't supposed to return
> +     * until the migration is complete.
> +     */
> +    if (domain->conn->driver->domainMigratePerform
> +        (domain, cookie, cookielen, uri, flags, dname, bandwidth) == -1)
> +        goto done;
> +
> +    /* Get the destination domain and return it or error.
> +     * 'domain' no longer actually exists at this point
> +     * (or so we hope), but we still use the object in memory
> +     * in order to get the name.
> +     */
> +    dname = dname ? dname : domain->name;
> +    if (dconn->driver->domainMigrateFinish)
> +        ddomain = dconn->driver->domainMigrateFinish
> +            (dconn, dname, cookie, cookielen, uri, flags);
> +    else
> +        ddomain = virDomainLookupByName (dconn, dname);
> +
> + done:
> +    VIR_FREE (uri_out);
> +    VIR_FREE (cookie);
> +    return ddomain;
> +}
> +
> +static virDomainPtr
> +virDomainMigrateVersion2 (virDomainPtr domain,
> +                          virConnectPtr dconn,
> +                          unsigned long flags,
> +                          const char *dname,
> +                          const char *uri,
> +                          unsigned long bandwidth)
> +{
> +    virDomainPtr ddomain = NULL;
> +    char *uri_out = NULL;
> +    char *cookie = NULL;
> +    char *dom_xml = NULL;
> +    int cookielen = 0, ret;
> +
> +    /* Prepare the migration.
> +     *
> +     * The destination host may return a cookie, or leave cookie as
> +     * NULL.
> +     *
> +     * The destination host MUST set uri_out if uri_in is NULL.
> +     *
> +     * If uri_in is non-NULL, then the destination host may modify
> +     * the URI by setting uri_out.  If it does not wish to modify
> +     * the URI, it should leave uri_out as NULL.
> +     */
> +
> +    /* In version 2 of the protocol, the prepare step is slightly
> +     * different.  We fetch the domain XML of the source domain
> +     * and pass it to Prepare2.
> +     */
> +    if (!domain->conn->driver->domainDumpXML) {
> +        virLibConnError (domain->conn, VIR_ERR_INTERNAL_ERROR, __FUNCTION__);
> +        return NULL;
> +    }
> +    dom_xml = domain->conn->driver->domainDumpXML (domain,
> +                                                   VIR_DOMAIN_XML_SECURE);
> +    if (!dom_xml)
> +        return NULL;
> +
> +    ret = dconn->driver->domainMigratePrepare2
> +        (dconn, &cookie, &cookielen, uri, &uri_out, flags, dname,
> +         bandwidth, dom_xml);
> +    VIR_FREE (dom_xml);
> +    if (ret == -1)
> +        goto done;
> +
> +    if (uri == NULL && uri_out == NULL) {
> +        virLibConnError (domain->conn, VIR_ERR_INTERNAL_ERROR,
> +                         _("domainMigratePrepare2 did not set uri"));
> +        goto done;
> +    }
> +    if (uri_out)
> +        uri = uri_out; /* Did domainMigratePrepare2 change URI? */
> +    assert (uri != NULL);
> +
> +    /* Perform the migration.  The driver isn't supposed to return
> +     * until the migration is complete.
> +     */
> +    ret = domain->conn->driver->domainMigratePerform
> +        (domain, cookie, cookielen, uri, flags, dname, bandwidth);
> +    if (ret == -1)
> +        goto done;
> +
> +    /* In version 2 of the migration protocol, we pass the
> +     * status code from the sender to the destination host,
> +     * so it can do any cleanup if the migration failed.
> +     */
> +    dname = dname ? dname : domain->name;
> +    ddomain = dconn->driver->domainMigrateFinish2
> +        (dconn, dname, cookie, cookielen, uri, flags, ret);
> +
> + done:
> +    VIR_FREE (uri_out);
> +    VIR_FREE (cookie);
> +    return ddomain;
> +}
> +
>  /**
>   * virDomainMigrate:
>   * @domain: a domain object
> @@ -2930,140 +3070,52 @@ virDomainMigrate (virDomainPtr domain,
>                    const char *uri,
>                    unsigned long bandwidth)
>  {
> -    virConnectPtr conn;
>      virDomainPtr ddomain = NULL;
> -    char *uri_out = NULL;
> -    char *cookie = NULL;
> -    char *dom_xml = NULL;
> -    int cookielen = 0, ret, version = 0;
>      DEBUG("domain=%p, dconn=%p, flags=%lu, dname=%s, uri=%s, bandwidth=%lu",
>            domain, dconn, flags, NULLSTR(dname), NULLSTR(uri), bandwidth);
>  
>      virResetLastError();
>  
> +    /* First checkout the source */
>      if (!VIR_IS_CONNECTED_DOMAIN (domain)) {
>          virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
>          return NULL;
>      }
> -    conn = domain->conn;        /* Source connection. */
> -    if (!VIR_IS_CONNECT (dconn)) {
> -        virLibConnError (conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
> +    if (domain->conn->flags & VIR_CONNECT_RO) {
> +        virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
>          goto error;
>      }
>  
> -    if (domain->conn->flags & VIR_CONNECT_RO) {
> -        virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
> +    /* Now checkout the destination */
> +    if (!VIR_IS_CONNECT (dconn)) {
> +        virLibConnError (domain->conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
>          goto error;
>      }
>      if (dconn->flags & VIR_CONNECT_RO) {
> -        /* NB, delibrately report error against source object, not dest here */
> -        virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
> +        /* NB, deliberately report error against source object, not dest */
> +        virLibDomainError (domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
>          goto error;
>      }
>  
>      /* Check that migration is supported by both drivers. */
> -    if (VIR_DRV_SUPPORTS_FEATURE (conn->driver, conn,
> +    if (VIR_DRV_SUPPORTS_FEATURE (domain->conn->driver, domain->conn,
>                                    VIR_DRV_FEATURE_MIGRATION_V1) &&
>          VIR_DRV_SUPPORTS_FEATURE (dconn->driver, dconn,
>                                    VIR_DRV_FEATURE_MIGRATION_V1))
> -        version = 1;
> -    else if (VIR_DRV_SUPPORTS_FEATURE (conn->driver, conn,
> +        ddomain = virDomainMigrateVersion1 (domain, dconn, flags, dname, uri, bandwidth);
> +    else if (VIR_DRV_SUPPORTS_FEATURE (domain->conn->driver, domain->conn,
>                                         VIR_DRV_FEATURE_MIGRATION_V2) &&
>               VIR_DRV_SUPPORTS_FEATURE (dconn->driver, dconn,
>                                         VIR_DRV_FEATURE_MIGRATION_V2))
> -        version = 2;
> +        ddomain = virDomainMigrateVersion2 (domain, dconn, flags, dname, uri, bandwidth);
>      else {
> -        virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
> +        virLibConnError (domain->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
>          goto error;
>      }
>  
> -    /* Prepare the migration.
> -     *
> -     * The destination host may return a cookie, or leave cookie as
> -     * NULL.
> -     *
> -     * The destination host MUST set uri_out if uri_in is NULL.
> -     *
> -     * If uri_in is non-NULL, then the destination host may modify
> -     * the URI by setting uri_out.  If it does not wish to modify
> -     * the URI, it should leave uri_out as NULL.
> -     */
> -    if (version == 1) {
> -        ret = dconn->driver->domainMigratePrepare
> -            (dconn, &cookie, &cookielen, uri, &uri_out, flags, dname,
> -             bandwidth);
> -        if (ret == -1) goto done;
> -        if (uri == NULL && uri_out == NULL) {
> -            virLibConnError (conn, VIR_ERR_INTERNAL_ERROR,
> -                             _("domainMigratePrepare did not set uri"));
> -            goto done;
> -        }
> -        if (uri_out) uri = uri_out; /* Did domainMigratePrepare change URI? */
> -
> -        assert (uri != NULL);
> -    }
> -    else /* if (version == 2) */ {
> -        /* In version 2 of the protocol, the prepare step is slightly
> -         * different.  We fetch the domain XML of the source domain
> -         * and pass it to Prepare2.
> -         */
> -        if (!conn->driver->domainDumpXML) {
> -            virLibConnError (conn, VIR_ERR_INTERNAL_ERROR, __FUNCTION__);
> -            goto error;
> -        }
> -        dom_xml = conn->driver->domainDumpXML (domain,
> -                                               VIR_DOMAIN_XML_SECURE);
> -
> -        if (!dom_xml)
> -            goto error;
> -
> -        ret = dconn->driver->domainMigratePrepare2
> -            (dconn, &cookie, &cookielen, uri, &uri_out, flags, dname,
> -             bandwidth, dom_xml);
> -        VIR_FREE (dom_xml);
> -        if (ret == -1) goto done;
> -        if (uri == NULL && uri_out == NULL) {
> -            virLibConnError (conn, VIR_ERR_INTERNAL_ERROR,
> -                             _("domainMigratePrepare2 did not set uri"));
> -            goto done;
> -        }
> -        if (uri_out) uri = uri_out; /* Did domainMigratePrepare2 change URI? */
> +     if (ddomain == NULL)
> +         goto error;
>  
> -        assert (uri != NULL);
> -    }
> -
> -    /* Perform the migration.  The driver isn't supposed to return
> -     * until the migration is complete.
> -     */
> -    ret = conn->driver->domainMigratePerform
> -        (domain, cookie, cookielen, uri, flags, dname, bandwidth);
> -
> -    if (version == 1) {
> -        if (ret == -1) goto done;
> -        /* Get the destination domain and return it or error.
> -         * 'domain' no longer actually exists at this point
> -         * (or so we hope), but we still use the object in memory
> -         * in order to get the name.
> -         */
> -        dname = dname ? dname : domain->name;
> -        if (dconn->driver->domainMigrateFinish)
> -            ddomain = dconn->driver->domainMigrateFinish
> -                (dconn, dname, cookie, cookielen, uri, flags);
> -        else
> -            ddomain = virDomainLookupByName (dconn, dname);
> -    } else /* if (version == 2) */ {
> -        /* In version 2 of the migration protocol, we pass the
> -         * status code from the sender to the destination host,
> -         * so it can do any cleanup if the migration failed.
> -         */
> -        dname = dname ? dname : domain->name;
> -        ddomain = dconn->driver->domainMigrateFinish2
> -            (dconn, dname, cookie, cookielen, uri, flags, ret);
> -    }
> -
> - done:
> -    VIR_FREE (uri_out);
> -    VIR_FREE (cookie);
>      return ddomain;
>  
>  error:

ACK

Daniel
-- 
|: Red Hat, Engineering, London   -o-   http://people.redhat.com/berrange/ :|
|: http://libvirt.org  -o-  http://virt-manager.org  -o-  http://ovirt.org :|
|: http://autobuild.org       -o-         http://search.cpan.org/~danberr/ :|
|: GnuPG: 7D3B9505  -o-  F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|




More information about the libvir-list mailing list