提交 4121a77c 编写于 作者: J Jiri Denemark

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.
上级 38ab1225
......@@ -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));
}
......
......@@ -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 */
};
......
......@@ -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;
......
......@@ -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;
}
......
......@@ -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);
......
......@@ -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;
......
......@@ -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);
......
......@@ -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;
}
......
......@@ -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,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册