reviewed-by: liguang <lig.fnst@xxxxxxxxxxxxxx> 在 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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list