[libvirt] [PATCH][RFC] helper of copy-storage-* features

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@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; +} 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

ping ... 在 2012-10-15一的 10:48 +0800,liguang写道:
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@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; +} 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;
-- liguang lig.fnst@cn.fujitsu.com FNST linux kernel team

On Sun, Oct 14, 2012 at 9:48 PM, liguang <lig.fnst@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@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@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
-- Doug Goldstein

在 2012-10-17三的 21:50 -0500,Doug Goldstein写道:
On Sun, Oct 14, 2012 at 9:48 PM, liguang <lig.fnst@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
+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.
maybe, but dirname has its own known issues(e.g. for old version glibc, dirname will "generate a segfault if given a NULL argument"), so I try to choose a loosely implementation. but, if libvirt cares nothing about these tiny issues, I'd like to choose dirname.
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@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
-- liguang lig.fnst@cn.fujitsu.com FNST linux kernel team

On Thu, Oct 18, 2012 at 12:47 AM, li guang <lig.fnst@cn.fujitsu.com> wrote:
在 2012-10-17三的 21:50 -0500,Doug Goldstein写道:
On Sun, Oct 14, 2012 at 9:48 PM, liguang <lig.fnst@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
+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.
maybe, but dirname has its own known issues(e.g. for old version glibc, dirname will "generate a segfault if given a NULL argument"), so I try to choose a loosely implementation. but, if libvirt cares nothing about these tiny issues, I'd like to choose dirname.
That's why I'm suggesting to use dirname from gnulib, which fixes several of those issues. Additionally the implementation above wouldn't work on Windows, not that we currently build the libvirtd on Windows but if the function was used in the future the function would have to be fixed.
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@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
-- liguang lig.fnst@cn.fujitsu.com FNST linux kernel team
-- Doug Goldstein

在 2012-10-18四的 01:03 -0500,Doug Goldstein写道:
On Thu, Oct 18, 2012 at 12:47 AM, li guang <lig.fnst@cn.fujitsu.com> wrote:
在 2012-10-17三的 21:50 -0500,Doug Goldstein写道:
On Sun, Oct 14, 2012 at 9:48 PM, liguang <lig.fnst@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
+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.
maybe, but dirname has its own known issues(e.g. for old version glibc, dirname will "generate a segfault if given a NULL argument"), so I try to choose a loosely implementation. but, if libvirt cares nothing about these tiny issues, I'd like to choose dirname.
That's why I'm suggesting to use dirname from gnulib, which fixes several of those issues. Additionally the implementation above wouldn't work on Windows, not that we currently build the libvirtd on Windows but if the function was used in the future the function would have to be fixed.
glad to hear that gnulib's dirname is a fixed version, if so, I'd like to use it instead of my silly re-implementation. Thanks!
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@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
-- liguang lig.fnst@cn.fujitsu.com FNST linux kernel team
-- liguang lig.fnst@cn.fujitsu.com FNST linux kernel team

On 10/17/2012 08:50 PM, Doug Goldstein wrote:
On Sun, Oct 14, 2012 at 9:48 PM, liguang <lig.fnst@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.
+char *virDirOfFile(const char *file)
Poor naming. Better might be virDirName, to match what we are wrapping.
+{ + 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.
'git grep mdir_name' - we're already using the gnulib interface in two places. It does not handle NULL input, but that would imply you just write: char * virDirName(const char *file) { if (!file) return NULL; return mdir_name(file); } and let the caller deal with NULL return. Then again, if the caller is going to virReportOOMError(), it may be better to just use mdir_name() directly, and guarantee that the caller doesn't pass in NULL in the first place. -- Eric Blake eblake@redhat.com +1-919-301-3266 Libvirt virtualization library http://libvirt.org

在 2012-10-18四的 06:52 -0600,Eric Blake写道:
On 10/17/2012 08:50 PM, Doug Goldstein wrote:
On Sun, Oct 14, 2012 at 9:48 PM, liguang <lig.fnst@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.
+char *virDirOfFile(const char *file)
Poor naming. Better might be virDirName, to match what we are wrapping.
+{ + 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.
'git grep mdir_name' - we're already using the gnulib interface in two places. It does not handle NULL input, but that would imply you just write:
char * virDirName(const char *file) { if (!file) return NULL; return mdir_name(file); }
and let the caller deal with NULL return. Then again, if the caller is going to virReportOOMError(), it may be better to just use mdir_name() directly, and guarantee that the caller doesn't pass in NULL in the first place.
OK, I'll use mdir_name directly, new patch will come up later. Thanks! -- liguang lig.fnst@cn.fujitsu.com FNST linux kernel team
participants (4)
-
Doug Goldstein
-
Eric Blake
-
li guang
-
liguang