1
0
mirror of https://gitlab.com/libvirt/libvirt.git synced 2025-03-07 17:28:15 +00:00

qemu: Parse more fields from query-migrate QMP command

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.
This commit is contained in:
Jiri Denemark 2013-02-08 09:58:03 +01:00
parent 38ab12251e
commit 4121a77c1a
9 changed files with 191 additions and 111 deletions

View File

@ -160,6 +160,7 @@ qemuDomainObjResetAsyncJob(qemuDomainObjPrivatePtr priv)
job->start = 0; job->start = 0;
job->dump_memory_only = false; job->dump_memory_only = false;
job->asyncAbort = false; job->asyncAbort = false;
memset(&job->status, 0, sizeof(job->status));
memset(&job->info, 0, sizeof(job->info)); memset(&job->info, 0, sizeof(job->info));
} }

View File

@ -110,7 +110,8 @@ struct qemuDomainJobObj {
unsigned long long mask; /* Jobs allowed during async job */ unsigned long long mask; /* Jobs allowed during async job */
unsigned long long start; /* When the async job started */ unsigned long long start; /* When the async job started */
bool dump_memory_only; /* use dump-guest-memory to do dump */ 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 */ bool asyncAbort; /* abort of async job requested */
}; };

View File

@ -1198,12 +1198,11 @@ qemuMigrationUpdateJobStatus(virQEMUDriverPtr driver,
{ {
qemuDomainObjPrivatePtr priv = vm->privateData; qemuDomainObjPrivatePtr priv = vm->privateData;
int ret; int ret;
int status;
bool wait_for_spice = false; bool wait_for_spice = false;
bool spice_migrated = false; bool spice_migrated = false;
unsigned long long memProcessed; qemuMonitorMigrationStatus status;
unsigned long long memRemaining;
unsigned long long memTotal; memset(&status, 0, sizeof(status));
/* If guest uses SPICE and supports seamles_migration we have to hold up /* If guest uses SPICE and supports seamles_migration we have to hold up
* migration finish until SPICE server transfers its data */ * migration finish until SPICE server transfers its data */
@ -1217,20 +1216,19 @@ qemuMigrationUpdateJobStatus(virQEMUDriverPtr driver,
/* Guest already exited; nothing further to update. */ /* Guest already exited; nothing further to update. */
return -1; return -1;
} }
ret = qemuMonitorGetMigrationStatus(priv->mon, ret = qemuMonitorGetMigrationStatus(priv->mon, &status);
&status,
&memProcessed,
&memRemaining,
&memTotal);
/* If qemu says migrated, check spice */ /* If qemu says migrated, check spice */
if (wait_for_spice && (ret == 0) && if (wait_for_spice &&
(status == QEMU_MONITOR_MIGRATION_STATUS_COMPLETED)) ret == 0 &&
status.status == QEMU_MONITOR_MIGRATION_STATUS_COMPLETED)
ret = qemuMonitorGetSpiceMigrationStatus(priv->mon, ret = qemuMonitorGetSpiceMigrationStatus(priv->mon,
&spice_migrated); &spice_migrated);
qemuDomainObjExitMonitor(driver, vm); qemuDomainObjExitMonitor(driver, vm);
priv->job.status = status;
if (ret < 0 || virTimeMillisNow(&priv->job.info.timeElapsed) < 0) { if (ret < 0 || virTimeMillisNow(&priv->job.info.timeElapsed) < 0) {
priv->job.info.type = VIR_DOMAIN_JOB_FAILED; priv->job.info.type = VIR_DOMAIN_JOB_FAILED;
return -1; return -1;
@ -1238,7 +1236,7 @@ qemuMigrationUpdateJobStatus(virQEMUDriverPtr driver,
priv->job.info.timeElapsed -= priv->job.start; priv->job.info.timeElapsed -= priv->job.start;
ret = -1; ret = -1;
switch (status) { switch (priv->job.status.status) {
case QEMU_MONITOR_MIGRATION_STATUS_INACTIVE: case QEMU_MONITOR_MIGRATION_STATUS_INACTIVE:
priv->job.info.type = VIR_DOMAIN_JOB_NONE; priv->job.info.type = VIR_DOMAIN_JOB_NONE;
virReportError(VIR_ERR_OPERATION_FAILED, virReportError(VIR_ERR_OPERATION_FAILED,
@ -1246,13 +1244,21 @@ qemuMigrationUpdateJobStatus(virQEMUDriverPtr driver,
break; break;
case QEMU_MONITOR_MIGRATION_STATUS_ACTIVE: case QEMU_MONITOR_MIGRATION_STATUS_ACTIVE:
priv->job.info.dataTotal = memTotal; priv->job.info.fileTotal = priv->job.status.disk_total;
priv->job.info.dataRemaining = memRemaining; priv->job.info.fileRemaining = priv->job.status.disk_remaining;
priv->job.info.dataProcessed = memProcessed; priv->job.info.fileProcessed = priv->job.status.disk_transferred;
priv->job.info.memTotal = memTotal; priv->job.info.memTotal = priv->job.status.ram_total;
priv->job.info.memRemaining = memRemaining; priv->job.info.memRemaining = priv->job.status.ram_remaining;
priv->job.info.memProcessed = memProcessed; 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; ret = 0;
break; break;

View File

@ -1805,10 +1805,7 @@ int qemuMonitorSetMigrationDowntime(qemuMonitorPtr mon,
int qemuMonitorGetMigrationStatus(qemuMonitorPtr mon, int qemuMonitorGetMigrationStatus(qemuMonitorPtr mon,
int *status, qemuMonitorMigrationStatusPtr status)
unsigned long long *transferred,
unsigned long long *remaining,
unsigned long long *total)
{ {
int ret; int ret;
VIR_DEBUG("mon=%p", mon); VIR_DEBUG("mon=%p", mon);
@ -1820,15 +1817,9 @@ int qemuMonitorGetMigrationStatus(qemuMonitorPtr mon,
} }
if (mon->json) if (mon->json)
ret = qemuMonitorJSONGetMigrationStatus(mon, status, ret = qemuMonitorJSONGetMigrationStatus(mon, status);
transferred,
remaining,
total);
else else
ret = qemuMonitorTextGetMigrationStatus(mon, status, ret = qemuMonitorTextGetMigrationStatus(mon, status);
transferred,
remaining,
total);
return ret; return ret;
} }

View File

@ -338,11 +338,37 @@ enum {
VIR_ENUM_DECL(qemuMonitorMigrationStatus) 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 qemuMonitorGetMigrationStatus(qemuMonitorPtr mon,
int *status, qemuMonitorMigrationStatusPtr status);
unsigned long long *transferred,
unsigned long long *remaining,
unsigned long long *total);
int qemuMonitorGetSpiceMigrationStatus(qemuMonitorPtr mon, int qemuMonitorGetSpiceMigrationStatus(qemuMonitorPtr mon,
bool *spice_migrated); bool *spice_migrated);

View File

@ -2258,14 +2258,11 @@ int qemuMonitorJSONSetMigrationDowntime(qemuMonitorPtr mon,
static int static int
qemuMonitorJSONGetMigrationStatusReply(virJSONValuePtr reply, qemuMonitorJSONGetMigrationStatusReply(virJSONValuePtr reply,
int *status, qemuMonitorMigrationStatusPtr status)
unsigned long long *transferred,
unsigned long long *remaining,
unsigned long long *total)
{ {
virJSONValuePtr ret; virJSONValuePtr ret;
const char *statusstr; const char *statusstr;
unsigned long long t; int rc;
if (!(ret = virJSONValueObjectGet(reply, "return"))) { if (!(ret = virJSONValueObjectGet(reply, "return"))) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
@ -2279,13 +2276,25 @@ qemuMonitorJSONGetMigrationStatusReply(virJSONValuePtr reply,
return -1; return -1;
} }
if ((*status = qemuMonitorMigrationStatusTypeFromString(statusstr)) < 0) { status->status = qemuMonitorMigrationStatusTypeFromString(statusstr);
if (status->status < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, virReportError(VIR_ERR_INTERNAL_ERROR,
_("unexpected migration status in %s"), statusstr); _("unexpected migration status in %s"), statusstr);
return -1; 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"); virJSONValuePtr ram = virJSONValueObjectGet(ret, "ram");
if (!ram) { if (!ram) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
@ -2294,51 +2303,112 @@ qemuMonitorJSONGetMigrationStatusReply(virJSONValuePtr reply,
} }
if (virJSONValueObjectGetNumberUlong(ram, "transferred", if (virJSONValueObjectGetNumberUlong(ram, "transferred",
transferred) < 0) { &status->ram_transferred) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("migration was active, but RAM 'transferred' " _("migration was active, but RAM 'transferred' "
"data was missing")); "data was missing"));
return -1; return -1;
} }
if (virJSONValueObjectGetNumberUlong(ram, "remaining", remaining) < 0) { if (virJSONValueObjectGetNumberUlong(ram, "remaining",
&status->ram_remaining) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("migration was active, but RAM 'remaining' " _("migration was active, but RAM 'remaining' "
"data was missing")); "data was missing"));
return -1; return -1;
} }
if (virJSONValueObjectGetNumberUlong(ram, "total", total) < 0) { if (virJSONValueObjectGetNumberUlong(ram, "total",
&status->ram_total) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("migration was active, but RAM 'total' " _("migration was active, but RAM 'total' "
"data was missing")); "data was missing"));
return -1; return -1;
} }
virJSONValuePtr disk = virJSONValueObjectGet(ret, "disk"); if (virJSONValueObjectGetNumberUlong(ram, "duplicate",
if (!disk) { &status->ram_duplicate) == 0)
return 0; status->ram_duplicate_set = true;
} virJSONValueObjectGetNumberUlong(ram, "normal", &status->ram_normal);
virJSONValueObjectGetNumberUlong(ram, "normal-bytes",
&status->ram_normal_bytes);
if (virJSONValueObjectGetNumberUlong(disk, "transferred", &t) < 0) { virJSONValuePtr disk = virJSONValueObjectGet(ret, "disk");
if (disk) {
rc = virJSONValueObjectGetNumberUlong(disk, "transferred",
&status->disk_transferred);
if (rc < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("disk migration was active, but 'transferred' " _("disk migration was active, but "
"data was missing")); "'transferred' data was missing"));
return -1; return -1;
} }
*transferred += t;
if (virJSONValueObjectGetNumberUlong(disk, "remaining", &t) < 0) { rc = virJSONValueObjectGetNumberUlong(disk, "remaining",
&status->disk_remaining);
if (rc < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("disk migration was active, but 'remaining' " _("disk migration was active, but 'remaining' "
"data was missing")); "data was missing"));
return -1; return -1;
} }
*remaining += t;
if (virJSONValueObjectGetNumberUlong(disk, "total", &t) < 0) { rc = virJSONValueObjectGetNumberUlong(disk, "total",
&status->disk_total);
if (rc < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("disk migration was active, but 'total' " _("disk migration was active, but 'total' "
"data was missing")); "data was missing"));
return -1; return -1;
} }
*total += t; }
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;
}
}
} }
return 0; return 0;
@ -2346,18 +2416,14 @@ qemuMonitorJSONGetMigrationStatusReply(virJSONValuePtr reply,
int qemuMonitorJSONGetMigrationStatus(qemuMonitorPtr mon, int qemuMonitorJSONGetMigrationStatus(qemuMonitorPtr mon,
int *status, qemuMonitorMigrationStatusPtr status)
unsigned long long *transferred,
unsigned long long *remaining,
unsigned long long *total)
{ {
int ret; int ret;
virJSONValuePtr cmd = qemuMonitorJSONMakeCommand("query-migrate", virJSONValuePtr cmd = qemuMonitorJSONMakeCommand("query-migrate",
NULL); NULL);
virJSONValuePtr reply = NULL; virJSONValuePtr reply = NULL;
*status = 0; memset(status, 0, sizeof(*status));
*transferred = *remaining = *total = 0;
if (!cmd) if (!cmd)
return -1; return -1;
@ -2368,13 +2434,11 @@ int qemuMonitorJSONGetMigrationStatus(qemuMonitorPtr mon,
ret = qemuMonitorJSONCheckError(cmd, reply); ret = qemuMonitorJSONCheckError(cmd, reply);
if (ret == 0 && if (ret == 0 &&
qemuMonitorJSONGetMigrationStatusReply(reply, qemuMonitorJSONGetMigrationStatusReply(reply, status) < 0)
status,
transferred,
remaining,
total) < 0)
ret = -1; ret = -1;
if (ret < 0)
memset(status, 0, sizeof(*status));
virJSONValueFree(cmd); virJSONValueFree(cmd);
virJSONValueFree(reply); virJSONValueFree(reply);
return ret; return ret;

View File

@ -121,10 +121,7 @@ int qemuMonitorJSONSetMigrationDowntime(qemuMonitorPtr mon,
unsigned long long downtime); unsigned long long downtime);
int qemuMonitorJSONGetMigrationStatus(qemuMonitorPtr mon, int qemuMonitorJSONGetMigrationStatus(qemuMonitorPtr mon,
int *status, qemuMonitorMigrationStatusPtr status);
unsigned long long *transferred,
unsigned long long *remaining,
unsigned long long *total);
int qemuMonitorJSONGetMigrationCapability(qemuMonitorPtr mon, int qemuMonitorJSONGetMigrationCapability(qemuMonitorPtr mon,
qemuMonitorMigrationCaps capability); qemuMonitorMigrationCaps capability);

View File

@ -1474,22 +1474,14 @@ cleanup:
#define MIGRATION_DISK_TOTAL_PREFIX "total disk: " #define MIGRATION_DISK_TOTAL_PREFIX "total disk: "
int qemuMonitorTextGetMigrationStatus(qemuMonitorPtr mon, int qemuMonitorTextGetMigrationStatus(qemuMonitorPtr mon,
int *status, qemuMonitorMigrationStatusPtr status)
unsigned long long *transferred, {
unsigned long long *remaining,
unsigned long long *total) {
char *reply; char *reply;
char *tmp; char *tmp;
char *end; char *end;
unsigned long long disk_transferred = 0;
unsigned long long disk_remaining = 0;
unsigned long long disk_total = 0;
int ret = -1; int ret = -1;
*status = QEMU_MONITOR_MIGRATION_STATUS_INACTIVE; memset(status, 0, sizeof(*status));
*transferred = 0;
*remaining = 0;
*total = 0;
if (qemuMonitorHMPCommand(mon, "info migrate", &reply) < 0) if (qemuMonitorHMPCommand(mon, "info migrate", &reply) < 0)
return -1; return -1;
@ -1504,52 +1496,54 @@ int qemuMonitorTextGetMigrationStatus(qemuMonitorPtr mon,
} }
*end = '\0'; *end = '\0';
if ((*status = qemuMonitorMigrationStatusTypeFromString(tmp)) < 0) { status->status = qemuMonitorMigrationStatusTypeFromString(tmp);
if (status->status < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, virReportError(VIR_ERR_INTERNAL_ERROR,
_("unexpected migration status in %s"), reply); _("unexpected migration status in %s"), reply);
goto cleanup; goto cleanup;
} }
if (*status == QEMU_MONITOR_MIGRATION_STATUS_ACTIVE) { if (status->status == QEMU_MONITOR_MIGRATION_STATUS_ACTIVE) {
tmp = end + 1; tmp = end + 1;
if (!(tmp = strstr(tmp, MIGRATION_TRANSFER_PREFIX))) if (!(tmp = strstr(tmp, MIGRATION_TRANSFER_PREFIX)))
goto done; goto done;
tmp += strlen(MIGRATION_TRANSFER_PREFIX); 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, virReportError(VIR_ERR_INTERNAL_ERROR,
_("cannot parse migration data transferred " _("cannot parse migration data transferred "
"statistic %s"), tmp); "statistic %s"), tmp);
goto cleanup; goto cleanup;
} }
*transferred *= 1024; status->ram_transferred *= 1024;
tmp = end; tmp = end;
if (!(tmp = strstr(tmp, MIGRATION_REMAINING_PREFIX))) if (!(tmp = strstr(tmp, MIGRATION_REMAINING_PREFIX)))
goto done; goto done;
tmp += strlen(MIGRATION_REMAINING_PREFIX); 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, virReportError(VIR_ERR_INTERNAL_ERROR,
_("cannot parse migration data remaining " _("cannot parse migration data remaining "
"statistic %s"), tmp); "statistic %s"), tmp);
goto cleanup; goto cleanup;
} }
*remaining *= 1024; status->ram_remaining *= 1024;
tmp = end; tmp = end;
if (!(tmp = strstr(tmp, MIGRATION_TOTAL_PREFIX))) if (!(tmp = strstr(tmp, MIGRATION_TOTAL_PREFIX)))
goto done; goto done;
tmp += strlen(MIGRATION_TOTAL_PREFIX); 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, virReportError(VIR_ERR_INTERNAL_ERROR,
_("cannot parse migration data total " _("cannot parse migration data total "
"statistic %s"), tmp); "statistic %s"), tmp);
goto cleanup; goto cleanup;
} }
*total *= 1024; status->ram_total *= 1024;
tmp = end; tmp = end;
/* /*
@ -1559,39 +1553,40 @@ int qemuMonitorTextGetMigrationStatus(qemuMonitorPtr mon,
goto done; goto done;
tmp += strlen(MIGRATION_DISK_TRANSFER_PREFIX); 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, virReportError(VIR_ERR_INTERNAL_ERROR,
_("cannot parse disk migration data " _("cannot parse disk migration data "
"transferred statistic %s"), tmp); "transferred statistic %s"), tmp);
goto cleanup; goto cleanup;
} }
*transferred += disk_transferred * 1024; status->disk_transferred *= 1024;
tmp = end; tmp = end;
if (!(tmp = strstr(tmp, MIGRATION_DISK_REMAINING_PREFIX))) if (!(tmp = strstr(tmp, MIGRATION_DISK_REMAINING_PREFIX)))
goto done; goto done;
tmp += strlen(MIGRATION_DISK_REMAINING_PREFIX); 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, virReportError(VIR_ERR_INTERNAL_ERROR,
_("cannot parse disk migration data remaining " _("cannot parse disk migration data remaining "
"statistic %s"), tmp); "statistic %s"), tmp);
goto cleanup; goto cleanup;
} }
*remaining += disk_remaining * 1024; status->disk_remaining *= 1024;
tmp = end; tmp = end;
if (!(tmp = strstr(tmp, MIGRATION_DISK_TOTAL_PREFIX))) if (!(tmp = strstr(tmp, MIGRATION_DISK_TOTAL_PREFIX)))
goto done; goto done;
tmp += strlen(MIGRATION_DISK_TOTAL_PREFIX); 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, virReportError(VIR_ERR_INTERNAL_ERROR,
_("cannot parse disk migration data total " _("cannot parse disk migration data total "
"statistic %s"), tmp); "statistic %s"), tmp);
goto cleanup; goto cleanup;
} }
*total += disk_total * 1024; status->disk_total *= 1024;
} }
} }
@ -1600,6 +1595,8 @@ done:
cleanup: cleanup:
VIR_FREE(reply); VIR_FREE(reply);
if (ret < 0)
memset(status, 0, sizeof(*status));
return ret; return ret;
} }

View File

@ -117,10 +117,7 @@ int qemuMonitorTextSetMigrationDowntime(qemuMonitorPtr mon,
unsigned long long downtime); unsigned long long downtime);
int qemuMonitorTextGetMigrationStatus(qemuMonitorPtr mon, int qemuMonitorTextGetMigrationStatus(qemuMonitorPtr mon,
int *status, qemuMonitorMigrationStatusPtr status);
unsigned long long *transferred,
unsigned long long *remaining,
unsigned long long *total);
int qemuMonitorTextMigrate(qemuMonitorPtr mon, int qemuMonitorTextMigrate(qemuMonitorPtr mon,
unsigned int flags, unsigned int flags,