]> xenbits.xensource.com Git - people/liuw/libxenctrl-split/libvirt.git/commitdiff
Implement virDomainMigrateSetMaxDowntime in qemu driver
authorJiri Denemark <jdenemar@redhat.com>
Wed, 17 Mar 2010 15:53:14 +0000 (16:53 +0100)
committerJiri Denemark <jdenemar@redhat.com>
Fri, 19 Mar 2010 21:47:45 +0000 (22:47 +0100)
src/qemu/qemu_driver.c
src/qemu/qemu_monitor.c
src/qemu/qemu_monitor.h
src/qemu/qemu_monitor_json.c
src/qemu/qemu_monitor_json.h
src/qemu/qemu_monitor_text.c
src/qemu/qemu_monitor_text.h

index 670e066026a92c0fd9685d67a122cd182b9042dc..1f2b11dbc908484974212037f088227de88090e8 100644 (file)
@@ -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);
@@ -4064,6 +4073,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 ms = priv->jobSignalsData.migrateDowntime;
+
+            priv->jobSignals ^= QEMU_JOB_SIGNAL_MIGRATE_DOWNTIME;
+            priv->jobSignalsData.migrateDowntime = 0;
+            VIR_DEBUG("Setting migration downtime to %llums", ms);
+            qemuDomainObjEnterMonitorWithDriver(driver, vm);
+            rc = qemuMonitorSetMigrationDowntime(priv->mon, ms);
+            qemuDomainObjExitMonitorWithDriver(driver, vm);
+            if (rc < 0)
+                VIR_WARN0("Unable to set migration downtime");
         }
 
         qemuDomainObjEnterMonitorWithDriver(driver, vm);
@@ -9520,6 +9540,60 @@ cleanup:
 }
 
 
+static int
+qemuDomainMigrateSetMaxDowntime(virDomainPtr dom,
+                                unsigned long long downtime,
+                                unsigned int flags)
+{
+    struct qemud_driver *driver = dom->conn->privateData;
+    virDomainObjPtr vm;
+    qemuDomainObjPrivatePtr priv;
+    int ret = -1;
+
+    if (flags != 0) {
+        qemuReportError(VIR_ERR_INVALID_ARG,
+                        _("unsupported flags (0x%x) passed to '%s'"), flags, __FUNCTION__);
+        return -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 %llums", 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",
@@ -9601,7 +9675,7 @@ static virDriver qemuDriver = {
     qemuCPUBaseline, /* cpuBaseline */
     qemuDomainGetJobInfo, /* domainGetJobInfo */
     qemuDomainAbortJob, /* domainAbortJob */
-    NULL, /* domainMigrateSetMaxDowntime */
+    qemuDomainMigrateSetMaxDowntime, /* domainMigrateSetMaxDowntime */
 };
 
 
index acc841bd74ea7c130dd48f7f1e50129f66151db5..6b68db83071b7fb636adaf3cf46b20b8a4aebd6a 100644 (file)
@@ -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,
index cfb76b60329861df98240872487473b2c1e12ca4..2557fb9ec439db8822527f9bc65a4e3e6bba15fa 100644 (file)
@@ -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,
index 7a263cb664600e0f59e94c3746f8ff77022d1672..4ae8093b7e758518c83f6dbb695b7976f1d5aefa 100644 (file)
@@ -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, "%llums", 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,
index 2906fee6c0d924836a568476c1881444df350b6e..fc051530a9e0fe26a721d695b9e08fc6d55448e9 100644 (file)
@@ -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,
index b7c41a1c465637d686c8696cab4d7ef447d43093..1596e59327e0619b8da92f79bd476c681a5f89cb 100644 (file)
@@ -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 %llums", 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: "
index 3215cae7742c0a8e671255cdd98863150c81fd3f..4e1939ccce37922c68b3b41c196cecc40df900b6 100644 (file)
@@ -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,