On 09/01/2014 11:05 AM, Jiri Denemark wrote: > When migrating a transient domain or with VIR_MIGRATE_UNDEFINE_SOURCE > flag, the domain may disappear from source host. And so will migration > statistics associated with the domain. We need to transfer the > statistics at the end of a migration so that they can be queried at the > destination host. > > Signed-off-by: Jiri Denemark <jdenemar@xxxxxxxxxx> > --- > src/qemu/qemu_migration.c | 190 +++++++++++++++++++++++++++++++++++++++++++++- > 1 file changed, 187 insertions(+), 3 deletions(-) > > diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c > index 208a21f..f1b3d50 100644 > --- a/src/qemu/qemu_migration.c > +++ b/src/qemu/qemu_migration.c > @@ -80,6 +80,7 @@ enum qemuMigrationCookieFlags { > QEMU_MIGRATION_COOKIE_FLAG_PERSISTENT, > QEMU_MIGRATION_COOKIE_FLAG_NETWORK, > QEMU_MIGRATION_COOKIE_FLAG_NBD, > + QEMU_MIGRATION_COOKIE_FLAG_STATS, > > QEMU_MIGRATION_COOKIE_FLAG_LAST > }; > @@ -91,7 +92,8 @@ VIR_ENUM_IMPL(qemuMigrationCookieFlag, > "lockstate", > "persistent", > "network", > - "nbd"); > + "nbd", > + "statistics"); > > enum qemuMigrationCookieFeatures { > QEMU_MIGRATION_COOKIE_GRAPHICS = (1 << QEMU_MIGRATION_COOKIE_FLAG_GRAPHICS), > @@ -99,6 +101,7 @@ enum qemuMigrationCookieFeatures { > QEMU_MIGRATION_COOKIE_PERSISTENT = (1 << QEMU_MIGRATION_COOKIE_FLAG_PERSISTENT), > QEMU_MIGRATION_COOKIE_NETWORK = (1 << QEMU_MIGRATION_COOKIE_FLAG_NETWORK), > QEMU_MIGRATION_COOKIE_NBD = (1 << QEMU_MIGRATION_COOKIE_FLAG_NBD), > + QEMU_MIGRATION_COOKIE_STATS = (1 << QEMU_MIGRATION_COOKIE_FLAG_STATS), > }; > > typedef struct _qemuMigrationCookieGraphics qemuMigrationCookieGraphics; > @@ -169,6 +172,9 @@ struct _qemuMigrationCookie { > > /* If (flags & QEMU_MIGRATION_COOKIE_NBD) */ > qemuMigrationCookieNBDPtr nbd; > + > + /* If (flags & QEMU_MIGRATION_COOKIE_STATS) */ > + qemuDomainJobInfoPtr jobInfo; > }; > > static void qemuMigrationCookieGraphicsFree(qemuMigrationCookieGraphicsPtr grap) > @@ -533,6 +539,25 @@ qemuMigrationCookieAddNBD(qemuMigrationCookiePtr mig, > } > > > +static int > +qemuMigrationCookieAddStatistics(qemuMigrationCookiePtr mig, > + virDomainObjPtr vm) > +{ > + qemuDomainObjPrivatePtr priv = vm->privateData; > + > + if (!priv->job.completed) > + return 0; > + > + if (!mig->jobInfo && VIR_ALLOC(mig->jobInfo) < 0) > + return -1; > + > + *mig->jobInfo = *priv->job.completed; > + mig->flags |= QEMU_MIGRATION_COOKIE_STATS; > + > + return 0; > +} > + > + > static void qemuMigrationCookieGraphicsXMLFormat(virBufferPtr buf, > qemuMigrationCookieGraphicsPtr grap) > { > @@ -589,6 +614,81 @@ qemuMigrationCookieNetworkXMLFormat(virBufferPtr buf, > } > > > +static void > +qemuMigrationCookieStatisticsXMLFormat(virBufferPtr buf, > + qemuDomainJobInfoPtr jobInfo) > +{ > + qemuMonitorMigrationStatus *status = &jobInfo->status; > + > + virBufferAddLit(buf, "<statistics>\n"); > + virBufferAdjustIndent(buf, 2); > + > + virBufferAsprintf(buf, "<%1$s>%2$llu</%1$s>\n", > + VIR_DOMAIN_JOB_TIME_ELAPSED, > + jobInfo->timeElapsed); > + virBufferAsprintf(buf, "<%1$s>%2$llu</%1$s>\n", > + VIR_DOMAIN_JOB_TIME_REMAINING, > + jobInfo->timeRemaining); qemuDomainJobInfoToParams will use jobInfo->type == VIR_DOMAIN_JOB_BOUNDED when printing the above - dies this need to as well? I would suspect this would be zero anyway, right? Since the job is done. > + if (status->downtime_set) > + virBufferAsprintf(buf, "<%1$s>%2$llu</%1$s>\n", > + VIR_DOMAIN_JOB_DOWNTIME, > + status->downtime); What about the VIR_DOMAIN_JOB_DATA_* values? I know they are calculable, but since they're > + > + virBufferAsprintf(buf, "<%1$s>%2$llu</%1$s>\n", > + VIR_DOMAIN_JOB_MEMORY_TOTAL, > + status->ram_total); > + virBufferAsprintf(buf, "<%1$s>%2$llu</%1$s>\n", > + VIR_DOMAIN_JOB_MEMORY_PROCESSED, > + status->ram_transferred); > + virBufferAsprintf(buf, "<%1$s>%2$llu</%1$s>\n", > + VIR_DOMAIN_JOB_MEMORY_REMAINING, > + status->ram_remaining); > + > + if (status->ram_duplicate_set) { > + virBufferAsprintf(buf, "<%1$s>%2$llu</%1$s>\n", > + VIR_DOMAIN_JOB_MEMORY_CONSTANT, > + status->ram_duplicate); > + virBufferAsprintf(buf, "<%1$s>%2$llu</%1$s>\n", > + VIR_DOMAIN_JOB_MEMORY_NORMAL, > + status->ram_normal); > + virBufferAsprintf(buf, "<%1$s>%2$llu</%1$s>\n", > + VIR_DOMAIN_JOB_MEMORY_NORMAL_BYTES, > + status->ram_normal_bytes); > + } > + > + virBufferAsprintf(buf, "<%1$s>%2$llu</%1$s>\n", > + VIR_DOMAIN_JOB_DISK_TOTAL, > + status->disk_total); > + virBufferAsprintf(buf, "<%1$s>%2$llu</%1$s>\n", > + VIR_DOMAIN_JOB_DISK_PROCESSED, > + status->disk_transferred); > + virBufferAsprintf(buf, "<%1$s>%2$llu</%1$s>\n", > + VIR_DOMAIN_JOB_DISK_REMAINING, > + status->disk_remaining); > + > + if (status->xbzrle_set) { > + virBufferAsprintf(buf, "<%1$s>%2$llu</%1$s>\n", > + VIR_DOMAIN_JOB_COMPRESSION_CACHE, > + status->xbzrle_cache_size); > + virBufferAsprintf(buf, "<%1$s>%2$llu</%1$s>\n", > + VIR_DOMAIN_JOB_COMPRESSION_BYTES, > + status->xbzrle_bytes); > + virBufferAsprintf(buf, "<%1$s>%2$llu</%1$s>\n", > + VIR_DOMAIN_JOB_COMPRESSION_PAGES, > + status->xbzrle_pages); > + virBufferAsprintf(buf, "<%1$s>%2$llu</%1$s>\n", > + VIR_DOMAIN_JOB_COMPRESSION_CACHE_MISSES, > + status->xbzrle_cache_miss); > + virBufferAsprintf(buf, "<%1$s>%2$llu</%1$s>\n", > + VIR_DOMAIN_JOB_COMPRESSION_OVERFLOW, > + status->xbzrle_overflow); > + } > + > + virBufferAdjustIndent(buf, -2); > + virBufferAddLit(buf, "</statistics>\n"); > +} > + > + > static int > qemuMigrationCookieXMLFormat(virQEMUDriverPtr driver, > virBufferPtr buf, > @@ -650,6 +750,9 @@ qemuMigrationCookieXMLFormat(virQEMUDriverPtr driver, > virBufferAddLit(buf, "/>\n"); > } > > + if (mig->flags & QEMU_MIGRATION_COOKIE_STATS && mig->jobInfo) > + qemuMigrationCookieStatisticsXMLFormat(buf, mig->jobInfo); > + > virBufferAdjustIndent(buf, -2); > virBufferAddLit(buf, "</qemu-migration>\n"); > return 0; > @@ -772,6 +875,70 @@ qemuMigrationCookieNetworkXMLParse(xmlXPathContextPtr ctxt) > } > > > +static qemuDomainJobInfoPtr > +qemuMigrationCookieStatisticsXMLParse(xmlXPathContextPtr ctxt) > +{ > + qemuDomainJobInfoPtr jobInfo = NULL; > + qemuMonitorMigrationStatus *status; > + xmlNodePtr save_ctxt = ctxt->node; > + > + if (!(ctxt->node = virXPathNode("./statistics", ctxt))) > + goto cleanup; > + > + if (VIR_ALLOC(jobInfo) < 0) > + goto cleanup; > + > + status = &jobInfo->status; > + jobInfo->type = VIR_DOMAIN_JOB_COMPLETED; > + > + virXPathULongLong("string(./" VIR_DOMAIN_JOB_TIME_ELAPSED "[1])", > + ctxt, &jobInfo->timeElapsed); > + virXPathULongLong("string(./" VIR_DOMAIN_JOB_TIME_REMAINING "[1])", > + ctxt, &jobInfo->timeRemaining); > + if (virXPathULongLong("string(./" VIR_DOMAIN_JOB_DOWNTIME "[1])", > + ctxt, &status->downtime) == 0) > + status->downtime_set = true; > + > + virXPathULongLong("string(./" VIR_DOMAIN_JOB_MEMORY_TOTAL "[1])", > + ctxt, &status->ram_total); > + virXPathULongLong("string(./" VIR_DOMAIN_JOB_MEMORY_PROCESSED "[1])", > + ctxt, &status->ram_transferred); > + virXPathULongLong("string(./" VIR_DOMAIN_JOB_MEMORY_REMAINING "[1])", > + ctxt, &status->ram_remaining); > + > + if (virXPathULongLong("string(./" VIR_DOMAIN_JOB_MEMORY_CONSTANT "[1])", > + ctxt, &status->ram_duplicate) == 0) > + status->ram_duplicate_set = true; > + virXPathULongLong("string(./" VIR_DOMAIN_JOB_MEMORY_NORMAL "[1])", > + ctxt, &status->ram_normal); > + virXPathULongLong("string(./" VIR_DOMAIN_JOB_MEMORY_NORMAL_BYTES "[1])", > + ctxt, &status->ram_normal_bytes); > + > + virXPathULongLong("string(./" VIR_DOMAIN_JOB_DISK_TOTAL "[1])", > + ctxt, &status->disk_total); > + virXPathULongLong("string(./" VIR_DOMAIN_JOB_DISK_PROCESSED "[1])", > + ctxt, &status->disk_transferred); > + virXPathULongLong("string(./" VIR_DOMAIN_JOB_DISK_REMAINING "[1])", > + ctxt, &status->disk_remaining); > + > + if (virXPathULongLong("string(./" VIR_DOMAIN_JOB_COMPRESSION_CACHE "[1])", > + ctxt, &status->xbzrle_cache_size) == 0) > + status->xbzrle_set = true; > + virXPathULongLong("string(./" VIR_DOMAIN_JOB_COMPRESSION_BYTES "[1])", > + ctxt, &status->xbzrle_bytes); > + virXPathULongLong("string(./" VIR_DOMAIN_JOB_COMPRESSION_PAGES "[1])", > + ctxt, &status->xbzrle_pages); > + virXPathULongLong("string(./" VIR_DOMAIN_JOB_COMPRESSION_CACHE_MISSES "[1])", > + ctxt, &status->xbzrle_cache_miss); > + virXPathULongLong("string(./" VIR_DOMAIN_JOB_COMPRESSION_OVERFLOW "[1])", > + ctxt, &status->xbzrle_overflow); > + > + cleanup: > + ctxt->node = save_ctxt; > + return jobInfo; > +} > + > + > static int > qemuMigrationCookieXMLParse(qemuMigrationCookiePtr mig, > virQEMUDriverPtr driver, > @@ -947,6 +1114,11 @@ qemuMigrationCookieXMLParse(qemuMigrationCookiePtr mig, > VIR_FREE(port); > } > > + if (flags & QEMU_MIGRATION_COOKIE_STATS && > + virXPathBoolean("boolean(./statistics)", ctxt) && > + (!(mig->jobInfo = qemuMigrationCookieStatisticsXMLParse(ctxt)))) > + goto error; > + > virObjectUnref(caps); > return 0; > > @@ -1017,6 +1189,10 @@ qemuMigrationBakeCookie(qemuMigrationCookiePtr mig, > qemuMigrationCookieAddNBD(mig, driver, dom) < 0) > return -1; > > + if (flags & QEMU_MIGRATION_COOKIE_STATS && > + qemuMigrationCookieAddStatistics(mig, dom) < 0) > + return -1; > + In the not that it matters department, but some flags checks have "(flags & FLAG)" while others go with just "flags & FLAG" - doesn't matter to me, but it's not consistent. > if (!(*cookieout = qemuMigrationCookieXMLFormatStr(driver, mig))) > return -1; > > @@ -3424,7 +3600,8 @@ qemuMigrationRun(virQEMUDriverPtr driver, > if (priv->job.completed) > qemuDomainJobInfoUpdateTime(priv->job.completed); > > - cookieFlags |= QEMU_MIGRATION_COOKIE_NETWORK; > + cookieFlags |= QEMU_MIGRATION_COOKIE_NETWORK | > + QEMU_MIGRATION_COOKIE_STATS; > if (flags & VIR_MIGRATE_PERSIST_DEST) > cookieFlags |= QEMU_MIGRATION_COOKIE_PERSISTENT; > if (ret == 0 && > @@ -4508,8 +4685,10 @@ qemuMigrationFinish(virQEMUDriverPtr driver, > : QEMU_MIGRATION_PHASE_FINISH2); > > qemuDomainCleanupRemove(vm, qemuMigrationPrepareCleanup); > + VIR_FREE(priv->job.completed); This seems out of place - is it because of the impending copy mig->jobInfo copy? What if that data wasn't there? We just wipe out whatever was possibly there. ACK - seems OK to me. Just curious about the above. John > > - cookie_flags = QEMU_MIGRATION_COOKIE_NETWORK; > + cookie_flags = QEMU_MIGRATION_COOKIE_NETWORK | > + QEMU_MIGRATION_COOKIE_STATS; > if (flags & VIR_MIGRATE_PERSIST_DEST) > cookie_flags |= QEMU_MIGRATION_COOKIE_PERSISTENT; > > @@ -4527,6 +4706,11 @@ qemuMigrationFinish(virQEMUDriverPtr driver, > goto endjob; > } > > + if (mig->jobInfo) { > + priv->job.completed = mig->jobInfo; > + mig->jobInfo = NULL; > + } > + > if (!(flags & VIR_MIGRATE_OFFLINE)) { > if (qemuMigrationVPAssociatePortProfiles(vm->def) < 0) { > qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_FAILED, > -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list