在 2012-11-22四的 13:41 +0800,li guang写道: > 在 2012-11-21三的 23:21 -0600,Doug Goldstein写道: > > On Nov 21, 2012, at 8:14 PM, li guang <lig.f...@cn.fujitsu.com> wrote: > > > > > ping ... > > > > The last review I asked that you drop the usage of qemu-img and use > > libvirt's block APIs and extend them as necessary to make it easier to call > > it. Otherwise you are duplicating functionality, not respecting the probe > > option, and only supporting file types supported by qemu-img. > > yes, I'm considering your opinion, > but, seems it's not so convenience to use that function, you know? > or do you have a suitable way to call it during MigrationPrepareAny?
I mean during BakeCookie, it's hard to grab a virDomainPtr parameter for qemuDomainGetBlockInfo, and also it's unusual to BakeCookie for storage at qemu_driver.c. I've said this several days ago. > > > > > > > > > > > 在 2012-11-15四的 10:04 +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.f...@cn.fujitsu.com> > > >> --- > > >> src/qemu/qemu_migration.c | 285 > > >> ++++++++++++++++++++++++++++++++++++++++++++- > > >> 1 files changed, 284 insertions(+), 1 deletions(-) > > >> > > >> diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c > > >> index 54359c3..9e7ee4f 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,64 @@ error: > > >> return NULL; > > >> } > > >> > > >> +static qemuMigrationCookieStoragePtr > > >> +qemuMigrationCookieStorageAlloc(struct qemud_driver *driver, > > >> + virDomainDefPtr def) > > >> +{ > > >> + int i, exitstatus; > > >> + char *info = NULL, *start, *end, *tmp = NULL; > > >> + virCommandPtr cmd = NULL; > > >> + qemuMigrationCookieStoragePtr mig; > > >> + > > >> + if (VIR_ALLOC(mig) < 0) > > >> + goto no_memory; > > >> + > > >> + if (VIR_ALLOC_N(mig->disk, def->ndisks) < 0) > > >> + goto no_memory; > > >> + if (!driver->qemuImgTool) { > > >> + virReportError(VIR_ERR_INTERNAL_ERROR, > > >> + "%s", _("unable to find kvm-img or qemu-img")); > > >> + goto error; > > >> + } > > >> + mig->ndisks = def->ndisks; > > >> + > > >> + for (i = 0; i < mig->ndisks; i++) { > > >> + cmd = virCommandNewArgList(driver->qemuImgTool, "info", > > >> + def->disks[i]->src, NULL); > > >> + virCommandAddEnvString(cmd, "LC_ALL=C"); > > >> + virCommandSetOutputBuffer(cmd, &info); > > >> + virCommandClearCaps(cmd); > > >> + if (virCommandRun(cmd, &exitstatus) < 0) > > >> + goto error; > > >> + if ((start = strstr(info, "virtual size: ")) == NULL || > > >> + ((end = strstr(start, "\n")) == NULL)) { > > >> + virReportError(VIR_ERR_INTERNAL_ERROR, > > >> + _("unable to parse qemu-img output '%s'"), > > >> + info); > > >> + goto error; > > >> + } > > >> + if ((tmp = strstr(start, " (")) && tmp < end) > > >> + end = tmp; > > >> + start += strlen("virtual size: "); > > >> + if (start >= end) > > >> + goto error; > > >> + if (!(mig->disk[i].dsize = strndup(start, end-start))) > > >> + goto error; > > >> + VIR_FREE(info); > > >> + virCommandFree(cmd); > > >> + } > > >> + > > >> + return mig; > > >> + > > >> +no_memory: > > >> + virReportOOMError(); > > >> +error: > > >> + virCommandFree(cmd); > > >> + VIR_FREE(info); > > >> + qemuMigrationCookieStorageFree(mig); > > >> + return NULL; > > >> +} > > >> + > > >> static qemuMigrationCookiePtr > > >> qemuMigrationCookieNew(virDomainObjPtr dom) > > >> { > > >> @@ -491,6 +586,25 @@ > > >> 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; > > >> + } > > >> + > > >> + if (dom->def->ndisks > 0) { > > >> + mig->storage = qemuMigrationCookieStorageAlloc(driver, > > >> dom->def); > > >> + if (!mig->storage) > > >> + return -1; > > >> + mig->flags |= QEMU_MIGRATION_COOKIE_COPYSTORAGE; > > >> + } > > >> + > > >> + return 0; > > >> +} > > >> > > >> static void qemuMigrationCookieGraphicsXMLFormat(virBufferPtr buf, > > >> > > >> qemuMigrationCookieGraphicsPtr grap) > > >> @@ -540,6 +654,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 +721,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; > > >> } > > >> @@ -722,6 +852,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, > > >> @@ -874,6 +1042,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: > > >> @@ -938,6 +1111,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; > > >> > > >> @@ -1443,6 +1621,11 @@ char *qemuMigrationBegin(struct qemud_driver > > >> *driver, > > >> QEMU_MIGRATION_COOKIE_LOCKSTATE) < 0) > > >> goto cleanup; > > >> > > >> + 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)) { > > >> @@ -1484,6 +1667,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. > > >> */ > > >> > > >> @@ -1599,6 +1867,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; > > >> @@ -3250,6 +3527,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", > > >> @@ -3415,7 +3693,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.f...@cn.fujitsu.com > > > linux kernel team at FNST, china > > > > > > > > > -- > > > libvir-list mailing list > > > libvir-list@redhat.com > > > https://www.redhat.com/mailman/listinfo/libvir-list > -- li guang lig.f...@cn.fujitsu.com linux kernel team at FNST, china -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list