在 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@xxxxxxxxxx > > https://www.redhat.com/mailman/listinfo/libvir-list > > > -- li guang lig.fnst@xxxxxxxxxxxxxx linux kernel team at FNST, china -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list