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 v1: -substitute passing driver with cappabilities -s/qemuDomainDefFormatXML/virDomainDefParseString/ src/qemu/qemu_migration.c | 92 ++++++++++++++++++++++++++++++++++++++++---- 1 files changed, 83 insertions(+), 9 deletions(-) diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index d9f8d93..0b53141 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) @@ -354,10 +379,12 @@ static void qemuMigrationCookieGraphicsXMLFormat(virBufferPtr buf, static void qemuMigrationCookieXMLFormat(virBufferPtr buf, - qemuMigrationCookiePtr mig) + qemuMigrationCookiePtr mig, + virCapsPtr caps) { char uuidstr[VIR_UUID_STRING_BUFLEN]; char hostuuidstr[VIR_UUID_STRING_BUFLEN]; + char *domXML; int i; virUUIDFormat(mig->uuid, uuidstr); @@ -388,15 +415,26 @@ static void qemuMigrationCookieXMLFormat(virBufferPtr buf, virBufferAddLit(buf, " </lockstate>\n"); } + if ((mig->flags & QEMU_MIGRATION_COOKIE_PERSISTENT) && + mig->persistent) { + domXML = virDomainDefParseString(caps, mig->persistent, + QEMU_EXPECTED_VIRT_TYPES, + VIR_DOMAIN_XML_INACTIVE | + VIR_DOMAIN_XML_SECURE); + virBufferAdd(buf, domXML, -1); + VIR_FREE(domXML); + } + virBufferAddLit(buf, "</qemu-migration>\n"); } -static char *qemuMigrationCookieXMLFormatStr(qemuMigrationCookiePtr mig) +static char *qemuMigrationCookieXMLFormatStr(qemuMigrationCookiePtr mig, + virCapsPtr caps) { virBuffer buf = VIR_BUFFER_INITIALIZER; - qemuMigrationCookieXMLFormat(&buf, mig); + qemuMigrationCookieXMLFormat(&buf, mig, caps); if (virBufferError(&buf)) { virReportOOMError(); @@ -460,6 +498,8 @@ error: static int qemuMigrationCookieXMLParse(qemuMigrationCookiePtr mig, + virCapsPtr caps, + xmlDocPtr doc, xmlXPathContextPtr ctxt, unsigned int flags) { @@ -583,6 +623,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(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 +653,7 @@ error: static int qemuMigrationCookieXMLParseStr(qemuMigrationCookiePtr mig, + virCapsPtr caps, const char *xml, unsigned int flags) { @@ -606,7 +666,7 @@ qemuMigrationCookieXMLParseStr(qemuMigrationCookiePtr mig, if (!(doc = virXMLParseStringCtxt(xml, _("(qemu_migration_cookie)"), &ctxt))) goto cleanup; - ret = qemuMigrationCookieXMLParse(mig, ctxt, flags); + ret = qemuMigrationCookieXMLParse(mig, caps, doc, ctxt, flags); cleanup: xmlXPathFreeContext(ctxt); @@ -637,7 +697,11 @@ qemuMigrationBakeCookie(qemuMigrationCookiePtr mig, qemuMigrationCookieAddLockstate(mig, driver, dom) < 0) return -1; - if (!(*cookieout = qemuMigrationCookieXMLFormatStr(mig))) + if (flags & QEMU_MIGRATION_COOKIE_PERSISTENT && + qemuMigrationCookieAddPersistent(mig, dom) < 0) + return -1; + + if (!(*cookieout = qemuMigrationCookieXMLFormatStr(mig, driver->caps))) return -1; *cookieoutlen = strlen(*cookieout) + 1; @@ -672,6 +736,7 @@ qemuMigrationEatCookie(struct qemud_driver *driver, if (cookiein && cookieinlen && qemuMigrationCookieXMLParseStr(mig, + driver->caps, cookiein, flags) < 0) goto error; @@ -1575,7 +1640,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 +2543,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 +2557,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 +2581,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