[libvirt] [PATCH v2 4/5] Implement virDomainMigrateSetMaxDowntime in qemu driver

Jiri Denemark jdenemar at redhat.com
Thu Mar 18 19:12:47 UTC 2010


---
 src/qemu/qemu_driver.c       |   70 +++++++++++++++++++++++++++++++++++++++++-
 src/qemu/qemu_monitor.c      |   15 +++++++++
 src/qemu/qemu_monitor.h      |    3 ++
 src/qemu/qemu_monitor_json.c |   29 +++++++++++++++++
 src/qemu/qemu_monitor_json.h |    3 ++
 src/qemu/qemu_monitor_text.c |   27 ++++++++++++++++
 src/qemu/qemu_monitor_text.h |    3 ++
 7 files changed, 149 insertions(+), 1 deletions(-)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 4cb47f7..d04d9bf 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -99,6 +99,11 @@ enum qemuDomainJob {
 enum qemuDomainJobSignals {
     QEMU_JOB_SIGNAL_CANCEL  = 1 << 0, /* Request job cancellation */
     QEMU_JOB_SIGNAL_SUSPEND = 1 << 1, /* Request VM suspend to finish live migration offline */
+    QEMU_JOB_SIGNAL_MIGRATE_DOWNTIME = 1 << 2, /* Request migration downtime change */
+};
+
+struct qemuDomainJobSignalsData {
+    unsigned long long migrateDowntime; /* Data for QEMU_JOB_SIGNAL_MIGRATE_DOWNTIME */
 };
 
 typedef struct _qemuDomainObjPrivate qemuDomainObjPrivate;
@@ -107,6 +112,7 @@ struct _qemuDomainObjPrivate {
     virCond jobCond; /* Use in conjunction with main virDomainObjPtr lock */
     enum qemuDomainJob jobActive;   /* Currently running job */
     unsigned int jobSignals;        /* Signals for running job */
+    struct qemuDomainJobSignalsData jobSignalsData; /* Signal specific data */
     virDomainJobInfo jobInfo;
     unsigned long long jobStart;
 
@@ -352,6 +358,7 @@ static int qemuDomainObjBeginJob(virDomainObjPtr obj)
     }
     priv->jobActive = QEMU_JOB_UNSPECIFIED;
     priv->jobSignals = 0;
+    memset(&priv->jobSignalsData, 0, sizeof(priv->jobSignalsData));
     priv->jobStart = (now.tv_sec * 1000ull) + (now.tv_usec / 1000);
     memset(&priv->jobInfo, 0, sizeof(priv->jobInfo));
 
@@ -399,6 +406,7 @@ static int qemuDomainObjBeginJobWithDriver(struct qemud_driver *driver,
     }
     priv->jobActive = QEMU_JOB_UNSPECIFIED;
     priv->jobSignals = 0;
+    memset(&priv->jobSignalsData, 0, sizeof(priv->jobSignalsData));
     priv->jobStart = (now.tv_sec * 1000ull) + (now.tv_usec / 1000);
     memset(&priv->jobInfo, 0, sizeof(priv->jobInfo));
 
@@ -424,6 +432,7 @@ static int ATTRIBUTE_RETURN_CHECK qemuDomainObjEndJob(virDomainObjPtr obj)
 
     priv->jobActive = QEMU_JOB_NONE;
     priv->jobSignals = 0;
+    memset(&priv->jobSignalsData, 0, sizeof(priv->jobSignalsData));
     priv->jobStart = 0;
     memset(&priv->jobInfo, 0, sizeof(priv->jobInfo));
     virCondSignal(&priv->jobCond);
@@ -4061,6 +4070,17 @@ qemuDomainWaitForMigrationComplete(struct qemud_driver *driver, virDomainObjPtr
             VIR_DEBUG0("Pausing domain for non-live migration");
             if (qemuDomainMigrateOffline(driver, vm) < 0)
                 VIR_WARN0("Unable to pause domain");
+        } else if (priv->jobSignals & QEMU_JOB_SIGNAL_MIGRATE_DOWNTIME) {
+            unsigned long long ns = priv->jobSignalsData.migrateDowntime;
+
+            priv->jobSignals ^= QEMU_JOB_SIGNAL_MIGRATE_DOWNTIME;
+            priv->jobSignalsData.migrateDowntime = 0;
+            VIR_DEBUG("Setting migration downtime to %lluns", ns);
+            qemuDomainObjEnterMonitorWithDriver(driver, vm);
+            rc = qemuMonitorSetMigrationDowntime(priv->mon, ns);
+            qemuDomainObjExitMonitorWithDriver(driver, vm);
+            if (rc < 0)
+                VIR_WARN0("Unable to set migration downtime");
         }
 
         qemuDomainObjEnterMonitorWithDriver(driver, vm);
@@ -9516,6 +9536,54 @@ cleanup:
 }
 
 
