On Sun, Oct 14, 2012 at 9:48 PM, liguang <lig.fnst@xxxxxxxxxxxxxx> wrote: > help to create disk images copy-storage-* required, > try to do non-shared migration without bothering to > create disk images at target by hand. > > consider this situation: > 1. non-shared migration > virsh migrate --copy-storage-all ... > 2. migration fails > 3. create disk images required > qemu-img create ... > 4 migration run smoothly > so, try do remove step 2, 3, 4 > > this kind of use had been discussed before, > http://www.redhat.com/archives/libvir-list/2011-December/msg00451.html > > It did not handle more about complete situations > suggested by Daniel P. Berrange, > https://www.redhat.com/archives/libvir-list/2012-October/msg00407.html > > Signed-off-by: liguang <lig.fnst@xxxxxxxxxxxxxx> > --- > src/libvirt_private.syms | 1 + > src/qemu/qemu_migration.c | 92 +++++++++++++++++++++++++++++++++++++++++++- > src/util/util.c | 17 ++++++++ > src/util/util.h | 1 + > 4 files changed, 108 insertions(+), 3 deletions(-) > > diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms > index a8c81e7..a293184 100644 > --- a/src/libvirt_private.syms > +++ b/src/libvirt_private.syms > @@ -1202,6 +1202,7 @@ virArgvToString; > virAsprintf; > virBuildPathInternal; > virDirCreate; > +virDirOfFile; > virDoubleToStr; > virEnumFromString; > virEnumToString; > diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c > index db69a0a..ac3e1c3 100644 > --- a/src/qemu/qemu_migration.c > +++ b/src/qemu/qemu_migration.c > @@ -70,6 +70,7 @@ enum qemuMigrationCookieFlags { > QEMU_MIGRATION_COOKIE_FLAG_GRAPHICS, > QEMU_MIGRATION_COOKIE_FLAG_LOCKSTATE, > QEMU_MIGRATION_COOKIE_FLAG_PERSISTENT, > + QEMU_MIGRATION_COOKIE_FLAG_COPYSTORAGE, > > QEMU_MIGRATION_COOKIE_FLAG_LAST > }; > @@ -77,12 +78,13 @@ enum qemuMigrationCookieFlags { > VIR_ENUM_DECL(qemuMigrationCookieFlag); > VIR_ENUM_IMPL(qemuMigrationCookieFlag, > QEMU_MIGRATION_COOKIE_FLAG_LAST, > - "graphics", "lockstate", "persistent"); > + "graphics", "lockstate", "persistent", "copystorage"); > > 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_COPYSTORAGE = (1 << QEMU_MIGRATION_COOKIE_FLAG_COPYSTORAGE), > }; > > typedef struct _qemuMigrationCookieGraphics qemuMigrationCookieGraphics; > @@ -439,6 +441,10 @@ qemuMigrationCookieXMLFormat(struct qemud_driver *driver, > virBufferAdjustIndent(buf, -2); > } > > + if (mig->flags & QEMU_MIGRATION_COOKIE_COPYSTORAGE) > + virBufferAsprintf(buf, " <copystorage/>\n"); > + > + > virBufferAddLit(buf, "</qemu-migration>\n"); > return 0; > } > @@ -662,6 +668,11 @@ qemuMigrationCookieXMLParse(qemuMigrationCookiePtr mig, > VIR_FREE(nodes); > } > > + if ((flags & QEMU_MIGRATION_COOKIE_COPYSTORAGE)) { > + if (virXPathBoolean("count(./copystorage) > 0", ctxt)) > + mig->flags |= QEMU_MIGRATION_COOKIE_COPYSTORAGE; > + } > + > return 0; > > error: > @@ -1215,6 +1226,60 @@ qemuMigrationPrepareCleanup(struct qemud_driver *driver, > qemuDomainObjDiscardAsyncJob(driver, vm); > } > > +static int qemuMigrationHandleDiskFiles(const char *dom_xml, int pin) > +{ > + xmlDocPtr doc = NULL; > + xmlXPathContextPtr ctxt = NULL; > + xmlNodePtr *disks = NULL; > + virCommandPtr cmd = NULL; > + int i, nr, ret = -1; > + char *file_name[] = {}, *file_fmt[] = {}; > + char *driver_name, *tmp_dir; > + > + if (!(doc = virXMLParseStringCtxt(dom_xml, _("(domain_definition)"), &ctxt))) > + goto cleanup; > + > + if ((nr = virXPathNodeSet("./devices/disk", ctxt, &disks)) <= 0) > + goto cleanup; > + > + for (i = 0; i < nr; i++) { > + ctxt->node = disks[i]; > + driver_name = virXPathString("string(./driver/@name)", ctxt); > + if (STRNEQ(driver_name, "qemu")) > + continue; > + file_fmt[i] = virXPathString("string(./driver/@type)", ctxt); > + file_name[i] = virXPathString("string(./source/file)", ctxt); > + if (virFileExists(file_name[i]) && !pin) > + continue; > + if ((tmp_dir = virDirOfFile(file_name[i])) == NULL) > + continue; > + if (!virFileExists(tmp_dir)) > + if (virFileMakePath(tmp_dir) < 0) > + continue; > + if (pin) > + cmd = virCommandNewArgList("qemu-img", "create", "-f", > + file_fmt[i], file_name[i], ~0UL, NULL); > + else > + cmd = virCommandNewArgList("rm", "-f", file_name[i], NULL); > + if (virCommandRun(cmd, NULL) < 0) { > + goto cleanup; > + virReportSystemError(errno, "%s", > + _("unable create disk images by qemu-img")); > + } > + } > + > + ret = 0; > + > +cleanup: > + xmlXPathFreeContext(ctxt); > + xmlFreeDoc(doc); > + VIR_FREE(disks); > + virCommandFree(cmd); > + VIR_FREE(driver_name); > + VIR_FREE(tmp_dir); > + return ret; > +} > + > static int > qemuMigrationPrepareAny(struct qemud_driver *driver, > virConnectPtr dconn, > @@ -1314,6 +1379,14 @@ qemuMigrationPrepareAny(struct qemud_driver *driver, > origname = NULL; > > if (!(mig = qemuMigrationEatCookie(driver, vm, cookiein, cookieinlen, > + QEMU_MIGRATION_COOKIE_COPYSTORAGE))) > + goto cleanup; > + > + if (mig->flags & QEMU_MIGRATION_COOKIE_COPYSTORAGE) > + if (qemuMigrationHandleDiskFiles(dom_xml, 1) < 0) > + goto cleanup; > + > + if (!(mig = qemuMigrationEatCookie(driver, vm, cookiein, cookieinlen, > QEMU_MIGRATION_COOKIE_LOCKSTATE))) > goto cleanup; > > @@ -1900,8 +1973,13 @@ qemuMigrationRun(struct qemud_driver *driver, > if (flags & VIR_MIGRATE_NON_SHARED_DISK) > migrate_flags |= QEMU_MONITOR_MIGRATE_NON_SHARED_DISK; > > - if (flags & VIR_MIGRATE_NON_SHARED_INC) > + if (flags & VIR_MIGRATE_NON_SHARED_INC) { > migrate_flags |= QEMU_MONITOR_MIGRATE_NON_SHARED_INC; > + if (qemuMigrationBakeCookie(mig, driver, vm, > + cookieout, cookieoutlen, > + QEMU_MIGRATION_COOKIE_COPYSTORAGE) < 0) > + goto cleanup; > + } > > /* connect to the destination qemu if needed */ > if (spec->destType == MIGRATION_DEST_CONNECT_HOST && > @@ -2929,14 +3007,18 @@ qemuMigrationFinish(struct qemud_driver *driver, > int newVM = 1; > qemuMigrationCookiePtr mig = NULL; > virErrorPtr orig_err = NULL; > - int cookie_flags = 0; > + int cookie_flags = 0, migration_status = 0; > qemuDomainObjPrivatePtr priv = vm->privateData; > + char *dom_xml = NULL; > > VIR_DEBUG("driver=%p, dconn=%p, vm=%p, cookiein=%s, cookieinlen=%d, " > "cookieout=%p, cookieoutlen=%p, flags=%lx, retcode=%d", > driver, dconn, vm, NULLSTR(cookiein), cookieinlen, > cookieout, cookieoutlen, flags, retcode); > > + if (!(dom_xml = qemuDomainFormatXML(driver, vm, VIR_DOMAIN_XML_SECURE, false))) > + goto cleanup; > + > if (!qemuMigrationJobIsActive(vm, QEMU_ASYNC_JOB_MIGRATION_IN)) > goto cleanup; > > @@ -3088,7 +3170,11 @@ qemuMigrationFinish(struct qemud_driver *driver, > if (qemuMigrationBakeCookie(mig, driver, vm, cookieout, cookieoutlen, 0) < 0) > VIR_WARN("Unable to encode migration cookie"); > > + migration_status = 1; > + > endjob: > + if (!migration_status) > + qemuMigrationHandleDiskFiles(dom_xml, 0); > if (qemuMigrationJobFinish(driver, vm) == 0) { > vm = NULL; > } else if (!vm->persistent && !virDomainObjIsActive(vm)) { > diff --git a/src/util/util.c b/src/util/util.c > index 348c388..1f51a77 100644 > --- a/src/util/util.c > +++ b/src/util/util.c > @@ -3108,3 +3108,20 @@ virValidateWWN(const char *wwn) { > > return true; > } > + > +char *virDirOfFile(const char *file) > +{ > + char *p, *tmp; > + > + if (file == NULL) > + return NULL; > + if ((tmp = strdup(file)) == NULL) > + return NULL; > + if ((p = strrchr(file, '/')) == NULL) > + return getcwd(tmp, strlen(file)); > + if (strlen(p) == 0) > + return NULL; > + tmp[strlen(file) - strlen(p)] = '\0'; > + > + return tmp; > +} Eric probably knows better than I do but it seems like we can probably pull in dirname() from gnulib for this rather than implementing our own version. > diff --git a/src/util/util.h b/src/util/util.h > index 4316ab1..255b7b2 100644 > --- a/src/util/util.h > +++ b/src/util/util.h > @@ -114,6 +114,7 @@ enum { > }; > int virDirCreate(const char *path, mode_t mode, uid_t uid, gid_t gid, > unsigned int flags) ATTRIBUTE_RETURN_CHECK; > +char *virDirOfFile(const char *file) ATTRIBUTE_RETURN_CHECK; > int virFileMakePath(const char *path) ATTRIBUTE_RETURN_CHECK; > int virFileMakePathWithMode(const char *path, > mode_t mode) ATTRIBUTE_RETURN_CHECK; > -- > 1.7.2.5 > > -- > libvir-list mailing list > libvir-list@xxxxxxxxxx > https://www.redhat.com/mailman/listinfo/libvir-list -- Doug Goldstein -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list