[libvirt] [PATCH 0/3] Introduce virDomainPMWakeup API

This is counterpart for virDomainPMSuspendForDuration API which we have already in. It allows user to wake up guest from S3 state. Michal Privoznik (3): Introduce virDomainPMWakeup API virsh: Expose virDomainPMWakeup qemu: Implement virDomainPMWakeup API include/libvirt/libvirt.h.in | 2 + src/driver.h | 4 +++ src/libvirt.c | 50 ++++++++++++++++++++++++++++++++++++++ src/libvirt_public.syms | 1 + src/qemu/qemu_driver.c | 54 ++++++++++++++++++++++++++++++++++++++++++ src/qemu/qemu_monitor.c | 20 +++++++++++++++ src/qemu/qemu_monitor.h | 2 + src/qemu/qemu_monitor_json.c | 21 ++++++++++++++++ src/qemu/qemu_monitor_json.h | 2 + src/qemu/qemu_monitor_text.c | 26 ++++++++++++++++++++ src/qemu/qemu_monitor_text.h | 2 + src/remote/remote_driver.c | 1 + src/remote/remote_protocol.x | 8 +++++- src/remote_protocol-structs | 5 ++++ tools/virsh.c | 46 +++++++++++++++++++++++++++++++++++ 15 files changed, 243 insertions(+), 1 deletions(-) -- 1.7.3.4

