--- 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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list