在 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(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