[libvirt] [PATCH v2.1 02/11] Introduce NBD migration cookie

li guang lig.fnst at cn.fujitsu.com
Thu Dec 20 05:42:51 UTC 2012


reviewed-by: liguang <lig.fnst at cn.fujitsu.com>

在 2012-12-18二的 15:36 +0100,Michal Privoznik写道:
> This migration cookie is meant for two purposes. The first is to be sent
> in begin phase from source to destination to let it know we support new
> implementation of VIR_MIGRATE_NON_SHARED_{DISK,INC} so destination can
> start NBD server. Then, the second purpose is, destination can let us
> know, on which port is NBD server running.
> ---
>  src/qemu/qemu_migration.c | 145 +++++++++++++++++++++++++++++++++++++++-------
>  1 file changed, 124 insertions(+), 21 deletions(-)
> 
> diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
> index 5dcbb07..7d61ec7 100644
> --- a/src/qemu/qemu_migration.c
> +++ b/src/qemu/qemu_migration.c
> @@ -72,6 +72,7 @@ enum qemuMigrationCookieFlags {
>      QEMU_MIGRATION_COOKIE_FLAG_LOCKSTATE,
>      QEMU_MIGRATION_COOKIE_FLAG_PERSISTENT,
>      QEMU_MIGRATION_COOKIE_FLAG_NETWORK,
> +    QEMU_MIGRATION_COOKIE_FLAG_NBD,
>  
>      QEMU_MIGRATION_COOKIE_FLAG_LAST
>  };
> @@ -79,13 +80,18 @@ enum qemuMigrationCookieFlags {
>  VIR_ENUM_DECL(qemuMigrationCookieFlag);
>  VIR_ENUM_IMPL(qemuMigrationCookieFlag,
>                QEMU_MIGRATION_COOKIE_FLAG_LAST,
> -              "graphics", "lockstate", "persistent", "network");
> +              "graphics",
> +              "lockstate",
> +              "persistent",
> +              "network",
> +              "nbd");
>  
>  enum qemuMigrationCookieFeatures {
>      QEMU_MIGRATION_COOKIE_GRAPHICS  = (1 << QEMU_MIGRATION_COOKIE_FLAG_GRAPHICS),
>      QEMU_MIGRATION_COOKIE_LOCKSTATE = (1 << QEMU_MIGRATION_COOKIE_FLAG_LOCKSTATE),
>      QEMU_MIGRATION_COOKIE_PERSISTENT = (1 << QEMU_MIGRATION_COOKIE_FLAG_PERSISTENT),
>      QEMU_MIGRATION_COOKIE_NETWORK = (1 << QEMU_MIGRATION_COOKIE_FLAG_NETWORK),
> +    QEMU_MIGRATION_COOKIE_NBD = (1 << QEMU_MIGRATION_COOKIE_FLAG_NBD),
>  };
>  
>  typedef struct _qemuMigrationCookieGraphics qemuMigrationCookieGraphics;
> @@ -119,6 +125,17 @@ struct _qemuMigrationCookieNetwork {
>      qemuMigrationCookieNetDataPtr net;
>  };
>  
> +typedef struct _qemuMigrationCookieNBD qemuMigrationCookieNBD;
> +typedef qemuMigrationCookieNBD *qemuMigrationCookieNBDPtr;
> +struct _qemuMigrationCookieNBD {
> +    int port; /* on which port does NBD server listen for incoming data.
> +                 Zero value has special meaning - it is there just to let
> +                 destination know we (the source) do support NBD.
> +                 Negative one is meant to be sent when translating from
> +                 perform to finish phase to let destination know it's
> +                 safe to stop NBD server.*/
> +};
> +
>  typedef struct _qemuMigrationCookie qemuMigrationCookie;
>  typedef qemuMigrationCookie *qemuMigrationCookiePtr;
>  struct _qemuMigrationCookie {
> @@ -147,6 +164,9 @@ struct _qemuMigrationCookie {
>  
>      /* If (flags & QEMU_MIGRATION_COOKIE_NETWORK) */
>      qemuMigrationCookieNetworkPtr network;
> +
> +    /* If (flags & QEMU_MIGRATION_COOKIE_NBD) */
> +    qemuMigrationCookieNBDPtr nbd;
>  };
>  
>  static void qemuMigrationCookieGraphicsFree(qemuMigrationCookieGraphicsPtr grap)
> @@ -192,6 +212,7 @@ static void qemuMigrationCookieFree(qemuMigrationCookiePtr mig)
>      VIR_FREE(mig->name);
>      VIR_FREE(mig->lockState);
>      VIR_FREE(mig->lockDriver);
> +    VIR_FREE(mig->nbd);
>      VIR_FREE(mig);
>  }
>  
> @@ -492,6 +513,24 @@ qemuMigrationCookieAddNetwork(qemuMigrationCookiePtr mig,
>  }
>  
> 
> +static int
> +qemuMigrationCookieAddNBD(qemuMigrationCookiePtr mig,
> +                          int nbdPort)
> +{
> +    /* It is not a bug if there already is a NBD data */
> +    if (!mig->nbd &&
> +        VIR_ALLOC(mig->nbd) < 0) {
> +        virReportOOMError();
> +        return -1;
> +    }
> +
> +    mig->nbd->port = nbdPort;
> +    mig->flags |= QEMU_MIGRATION_COOKIE_NBD;
> +
> +    return 0;
> +}
> +
> +
>  static void qemuMigrationCookieGraphicsXMLFormat(virBufferPtr buf,
>                                                   qemuMigrationCookieGraphicsPtr grap)
>  {
> @@ -594,6 +633,13 @@ qemuMigrationCookieXMLFormat(virQEMUDriverPtr driver,
>      if ((mig->flags & QEMU_MIGRATION_COOKIE_NETWORK) && mig->network)
>          qemuMigrationCookieNetworkXMLFormat(buf, mig->network);
>  
> +    if ((mig->flags & QEMU_MIGRATION_COOKIE_NBD) && mig->nbd) {
> +        virBufferAddLit(buf, "  <nbd");
> +        if (mig->nbd->port)
> +            virBufferAsprintf(buf, " port='%d'", mig->nbd->port);
> +        virBufferAddLit(buf, "/>\n");
> +    }
> +
>      virBufferAddLit(buf, "</qemu-migration>\n");
>      return 0;
>  }
> @@ -821,6 +867,12 @@ qemuMigrationCookieXMLParse(qemuMigrationCookiePtr mig,
>              goto error;
>          }
>  
> +        /* nbd is optional */
> +        if (val == QEMU_MIGRATION_COOKIE_FLAG_NBD) {
> +            VIR_FREE(str);
> +            continue;
> +        }
> +
>          if ((flags & (1 << val)) == 0) {
>              virReportError(VIR_ERR_INTERNAL_ERROR,
>                             _("Unsupported migration cookie feature %s"),
> @@ -873,6 +925,25 @@ qemuMigrationCookieXMLParse(qemuMigrationCookiePtr mig,
>          (!(mig->network = qemuMigrationCookieNetworkXMLParse(ctxt))))
>          goto error;
>  
> +    if (flags & QEMU_MIGRATION_COOKIE_NBD &&
> +        virXPathBoolean("count(./nbd) > 0", ctxt)) {
> +        char *port;
> +
> +        if (VIR_ALLOC(mig->nbd) < 0) {
> +            virReportOOMError();
> +            goto error;
> +        }
> +
> +        port = virXPathString("string(./nbd/@port)", ctxt);
> +        if (port &&
> +            virStrToLong_i(port, NULL, 10, &mig->nbd->port) < 0) {
> +            virReportError(VIR_ERR_INTERNAL_ERROR,
> +                           _("Malformed nbd port '%s'"),
> +                           port);
> +            goto error;
> +        }
> +    }
> +
>      return 0;
>  
>  error:
> @@ -911,6 +982,7 @@ static int
>  qemuMigrationBakeCookie(qemuMigrationCookiePtr mig,
>                          virQEMUDriverPtr driver,
>                          virDomainObjPtr dom,
> +                        int nbdPort,
>                          char **cookieout,
>                          int *cookieoutlen,
>                          unsigned int flags)
> @@ -937,6 +1009,10 @@ qemuMigrationBakeCookie(qemuMigrationCookiePtr mig,
>          return -1;
>      }
>  
> +    if (flags & QEMU_MIGRATION_COOKIE_NBD &&
> +        qemuMigrationCookieAddNBD(mig, nbdPort) < 0)
> +        return -1;
> +
>      if (!(*cookieout = qemuMigrationCookieXMLFormatStr(driver, mig)))
>          return -1;
>  
> @@ -1422,6 +1498,7 @@ char *qemuMigrationBegin(virQEMUDriverPtr driver,
>      qemuMigrationCookiePtr mig = NULL;
>      virDomainDefPtr def = NULL;
>      qemuDomainObjPrivatePtr priv = vm->privateData;
> +    unsigned int cookieFlags = QEMU_MIGRATION_COOKIE_LOCKSTATE;
>  
>      VIR_DEBUG("driver=%p, vm=%p, xmlin=%s, dname=%s,"
>                " cookieout=%p, cookieoutlen=%p, flags=%lx",
> @@ -1441,12 +1518,21 @@ char *qemuMigrationBegin(virQEMUDriverPtr driver,
>      if (!(flags & VIR_MIGRATE_UNSAFE) && !qemuMigrationIsSafe(vm->def))
>          goto cleanup;
>  
> +    if (flags & (VIR_MIGRATE_NON_SHARED_DISK | VIR_MIGRATE_NON_SHARED_INC) &&
> +        qemuCapsGet(priv->caps, QEMU_CAPS_NBD_SERVER)) {
> +        /* TODO support NBD for TUNNELLED migration */
> +        if (flags & VIR_MIGRATE_TUNNELLED)
> +            VIR_DEBUG("NBD in tunnelled migration is currently not supported");
> +        else
> +            cookieFlags |= QEMU_MIGRATION_COOKIE_NBD;
> +    }
> +
>      if (!(mig = qemuMigrationEatCookie(driver, vm, NULL, 0, 0)))
>          goto cleanup;
>  
> -    if (qemuMigrationBakeCookie(mig, driver, vm,
> +    if (qemuMigrationBakeCookie(mig, driver, vm, 0,
>                                  cookieout, cookieoutlen,
> -                                QEMU_MIGRATION_COOKIE_LOCKSTATE) < 0)
> +                                cookieFlags) < 0)
>          goto cleanup;
>  
>      if (flags & VIR_MIGRATE_OFFLINE) {
> @@ -1543,6 +1629,7 @@ qemuMigrationPrepareAny(virQEMUDriverPtr driver,
>      char *origname = NULL;
>      char *xmlout = NULL;
>      unsigned int cookieFlags;
> +    int nbdPort = 0;
>  
>      if (virTimeMillisNow(&now) < 0)
>          return -1;
> @@ -1642,7 +1729,8 @@ qemuMigrationPrepareAny(virQEMUDriverPtr driver,
>      origname = NULL;
>  
>      if (!(mig = qemuMigrationEatCookie(driver, vm, cookiein, cookieinlen,
> -                                       QEMU_MIGRATION_COOKIE_LOCKSTATE)))
> +                                       QEMU_MIGRATION_COOKIE_LOCKSTATE |
> +                                       QEMU_MIGRATION_COOKIE_NBD)))
>          goto cleanup;
>  
>      if (qemuMigrationJobStart(driver, vm, QEMU_ASYNC_JOB_MIGRATION_IN) < 0)
> @@ -1702,8 +1790,12 @@ done:
>      else
>          cookieFlags = QEMU_MIGRATION_COOKIE_GRAPHICS;
>  
> -    if (qemuMigrationBakeCookie(mig, driver, vm, cookieout, cookieoutlen,
> -                                cookieFlags) < 0) {
> +    /* dummy place holder for real work */
> +    nbdPort = 0;
> +    cookieFlags |= QEMU_MIGRATION_COOKIE_NBD;
> +
> +    if (qemuMigrationBakeCookie(mig, driver, vm, nbdPort,
> +                                cookieout, cookieoutlen, cookieFlags) < 0) {
>          /* We could tear down the whole guest here, but
>           * cookie data is (so far) non-critical, so that
>           * seems a little harsh. We'll just warn for now.
> @@ -2198,6 +2290,7 @@ qemuMigrationRun(virQEMUDriverPtr driver,
>      int fd = -1;
>      unsigned long migrate_speed = resource ? resource : priv->migMaxBandwidth;
>      virErrorPtr orig_err = NULL;
> +    unsigned int cookieFlags = QEMU_MIGRATION_COOKIE_GRAPHICS;
>  
>      VIR_DEBUG("driver=%p, vm=%p, cookiein=%s, cookieinlen=%d, "
>                "cookieout=%p, cookieoutlen=%p, flags=%lx, resource=%lu, "
> @@ -2206,6 +2299,16 @@ qemuMigrationRun(virQEMUDriverPtr driver,
>                cookieout, cookieoutlen, flags, resource,
>                spec, spec->destType, spec->fwdType);
>  
> +    if (flags & VIR_MIGRATE_NON_SHARED_DISK) {
> +        migrate_flags |= QEMU_MONITOR_MIGRATE_NON_SHARED_DISK;
> +        cookieFlags |= QEMU_MIGRATION_COOKIE_NBD;
> +    }
> +
> +    if (flags & VIR_MIGRATE_NON_SHARED_INC) {
> +        migrate_flags |= QEMU_MONITOR_MIGRATE_NON_SHARED_INC;
> +        cookieFlags |= QEMU_MIGRATION_COOKIE_NBD;
> +    }
> +
>      if (virLockManagerPluginUsesState(driver->lockManager) &&
>          !cookieout) {
>          virReportError(VIR_ERR_INTERNAL_ERROR,
> @@ -2215,9 +2318,12 @@ qemuMigrationRun(virQEMUDriverPtr driver,
>          return -1;
>      }
>  
> -    if (!(mig = qemuMigrationEatCookie(driver, vm, cookiein, cookieinlen,
> -                                       QEMU_MIGRATION_COOKIE_GRAPHICS)))
> +    if (!(mig = qemuMigrationEatCookie(driver, vm, cookiein,
> +                                       cookieinlen, cookieFlags))) {
> +        cookieFlags &= ~QEMU_MIGRATION_COOKIE_GRAPHICS;
>          goto cleanup;
> +    }
> +    cookieFlags &= ~QEMU_MIGRATION_COOKIE_GRAPHICS;
>  
>      if (qemuDomainMigrateGraphicsRelocate(driver, vm, mig) < 0)
>          VIR_WARN("unable to provide data for graphics client relocation");
> @@ -2249,11 +2355,6 @@ qemuMigrationRun(virQEMUDriverPtr driver,
>          goto cleanup;
>      }
>  
> -    if (flags & VIR_MIGRATE_NON_SHARED_DISK)
> -        migrate_flags |= QEMU_MONITOR_MIGRATE_NON_SHARED_DISK;
> -
> -    if (flags & VIR_MIGRATE_NON_SHARED_INC)
> -        migrate_flags |= QEMU_MONITOR_MIGRATE_NON_SHARED_INC;
>  
>      /* connect to the destination qemu if needed */
>      if (spec->destType == MIGRATION_DEST_CONNECT_HOST &&
> @@ -2361,10 +2462,11 @@ cleanup:
>          VIR_FORCE_CLOSE(fd);
>      }
>  
> +    cookieFlags |= (QEMU_MIGRATION_COOKIE_PERSISTENT |
> +                    QEMU_MIGRATION_COOKIE_NETWORK);
>      if (ret == 0 &&
> -        qemuMigrationBakeCookie(mig, driver, vm, cookieout, cookieoutlen,
> -                                QEMU_MIGRATION_COOKIE_PERSISTENT |
> -                                QEMU_MIGRATION_COOKIE_NETWORK) < 0) {
> +        qemuMigrationBakeCookie(mig, driver, vm, -1, cookieout,
> +                                cookieoutlen, cookieFlags) < 0) {
>          VIR_WARN("Unable to encode migration cookie");
>      }
>  
> @@ -3301,7 +3403,7 @@ qemuMigrationFinish(virQEMUDriverPtr driver,
>      int newVM = 1;
>      qemuMigrationCookiePtr mig = NULL;
>      virErrorPtr orig_err = NULL;
> -    int cookie_flags = 0;
> +    int cookieFlags = 0;
>      qemuDomainObjPrivatePtr priv = vm->privateData;
>  
>      VIR_DEBUG("driver=%p, dconn=%p, vm=%p, cookiein=%s, cookieinlen=%d, "
> @@ -3318,12 +3420,12 @@ qemuMigrationFinish(virQEMUDriverPtr driver,
>  
>      qemuDomainCleanupRemove(vm, qemuMigrationPrepareCleanup);
>  
> -    cookie_flags = QEMU_MIGRATION_COOKIE_NETWORK;
> +    cookieFlags = QEMU_MIGRATION_COOKIE_NETWORK | QEMU_MIGRATION_COOKIE_NBD;
>      if (flags & VIR_MIGRATE_PERSIST_DEST)
> -        cookie_flags |= QEMU_MIGRATION_COOKIE_PERSISTENT;
> +        cookieFlags |= QEMU_MIGRATION_COOKIE_PERSISTENT;
>  
>      if (!(mig = qemuMigrationEatCookie(driver, vm, cookiein,
> -                                       cookieinlen, cookie_flags)))
> +                                       cookieinlen, cookieFlags)))
>          goto endjob;
>  
>      /* Did the migration go as planned?  If yes, return the domain
> @@ -3470,7 +3572,8 @@ qemuMigrationFinish(virQEMUDriverPtr driver,
>                                           VIR_DOMAIN_EVENT_STOPPED_FAILED);
>      }
>  
> -    if (qemuMigrationBakeCookie(mig, driver, vm, cookieout, cookieoutlen, 0) < 0)
> +    if (qemuMigrationBakeCookie(mig, driver, vm, 0,
> +                                cookieout, cookieoutlen, 0) < 0)
>          VIR_WARN("Unable to encode migration cookie");
>  
>  endjob:

-- 
regards!
li guang





More information about the libvir-list mailing list