[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