[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

Re: [libvirt] [PATCH][RFC] helper of copy-storage-* features



On Sun, Oct 14, 2012 at 9:48 PM, liguang <lig fnst cn fujitsu com> wrote:
> help to create disk images copy-storage-* required,
> 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 use had been discussed before,
> http://www.redhat.com/archives/libvir-list/2011-December/msg00451.html
>
> It did not handle more about complete situations
> suggested by Daniel P. Berrange,
> https://www.redhat.com/archives/libvir-list/2012-October/msg00407.html
>
> Signed-off-by: liguang <lig fnst cn fujitsu com>
> ---
>  src/libvirt_private.syms  |    1 +
>  src/qemu/qemu_migration.c |   92 +++++++++++++++++++++++++++++++++++++++++++-
>  src/util/util.c           |   17 ++++++++
>  src/util/util.h           |    1 +
>  4 files changed, 108 insertions(+), 3 deletions(-)
>
> diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
> index a8c81e7..a293184 100644
> --- a/src/libvirt_private.syms
> +++ b/src/libvirt_private.syms
> @@ -1202,6 +1202,7 @@ virArgvToString;
>  virAsprintf;
>  virBuildPathInternal;
>  virDirCreate;
> +virDirOfFile;
>  virDoubleToStr;
>  virEnumFromString;
>  virEnumToString;
> diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
> index db69a0a..ac3e1c3 100644
> --- a/src/qemu/qemu_migration.c
> +++ b/src/qemu/qemu_migration.c
> @@ -70,6 +70,7 @@ enum qemuMigrationCookieFlags {
>      QEMU_MIGRATION_COOKIE_FLAG_GRAPHICS,
>      QEMU_MIGRATION_COOKIE_FLAG_LOCKSTATE,
>      QEMU_MIGRATION_COOKIE_FLAG_PERSISTENT,
> +    QEMU_MIGRATION_COOKIE_FLAG_COPYSTORAGE,
>
>      QEMU_MIGRATION_COOKIE_FLAG_LAST
>  };
> @@ -77,12 +78,13 @@ enum qemuMigrationCookieFlags {
>  VIR_ENUM_DECL(qemuMigrationCookieFlag);
>  VIR_ENUM_IMPL(qemuMigrationCookieFlag,
>                QEMU_MIGRATION_COOKIE_FLAG_LAST,
> -              "graphics", "lockstate", "persistent");
> +              "graphics", "lockstate", "persistent", "copystorage");
>
>  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_COPYSTORAGE = (1 << QEMU_MIGRATION_COOKIE_FLAG_COPYSTORAGE),
>  };
>
>  typedef struct _qemuMigrationCookieGraphics qemuMigrationCookieGraphics;
> @@ -439,6 +441,10 @@ qemuMigrationCookieXMLFormat(struct qemud_driver *driver,
>          virBufferAdjustIndent(buf, -2);
>      }
>
> +    if (mig->flags & QEMU_MIGRATION_COOKIE_COPYSTORAGE)
> +        virBufferAsprintf(buf, "  <copystorage/>\n");
> +
> +
>      virBufferAddLit(buf, "</qemu-migration>\n");
>      return 0;
>  }
> @@ -662,6 +668,11 @@ qemuMigrationCookieXMLParse(qemuMigrationCookiePtr mig,
>          VIR_FREE(nodes);
>      }
>
> +    if ((flags & QEMU_MIGRATION_COOKIE_COPYSTORAGE)) {
> +        if (virXPathBoolean("count(./copystorage) > 0", ctxt))
> +            mig->flags |= QEMU_MIGRATION_COOKIE_COPYSTORAGE;
> +    }
> +
>      return 0;
>
>  error:
> @@ -1215,6 +1226,60 @@ qemuMigrationPrepareCleanup(struct qemud_driver *driver,
>      qemuDomainObjDiscardAsyncJob(driver, vm);
>  }
>
> +static int qemuMigrationHandleDiskFiles(const char *dom_xml, int pin)
> +{
> +    xmlDocPtr doc = NULL;
> +    xmlXPathContextPtr ctxt = NULL;
> +    xmlNodePtr *disks = NULL;
> +    virCommandPtr cmd = NULL;
> +    int i, nr, ret = -1;
> +    char *file_name[] = {}, *file_fmt[] = {};
> +    char *driver_name, *tmp_dir;
> +
> +    if (!(doc = virXMLParseStringCtxt(dom_xml, _("(domain_definition)"), &ctxt)))
> +        goto cleanup;
> +
> +    if ((nr = virXPathNodeSet("./devices/disk", ctxt, &disks)) <= 0)
> +        goto cleanup;
> +
> +    for (i = 0; i < nr; i++) {
> +        ctxt->node = disks[i];
> +        driver_name = virXPathString("string(./driver/@name)", ctxt);
> +        if (STRNEQ(driver_name, "qemu"))
> +            continue;
> +        file_fmt[i] = virXPathString("string(./driver/@type)", ctxt);
> +        file_name[i] = virXPathString("string(./source/file)", ctxt);
> +        if (virFileExists(file_name[i]) && !pin)
> +            continue;
> +        if ((tmp_dir = virDirOfFile(file_name[i])) == NULL)
> +            continue;
> +        if (!virFileExists(tmp_dir))
> +            if (virFileMakePath(tmp_dir) < 0)
> +                continue;
> +        if (pin)
> +            cmd = virCommandNewArgList("qemu-img", "create", "-f",
> +                                       file_fmt[i], file_name[i], ~0UL, NULL);
> +        else
> +            cmd = virCommandNewArgList("rm", "-f", file_name[i], NULL);
> +        if (virCommandRun(cmd, NULL) < 0) {
> +            goto cleanup;
> +            virReportSystemError(errno, "%s",
> +                                 _("unable create disk images by qemu-img"));
> +        }
> +    }
> +
> +    ret = 0;
> +
> +cleanup:
> +    xmlXPathFreeContext(ctxt);
> +    xmlFreeDoc(doc);
> +    VIR_FREE(disks);
> +    virCommandFree(cmd);
> +    VIR_FREE(driver_name);
> +    VIR_FREE(tmp_dir);
> +    return ret;
> +}
> +
>  static int
>  qemuMigrationPrepareAny(struct qemud_driver *driver,
>                          virConnectPtr dconn,
> @@ -1314,6 +1379,14 @@ qemuMigrationPrepareAny(struct qemud_driver *driver,
>      origname = NULL;
>
>      if (!(mig = qemuMigrationEatCookie(driver, vm, cookiein, cookieinlen,
> +                                       QEMU_MIGRATION_COOKIE_COPYSTORAGE)))
> +        goto cleanup;
> +
> +    if (mig->flags & QEMU_MIGRATION_COOKIE_COPYSTORAGE)
> +        if (qemuMigrationHandleDiskFiles(dom_xml, 1) < 0)
> +            goto cleanup;
> +
> +    if (!(mig = qemuMigrationEatCookie(driver, vm, cookiein, cookieinlen,
>                                         QEMU_MIGRATION_COOKIE_LOCKSTATE)))
>          goto cleanup;
>
> @@ -1900,8 +1973,13 @@ qemuMigrationRun(struct qemud_driver *driver,
>      if (flags & VIR_MIGRATE_NON_SHARED_DISK)
>          migrate_flags |= QEMU_MONITOR_MIGRATE_NON_SHARED_DISK;
>
> -    if (flags & VIR_MIGRATE_NON_SHARED_INC)
> +    if (flags & VIR_MIGRATE_NON_SHARED_INC) {
>          migrate_flags |= QEMU_MONITOR_MIGRATE_NON_SHARED_INC;
> +        if (qemuMigrationBakeCookie(mig, driver, vm,
> +                                    cookieout, cookieoutlen,
> +                                    QEMU_MIGRATION_COOKIE_COPYSTORAGE) < 0)
> +            goto cleanup;
> +    }
>
>      /* connect to the destination qemu if needed */
>      if (spec->destType == MIGRATION_DEST_CONNECT_HOST &&
> @@ -2929,14 +3007,18 @@ qemuMigrationFinish(struct qemud_driver *driver,
>      int newVM = 1;
>      qemuMigrationCookiePtr mig = NULL;
>      virErrorPtr orig_err = NULL;
> -    int cookie_flags = 0;
> +    int cookie_flags = 0, migration_status = 0;
>      qemuDomainObjPrivatePtr priv = vm->privateData;
> +    char *dom_xml = NULL;
>
>      VIR_DEBUG("driver=%p, dconn=%p, vm=%p, cookiein=%s, cookieinlen=%d, "
>                "cookieout=%p, cookieoutlen=%p, flags=%lx, retcode=%d",
>                driver, dconn, vm, NULLSTR(cookiein), cookieinlen,
>                cookieout, cookieoutlen, flags, retcode);
>
> +    if (!(dom_xml = qemuDomainFormatXML(driver, vm, VIR_DOMAIN_XML_SECURE, false)))
> +        goto cleanup;
> +
>      if (!qemuMigrationJobIsActive(vm, QEMU_ASYNC_JOB_MIGRATION_IN))
>          goto cleanup;
>
> @@ -3088,7 +3170,11 @@ qemuMigrationFinish(struct qemud_driver *driver,
>      if (qemuMigrationBakeCookie(mig, driver, vm, cookieout, cookieoutlen, 0) < 0)
>          VIR_WARN("Unable to encode migration cookie");
>
> +    migration_status = 1;
> +
>  endjob:
> +    if (!migration_status)
> +        qemuMigrationHandleDiskFiles(dom_xml, 0);
>      if (qemuMigrationJobFinish(driver, vm) == 0) {
>          vm = NULL;
>      } else if (!vm->persistent && !virDomainObjIsActive(vm)) {
> diff --git a/src/util/util.c b/src/util/util.c
> index 348c388..1f51a77 100644
> --- a/src/util/util.c
> +++ b/src/util/util.c
> @@ -3108,3 +3108,20 @@ virValidateWWN(const char *wwn) {
>
>      return true;
>  }
> +
> +char *virDirOfFile(const char *file)
> +{
> +    char *p, *tmp;
> +
> +    if (file == NULL)
> +        return NULL;
> +    if ((tmp = strdup(file)) == NULL)
> +        return NULL;
> +    if ((p = strrchr(file, '/')) == NULL)
> +        return getcwd(tmp, strlen(file));
> +    if (strlen(p) == 0)
> +        return NULL;
> +    tmp[strlen(file) - strlen(p)] = '\0';
> +
> +    return tmp;
> +}

Eric probably knows better than I do but it seems like we can probably
pull in dirname() from gnulib for this rather than implementing our
own version.

> diff --git a/src/util/util.h b/src/util/util.h
> index 4316ab1..255b7b2 100644
> --- a/src/util/util.h
> +++ b/src/util/util.h
> @@ -114,6 +114,7 @@ enum {
>  };
>  int virDirCreate(const char *path, mode_t mode, uid_t uid, gid_t gid,
>                   unsigned int flags) ATTRIBUTE_RETURN_CHECK;
> +char *virDirOfFile(const char *file) ATTRIBUTE_RETURN_CHECK;
>  int virFileMakePath(const char *path) ATTRIBUTE_RETURN_CHECK;
>  int virFileMakePathWithMode(const char *path,
>                              mode_t mode) ATTRIBUTE_RETURN_CHECK;
> --
> 1.7.2.5
>
> --
> libvir-list mailing list
> libvir-list redhat com
> https://www.redhat.com/mailman/listinfo/libvir-list



-- 
Doug Goldstein


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]