在 2012-11-21三的 23:21 -0600,Doug Goldstein写道:
> On Nov 21, 2012, at 8:14 PM, li guang <lig.fnst(a)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.fnst(a)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.fnst(a)cn.fujitsu.com
>> linux kernel team at FNST, china
>>
>>
>> --
>> libvir-list mailing list
>> libvir-list(a)redhat.com
>>
https://www.redhat.com/mailman/listinfo/libvir-list
--
li guang lig.fnst(a)cn.fujitsu.com
linux kernel team at FNST, china