On Nov 21, 2012, at 11:41 PM, li guang <lig.f...@cn.fujitsu.com> wrote:
> 在 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? All the pieces are available if I recall when I looked before. I believe I suggested splitting the function into too since there was some unnecessary up front bits being done that would make the args even easier. When I get back to a PC I can hack up a patch. > 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