[libvirt] [PATCH v1 2/2][RFC] help to create disk images of non-shared migration
li guang
lig.fnst at cn.fujitsu.com
Fri Nov 23 05:48:33 UTC 2012
Hi, Doug
for your comment, I changed to use virDomainGetBlockInfo()
to prepare disk images for non-shared migration,
but, it really looks ugly and doesn't make much sense.
what's your opinion?
在 2012-11-23五的 13:28 +0800,liguang写道:
> 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 usage had been discussed before,
> http://www.redhat.com/archives/libvir-list/2011-December/msg00451.html
>
> this patch depends on my support offline migration patch:
> https://www.redhat.com/archives/libvir-list/2012-November/msg00512.html
>
> Signed-off-by: liguang <lig.fnst at cn.fujitsu.com>
> ---
> src/qemu/qemu_conf.h | 2 +
> src/qemu/qemu_driver.c | 1 +
> src/qemu/qemu_migration.c | 275 ++++++++++++++++++++++++++++++++++++++++++++-
> 3 files changed, 277 insertions(+), 1 deletions(-)
>
> diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h
> index 47f349c..ad789e9 100644
> --- a/src/qemu/qemu_conf.h
> +++ b/src/qemu/qemu_conf.h
> @@ -102,6 +102,8 @@ struct qemud_driver {
> char *hugetlbfs_mount;
> char *hugepage_path;
>
> + void *private;
> +
> unsigned int macFilter : 1;
> ebtablesContext *ebtables;
>
> diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
> index b23056b..db11629 100644
> --- a/src/qemu/qemu_driver.c
> +++ b/src/qemu/qemu_driver.c
> @@ -1133,6 +1133,7 @@ static virDrvOpenStatus qemudOpen(virConnectPtr conn,
> }
> }
> }
> + qemu_driver->private = conn;
> conn->privateData = qemu_driver;
>
> return VIR_DRV_OPEN_SUCCESS;
> diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
> index 53171df..8b4e563 100644
> --- a/src/qemu/qemu_migration.c
> +++ b/src/qemu/qemu_migration.c
> @@ -50,6 +50,7 @@
> #include "storage_file.h"
> #include "viruri.h"
> #include "hooks.h"
> +#include "dirname.h"
>
>
> #define VIR_FROM_THIS VIR_FROM_QEMU
> @@ -72,6 +73,7 @@ enum qemuMigrationCookieFlags {
> QEMU_MIGRATION_COOKIE_FLAG_LOCKSTATE,
> QEMU_MIGRATION_COOKIE_FLAG_PERSISTENT,
> QEMU_MIGRATION_COOKIE_FLAG_NETWORK,
> + QEMU_MIGRATION_COOKIE_FLAG_COPYSTORAGE,
>
> QEMU_MIGRATION_COOKIE_FLAG_LAST
> };
> @@ -79,13 +81,14 @@ enum qemuMigrationCookieFlags {
> VIR_ENUM_DECL(qemuMigrationCookieFlag);
> VIR_ENUM_IMPL(qemuMigrationCookieFlag,
> QEMU_MIGRATION_COOKIE_FLAG_LAST,
> - "graphics", "lockstate", "persistent", "network");
> + "graphics", "lockstate", "persistent", "network", "storage");
>
> 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_NETWORK = (1 << QEMU_MIGRATION_COOKIE_FLAG_NETWORK),
> + QEMU_MIGRATION_COOKIE_COPYSTORAGE = (1 << QEMU_MIGRATION_COOKIE_FLAG_COPYSTORAGE),
> };
>
> typedef struct _qemuMigrationCookieGraphics qemuMigrationCookieGraphics;
> @@ -119,6 +122,19 @@ struct _qemuMigrationCookieNetwork {
> qemuMigrationCookieNetDataPtr net;
> };
>
> +typedef struct _qemuMigrationCookieStorageData qemuMigrationCookieStorageData;
> +typedef qemuMigrationCookieStorageData *qemuMigrationCookieStorageDataPtr;
> +struct _qemuMigrationCookieStorageData {
> + char *dsize;
> +};
> +
> +typedef struct _qemuMigrationCookieStorage qemuMigrationCookieStorage;
> +typedef qemuMigrationCookieStorage *qemuMigrationCookieStoragePtr;
> +struct _qemuMigrationCookieStorage {
> + int ndisks;
> + qemuMigrationCookieStorageDataPtr disk;
> +};
> +
> typedef struct _qemuMigrationCookie qemuMigrationCookie;
> typedef qemuMigrationCookie *qemuMigrationCookiePtr;
> struct _qemuMigrationCookie {
> @@ -147,6 +163,9 @@ struct _qemuMigrationCookie {
>
> /* If (flags & QEMU_MIGRATION_COOKIE_NETWORK) */
> qemuMigrationCookieNetworkPtr network;
> +
> + /* If (flags & QEMU_MIGRATION_COOKIE_COPYSTORAGE) */
> + qemuMigrationCookieStoragePtr storage;
> };
>
> static void qemuMigrationCookieGraphicsFree(qemuMigrationCookieGraphicsPtr grap)
> @@ -175,6 +194,21 @@ qemuMigrationCookieNetworkFree(qemuMigrationCookieNetworkPtr network)
> VIR_FREE(network);
> }
>
> +static void
> +qemuMigrationCookieStorageFree(qemuMigrationCookieStoragePtr storage)
> +{
> + int i;
> +
> + if (!storage)
> + return;
> +
> + if (storage->disk) {
> + for (i = 0; i < storage->ndisks; i++)
> + VIR_FREE(storage->disk[i].dsize);
> + }
> + VIR_FREE(storage->disk);
> + VIR_FREE(storage);
> +}
>
> static void qemuMigrationCookieFree(qemuMigrationCookiePtr mig)
> {
> @@ -187,6 +221,9 @@ static void qemuMigrationCookieFree(qemuMigrationCookiePtr mig)
> if (mig->flags & QEMU_MIGRATION_COOKIE_NETWORK)
> qemuMigrationCookieNetworkFree(mig->network);
>
> + if (mig->flags & QEMU_MIGRATION_COOKIE_COPYSTORAGE)
> + qemuMigrationCookieStorageFree(mig->storage);
> +
> VIR_FREE(mig->localHostname);
> VIR_FREE(mig->remoteHostname);
> VIR_FREE(mig->name);
> @@ -356,6 +393,45 @@ error:
> return NULL;
> }
>
> +static qemuMigrationCookieStoragePtr
> +qemuMigrationCookieStorageAlloc(struct qemud_driver *driver,
> + virDomainDefPtr def)
> +{
> + int i;
> + qemuMigrationCookieStoragePtr mig;
> + virDomainBlockInfo info;
> + virDomainPtr dom;
> + virConnectPtr conn = driver->private;
> +
> + dom = virGetDomain(conn, def->name, def->uuid);
> + if (!dom)
> + goto error;
> + dom->id = def->id;
> +
> + if (VIR_ALLOC(mig) < 0)
> + goto no_memory;
> + if (VIR_ALLOC_N(mig->disk, def->ndisks) < 0)
> + goto no_memory;
> +
> + mig->ndisks = def->ndisks;
> +
> + for (i = 0; i < mig->ndisks; i++) {
> + if (virDomainGetBlockInfo(dom, def->disks[i]->src,
> + &info, 0) < 0)
> + goto error;
> + if (virAsprintf(&(mig->disk[i].dsize), "%llu", info.capacity) < 0)
> + goto no_memory;
> + }
> +
> + return mig;
> +
> +no_memory:
> + virReportOOMError();
> +error:
> + qemuMigrationCookieStorageFree(mig);
> + return NULL;
> +}
> +
> static qemuMigrationCookiePtr
> qemuMigrationCookieNew(virDomainObjPtr dom)
> {
> @@ -491,6 +567,31 @@ qemuMigrationCookieAddNetwork(qemuMigrationCookiePtr mig,
> return 0;
> }
>
> +static int qemuMigrationCookieAddStorage(qemuMigrationCookiePtr mig,
> + struct qemud_driver *driver,
> + virDomainObjPtr dom)
> +{
> + if (mig->flags & QEMU_MIGRATION_COOKIE_COPYSTORAGE) {
> + virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> + _("migration storage data already present"));
> + return -1;
> + }
> +
> + virDomainObjUnlock(dom);
> + qemuDriverUnlock(driver);
> +
> + if (dom->def->ndisks > 0) {
> + mig->storage = qemuMigrationCookieStorageAlloc(driver, dom->def);
> + if (!mig->storage)
> + return -1;
> + mig->flags |= QEMU_MIGRATION_COOKIE_COPYSTORAGE;
> + }
> +
> + qemuDriverLock(driver);
> + virDomainObjLock(dom);
> +
> + return 0;
> +}
>
> static void qemuMigrationCookieGraphicsXMLFormat(virBufferPtr buf,
> qemuMigrationCookieGraphicsPtr grap)
> @@ -540,6 +641,19 @@ qemuMigrationCookieNetworkXMLFormat(virBufferPtr buf,
> virBufferAddLit(buf, " </network>\n");
> }
>
> +static void
> +qemuMigrationCookieStorageXMLFormat(virBufferPtr buf,
> + qemuMigrationCookieStoragePtr dsz)
> +{
> + int i = 0;
> +
> + for (i = 0; i < dsz->ndisks; i++) {
> + char *dsize = dsz->disk[i].dsize;
> + virBufferAsprintf(buf, " <copystorage>\n");
> + virBufferAsprintf(buf, " <disksize>%s</disksize>\n", dsize);
> + virBufferAddLit(buf, " </copystorage>\n");
> + }
> +}
>
> static int
> qemuMigrationCookieXMLFormat(struct qemud_driver *driver,
> @@ -594,6 +708,9 @@ qemuMigrationCookieXMLFormat(struct qemud_driver *driver,
> if ((mig->flags & QEMU_MIGRATION_COOKIE_NETWORK) && mig->network)
> qemuMigrationCookieNetworkXMLFormat(buf, mig->network);
>
> + if ((mig->flags & QEMU_MIGRATION_COOKIE_COPYSTORAGE) && mig->storage)
> + qemuMigrationCookieStorageXMLFormat(buf, mig->storage);
> +
> virBufferAddLit(buf, "</qemu-migration>\n");
> return 0;
> }
> @@ -721,6 +838,44 @@ error:
> goto cleanup;
> }
>
> +static qemuMigrationCookieStoragePtr
> +qemuMigrationCookieStorageXMLParse(xmlXPathContextPtr ctxt)
> +{
> + qemuMigrationCookieStoragePtr dsz;
> + int i, n;
> + xmlNodePtr *storage = NULL;
> +
> + if (VIR_ALLOC(dsz) < 0)
> + goto no_memory;
> +
> + if ((n = virXPathNodeSet("./copystorage", ctxt, &storage)) < 0) {
> + virReportError(VIR_ERR_INTERNAL_ERROR,
> + "%s", _("missing storage information"));
> + goto error;
> + }
> +
> + dsz->ndisks = n;
> + if (VIR_ALLOC_N(dsz->disk, dsz->ndisks) < 0)
> + goto no_memory;
> +
> + for (i = 0; i < dsz->ndisks; i++) {
> + ctxt->node = storage[i];
> + if (!(dsz->disk[i].dsize = virXPathString("string(./disksize[1])", ctxt)))
> + virReportError(VIR_ERR_INTERNAL_ERROR,
> + "%s", _("missing tlsPort attribute in migration data"));
> + }
> +
> +cleanup:
> + VIR_FREE(storage);
> + return dsz;
> +
> +no_memory:
> + virReportOOMError();
> +error:
> + qemuMigrationCookieStorageFree(dsz);
> + dsz = NULL;
> + goto cleanup;
> +}
>
> static int
> qemuMigrationCookieXMLParse(qemuMigrationCookiePtr mig,
> @@ -873,6 +1028,11 @@ qemuMigrationCookieXMLParse(qemuMigrationCookiePtr mig,
> (!(mig->network = qemuMigrationCookieNetworkXMLParse(ctxt))))
> goto error;
>
> + if ((flags & QEMU_MIGRATION_COOKIE_COPYSTORAGE) &&
> + virXPathBoolean("count(./copystorage) > 0", ctxt) &&
> + (!(mig->storage = qemuMigrationCookieStorageXMLParse(ctxt))))
> + goto error;
> +
> return 0;
>
> error:
> @@ -937,6 +1097,11 @@ qemuMigrationBakeCookie(qemuMigrationCookiePtr mig,
> return -1;
> }
>
> + if (flags & QEMU_MIGRATION_COOKIE_COPYSTORAGE &&
> + qemuMigrationCookieAddStorage(mig, driver, dom) < 0) {
> + return -1;
> + }
> +
> if (!(*cookieout = qemuMigrationCookieXMLFormatStr(driver, mig)))
> return -1;
>
> @@ -1442,6 +1607,14 @@ char *qemuMigrationBegin(struct qemud_driver *driver,
> QEMU_MIGRATION_COOKIE_LOCKSTATE) < 0)
> goto cleanup;
>
> + if (flags & (VIR_MIGRATE_NON_SHARED_DISK |
> + VIR_MIGRATE_NON_SHARED_INC)) {
> + if (qemuMigrationBakeCookie(mig, driver, vm,
> + cookieout, cookieoutlen,
> + QEMU_MIGRATION_COOKIE_COPYSTORAGE) < 0)
> + goto cleanup;
> + }
> +
> if (flags & VIR_MIGRATE_OFFLINE) {
> if (flags & (VIR_MIGRATE_NON_SHARED_DISK |
> VIR_MIGRATE_NON_SHARED_INC)) {
> @@ -1487,6 +1660,91 @@ cleanup:
> }
>
>
> +/*
> + if gen is true, find out disk images migration required,
> + so try to generate them at target,
> + if gen is false, delete disk images generated before.
> +*/
> +static int qemuMigrationHandleDiskFiles(struct qemud_driver *driver,
> + virDomainDefPtr def, bool gen,
> + qemuMigrationCookiePtr mig)
> +{
> + char *tmp_dir = NULL, *outbuf = NULL;
> + const char *img_tool = driver->qemuImgTool;
> + const char *disk_format[] = {"none", "raw", "none", "none", "none",
> + "cow", "none", "none", "qcow", "qcow2",
> + "qed", "vmdk", "vpc","none", "none"
> + };
> + virCommandPtr cmd = NULL;
> + int i, ret = -1;
> +
> + if (!def->ndisks)
> + return 0;
> +
> + if (img_tool == NULL) {
> + virReportError(VIR_ERR_INTERNAL_ERROR,
> + "%s", _("unable to find kvm-img or qemu-img"));
> + goto error;
> + }
> +
> + for (i = 0; i < def->ndisks; i++) {
> + if (STRNEQ(def->disks[i]->driverName, "qemu"))
> + continue;
> + if (def->disks[i]->src == NULL)
> + continue;
> + if (virFileExists(def->disks[i]->src) && gen)
> + continue;
> + if (!gen && !virFileExists(def->disks[i]->src))
> + continue;
> + if ((tmp_dir = mdir_name(def->disks[i]->src)) == NULL)
> + continue;
> + if (!virFileExists(tmp_dir))
> + if (virFileMakePath(tmp_dir) < 0)
> + continue;
> + if (STREQ(disk_format[def->disks[i]->format], "none"))
> + continue;
> + if (def->disks[i]->format < VIR_STORAGE_FILE_RAW)
> + goto error;
> + if (def->disks[i]->format >= VIR_STORAGE_FILE_LAST)
> + goto error;
> +
> + if (gen) {
> + char *dsize = mig->storage->disk[i].dsize;
> + cmd = virCommandNewArgList(img_tool, "create", "-f",
> + disk_format[def->disks[i]->format],
> + def->disks[i]->src, NULL);
> + virCommandAddArgFormat(cmd, "%s", dsize);
> + if (def->disks[i]->encryption)
> + virCommandAddArgList(cmd, "-o", "encryption=on", NULL);
> + virCommandSetOutputBuffer(cmd, &outbuf);
> + if (virCommandRun(cmd, NULL) < 0) {
> + virReportSystemError(errno, "%s", outbuf);
> + goto cleanup;
> + }
> + } else {
> + if (unlink(def->disks[i]->src) < 0) {
> + virReportError(errno, "%s", _("fail to unlink disk image file"));
> + goto cleanup;
> + }
> + }
> + virCommandFree(cmd);
> + VIR_FREE(tmp_dir);
> + VIR_FREE(outbuf);
> + }
> +
> + ret = 0;
> +
> +cleanup:
> + if (ret < 0) {
> + virCommandFree(cmd);
> + VIR_FREE(tmp_dir);
> + VIR_FREE(outbuf);
> + }
> +error:
> + return ret;
> +}
> +
> +
> /* Prepare is the first step, and it runs on the destination host.
> */
>
> @@ -1602,6 +1860,15 @@ qemuMigrationPrepareAny(struct qemud_driver *driver,
> /* virDomainAssignDef already set the error */
> goto cleanup;
> }
> +
> + if (!(mig = qemuMigrationEatCookie(driver, vm, cookiein, cookieinlen,
> + QEMU_MIGRATION_COOKIE_COPYSTORAGE)))
> + goto cleanup;
> +
> + if (flags & (VIR_MIGRATE_NON_SHARED_DISK | VIR_MIGRATE_NON_SHARED_INC))
> + if (qemuMigrationHandleDiskFiles(driver, def, true, mig) < 0)
> + goto endjob;
> +
> def = NULL;
> priv = vm->privateData;
> priv->origname = origname;
> @@ -3247,6 +3514,7 @@ qemuMigrationFinish(struct qemud_driver *driver,
> virErrorPtr orig_err = NULL;
> int cookie_flags = 0;
> qemuDomainObjPrivatePtr priv = vm->privateData;
> + bool migration_status = false;
>
> VIR_DEBUG("driver=%p, dconn=%p, vm=%p, cookiein=%s, cookieinlen=%d, "
> "cookieout=%p, cookieoutlen=%p, flags=%lx, retcode=%d",
> @@ -3416,7 +3684,12 @@ qemuMigrationFinish(struct qemud_driver *driver,
> if (qemuMigrationBakeCookie(mig, driver, vm, cookieout, cookieoutlen, 0) < 0)
> VIR_WARN("Unable to encode migration cookie");
>
> + migration_status = true;
> +
> endjob:
> + if (!migration_status && flags &
> + (VIR_MIGRATE_NON_SHARED_DISK | VIR_MIGRATE_NON_SHARED_INC))
> + qemuMigrationHandleDiskFiles(driver, vm->def, false, NULL);
> if (qemuMigrationJobFinish(driver, vm) == 0) {
> vm = NULL;
> } else if (!vm->persistent && !virDomainObjIsActive(vm)) {
--
li guang lig.fnst at cn.fujitsu.com
linux kernel team at FNST, china
More information about the libvir-list
mailing list