在 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? > > > > > > 在 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