[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