If a domain has inactive XML we want to transfer it to destination when migrating with VIR_MIGRATE_PERSIST_DEST. In order to harm the migration protocol as least as possible, a optional cookie was chosen. --- diff to v2: -Fix substitution on wrong place src/qemu/qemu_migration.c | 81 ++++++++++++++++++++++++++++++++++++++++++--- 1 files changed, 76 insertions(+), 5 deletions(-) diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index d9f8d93..8ea8508 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -64,6 +64,7 @@ VIR_ENUM_IMPL(qemuMigrationJobPhase, QEMU_MIGRATION_PHASE_LAST, enum qemuMigrationCookieFlags { QEMU_MIGRATION_COOKIE_FLAG_GRAPHICS, QEMU_MIGRATION_COOKIE_FLAG_LOCKSTATE, + QEMU_MIGRATION_COOKIE_FLAG_PERSISTENT, QEMU_MIGRATION_COOKIE_FLAG_LAST }; @@ -71,11 +72,12 @@ enum qemuMigrationCookieFlags { VIR_ENUM_DECL(qemuMigrationCookieFlag); VIR_ENUM_IMPL(qemuMigrationCookieFlag, QEMU_MIGRATION_COOKIE_FLAG_LAST, - "graphics", "lockstate"); + "graphics", "lockstate", "persistent"); 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), }; typedef struct _qemuMigrationCookieGraphics qemuMigrationCookieGraphics; @@ -110,6 +112,9 @@ struct _qemuMigrationCookie { /* If (flags & QEMU_MIGRATION_COOKIE_GRAPHICS) */ qemuMigrationCookieGraphicsPtr graphics; + + /* If (flags & QEMU_MIGRATION_COOKIE_PERSISTENT) */ + virDomainDefPtr persistent; }; static void qemuMigrationCookieGraphicsFree(qemuMigrationCookieGraphicsPtr grap) @@ -334,6 +339,26 @@ qemuMigrationCookieAddLockstate(qemuMigrationCookiePtr mig, } +static int +qemuMigrationCookieAddPersistent(qemuMigrationCookiePtr mig, + virDomainObjPtr dom) +{ + if (mig->flags & QEMU_MIGRATION_COOKIE_PERSISTENT) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Migration persistent data already present")); + return -1; + } + + if (!dom->newDef) + return 0; + + mig->persistent = dom->newDef; + mig->flags |= QEMU_MIGRATION_COOKIE_PERSISTENT; + mig->flagsMandatory |= QEMU_MIGRATION_COOKIE_PERSISTENT; + return 0; +} + + static void qemuMigrationCookieGraphicsXMLFormat(virBufferPtr buf, qemuMigrationCookieGraphicsPtr grap) @@ -358,6 +383,7 @@ static void qemuMigrationCookieXMLFormat(virBufferPtr buf, { char uuidstr[VIR_UUID_STRING_BUFLEN]; char hostuuidstr[VIR_UUID_STRING_BUFLEN]; + char *domXML; int i; virUUIDFormat(mig->uuid, uuidstr); @@ -388,6 +414,15 @@ static void qemuMigrationCookieXMLFormat(virBufferPtr buf, virBufferAddLit(buf, " </lockstate>\n"); } + if ((mig->flags & QEMU_MIGRATION_COOKIE_PERSISTENT) && + mig->persistent) { + domXML = virDomainDefFormat(mig->persistent, + VIR_DOMAIN_XML_INACTIVE | + VIR_DOMAIN_XML_SECURE); + virBufferAdd(buf, domXML, -1); + VIR_FREE(domXML); + } + virBufferAddLit(buf, "</qemu-migration>\n"); } @@ -460,6 +495,8 @@ error: static int qemuMigrationCookieXMLParse(qemuMigrationCookiePtr mig, + struct qemud_driver *driver, + xmlDocPtr doc, xmlXPathContextPtr ctxt, unsigned int flags) { @@ -583,6 +620,25 @@ qemuMigrationCookieXMLParse(qemuMigrationCookiePtr mig, VIR_FREE(mig->lockState); } + if ((flags & QEMU_MIGRATION_COOKIE_PERSISTENT) && + virXPathBoolean("count(./domain) > 0", ctxt)) { + if ((n = virXPathNodeSet("./domain", ctxt, &nodes)) > 1) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, + _("Too many domain elements in " + "migration cookie: %d"), + n); + goto error; + } + mig->persistent = virDomainDefParseNode(driver->caps, doc, nodes[0], + -1, VIR_DOMAIN_XML_INACTIVE); + if (!mig->persistent) { + /* virDomainDefParseNode already reported + * an error for us */ + goto error; + } + VIR_FREE(nodes); + } + return 0; error: @@ -594,6 +650,7 @@ error: static int qemuMigrationCookieXMLParseStr(qemuMigrationCookiePtr mig, + struct qemud_driver *driver, const char *xml, unsigned int flags) { @@ -606,7 +663,7 @@ qemuMigrationCookieXMLParseStr(qemuMigrationCookiePtr mig, if (!(doc = virXMLParseStringCtxt(xml, _("(qemu_migration_cookie)"), &ctxt))) goto cleanup; - ret = qemuMigrationCookieXMLParse(mig, ctxt, flags); + ret = qemuMigrationCookieXMLParse(mig, driver, doc, ctxt, flags); cleanup: xmlXPathFreeContext(ctxt); @@ -637,6 +694,10 @@ qemuMigrationBakeCookie(qemuMigrationCookiePtr mig, qemuMigrationCookieAddLockstate(mig, driver, dom) < 0) return -1; + if (flags & QEMU_MIGRATION_COOKIE_PERSISTENT && + qemuMigrationCookieAddPersistent(mig, dom) < 0) + return -1; + if (!(*cookieout = qemuMigrationCookieXMLFormatStr(mig))) return -1; @@ -672,6 +733,7 @@ qemuMigrationEatCookie(struct qemud_driver *driver, if (cookiein && cookieinlen && qemuMigrationCookieXMLParseStr(mig, + driver, cookiein, flags) < 0) goto error; @@ -1575,7 +1637,8 @@ cleanup: } if (ret == 0 && - qemuMigrationBakeCookie(mig, driver, vm, cookieout, cookieoutlen, 0) < 0) + qemuMigrationBakeCookie(mig, driver, vm, cookieout, cookieoutlen, + QEMU_MIGRATION_COOKIE_PERSISTENT ) < 0) VIR_WARN("Unable to encode migration cookie"); qemuMigrationCookieFree(mig); @@ -2477,6 +2540,7 @@ qemuMigrationFinish(struct qemud_driver *driver, int newVM = 1; qemuMigrationCookiePtr mig = NULL; virErrorPtr orig_err = NULL; + int cookie_flags = 0; VIR_DEBUG("driver=%p, dconn=%p, vm=%p, cookiein=%s, cookieinlen=%d, " "cookieout=%p, cookieoutlen=%p, flags=%lx, retcode=%d", @@ -2490,7 +2554,11 @@ qemuMigrationFinish(struct qemud_driver *driver, v3proto ? QEMU_MIGRATION_PHASE_FINISH3 : QEMU_MIGRATION_PHASE_FINISH2); - if (!(mig = qemuMigrationEatCookie(driver, vm, cookiein, cookieinlen, 0))) + if (flags & VIR_MIGRATE_PERSIST_DEST) + cookie_flags |= QEMU_MIGRATION_COOKIE_PERSISTENT; + + if (!(mig = qemuMigrationEatCookie(driver, vm, cookiein, + cookieinlen, cookie_flags))) goto endjob; /* Did the migration go as planned? If yes, return the domain @@ -2510,7 +2578,10 @@ qemuMigrationFinish(struct qemud_driver *driver, if (vm->persistent) newVM = 0; vm->persistent = 1; - vmdef = virDomainObjGetPersistentDef(driver->caps, vm); + if (mig->persistent) + vm->newDef = vmdef = mig->persistent; + else + vmdef = virDomainObjGetPersistentDef(driver->caps, vm); if (virDomainSaveConfig(driver->configDir, vmdef) < 0) { /* Hmpf. Migration was successful, but making it persistent * was not. If we report successful, then when this domain -- 1.7.3.4 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list