[libvirt] [PATCH][RFC] helper of copy-storage-* features
Doug Goldstein
cardoe at gentoo.org
Thu Oct 18 02:50:38 UTC 2012
On Sun, Oct 14, 2012 at 9:48 PM, liguang <lig.fnst at cn.fujitsu.com> 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 at cn.fujitsu.com>
> ---
> 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 at redhat.com
> https://www.redhat.com/mailman/listinfo/libvir-list
--
Doug Goldstein
More information about the libvir-list
mailing list