---
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