* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h: Add new qemuMonitorGetMigrationStatus() command. * src/qemu/qemu_driver.c: Use new qemuMonitorGetMigrationStatus() command to check completion status. --- src/qemu/qemu_driver.c | 15 +++++-- src/qemu/qemu_monitor_text.c | 91 ++++++++++++++++++++++++++++++++++++++++++ src/qemu/qemu_monitor_text.h | 16 +++++++ 3 files changed, 117 insertions(+), 5 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index ccc13c4..a6300c9 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -6499,6 +6499,8 @@ qemudDomainMigratePerform (virDomainPtr dom, char *info = NULL; int ret = -1; int paused = 0; + int status; + unsigned long long transferred, remaining, total; qemuDriverLock(driver); vm = virDomainFindByUUID(&driver->domains, dom->uuid); @@ -6562,14 +6564,17 @@ qemudDomainMigratePerform (virDomainPtr dom, * rather failed later on. Check the output of "info migrate" */ VIR_FREE(info); - if (qemudMonitorCommand(vm, "info migrate", &info) < 0) { - qemudReportError (dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, - "%s", _("could not get info about migration")); + + if (qemuMonitorGetMigrationStatus(vm, &status, + &transferred, + &remaining, + &total) < 0) { goto cleanup; } - if (strstr(info, "fail") != NULL) { + + if (status != QEMU_MONITOR_MIGRATION_STATUS_COMPLETED) { qemudReportError (dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, - _("migrate failed: %s"), info); + "%s", _("migrate did not successfully complete")); goto cleanup; } diff --git a/src/qemu/qemu_monitor_text.c b/src/qemu/qemu_monitor_text.c index d9227a2..0b746b9 100644 --- a/src/qemu/qemu_monitor_text.c +++ b/src/qemu/qemu_monitor_text.c @@ -28,6 +28,7 @@ #include <sys/un.h> #include <poll.h> #include <unistd.h> +#include <string.h> #include "qemu_monitor_text.h" #include "qemu_conf.h" @@ -997,3 +998,93 @@ cleanup: VIR_FREE(cmd); return ret; } + + +#define MIGRATION_PREFIX "Migration status: " +#define MIGRATION_TRANSFER_PREFIX "transferred ram: " +#define MIGRATION_REMAINING_PREFIX "remaining ram: " +#define MIGRATION_TOTAL_PREFIX "total ram: " + +VIR_ENUM_DECL(qemuMonitorMigrationStatus) +VIR_ENUM_IMPL(qemuMonitorMigrationStatus, + QEMU_MONITOR_MIGRATION_STATUS_LAST, + "inactive", "active", "completed", "failed", "cancelled") + +int qemuMonitorGetMigrationStatus(const virDomainObjPtr vm, + int *status, + unsigned long long *transferred, + unsigned long long *remaining, + unsigned long long *total) { + char *reply; + char *tmp; + char *end; + int ret = -1; + + *status = QEMU_MONITOR_MIGRATION_STATUS_INACTIVE; + *transferred = 0; + *remaining = 0; + *total = 0; + + if (qemudMonitorCommand(vm, "info migration", &reply) < 0) { + qemudReportError(NULL, NULL, NULL, VIR_ERR_OPERATION_FAILED, + "%s", _("cannot query migration status")); + return -1; + } + + if ((tmp = strstr(reply, MIGRATION_PREFIX)) != NULL) { + tmp += strlen(MIGRATION_PREFIX); + end = strchr(tmp, '\n'); + *end = '\0'; + + if ((*status = qemuMonitorMigrationStatusTypeFromString(tmp)) < 0) { + qemudReportError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR, + _("unexpected migration status in %s"), reply); + goto cleanup; + } + + if (*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, NULL, 10, transferred) < 0) { + qemudReportError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR, + _("cannot parse migration data transferred statistic %s"), tmp); + goto cleanup; + } + *transferred *= 1024; + + if (!(tmp = strstr(tmp, MIGRATION_REMAINING_PREFIX))) + goto done; + tmp += strlen(MIGRATION_REMAINING_PREFIX); + + if (virStrToLong_ull(tmp, NULL, 10, remaining) < 0) { + qemudReportError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR, + _("cannot parse migration data remaining statistic %s"), tmp); + goto cleanup; + } + *remaining *= 1024; + + if (!(tmp = strstr(tmp, MIGRATION_TOTAL_PREFIX))) + goto done; + tmp += strlen(MIGRATION_TOTAL_PREFIX); + + if (virStrToLong_ull(tmp, NULL, 10, total) < 0) { + qemudReportError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR, + _("cannot parse migration data total statistic %s"), tmp); + goto cleanup; + } + *total *= 1024; + + } + } + +done: + ret = 0; + +cleanup: + VIR_FREE(reply); + return ret; +} diff --git a/src/qemu/qemu_monitor_text.h b/src/qemu/qemu_monitor_text.h index 0591f3c..c972672 100644 --- a/src/qemu/qemu_monitor_text.h +++ b/src/qemu/qemu_monitor_text.h @@ -112,4 +112,20 @@ int qemuMonitorSavePhysicalMemory(const virDomainObjPtr vm, int qemuMonitorSetMigrationSpeed(const virDomainObjPtr vm, unsigned long bandwidth); +enum { + QEMU_MONITOR_MIGRATION_STATUS_INACTIVE, + QEMU_MONITOR_MIGRATION_STATUS_ACTIVE, + QEMU_MONITOR_MIGRATION_STATUS_COMPLETED, + QEMU_MONITOR_MIGRATION_STATUS_ERROR, + QEMU_MONITOR_MIGRATION_STATUS_CANCELLED, + + QEMU_MONITOR_MIGRATION_STATUS_LAST +}; + +int qemuMonitorGetMigrationStatus(const virDomainObjPtr vm, + int *status, + unsigned long long *transferred, + unsigned long long *remaining, + unsigned long long *total); + #endif /* QEMU_MONITOR_TEXT_H */ -- 1.6.2.5 -- Libvir-list mailing list Libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list