As a side effect, this also fixes reporting disk migration process.
It was added to memory migration progress, which was wrong. Disk
progress has dedicated fields in virDomainJobInfo structure.
---
src/qemu/qemu_domain.c | 1 +
src/qemu/qemu_domain.h | 3 +-
src/qemu/qemu_migration.c | 44 +++++++------
src/qemu/qemu_monitor.c | 15 +----
src/qemu/qemu_monitor.h | 34 ++++++++--
src/qemu/qemu_monitor_json.c | 150 ++++++++++++++++++++++++++++++-------------
src/qemu/qemu_monitor_json.h | 5 +-
src/qemu/qemu_monitor_text.c | 47 +++++++-------
src/qemu/qemu_monitor_text.h | 5 +-
9 files changed, 192 insertions(+), 112 deletions(-)
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 482f64a..eca85fc 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -160,6 +160,7 @@ qemuDomainObjResetAsyncJob(qemuDomainObjPrivatePtr priv)
job->start = 0;
job->dump_memory_only = false;
job->asyncAbort = false;
+ memset(&job->status, 0, sizeof(job->status));
memset(&job->info, 0, sizeof(job->info));
}
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
index c9d5f8b..e4fb2f6 100644
--- a/src/qemu/qemu_domain.h
+++ b/src/qemu/qemu_domain.h
@@ -110,7 +110,8 @@ struct qemuDomainJobObj {
unsigned long long mask; /* Jobs allowed during async job */
unsigned long long start; /* When the async job started */
bool dump_memory_only; /* use dump-guest-memory to do dump */
- virDomainJobInfo info; /* Async job progress data */
+ qemuMonitorMigrationStatus status; /* Raw async job progress data */
+ virDomainJobInfo info; /* Processed async job progress data */
bool asyncAbort; /* abort of async job requested */
};
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index de8dfec..4142872 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -1198,12 +1198,11 @@ qemuMigrationUpdateJobStatus(virQEMUDriverPtr driver,
{
qemuDomainObjPrivatePtr priv = vm->privateData;
int ret;
- int status;
bool wait_for_spice = false;
bool spice_migrated = false;
- unsigned long long memProcessed;
- unsigned long long memRemaining;
- unsigned long long memTotal;
+ qemuMonitorMigrationStatus status;
+
+ memset(&status, 0, sizeof(status));
/* If guest uses SPICE and supports seamles_migration we have to hold up
* migration finish until SPICE server transfers its data */
@@ -1217,20 +1216,19 @@ qemuMigrationUpdateJobStatus(virQEMUDriverPtr driver,
/* Guest already exited; nothing further to update. */
return -1;
}
- ret = qemuMonitorGetMigrationStatus(priv->mon,
- &status,
- &memProcessed,
- &memRemaining,
- &memTotal);
+ ret = qemuMonitorGetMigrationStatus(priv->mon, &status);
/* If qemu says migrated, check spice */
- if (wait_for_spice && (ret == 0) &&
- (status == QEMU_MONITOR_MIGRATION_STATUS_COMPLETED))
+ if (wait_for_spice &&
+ ret == 0 &&
+ status.status == QEMU_MONITOR_MIGRATION_STATUS_COMPLETED)
ret = qemuMonitorGetSpiceMigrationStatus(priv->mon,
&spice_migrated);
qemuDomainObjExitMonitor(driver, vm);
+ priv->job.status = status;
+
if (ret < 0 || virTimeMillisNow(&priv->job.info.timeElapsed) < 0) {
priv->job.info.type = VIR_DOMAIN_JOB_FAILED;
return -1;
@@ -1238,7 +1236,7 @@ qemuMigrationUpdateJobStatus(virQEMUDriverPtr driver,
priv->job.info.timeElapsed -= priv->job.start;
ret = -1;
- switch (status) {
+ switch (priv->job.status.status) {
case QEMU_MONITOR_MIGRATION_STATUS_INACTIVE:
priv->job.info.type = VIR_DOMAIN_JOB_NONE;
virReportError(VIR_ERR_OPERATION_FAILED,
@@ -1246,13 +1244,21 @@ qemuMigrationUpdateJobStatus(virQEMUDriverPtr driver,
break;
case QEMU_MONITOR_MIGRATION_STATUS_ACTIVE:
- priv->job.info.dataTotal = memTotal;
- priv->job.info.dataRemaining = memRemaining;
- priv->job.info.dataProcessed = memProcessed;
-
- priv->job.info.memTotal = memTotal;
- priv->job.info.memRemaining = memRemaining;
- priv->job.info.memProcessed = memProcessed;
+ priv->job.info.fileTotal = priv->job.status.disk_total;
+ priv->job.info.fileRemaining = priv->job.status.disk_remaining;
+ priv->job.info.fileProcessed = priv->job.status.disk_transferred;
+
+ priv->job.info.memTotal = priv->job.status.ram_total;
+ priv->job.info.memRemaining = priv->job.status.ram_remaining;
+ priv->job.info.memProcessed = priv->job.status.ram_transferred;
+
+ priv->job.info.dataTotal =
+ priv->job.status.ram_total + priv->job.status.disk_total;
+ priv->job.info.dataRemaining =
+ priv->job.status.ram_remaining + priv->job.status.disk_remaining;
+ priv->job.info.dataProcessed =
+ priv->job.status.ram_transferred +
+ priv->job.status.disk_transferred;
ret = 0;
break;
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index 631ff92..21489fb 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -1805,10 +1805,7 @@ int qemuMonitorSetMigrationDowntime(qemuMonitorPtr mon,
int qemuMonitorGetMigrationStatus(qemuMonitorPtr mon,
- int *status,
- unsigned long long *transferred,
- unsigned long long *remaining,
- unsigned long long *total)
+ qemuMonitorMigrationStatusPtr status)
{
int ret;
VIR_DEBUG("mon=%p", mon);
@@ -1820,15 +1817,9 @@ int qemuMonitorGetMigrationStatus(qemuMonitorPtr mon,
}
if (mon->json)
- ret = qemuMonitorJSONGetMigrationStatus(mon, status,
- transferred,
- remaining,
- total);
+ ret = qemuMonitorJSONGetMigrationStatus(mon, status);
else
- ret = qemuMonitorTextGetMigrationStatus(mon, status,
- transferred,
- remaining,
- total);
+ ret = qemuMonitorTextGetMigrationStatus(mon, status);
return ret;
}
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index e3a4568..40e635d 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -338,11 +338,37 @@ enum {
VIR_ENUM_DECL(qemuMonitorMigrationStatus)
+typedef struct _qemuMonitorMigrationStatus qemuMonitorMigrationStatus;
+typedef qemuMonitorMigrationStatus *qemuMonitorMigrationStatusPtr;
+struct _qemuMonitorMigrationStatus {
+ int status;
+ unsigned long long total_time;
+ /* total or expected depending on status */
+ bool downtime_set;
+ unsigned long long downtime;
+
+ unsigned long long ram_transferred;
+ unsigned long long ram_remaining;
+ unsigned long long ram_total;
+ bool ram_duplicate_set;
+ unsigned long long ram_duplicate;
+ unsigned long long ram_normal;
+ unsigned long long ram_normal_bytes;
+
+ unsigned long long disk_transferred;
+ unsigned long long disk_remaining;
+ unsigned long long disk_total;
+
+ bool xbzrle_set;
+ unsigned long long xbzrle_cache_size;
+ unsigned long long xbzrle_bytes;
+ unsigned long long xbzrle_pages;
+ unsigned long long xbzrle_cache_miss;
+ unsigned long long xbzrle_overflow;
+};
+
int qemuMonitorGetMigrationStatus(qemuMonitorPtr mon,
- int *status,
- unsigned long long *transferred,
- unsigned long long *remaining,
- unsigned long long *total);
+ qemuMonitorMigrationStatusPtr status);
int qemuMonitorGetSpiceMigrationStatus(qemuMonitorPtr mon,
bool *spice_migrated);
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index 545d4d4..e8c1f81 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -2258,14 +2258,11 @@ int qemuMonitorJSONSetMigrationDowntime(qemuMonitorPtr mon,
static int
qemuMonitorJSONGetMigrationStatusReply(virJSONValuePtr reply,
- int *status,
- unsigned long long *transferred,
- unsigned long long *remaining,
- unsigned long long *total)
+ qemuMonitorMigrationStatusPtr status)
{
virJSONValuePtr ret;
const char *statusstr;
- unsigned long long t;
+ int rc;
if (!(ret = virJSONValueObjectGet(reply, "return"))) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
@@ -2279,13 +2276,25 @@ qemuMonitorJSONGetMigrationStatusReply(virJSONValuePtr reply,
return -1;
}
- if ((*status = qemuMonitorMigrationStatusTypeFromString(statusstr)) < 0) {
+ status->status = qemuMonitorMigrationStatusTypeFromString(statusstr);
+ if (status->status < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("unexpected migration status in %s"), statusstr);
return -1;
}
- if (*status == QEMU_MONITOR_MIGRATION_STATUS_ACTIVE) {
+ virJSONValueObjectGetNumberUlong(ret, "total-time",
&status->total_time);
+ if (status->status == QEMU_MONITOR_MIGRATION_STATUS_COMPLETED) {
+ rc = virJSONValueObjectGetNumberUlong(ret, "downtime",
+ &status->downtime);
+ } else {
+ rc = virJSONValueObjectGetNumberUlong(ret, "expected-downtime",
+ &status->downtime);
+ }
+ if (rc == 0)
+ status->downtime_set = true;
+
+ if (status->status == QEMU_MONITOR_MIGRATION_STATUS_ACTIVE) {
virJSONValuePtr ram = virJSONValueObjectGet(ret, "ram");
if (!ram) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
@@ -2294,51 +2303,112 @@ qemuMonitorJSONGetMigrationStatusReply(virJSONValuePtr reply,
}
if (virJSONValueObjectGetNumberUlong(ram, "transferred",
- transferred) < 0) {
+ &status->ram_transferred) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("migration was active, but RAM 'transferred'
"
"data was missing"));
return -1;
}
- if (virJSONValueObjectGetNumberUlong(ram, "remaining", remaining) <
0) {
+ if (virJSONValueObjectGetNumberUlong(ram, "remaining",
+ &status->ram_remaining) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("migration was active, but RAM 'remaining'
"
"data was missing"));
return -1;
}
- if (virJSONValueObjectGetNumberUlong(ram, "total", total) < 0) {
+ if (virJSONValueObjectGetNumberUlong(ram, "total",
+ &status->ram_total) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("migration was active, but RAM 'total' "
"data was missing"));
return -1;
}
+ if (virJSONValueObjectGetNumberUlong(ram, "duplicate",
+ &status->ram_duplicate) == 0)
+ status->ram_duplicate_set = true;
+ virJSONValueObjectGetNumberUlong(ram, "normal",
&status->ram_normal);
+ virJSONValueObjectGetNumberUlong(ram, "normal-bytes",
+ &status->ram_normal_bytes);
+
virJSONValuePtr disk = virJSONValueObjectGet(ret, "disk");
- if (!disk) {
- return 0;
- }
+ if (disk) {
+ rc = virJSONValueObjectGetNumberUlong(disk, "transferred",
+ &status->disk_transferred);
+ if (rc < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("disk migration was active, but "
+ "'transferred' data was missing"));
+ return -1;
+ }
- if (virJSONValueObjectGetNumberUlong(disk, "transferred", &t) <
0) {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("disk migration was active, but 'transferred'
"
- "data was missing"));
- return -1;
- }
- *transferred += t;
- if (virJSONValueObjectGetNumberUlong(disk, "remaining", &t) < 0)
{
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("disk migration was active, but 'remaining'
"
- "data was missing"));
- return -1;
+ rc = virJSONValueObjectGetNumberUlong(disk, "remaining",
+ &status->disk_remaining);
+ if (rc < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("disk migration was active, but 'remaining'
"
+ "data was missing"));
+ return -1;
+ }
+
+ rc = virJSONValueObjectGetNumberUlong(disk, "total",
+ &status->disk_total);
+ if (rc < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("disk migration was active, but 'total'
"
+ "data was missing"));
+ return -1;
+ }
}
- *remaining += t;
- if (virJSONValueObjectGetNumberUlong(disk, "total", &t) < 0) {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("disk migration was active, but 'total' "
- "data was missing"));
- return -1;
+
+ virJSONValuePtr comp = virJSONValueObjectGet(ret, "xbzrle-cache");
+ if (comp) {
+ status->xbzrle_set = true;
+ rc = virJSONValueObjectGetNumberUlong(comp, "cache-size",
+ &status->xbzrle_cache_size);
+ if (rc < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("XBZRLE is active, but 'cache-size' data
"
+ "was missing"));
+ return -1;
+ }
+
+ rc = virJSONValueObjectGetNumberUlong(comp, "bytes",
+ &status->xbzrle_bytes);
+ if (rc < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("XBZRLE is active, but 'bytes' data "
+ "was missing"));
+ return -1;
+ }
+
+ rc = virJSONValueObjectGetNumberUlong(comp, "pages",
+ &status->xbzrle_pages);
+ if (rc < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("XBZRLE is active, but 'pages' data "
+ "was missing"));
+ return -1;
+ }
+
+ rc = virJSONValueObjectGetNumberUlong(comp, "cache-miss",
+ &status->xbzrle_cache_miss);
+ if (rc < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("XBZRLE is active, but 'cache-miss' data
"
+ "was missing"));
+ return -1;
+ }
+
+ rc = virJSONValueObjectGetNumberUlong(comp, "overflow",
+ &status->xbzrle_overflow);
+ if (rc < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("XBZRLE is active, but 'overflow' data
"
+ "was missing"));
+ return -1;
+ }
}
- *total += t;
}
return 0;
@@ -2346,18 +2416,14 @@ qemuMonitorJSONGetMigrationStatusReply(virJSONValuePtr reply,
int qemuMonitorJSONGetMigrationStatus(qemuMonitorPtr mon,
- int *status,
- unsigned long long *transferred,
- unsigned long long *remaining,
- unsigned long long *total)
+ qemuMonitorMigrationStatusPtr status)
{
int ret;
virJSONValuePtr cmd = qemuMonitorJSONMakeCommand("query-migrate",
NULL);
virJSONValuePtr reply = NULL;
- *status = 0;
- *transferred = *remaining = *total = 0;
+ memset(status, 0, sizeof(*status));
if (!cmd)
return -1;
@@ -2368,13 +2434,11 @@ int qemuMonitorJSONGetMigrationStatus(qemuMonitorPtr mon,
ret = qemuMonitorJSONCheckError(cmd, reply);
if (ret == 0 &&
- qemuMonitorJSONGetMigrationStatusReply(reply,
- status,
- transferred,
- remaining,
- total) < 0)
+ qemuMonitorJSONGetMigrationStatusReply(reply, status) < 0)
ret = -1;
+ if (ret < 0)
+ memset(status, 0, sizeof(*status));
virJSONValueFree(cmd);
virJSONValueFree(reply);
return ret;
diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h
index 356c10a..66635fd 100644
--- a/src/qemu/qemu_monitor_json.h
+++ b/src/qemu/qemu_monitor_json.h
@@ -121,10 +121,7 @@ int qemuMonitorJSONSetMigrationDowntime(qemuMonitorPtr mon,
unsigned long long downtime);
int qemuMonitorJSONGetMigrationStatus(qemuMonitorPtr mon,
- int *status,
- unsigned long long *transferred,
- unsigned long long *remaining,
- unsigned long long *total);
+ qemuMonitorMigrationStatusPtr status);
int qemuMonitorJSONGetMigrationCapability(qemuMonitorPtr mon,
qemuMonitorMigrationCaps capability);
diff --git a/src/qemu/qemu_monitor_text.c b/src/qemu/qemu_monitor_text.c
index bc0a11d..58f6323 100644
--- a/src/qemu/qemu_monitor_text.c
+++ b/src/qemu/qemu_monitor_text.c
@@ -1474,22 +1474,14 @@ cleanup:
#define MIGRATION_DISK_TOTAL_PREFIX "total disk: "
int qemuMonitorTextGetMigrationStatus(qemuMonitorPtr mon,
- int *status,
- unsigned long long *transferred,
- unsigned long long *remaining,
- unsigned long long *total) {
+ qemuMonitorMigrationStatusPtr status)
+{
char *reply;
char *tmp;
char *end;
- unsigned long long disk_transferred = 0;
- unsigned long long disk_remaining = 0;
- unsigned long long disk_total = 0;
int ret = -1;
- *status = QEMU_MONITOR_MIGRATION_STATUS_INACTIVE;
- *transferred = 0;
- *remaining = 0;
- *total = 0;
+ memset(status, 0, sizeof(*status));
if (qemuMonitorHMPCommand(mon, "info migrate", &reply) < 0)
return -1;
@@ -1504,52 +1496,54 @@ int qemuMonitorTextGetMigrationStatus(qemuMonitorPtr mon,
}
*end = '\0';
- if ((*status = qemuMonitorMigrationStatusTypeFromString(tmp)) < 0) {
+ status->status = qemuMonitorMigrationStatusTypeFromString(tmp);
+ if (status->status < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("unexpected migration status in %s"), reply);
goto cleanup;
}
- if (*status == QEMU_MONITOR_MIGRATION_STATUS_ACTIVE) {
+ if (status->status == QEMU_MONITOR_MIGRATION_STATUS_ACTIVE) {
tmp = end + 1;
if (!(tmp = strstr(tmp, MIGRATION_TRANSFER_PREFIX)))
goto done;
tmp += strlen(MIGRATION_TRANSFER_PREFIX);
- if (virStrToLong_ull(tmp, &end, 10, transferred) < 0) {
+ if (virStrToLong_ull(tmp, &end, 10,
+ &status->ram_transferred) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("cannot parse migration data transferred "
"statistic %s"), tmp);
goto cleanup;
}
- *transferred *= 1024;
+ status->ram_transferred *= 1024;
tmp = end;
if (!(tmp = strstr(tmp, MIGRATION_REMAINING_PREFIX)))
goto done;
tmp += strlen(MIGRATION_REMAINING_PREFIX);
- if (virStrToLong_ull(tmp, &end, 10, remaining) < 0) {
+ if (virStrToLong_ull(tmp, &end, 10, &status->ram_remaining) <
0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("cannot parse migration data remaining "
"statistic %s"), tmp);
goto cleanup;
}
- *remaining *= 1024;
+ status->ram_remaining *= 1024;
tmp = end;
if (!(tmp = strstr(tmp, MIGRATION_TOTAL_PREFIX)))
goto done;
tmp += strlen(MIGRATION_TOTAL_PREFIX);
- if (virStrToLong_ull(tmp, &end, 10, total) < 0) {
+ if (virStrToLong_ull(tmp, &end, 10, &status->ram_total) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("cannot parse migration data total "
"statistic %s"), tmp);
goto cleanup;
}
- *total *= 1024;
+ status->ram_total *= 1024;
tmp = end;
/*
@@ -1559,39 +1553,40 @@ int qemuMonitorTextGetMigrationStatus(qemuMonitorPtr mon,
goto done;
tmp += strlen(MIGRATION_DISK_TRANSFER_PREFIX);
- if (virStrToLong_ull(tmp, &end, 10, &disk_transferred) < 0) {
+ if (virStrToLong_ull(tmp, &end, 10,
+ &status->disk_transferred) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("cannot parse disk migration data "
"transferred statistic %s"), tmp);
goto cleanup;
}
- *transferred += disk_transferred * 1024;
+ status->disk_transferred *= 1024;
tmp = end;
if (!(tmp = strstr(tmp, MIGRATION_DISK_REMAINING_PREFIX)))
goto done;
tmp += strlen(MIGRATION_DISK_REMAINING_PREFIX);
- if (virStrToLong_ull(tmp, &end, 10, &disk_remaining) < 0) {
+ if (virStrToLong_ull(tmp, &end, 10, &status->disk_remaining) <
0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("cannot parse disk migration data remaining "
"statistic %s"), tmp);
goto cleanup;
}
- *remaining += disk_remaining * 1024;
+ status->disk_remaining *= 1024;
tmp = end;
if (!(tmp = strstr(tmp, MIGRATION_DISK_TOTAL_PREFIX)))
goto done;
tmp += strlen(MIGRATION_DISK_TOTAL_PREFIX);
- if (virStrToLong_ull(tmp, &end, 10, &disk_total) < 0) {
+ if (virStrToLong_ull(tmp, &end, 10, &status->disk_total) < 0)
{
virReportError(VIR_ERR_INTERNAL_ERROR,
_("cannot parse disk migration data total "
"statistic %s"), tmp);
goto cleanup;
}
- *total += disk_total * 1024;
+ status->disk_total *= 1024;
}
}
@@ -1600,6 +1595,8 @@ done:
cleanup:
VIR_FREE(reply);
+ if (ret < 0)
+ memset(status, 0, sizeof(*status));
return ret;
}
diff --git a/src/qemu/qemu_monitor_text.h b/src/qemu/qemu_monitor_text.h
index 97abad6..fb8e904 100644
--- a/src/qemu/qemu_monitor_text.h
+++ b/src/qemu/qemu_monitor_text.h
@@ -117,10 +117,7 @@ int qemuMonitorTextSetMigrationDowntime(qemuMonitorPtr mon,
unsigned long long downtime);
int qemuMonitorTextGetMigrationStatus(qemuMonitorPtr mon,
- int *status,
- unsigned long long *transferred,
- unsigned long long *remaining,
- unsigned long long *total);
+ qemuMonitorMigrationStatusPtr status);
int qemuMonitorTextMigrate(qemuMonitorPtr mon,
unsigned int flags,
--
1.8.1.2