|
|
@@ -2158,10 +2158,6 @@ qemuMonitorJSONSetBalloon(qemuMonitorPtr mon, |
|
|
} |
|
|
|
|
|
|
|
|
/* |
|
|
* Returns: 0 if CPU hotplug not supported, +1 if CPU hotplug worked |
|
|
* or -1 on failure |
|
|
*/ |
|
|
int qemuMonitorJSONSetCPU(qemuMonitorPtr mon, |
|
|
int cpu, bool online) |
|
|
{ |
|
|
@@ -2188,10 +2184,6 @@ int qemuMonitorJSONSetCPU(qemuMonitorPtr mon, |
|
|
else |
|
|
ret = qemuMonitorJSONCheckError(cmd, reply); |
|
|
|
|
|
/* this function has non-standard return values, so adapt it */ |
|
|
if (ret == 0) |
|
|
ret = 1; |
|
|
|
|
|
cleanup: |
|
|
virJSONValueFree(cmd); |
|
|
virJSONValueFree(reply); |
|
|
@@ -2230,10 +2222,14 @@ int qemuMonitorJSONEjectMedia(qemuMonitorPtr mon, |
|
|
if (ret == 0) |
|
|
ret = qemuMonitorJSONCheckError(cmd, reply); |
|
|
|
|
|
VIR_DEBUG("%s", virJSONValueToString(reply, false)); |
|
|
|
|
|
if (ret < 0 && c_strcasestr(virJSONValueToString(reply, false), "is locked")) |
|
|
ret = -2; |
|
|
if (ret < 0) { |
|
|
virJSONValuePtr error = virJSONValueObjectGet(reply, "error"); |
|
|
if (error) { |
|
|
const char *errorStr = virJSONValueObjectGetString(error, "desc"); |
|
|
if (errorStr && c_strcasestr(errorStr, "is locked")) |
|
|
ret = -2; |
|
|
} |
|
|
} |
|
|
|
|
|
virJSONValueFree(cmd); |
|
|
virJSONValueFree(reply); |
|
|
@@ -2425,10 +2421,13 @@ qemuMonitorJSONSetMigrationCacheSize(qemuMonitorPtr mon, |
|
|
|
|
|
|
|
|
static int |
|
|
qemuMonitorJSONGetMigrationStatusReply(virJSONValuePtr reply, |
|
|
qemuMonitorMigrationStatusPtr status) |
|
|
qemuMonitorJSONGetMigrationStatsReply(virJSONValuePtr reply, |
|
|
qemuMonitorMigrationStatsPtr stats) |
|
|
{ |
|
|
virJSONValuePtr ret; |
|
|
virJSONValuePtr ram; |
|
|
virJSONValuePtr disk; |
|
|
virJSONValuePtr comp; |
|
|
const char *statusstr; |
|
|
int rc; |
|
|
double mbps; |
|
|
@@ -2445,55 +2444,63 @@ qemuMonitorJSONGetMigrationStatusReply(virJSONValuePtr reply, |
|
|
return -1; |
|
|
} |
|
|
|
|
|
status->status = qemuMonitorMigrationStatusTypeFromString(statusstr); |
|
|
if (status->status < 0) { |
|
|
stats->status = qemuMonitorMigrationStatusTypeFromString(statusstr); |
|
|
if (stats->status < 0) { |
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, |
|
|
_("unexpected migration status in %s"), statusstr); |
|
|
return -1; |
|
|
} |
|
|
|
|
|
ignore_value(virJSONValueObjectGetNumberUlong(ret, "total-time", |
|
|
&status->total_time)); |
|
|
if (status->status == QEMU_MONITOR_MIGRATION_STATUS_COMPLETED) { |
|
|
&stats->total_time)); |
|
|
if (stats->status == QEMU_MONITOR_MIGRATION_STATUS_COMPLETED) { |
|
|
rc = virJSONValueObjectGetNumberUlong(ret, "downtime", |
|
|
&status->downtime); |
|
|
&stats->downtime); |
|
|
} else { |
|
|
rc = virJSONValueObjectGetNumberUlong(ret, "expected-downtime", |
|
|
&status->downtime); |
|
|
&stats->downtime); |
|
|
} |
|
|
if (rc == 0) |
|
|
status->downtime_set = true; |
|
|
stats->downtime_set = true; |
|
|
|
|
|
if (virJSONValueObjectGetNumberUlong(ret, "setup-time", |
|
|
&status->setup_time) == 0) |
|
|
status->setup_time_set = true; |
|
|
&stats->setup_time) == 0) |
|
|
stats->setup_time_set = true; |
|
|
|
|
|
switch ((qemuMonitorMigrationStatus) stats->status) { |
|
|
case QEMU_MONITOR_MIGRATION_STATUS_INACTIVE: |
|
|
case QEMU_MONITOR_MIGRATION_STATUS_SETUP: |
|
|
case QEMU_MONITOR_MIGRATION_STATUS_ERROR: |
|
|
case QEMU_MONITOR_MIGRATION_STATUS_CANCELLED: |
|
|
case QEMU_MONITOR_MIGRATION_STATUS_LAST: |
|
|
break; |
|
|
|
|
|
if (status->status == QEMU_MONITOR_MIGRATION_STATUS_ACTIVE || |
|
|
status->status == QEMU_MONITOR_MIGRATION_STATUS_CANCELLING || |
|
|
status->status == QEMU_MONITOR_MIGRATION_STATUS_COMPLETED) { |
|
|
virJSONValuePtr ram = virJSONValueObjectGetObject(ret, "ram"); |
|
|
case QEMU_MONITOR_MIGRATION_STATUS_ACTIVE: |
|
|
case QEMU_MONITOR_MIGRATION_STATUS_COMPLETED: |
|
|
case QEMU_MONITOR_MIGRATION_STATUS_CANCELLING: |
|
|
ram = virJSONValueObjectGetObject(ret, "ram"); |
|
|
if (!ram) { |
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", |
|
|
_("migration was active, but no RAM info was set")); |
|
|
return -1; |
|
|
} |
|
|
|
|
|
if (virJSONValueObjectGetNumberUlong(ram, "transferred", |
|
|
&status->ram_transferred) < 0) { |
|
|
&stats->ram_transferred) < 0) { |
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", |
|
|
_("migration was active, but RAM 'transferred' " |
|
|
"data was missing")); |
|
|
return -1; |
|
|
} |
|
|
if (virJSONValueObjectGetNumberUlong(ram, "remaining", |
|
|
&status->ram_remaining) < 0) { |
|
|
&stats->ram_remaining) < 0) { |
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", |
|
|
_("migration was active, but RAM 'remaining' " |
|
|
"data was missing")); |
|
|
return -1; |
|
|
} |
|
|
if (virJSONValueObjectGetNumberUlong(ram, "total", |
|
|
&status->ram_total) < 0) { |
|
|
&stats->ram_total) < 0) { |
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", |
|
|
_("migration was active, but RAM 'total' " |
|
|
"data was missing")); |
|
|
@@ -2503,21 +2510,25 @@ qemuMonitorJSONGetMigrationStatusReply(virJSONValuePtr reply, |
|
|
if (virJSONValueObjectGetNumberDouble(ram, "mbps", &mbps) == 0 && |
|
|
mbps > 0) { |
|
|
/* mpbs from QEMU reports Mbits/s (M as in 10^6 not Mi as 2^20) */ |
|
|
status->ram_bps = mbps * (1000 * 1000 / 8); |
|
|
stats->ram_bps = mbps * (1000 * 1000 / 8); |
|
|
} |
|
|
|
|
|
if (virJSONValueObjectGetNumberUlong(ram, "duplicate", |
|
|
&status->ram_duplicate) == 0) |
|
|
status->ram_duplicate_set = true; |
|
|
&stats->ram_duplicate) == 0) |
|
|
stats->ram_duplicate_set = true; |
|
|
ignore_value(virJSONValueObjectGetNumberUlong(ram, "normal", |
|
|
&status->ram_normal)); |
|
|
&stats->ram_normal)); |
|
|
ignore_value(virJSONValueObjectGetNumberUlong(ram, "normal-bytes", |
|
|
&status->ram_normal_bytes)); |
|
|
&stats->ram_normal_bytes)); |
|
|
ignore_value(virJSONValueObjectGetNumberUlong(ram, "dirty-pages-rate", |
|
|
&stats->ram_dirty_rate)); |
|
|
ignore_value(virJSONValueObjectGetNumberUlong(ram, "dirty-sync-count", |
|
|
&stats->ram_iteration)); |
|
|
|
|
|
virJSONValuePtr disk = virJSONValueObjectGetObject(ret, "disk"); |
|
|
disk = virJSONValueObjectGetObject(ret, "disk"); |
|
|
if (disk) { |
|
|
rc = virJSONValueObjectGetNumberUlong(disk, "transferred", |
|
|
&status->disk_transferred); |
|
|
&stats->disk_transferred); |
|
|
if (rc < 0) { |
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", |
|
|
_("disk migration was active, but " |
|
|
@@ -2526,7 +2537,7 @@ qemuMonitorJSONGetMigrationStatusReply(virJSONValuePtr reply, |
|
|
} |
|
|
|
|
|
rc = virJSONValueObjectGetNumberUlong(disk, "remaining", |
|
|
&status->disk_remaining); |
|
|
&stats->disk_remaining); |
|
|
if (rc < 0) { |
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", |
|
|
_("disk migration was active, but 'remaining' " |
|
|
@@ -2535,7 +2546,7 @@ qemuMonitorJSONGetMigrationStatusReply(virJSONValuePtr reply, |
|
|
} |
|
|
|
|
|
rc = virJSONValueObjectGetNumberUlong(disk, "total", |
|
|
&status->disk_total); |
|
|
&stats->disk_total); |
|
|
if (rc < 0) { |
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", |
|
|
_("disk migration was active, but 'total' " |
|
|
@@ -2546,15 +2557,15 @@ qemuMonitorJSONGetMigrationStatusReply(virJSONValuePtr reply, |
|
|
if (virJSONValueObjectGetNumberDouble(disk, "mbps", &mbps) == 0 && |
|
|
mbps > 0) { |
|
|
/* mpbs from QEMU reports Mbits/s (M as in 10^6 not Mi as 2^20) */ |
|
|
status->disk_bps = mbps * (1000 * 1000 / 8); |
|
|
stats->disk_bps = mbps * (1000 * 1000 / 8); |
|
|
} |
|
|
} |
|
|
|
|
|
virJSONValuePtr comp = virJSONValueObjectGetObject(ret, "xbzrle-cache"); |
|
|
comp = virJSONValueObjectGetObject(ret, "xbzrle-cache"); |
|
|
if (comp) { |
|
|
status->xbzrle_set = true; |
|
|
stats->xbzrle_set = true; |
|
|
rc = virJSONValueObjectGetNumberUlong(comp, "cache-size", |
|
|
&status->xbzrle_cache_size); |
|
|
&stats->xbzrle_cache_size); |
|
|
if (rc < 0) { |
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", |
|
|
_("XBZRLE is active, but 'cache-size' data " |
|
|
@@ -2563,7 +2574,7 @@ qemuMonitorJSONGetMigrationStatusReply(virJSONValuePtr reply, |
|
|
} |
|
|
|
|
|
rc = virJSONValueObjectGetNumberUlong(comp, "bytes", |
|
|
&status->xbzrle_bytes); |
|
|
&stats->xbzrle_bytes); |
|
|
if (rc < 0) { |
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", |
|
|
_("XBZRLE is active, but 'bytes' data " |
|
|
@@ -2572,7 +2583,7 @@ qemuMonitorJSONGetMigrationStatusReply(virJSONValuePtr reply, |
|
|
} |
|
|
|
|
|
rc = virJSONValueObjectGetNumberUlong(comp, "pages", |
|
|
&status->xbzrle_pages); |
|
|
&stats->xbzrle_pages); |
|
|
if (rc < 0) { |
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", |
|
|
_("XBZRLE is active, but 'pages' data " |
|
|
@@ -2581,7 +2592,7 @@ qemuMonitorJSONGetMigrationStatusReply(virJSONValuePtr reply, |
|
|
} |
|
|
|
|
|
rc = virJSONValueObjectGetNumberUlong(comp, "cache-miss", |
|
|
&status->xbzrle_cache_miss); |
|
|
&stats->xbzrle_cache_miss); |
|
|
if (rc < 0) { |
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", |
|
|
_("XBZRLE is active, but 'cache-miss' data " |
|
|
@@ -2590,29 +2601,30 @@ qemuMonitorJSONGetMigrationStatusReply(virJSONValuePtr reply, |
|
|
} |
|
|
|
|
|
rc = virJSONValueObjectGetNumberUlong(comp, "overflow", |
|
|
&status->xbzrle_overflow); |
|
|
&stats->xbzrle_overflow); |
|
|
if (rc < 0) { |
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", |
|
|
_("XBZRLE is active, but 'overflow' data " |
|
|
"was missing")); |
|
|
return -1; |
|
|
} |
|
|
} |
|
|
break; |
|
|
} |
|
|
|
|
|
return 0; |
|
|
} |
|
|
|
|
|
|
|
|
int qemuMonitorJSONGetMigrationStatus(qemuMonitorPtr mon, |
|
|
qemuMonitorMigrationStatusPtr status) |
|
|
int qemuMonitorJSONGetMigrationStats(qemuMonitorPtr mon, |
|
|
qemuMonitorMigrationStatsPtr stats) |
|
|
{ |
|
|
int ret; |
|
|
virJSONValuePtr cmd = qemuMonitorJSONMakeCommand("query-migrate", |
|
|
NULL); |
|
|
virJSONValuePtr reply = NULL; |
|
|
|
|
|
memset(status, 0, sizeof(*status)); |
|
|
memset(stats, 0, sizeof(*stats)); |
|
|
|
|
|
if (!cmd) |
|
|
return -1; |
|
|
@@ -2623,11 +2635,11 @@ int qemuMonitorJSONGetMigrationStatus(qemuMonitorPtr mon, |
|
|
ret = qemuMonitorJSONCheckError(cmd, reply); |
|
|
|
|
|
if (ret == 0 && |
|
|
qemuMonitorJSONGetMigrationStatusReply(reply, status) < 0) |
|
|
qemuMonitorJSONGetMigrationStatsReply(reply, stats) < 0) |
|
|
ret = -1; |
|
|
|
|
|
if (ret < 0) |
|
|
memset(status, 0, sizeof(*status)); |
|
|
memset(stats, 0, sizeof(*stats)); |
|
|
virJSONValueFree(cmd); |
|
|
virJSONValueFree(reply); |
|
|
return ret; |
|
|
|