diff --git a/tools/virsh.c b/tools/virsh.c index ffcd746b36..3a5974662c 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -2169,6 +2169,77 @@ cmdSuspend(vshControl *ctl, const vshCmd *cmd) return ret; } +/* + * "dompmsuspend" command + */ +static const vshCmdInfo info_dom_pm_suspend[] = { + {"help", N_("suspend a domain for a given time duration")}, + {"desc", N_("Suspend a running domain for a given time duration.")}, + {NULL, NULL} +}; + +static const vshCmdOptDef opts_dom_pm_suspend[] = { + {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")}, + {"duration", VSH_OT_INT, VSH_OFLAG_REQ_OPT, N_("duration in seconds")}, + {"target", VSH_OT_STRING, VSH_OFLAG_REQ, N_("mem(Suspend-to-RAM), " + "disk(Suspend-to-Disk), " + "hybrid(Hybrid-Suspend)")}, + {NULL, 0, 0, NULL} +}; + +static bool +cmdDomPMSuspend(vshControl *ctl, const vshCmd *cmd) +{ + virDomainPtr dom; + const char *name; + bool ret = false; + const char *target = NULL; + unsigned int suspendTarget; + unsigned long long duration = 0; + + if (!vshConnectionUsability(ctl, ctl->conn)) + return false; + + if (!(dom = vshCommandOptDomain(ctl, cmd, &name))) + return false; + + if (vshCommandOptULongLong(cmd, "duration", &duration) < 0) { + vshError(ctl, _("Invalid duration argument")); + goto cleanup; + } + + if (vshCommandOptString(cmd, "target", &target) < 0) { + vshError(ctl, _("Invalid target argument")); + goto cleanup; + } + + if (STREQ(target, "mem")) + suspendTarget = VIR_NODE_SUSPEND_TARGET_MEM; + else if (STREQ(target, "disk")) + suspendTarget = VIR_NODE_SUSPEND_TARGET_DISK; + else if (STREQ(target, "hybrid")) + suspendTarget = VIR_NODE_SUSPEND_TARGET_HYBRID; + else { + vshError(ctl, "%s", _("Invalid target")); + goto cleanup; + } + + if (virDomainPMSuspendForDuration(dom, suspendTarget, duration, 0) < 0) { + vshError(ctl, _("Domain %s could not be suspended"), + virDomainGetName(dom)); + goto cleanup; + } + + vshPrint(ctl, _("Domain %s successfully suspended"), + virDomainGetName(dom)); + + ret = true; + +cleanup: + virDomainFree(dom); + return ret; +} + /* * "create" command */ @@ -16109,6 +16180,8 @@ static const vshCmdDef domManagementCmds[] = { {"domjobabort", cmdDomjobabort, opts_domjobabort, info_domjobabort, 0}, {"domjobinfo", cmdDomjobinfo, opts_domjobinfo, info_domjobinfo, 0}, {"domname", cmdDomname, opts_domname, info_domname, 0}, + {"dompmsuspend", cmdDomPMSuspend, + opts_dom_pm_suspend, info_dom_pm_suspend, 0}, {"domuuid", cmdDomuuid, opts_domuuid, info_domuuid, 0}, {"domxml-from-native", cmdDomXMLFromNative, opts_domxmlfromnative, info_domxmlfromnative, 0}, diff --git a/tools/virsh.pod b/tools/virsh.pod index 6622caf3e7..4bc25bf366 100644 --- a/tools/virsh.pod +++ b/tools/virsh.pod @@ -1239,6 +1239,14 @@ Moves a domain out of the suspended state. This will allow a previously suspended domain to now be eligible for scheduling by the underlying hypervisor. +=item B I I + +Suspend a running domain into one of these states (possible I +values): + mem equivallent of S3 ACPI state + disk equivallent of S4 ACPI state + hybrid RAM is saved to disk but not powered off + =item B I Output the device used for the TTY console of the domain. If the information