]> xenbits.xensource.com Git - libvirt.git/commitdiff
qemu: Implement DomainPMSuspendForDuration
authorMichal Privoznik <mprivozn@redhat.com>
Mon, 13 Feb 2012 11:27:25 +0000 (12:27 +0100)
committerMichal Privoznik <mprivozn@redhat.com>
Wed, 15 Feb 2012 10:45:45 +0000 (11:45 +0100)
via user agent. Allow targets mem & hybrid iff system_wakeup
monitor command is available.

src/qemu/qemu_agent.c
src/qemu/qemu_agent.h
src/qemu/qemu_driver.c

index 9df5546d54fa008228b32ef32f2ba34a50586712..a17d02519e7f2840fc43a78ea3e2d5bc9da460c6 100644 (file)
@@ -1184,3 +1184,34 @@ cleanup:
     virJSONValueFree(reply);
     return ret;
 }
+
+VIR_ENUM_DECL(qemuAgentSuspendMode);
+
+VIR_ENUM_IMPL(qemuAgentSuspendMode,
+              VIR_NODE_SUSPEND_TARGET_LAST,
+              "guest-suspend-ram",
+              "guest-suspend-disk",
+              "guest-suspend-hybrid");
+
+int
+qemuAgentSuspend(qemuAgentPtr mon,
+                 unsigned int target)
+{
+    int ret = -1;
+    virJSONValuePtr cmd;
+    virJSONValuePtr reply = NULL;
+
+    cmd = qemuAgentMakeCommand(qemuAgentSuspendModeTypeToString(target),
+                               NULL);
+    if (!cmd)
+        return -1;
+
+    ret = qemuAgentCommand(mon, cmd, &reply);
+
+    if (ret == 0)
+        ret = qemuAgentCheckError(cmd, reply);
+
+    virJSONValueFree(cmd);
+    virJSONValueFree(reply);
+    return ret;
+}
index df59ef7fe8f53d5901f0df2b536ae4db9f62658c..98c23b0e21cfbab420441498019407677d4220e4 100644 (file)
@@ -69,4 +69,6 @@ int qemuAgentShutdown(qemuAgentPtr mon,
 int qemuAgentFSFreeze(qemuAgentPtr mon);
 int qemuAgentFSThaw(qemuAgentPtr mon);
 
+int qemuAgentSuspend(qemuAgentPtr mon,
+                     unsigned int target);
 #endif /* __QEMU_AGENT_H__ */
index e2e73b7f882b31982fd6e280a15ee028219af2e7..fddf8c67da09ef39699c702176fcdfe38d55dcdd 100644 (file)
@@ -12078,6 +12078,92 @@ cleanup:
     return ret;
 }
 
+static int
+qemuDomainPMSuspendForDuration(virDomainPtr dom,
+                               unsigned int target,
+                               unsigned long long duration,
+                               unsigned int flags)
+{
+    struct qemud_driver *driver = dom->conn->privateData;
+    qemuDomainObjPrivatePtr priv;
+    virDomainObjPtr vm;
+    int ret = -1;
+
+    virCheckFlags(0, -1);
+
+    if (duration) {
+        qemuReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
+                        _("Duration not supported. Use 0 for now"));
+        return -1;
+    }
+
+    if (!(target == VIR_NODE_SUSPEND_TARGET_MEM ||
+          target == VIR_NODE_SUSPEND_TARGET_DISK ||
+          target == VIR_NODE_SUSPEND_TARGET_HYBRID)) {
+        qemuReportError(VIR_ERR_INVALID_ARG,
+                        _("Unknown suspend target: %u"),
+                        target);
+        return -1;
+    }
+
+    qemuDriverLock(driver);
+    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+    qemuDriverUnlock(driver);
+
+    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;
+    }
+
+    priv = vm->privateData;
+
+    if (!qemuCapsGet(priv->qemuCaps, QEMU_CAPS_WAKEUP) &&
+        (target == VIR_NODE_SUSPEND_TARGET_MEM ||
+         target == VIR_NODE_SUSPEND_TARGET_HYBRID)) {
+       qemuReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
+                       _("Unable to suspend domain due to "
+                         "missing system_wakeup monitor command"));
+       goto cleanup;
+    }
+
+    if (priv->agentError) {
+        qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                        _("QEMU guest agent is not available due to an error"));
+        goto cleanup;
+    }
+
+    if (!priv->agent) {
+        qemuReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
+                        _("QEMU guest agent is not configured"));
+        goto cleanup;
+    }
+
+    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
+        goto cleanup;
+
+    if (!virDomainObjIsActive(vm)) {
+        qemuReportError(VIR_ERR_OPERATION_INVALID,
+                        "%s", _("domain is not running"));
+        goto endjob;
+    }
+
+    qemuDomainObjEnterAgent(driver, vm);
+    ret = qemuAgentSuspend(priv->agent, target);
+    qemuDomainObjExitAgent(driver, vm);
+
+endjob:
+    if (qemuDomainObjEndJob(driver, vm) == 0)
+        vm = NULL;
+
+cleanup:
+    if (vm)
+        virDomainObjUnlock(vm);
+    return ret;
+}
+
 static virDriver qemuDriver = {
     .no = VIR_DRV_QEMU,
     .name = "QEMU",
@@ -12235,6 +12321,7 @@ static virDriver qemuDriver = {
     .domainGetDiskErrors = qemuDomainGetDiskErrors, /* 0.9.10 */
     .domainSetMetadata = qemuDomainSetMetadata, /* 0.9.10 */
     .domainGetMetadata = qemuDomainGetMetadata, /* 0.9.10 */
+    .domainPMSuspendForDuration = qemuDomainPMSuspendForDuration, /* 0.9.11 */
 };