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

li guang lig.fnst at cn.fujitsu.com
Fri Nov 16 03:07:38 UTC 2012


在 2012-11-15四的 14:09 -0600,Doug Goldstein写道:
big cut ...
> >
> > +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");
> 
> You're still using a qemu-img callout directly rather than using the
> existing block storage API. This whole function is really just an
> implementation of qemuDomainGetBlockInfo().

can you imagine how to use qemuDomainGetBlockInfo from here?
seems hard to grab "virDomainPtr dom" at present?
maybe I should change more to adopt this function for getting
a parameter "dom" or "conn".
or, any good idea?
Thanks!

> 
> 
> > +        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)) {
> > --
> > 1.7.1
> >
> > --
> > 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