This API allows a domain which previously called virDomainPMSuspendForDuration() to be woken up. --- include/libvirt/libvirt.h.in | 2 + src/driver.h | 4 +++ src/libvirt.c | 50 ++++++++++++++++++++++++++++++++++++++++++ src/libvirt_public.syms | 1 + src/remote/remote_driver.c | 1 + src/remote/remote_protocol.x | 8 ++++++- src/remote_protocol-structs | 5 ++++ 7 files changed, 70 insertions(+), 1 deletions(-) diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index 798ab07..7ef37c8 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -1251,6 +1251,8 @@ int virDomainPMSuspendForDuration (virDomainPtr domain, unsigned int target, unsigned long long duration, unsigned int flags); +int virDomainPMWakeup (virDomainPtr domain, + unsigned int flags); /* * Domain save/restore */ diff --git a/src/driver.h b/src/driver.h index d27fa99..e5b3763 100644 --- a/src/driver.h +++ b/src/driver.h @@ -125,6 +125,9 @@ typedef int unsigned long long duration, unsigned int flags); typedef int + (*virDrvDomainPMWakeup) (virDomainPtr domain, + unsigned int flags); +typedef int (*virDrvDomainShutdown) (virDomainPtr domain); typedef int (*virDrvDomainReboot) (virDomainPtr domain, @@ -868,6 +871,7 @@ struct _virDriver { virDrvDomainLookupByName domainLookupByName; virDrvDomainSuspend domainSuspend; virDrvDomainPMSuspendForDuration domainPMSuspendForDuration; + virDrvDomainPMWakeup domainPMWakeup; virDrvDomainResume domainResume; virDrvDomainShutdown domainShutdown; virDrvDomainShutdownFlags domainShutdownFlags; diff --git a/src/libvirt.c b/src/libvirt.c index a55d823..3c81a06 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -2515,6 +2515,56 @@ error: } /** + * virDomainPMWakeup: + * @dom: a domain object + * @flags: extra flags; not used yet, so callers should always pass 0 + * + * Inject a wakeup into the guest that previously used + * virDomainPMSuspendForDuration, rather than waiting for the + * previously requested duration (if any) to elapse. + * + * Returns: 0 on success, + * -1 on failure. + */ +int +virDomainPMWakeup(virDomainPtr dom, + unsigned int flags) +{ + virConnectPtr conn; + + VIR_DOMAIN_DEBUG(dom, "flags=%x", flags); + + virResetLastError(); + + if (!VIR_IS_CONNECTED_DOMAIN(dom)) { + virLibDomainError(VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + virDispatchError(NULL); + return -1; + } + + conn = dom->conn; + + if (conn->flags & VIR_CONNECT_RO) { + virLibConnError(VIR_ERR_OPERATION_DENIED, __FUNCTION__); + goto error; + } + + if (conn->driver->domainPMWakeup) { + int ret; + ret = conn->driver->domainPMWakeup(dom, flags); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError(VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + virDispatchError(conn); + return -1; +} + +/** * virDomainSave: * @domain: a domain object * @to: path for the output file diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms index 7622b79..88b471d 100644 --- a/src/libvirt_public.syms +++ b/src/libvirt_public.syms @@ -527,6 +527,7 @@ LIBVIRT_0.9.10 { virDomainShutdownFlags; virStorageVolResize; virStorageVolWipePattern; + virDomainPMWakeup; } LIBVIRT_0.9.9; # .... define new API here using predicted next version number .... diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index 2dacb70..83e52b2 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -4922,6 +4922,7 @@ static virDriver remote_driver = { .domainGetDiskErrors = remoteDomainGetDiskErrors, /* 0.9.10 */ .domainSetMetadata = remoteDomainSetMetadata, /* 0.9.10 */ .domainGetMetadata = remoteDomainGetMetadata, /* 0.9.10 */ + .domainPMWakeup = remoteDomainPMWakeup, /* 0.9.10 */ }; static virNetworkDriver network_driver = { diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index 59774b2..b950103 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -759,6 +759,11 @@ struct remote_domain_pm_suspend_for_duration_args { unsigned int flags; }; +struct remote_domain_pm_wakeup_args { + remote_nonnull_domain dom; + unsigned int flags; +}; + struct remote_domain_resume_args { remote_nonnull_domain dom; }; @@ -2759,7 +2764,8 @@ enum remote_procedure { REMOTE_PROC_DOMAIN_GET_DISK_ERRORS = 263, /* skipgen skipgen */ REMOTE_PROC_DOMAIN_SET_METADATA = 264, /* autogen autogen */ REMOTE_PROC_DOMAIN_GET_METADATA = 265, /* autogen autogen */ - REMOTE_PROC_DOMAIN_BLOCK_REBASE = 266 /* autogen autogen */ + REMOTE_PROC_DOMAIN_BLOCK_REBASE = 266, /* autogen autogen */ + REMOTE_PROC_DOMAIN_PM_WAKEUP = 267 /* autogen autogen */ /* * Notice how the entries are grouped in sets of 10 ? diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs index 8492bee..5a6c7dd 100644 --- a/src/remote_protocol-structs +++ b/src/remote_protocol-structs @@ -450,6 +450,10 @@ struct remote_domain_pm_suspend_for_duration_args { uint64_t duration; u_int flags; }; +struct remote_domain_pm_wakeup_args { + remote_nonnull_domain dom; + u_int flags; +}; struct remote_domain_resume_args { remote_nonnull_domain dom; }; @@ -2173,4 +2177,5 @@ enum remote_procedure { REMOTE_PROC_DOMAIN_SET_METADATA = 264, REMOTE_PROC_DOMAIN_GET_METADATA = 265, REMOTE_PROC_DOMAIN_BLOCK_REBASE = 266, + REMOTE_PROC_DOMAIN_PM_WAKEUP = 267, }; -- 1.7.3.4

On 02/10/2012 06:43 AM, Michal Privoznik wrote:
This API allows a domain which previously called virDomainPMSuspendForDuration() to be woken up. --- include/libvirt/libvirt.h.in | 2 + src/driver.h | 4 +++ src/libvirt.c | 50 ++++++++++++++++++++++++++++++++++++++++++ src/libvirt_public.syms | 1 + src/remote/remote_driver.c | 1 + src/remote/remote_protocol.x | 8 ++++++- src/remote_protocol-structs | 5 ++++ 7 files changed, 70 insertions(+), 1 deletions(-)
I don't like the thought of adding new API post-freeze without good reason, but I think this is a case of good reason - we are already committing to adding a new feature in virDomainPMSuspendForDuration, and that feature will be broken by design for 2 of its 3 targets unless we also add this counterpart. On that basis, I will review this series and request that you include them prior to 0.9.10.
+++ b/src/libvirt.c @@ -2515,6 +2515,56 @@ error: }
/** + * virDomainPMWakeup: + * @dom: a domain object + * @flags: extra flags; not used yet, so callers should always pass 0 + * + * Inject a wakeup into the guest that previously used + * virDomainPMSuspendForDuration, rather than waiting for the + * previously requested duration (if any) to elapse. + * + * Returns: 0 on success, + * -1 on failure. + */
/me remarks that this looks an awful like my first RFC for this API - thanks for taking my idea and turning it into a patch :)
+++ b/src/libvirt_public.syms @@ -527,6 +527,7 @@ LIBVIRT_0.9.10 { virDomainShutdownFlags; virStorageVolResize; virStorageVolWipePattern; + virDomainPMWakeup;
Call me OCD, but I would have sorted this right after virDomainPMSuspendForDuration.
+++ b/src/remote/remote_driver.c @@ -4922,6 +4922,7 @@ static virDriver remote_driver = { .domainGetDiskErrors = remoteDomainGetDiskErrors, /* 0.9.10 */ .domainSetMetadata = remoteDomainSetMetadata, /* 0.9.10 */ .domainGetMetadata = remoteDomainGetMetadata, /* 0.9.10 */ + .domainPMWakeup = remoteDomainPMWakeup, /* 0.9.10 */
Also, since the driver.h patch stuck it next to PMSuspend, I would have stuck this line next to the remoteDomainPMSuspendForDuration line. ACK; ordering nits are trivial. -- Eric Blake eblake@redhat.com +1-919-301-3266 Libvirt virtualization library http://libvirt.org

On 02/10/2012 11:56 AM, Eric Blake wrote:
On 02/10/2012 06:43 AM, Michal Privoznik wrote:
This API allows a domain which previously called virDomainPMSuspendForDuration() to be woken up. --- include/libvirt/libvirt.h.in | 2 + src/driver.h | 4 +++ src/libvirt.c | 50 ++++++++++++++++++++++++++++++++++++++++++ src/libvirt_public.syms | 1 + src/remote/remote_driver.c | 1 + src/remote/remote_protocol.x | 8 ++++++- src/remote_protocol-structs | 5 ++++ 7 files changed, 70 insertions(+), 1 deletions(-)
I don't like the thought of adding new API post-freeze without good reason, but I think this is a case of good reason - we are already committing to adding a new feature in virDomainPMSuspendForDuration, and that feature will be broken by design for 2 of its 3 targets unless we also add this counterpart. On that basis, I will review this series and request that you include them prior to 0.9.10.
Before you push anything, let's first consider Dave's proposal [1] of adding a fourth PM state and slightly renaming the existing virDomainPMSuspendForDuration over to a more-encompassing virDomainPMSetPowerStateForDuration - if we go that route, this new API would not be appropriate, and the qemu work in 3/3 would have be tweaked slightly. [1] https://www.redhat.com/archives/libvir-list/2012-February/msg00548.html -- Eric Blake eblake@redhat.com +1-919-301-3266 Libvirt virtualization library http://libvirt.org

--- tools/virsh.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 46 insertions(+), 0 deletions(-) diff --git a/tools/virsh.c b/tools/virsh.c index 66ba61c..4971e36 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -2436,6 +2436,50 @@ cleanup: } /* + * "dompmwakeup" command + */ + +static const vshCmdInfo info_dom_pm_wakeup[] = { + {"help", N_("wakeup a domain suspended by dompmsuspend command")}, + {"desc", N_("Wakeup a domain previously suspended " + "by dompmsuspend command.")}, + {NULL, NULL} +}; + +static const vshCmdOptDef opts_dom_pm_wakeup[] = { + {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")}, + {NULL, 0, 0, NULL} +}; +cmdDomPMWakeup(vshControl *ctl, const vshCmd *cmd) +{ + virDomainPtr dom; + const char *name; + bool ret = false; + unsigned int flags = 0; + + if (!vshConnectionUsability(ctl, ctl->conn)) + return false; + + if (!(dom = vshCommandOptDomain(ctl, cmd, &name))) + return false; + + if (virDomainPMWakeup(dom, flags) < 0) { + vshError(ctl, _("Domain %s could not be woken up"), + virDomainGetName(dom)); + goto cleanup; + } + + vshPrint(ctl, _("Domain %s successfully woken up"), + virDomainGetName(dom)); + + ret = true; + +cleanup: + virDomainFree(dom); + return ret; +} + +/* * "create" command */ static const vshCmdInfo info_create[] = { @@ -16458,6 +16502,8 @@ static const vshCmdDef domManagementCmds[] = { {"domname", cmdDomname, opts_domname, info_domname, 0}, {"dompmsuspend", cmdDomPMSuspend, opts_dom_pm_suspend, info_dom_pm_suspend, 0}, + {"dompmwakeup", cmdDomPMWakeup, + opts_dom_pm_wakeup, info_dom_pm_wakeup, 0}, {"domuuid", cmdDomuuid, opts_domuuid, info_domuuid, 0}, {"domxml-from-native", cmdDomXMLFromNative, opts_domxmlfromnative, info_domxmlfromnative, 0}, -- 1.7.3.4

On 02/10/2012 06:43 AM, Michal Privoznik wrote:
--- tools/virsh.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 46 insertions(+), 0 deletions(-)
Missing documentation. I can't ack without at least something in virsh.pod. But the code looks correct. -- Eric Blake eblake@redhat.com +1-919-301-3266 Libvirt virtualization library http://libvirt.org

--- src/qemu/qemu_driver.c | 54 ++++++++++++++++++++++++++++++++++++++++++ src/qemu/qemu_monitor.c | 20 +++++++++++++++ src/qemu/qemu_monitor.h | 2 + src/qemu/qemu_monitor_json.c | 21 ++++++++++++++++ src/qemu/qemu_monitor_json.h | 2 + src/qemu/qemu_monitor_text.c | 26 ++++++++++++++++++++ src/qemu/qemu_monitor_text.h | 2 + 7 files changed, 127 insertions(+), 0 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 160cb37..40b0664 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -12041,6 +12041,59 @@ cleanup: return ret; } +static int qemuDomainPMWakeup(virDomainPtr dom, + unsigned int flags) +{ + struct qemud_driver *driver = dom->conn->privateData; + virDomainObjPtr vm; + int ret = -1; + qemuDomainObjPrivatePtr priv; + + virCheckFlags(0, -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; + } + + if (!virDomainObjIsActive(vm)) { + qemuReportError(VIR_ERR_OPERATION_INVALID, + "%s", _("domain is not running")); + 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; + } + + priv = vm->privateData; + + qemuDomainObjEnterMonitor(driver, vm); + ret = qemuMonitorSystemWakeup(priv->mon); + qemuDomainObjExitMonitor(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", @@ -12198,6 +12251,7 @@ static virDriver qemuDriver = { .domainGetDiskErrors = qemuDomainGetDiskErrors, /* 0.9.10 */ .domainSetMetadata = qemuDomainSetMetadata, /* 0.9.10 */ .domainGetMetadata = qemuDomainGetMetadata, /* 0.9.10 */ + .domainPMWakeup = qemuDomainPMWakeup, /* 0.9.10 */ }; diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index 7872e3d..77ae9c1 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -2785,3 +2785,23 @@ int qemuMonitorOpenGraphics(qemuMonitorPtr mon, return ret; } + +int qemuMonitorSystemWakeup(qemuMonitorPtr mon) +{ + int ret = -1; + + VIR_DEBUG("mon=%p", mon); + + if (!mon) { + qemuReportError(VIR_ERR_INVALID_ARG, "%s", + _("monitor must not be NULL")); + return -1; + } + + if (mon->json) + ret = qemuMonitorJSONSystemWakeup(mon); + else + ret = qemuMonitorTextSystemWakeup(mon); + + return ret; +} diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index 5945d3e..29f455b 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -534,6 +534,8 @@ int qemuMonitorGetBlockIoThrottle(qemuMonitorPtr mon, const char *device, virDomainBlockIoTuneInfoPtr reply); +int qemuMonitorSystemWakeup(qemuMonitorPtr mon); + /** * When running two dd process and using <> redirection, we need a * shell that will not truncate files. These two strings serve that diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index b0ae570..21f8aa5 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -3489,3 +3489,24 @@ int qemuMonitorJSONGetBlockIoThrottle(qemuMonitorPtr mon, virJSONValueFree(result); return ret; } + +int qemuMonitorJSONSystemWakeup(qemuMonitorPtr mon) +{ + int ret = -1; + virJSONValuePtr cmd = NULL; + virJSONValuePtr reply = NULL; + + cmd = qemuMonitorJSONMakeCommand("system_wakeup", NULL); + if (!cmd) { + return -1; + } + + ret = qemuMonitorJSONCommand(mon, cmd, &reply); + + if (ret == 0) + ret = qemuMonitorJSONCheckError(cmd, reply); + + virJSONValueFree(cmd); + virJSONValueFree(reply); + return ret; +} diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h index d221e59..3d78890 100644 --- a/src/qemu/qemu_monitor_json.h +++ b/src/qemu/qemu_monitor_json.h @@ -264,4 +264,6 @@ int qemuMonitorJSONGetBlockIoThrottle(qemuMonitorPtr mon, const char *device, virDomainBlockIoTuneInfoPtr reply); +int qemuMonitorJSONSystemWakeup(qemuMonitorPtr mon); + #endif /* QEMU_MONITOR_JSON_H */ diff --git a/src/qemu/qemu_monitor_text.c b/src/qemu/qemu_monitor_text.c index f051a86..0314d4f 100644 --- a/src/qemu/qemu_monitor_text.c +++ b/src/qemu/qemu_monitor_text.c @@ -3633,3 +3633,29 @@ cleanup: VIR_FREE(result); return ret; } + + +int qemuMonitorTextSystemWakeup(qemuMonitorPtr mon) +{ + char *result = NULL; + int ret = -1; + const char *cmd_name = "system_wakeup"; + + if (qemuMonitorHMPCommand(mon, cmd_name, &result) < 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, + "%s", _("cannot run monitor command")); + goto cleanup; + } + + if (qemuMonitorTextCommandNotFound(cmd_name, result)) { + qemuReportError(VIR_ERR_OPERATION_INVALID, + _("Command '%s' is not found"), cmd_name); + goto cleanup; + } + + ret = 0; + +cleanup: + VIR_FREE(result); + return ret; +} diff --git a/src/qemu/qemu_monitor_text.h b/src/qemu/qemu_monitor_text.h index 050c30e..84682f1 100644 --- a/src/qemu/qemu_monitor_text.h +++ b/src/qemu/qemu_monitor_text.h @@ -256,4 +256,6 @@ int qemuMonitorTextGetBlockIoThrottle(qemuMonitorPtr mon, const char *device, virDomainBlockIoTuneInfoPtr reply); +int qemuMonitorTextSystemWakeup(qemuMonitorPtr mon); + #endif /* QEMU_MONITOR_TEXT_H */ -- 1.7.3.4

On 02/10/2012 06:43 AM, Michal Privoznik wrote: Pretty light on the commit message.
--- src/qemu/qemu_driver.c | 54 ++++++++++++++++++++++++++++++++++++++++++ src/qemu/qemu_monitor.c | 20 +++++++++++++++ src/qemu/qemu_monitor.h | 2 + src/qemu/qemu_monitor_json.c | 21 ++++++++++++++++ src/qemu/qemu_monitor_json.h | 2 + src/qemu/qemu_monitor_text.c | 26 ++++++++++++++++++++ src/qemu/qemu_monitor_text.h | 2 +
I wouldn't bother touching qemu_monitor_text.[ch], but make this JSON-only. Why? Because this is a qemu-1.1 feature; and because you can't pmsuspend the guest without guest agent, which is JSON-only. The only reason to support a text command is if we are ever targetting an older qemu (pre-0.15) where json did not exist, or where text was more featured than json.
+ 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; + }
No need to check for isactive here,
+ + 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;
as well as here. The second one is mandatory (since obtaining the job temporarily drops lock, during which time the guest can change state), and the first one would only avoid obtaining the job just to still end in error, but penalizes the common case of no error.
+ } + + priv = vm->privateData; + + qemuDomainObjEnterMonitor(driver, vm); + ret = qemuMonitorSystemWakeup(priv->mon);
Should we be checking for QEMU_CAPS_WAKEUP here, and issuing a nicer error message if the command is not present?
+ qemuDomainObjExitMonitor(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", @@ -12198,6 +12251,7 @@ static virDriver qemuDriver = { .domainGetDiskErrors = qemuDomainGetDiskErrors, /* 0.9.10 */ .domainSetMetadata = qemuDomainSetMetadata, /* 0.9.10 */ .domainGetMetadata = qemuDomainGetMetadata, /* 0.9.10 */ + .domainPMWakeup = qemuDomainPMWakeup, /* 0.9.10 */
Minor, but I'd sort this next to .domainPMSuspendForDuration.
};
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index 7872e3d..77ae9c1 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -2785,3 +2785,23 @@ int qemuMonitorOpenGraphics(qemuMonitorPtr mon,
return ret; } + +int qemuMonitorSystemWakeup(qemuMonitorPtr mon) +{ + int ret = -1; + + VIR_DEBUG("mon=%p", mon); + + if (!mon) { + qemuReportError(VIR_ERR_INVALID_ARG, "%s", + _("monitor must not be NULL")); + return -1; + } + + if (mon->json) + ret = qemuMonitorJSONSystemWakeup(mon); + else + ret = qemuMonitorTextSystemWakeup(mon);
Error out if not json. -- Eric Blake eblake@redhat.com +1-919-301-3266 Libvirt virtualization library http://libvirt.org
participants (2)
-
Eric Blake
-
Michal Privoznik