* 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