+static int
+qemuDomainMigrateSetMaxDowntime(virDomainPtr dom,
+                                unsigned long long downtime,
+                                unsigned int flags ATTRIBUTE_UNUSED)
+{
+    struct qemud_driver *driver = dom->conn->privateData;
+    virDomainObjPtr vm;
+    qemuDomainObjPrivatePtr priv;
+    int ret = -1;
+
+    qemuDriverLock(driver);
+    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+
+    if (!vm) {
+        char uuidstr[VIR_UUID_STRING_BUFLEN];
+        virUUIDFormat(dom->uuid, uuidstr);
+        qemuReportError(VIR_ERR_NO_DOMAIN,
+                        _("no domain with matching uuid '%s'"), uuidstr);
+        goto cleanup;
+    }
+
+    if (!virDomainObjIsActive(vm)) {
+        qemuReportError(VIR_ERR_OPERATION_INVALID,
+                        "%s", _("domain is not running"));
+        goto cleanup;
+    }
+
+    priv = vm->privateData;
+
+    if (priv->jobActive != QEMU_JOB_MIGRATION) {
+        qemuReportError(VIR_ERR_OPERATION_INVALID,
+                        "%s", _("domain is not being migrated"));
+        goto cleanup;
+    }
+
+    VIR_DEBUG("Requesting migration downtime change to %lluns", downtime);
+    priv->jobSignals |= QEMU_JOB_SIGNAL_MIGRATE_DOWNTIME;
+    priv->jobSignalsData.migrateDowntime = downtime;
+    ret = 0;
+
+cleanup:
+    if (vm)
+        virDomainObjUnlock(vm);
+    qemuDriverUnlock(driver);
+    return ret;
+}
+
+
 static virDriver qemuDriver = {
     VIR_DRV_QEMU,
     "QEMU",
@@ -9597,7 +9665,7 @@ static virDriver qemuDriver = {
     qemuCPUBaseline, /* cpuBaseline */
     qemuDomainGetJobInfo, /* domainGetJobInfo */
     qemuDomainAbortJob, /* domainAbortJob */
-    NULL, /* domainMigrateSetMaxDowntime */
+    qemuDomainMigrateSetMaxDowntime, /* domainMigrateSetMaxDowntime */
 };
 
 
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index acc841b..6b68db8 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -1016,6 +1016,21 @@ int qemuMonitorSetMigrationSpeed(qemuMonitorPtr mon,
     return ret;
 }
 
+
+int qemuMonitorSetMigrationDowntime(qemuMonitorPtr mon,
+                                    unsigned long long downtime)
+{
+    int ret;
+    DEBUG("mon=%p, fd=%d downtime=%llu", mon, mon->fd, downtime);
+
+    if (mon->json)
+        ret = qemuMonitorJSONSetMigrationDowntime(mon, downtime);
+    else
+        ret = qemuMonitorTextSetMigrationDowntime(mon, downtime);
+    return ret;
+}
+
+
 int qemuMonitorGetMigrationStatus(qemuMonitorPtr mon,
                                   int *status,
                                   unsigned long long *transferred,
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index cfb76b6..2557fb9 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -176,6 +176,9 @@ int qemuMonitorSavePhysicalMemory(qemuMonitorPtr mon,
 int qemuMonitorSetMigrationSpeed(qemuMonitorPtr mon,
                                  unsigned long bandwidth);
 
+int qemuMonitorSetMigrationDowntime(qemuMonitorPtr mon,
+                                    unsigned long long downtime);
+
 enum {
     QEMU_MONITOR_MIGRATION_STATUS_INACTIVE,
     QEMU_MONITOR_MIGRATION_STATUS_ACTIVE,
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index 7a263cb..b259452 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -1088,6 +1088,35 @@ int qemuMonitorJSONSetMigrationSpeed(qemuMonitorPtr mon,
 }
 
 
+int qemuMonitorJSONSetMigrationDowntime(qemuMonitorPtr mon,
+                                        unsigned long long downtime)
+{
+    int ret;
+    char *downtimestr;
+    virJSONValuePtr cmd;
+    virJSONValuePtr reply = NULL;
+    if (virAsprintf(&downtimestr, "%llun", downtime) < 0) {
+        virReportOOMError();
+        return -1;
+    }
+    cmd = qemuMonitorJSONMakeCommand("migrate_set_downtime",
+                                     "s:value", downtimestr,
+                                     NULL);
+    VIR_FREE(downtimestr);
+    if (!cmd)
+        return -1;
+
+    ret = qemuMonitorJSONCommand(mon, cmd, &reply);
+
+    if (ret == 0)
+        ret = qemuMonitorJSONCheckError(cmd, reply);
+
+    virJSONValueFree(cmd);
+    virJSONValueFree(reply);
+    return ret;
+}
+
+
 static int
 qemuMonitorJSONGetMigrationStatusReply(virJSONValuePtr reply,
                                        int *status,
diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h
index 2906fee..fc05153 100644
--- a/src/qemu/qemu_monitor_json.h
+++ b/src/qemu/qemu_monitor_json.h
@@ -81,6 +81,9 @@ int qemuMonitorJSONSavePhysicalMemory(qemuMonitorPtr mon,
 int qemuMonitorJSONSetMigrationSpeed(qemuMonitorPtr mon,
                                      unsigned long bandwidth);
 
+int qemuMonitorJSONSetMigrationDowntime(qemuMonitorPtr mon,
+                                        unsigned long long downtime);
+
 int qemuMonitorJSONGetMigrationStatus(qemuMonitorPtr mon,
                                       int *status,
                                       unsigned long long *transferred,
diff --git a/src/qemu/qemu_monitor_text.c b/src/qemu/qemu_monitor_text.c
index b7c41a1..ca2fc97 100644
--- a/src/qemu/qemu_monitor_text.c
+++ b/src/qemu/qemu_monitor_text.c
@@ -999,6 +999,33 @@ cleanup:
 }
 
 
+int qemuMonitorTextSetMigrationDowntime(qemuMonitorPtr mon,
+                                        unsigned long long downtime)
+{
+    char *cmd = NULL;
+    char *info = NULL;
+    int ret = -1;
+
+    if (virAsprintf(&cmd, "migrate_set_downtime %llun", downtime) < 0) {
+        virReportOOMError();
+        goto cleanup;
+    }
+
+    if (qemuMonitorCommand(mon, cmd, &info) < 0) {
+        qemuReportError(VIR_ERR_OPERATION_FAILED,
+                        "%s", _("could not set maximum migration downtime"));
+        goto cleanup;
+    }
+
+    ret = 0;
+
+cleanup:
+    VIR_FREE(info);
+    VIR_FREE(cmd);
+    return ret;
+}
+
+
 #define MIGRATION_PREFIX "Migration status: "
 #define MIGRATION_TRANSFER_PREFIX "transferred ram: "
 #define MIGRATION_REMAINING_PREFIX "remaining ram: "
diff --git a/src/qemu/qemu_monitor_text.h b/src/qemu/qemu_monitor_text.h
index 3215cae..4e1939c 100644
--- a/src/qemu/qemu_monitor_text.h
+++ b/src/qemu/qemu_monitor_text.h
@@ -83,6 +83,9 @@ int qemuMonitorTextSavePhysicalMemory(qemuMonitorPtr mon,
 int qemuMonitorTextSetMigrationSpeed(qemuMonitorPtr mon,
                                      unsigned long bandwidth);
 
+int qemuMonitorTextSetMigrationDowntime(qemuMonitorPtr mon,
+                                        unsigned long long downtime);
+
 int qemuMonitorTextGetMigrationStatus(qemuMonitorPtr mon,
                                       int *status,
                                       unsigned long long *transferred,
-- 
1.7.0.2




More information about the libvir-list mailing list