[libvirt] [PATCH v1 2/2] help to create disk images of non-shared migration

li guang lig.fnst at cn.fujitsu.com
Thu Nov 22 06:32:17 UTC 2012


在 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.fnst at 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.fnst at 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 at cn.fujitsu.com
> > > linux kernel team at FNST, china
> > > 
> > > 
> > > --
> > > libvir-list mailing list
> > > libvir-list at redhat.com
> > > https://www.redhat.com/mailman/listinfo/libvir-list
> 

-- 
li guang  lig.fnst at cn.fujitsu.com
linux kernel team at FNST, china





More information about the libvir-list mailing list