From 7f4f1dd416ad12a5a357000b8c8e40690634c150 Mon Sep 17 00:00:00 2001 From: Jiri Denemark Date: Wed, 17 Mar 2010 16:53:14 +0100 Subject: [PATCH] Implement virDomainMigrateSetMaxDowntime in qemu driver --- src/qemu/qemu_driver.c | 76 +++++++++++++++++++++++++++++++++++- 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, 155 insertions(+), 1 deletion(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 670e066026..1f2b11dbc9 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); @@ -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 */ }; diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index acc841bd74..6b68db8307 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 cfb76b6032..2557fb9ec4 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 7a263cb664..4ae8093b7e 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, "%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, diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h index 2906fee6c0..fc051530a9 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 b7c41a1c46..1596e59327 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 %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: " diff --git a/src/qemu/qemu_monitor_text.h b/src/qemu/qemu_monitor_text.h index 3215cae774..4e1939ccce 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,