There is a new <pm/> element implemented that can control what ACPI
sleeping states will be advertised by BIOS and allowed to be switched
to by libvirt. The default keeps defaults on hypervisor, otherwise
forces chosen setting.
---
docs/schemas/domaincommon.rng | 33 ++++++++++++++++++++++++++++++
src/conf/domain_conf.c | 44 +++++++++++++++++++++++++++++++++++++++++
src/conf/domain_conf.h | 15 ++++++++++++++
src/libvirt_private.syms | 2 +
4 files changed, 94 insertions(+), 0 deletions(-)
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index c85d763..d0c6d47 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -53,6 +53,9 @@
<ref name="features"/>
<ref name="termination"/>
<optional>
+ <ref name="pm"/>
+ </optional>
+ <optional>
<ref name="devices"/>
</optional>
<optional>
@@ -2192,6 +2195,36 @@
</choice>
</define>
<!--
+ Control ACPI sleep states (dis)allowed for the domain
+ For each of the states the following rules apply:
+ on: the state will be forcefully enabled
+ off: the state will be forcefully disabled
+ not specified: hypervisor will be left to decide its defaults
+ -->
+ <define name="pm">
+ <element name="pm">
+ <interleave>
+ <optional>
+ <attribute name="suspend-to-mem">
+ <ref name="suspendChoices"/>
+ </attribute>
+ </optional>
+ <optional>
+ <attribute name="suspend-to-disk">
+ <ref name="suspendChoices"/>
+ </attribute>
+ </optional>
+ </interleave>
+ <empty/>
+ </element>
+ </define>
+ <define name="suspendChoices">
+ <choice>
+ <value>on</value>
+ <value>off</value>
+ </choice>
+ </define>
+ <!--
Specific setup for a qemu emulated character device. Note: this
definition doesn't fully specify the constraints on this node.
-->
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index d8c0969..04e0be5 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -124,6 +124,11 @@ VIR_ENUM_IMPL(virDomainLifecycleCrash,
VIR_DOMAIN_LIFECYCLE_CRASH_LAST,
"coredump-destroy",
"coredump-restart")
+VIR_ENUM_IMPL(virDomainPMState, VIR_DOMAIN_PM_STATE_LAST,
+ "default",
+ "on",
+ "off")
+
VIR_ENUM_IMPL(virDomainDevice, VIR_DOMAIN_DEVICE_LAST,
"none",
"disk",
@@ -8413,6 +8418,19 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps,
virDomainLifecycleCrashTypeFromString) < 0)
goto error;
+ if (virXPathNode("./pm", ctxt)) {
+ tmp = virXPathString("string(./pm/@suspend-to-mem)", ctxt);
+ if (tmp) {
+ def->pm.s3 = virDomainPMStateTypeFromString(tmp);
+ VIR_FREE(tmp);
+ }
+ tmp = virXPathString("string(./pm/@suspend-to-disk)", ctxt);
+ if (tmp) {
+ def->pm.s4 = virDomainPMStateTypeFromString(tmp);
+ VIR_FREE(tmp);
+ }
+ }
+
tmp = virXPathString("string(./clock/@offset)", ctxt);
if (tmp) {
if ((def->clock.offset = virDomainClockOffsetTypeFromString(tmp)) < 0) {
@@ -13092,6 +13110,32 @@ virDomainDefFormatInternal(virDomainDefPtr def,
virDomainLifecycleCrashTypeToString) < 0)
goto cleanup;
+ if (def->pm.s3 || def->pm.s4) {
+ virBufferAddLit(buf, " <pm");
+
+ if (def->pm.s3) {
+ const char *tmp = virDomainPMStateTypeToString(def->pm.s3);
+ if (!tmp) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("unexpected PM state %d"), def->pm.s3);
+ goto cleanup;
+ }
+ virBufferAsprintf(buf, " suspend-to-mem='%s'", tmp);
+ }
+
+ if (def->pm.s4) {
+ const char *tmp = virDomainPMStateTypeToString(def->pm.s4);
+ if (!tmp) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("unexpected PM state %d"), def->pm.s4);
+ goto cleanup;
+ }
+ virBufferAsprintf(buf, " suspend-to-disk='%s'", tmp);
+ }
+
+ virBufferAddLit(buf, "/>\n");
+ }
+
virBufferAddLit(buf, " <devices>\n");
virBufferEscapeString(buf, " <emulator>%s</emulator>\n",
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 3f25ad2..ecca72f 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -1373,6 +1373,14 @@ enum virDomainLifecycleCrashAction {
VIR_DOMAIN_LIFECYCLE_CRASH_LAST
};
+enum virDomainPMState {
+ VIR_DOMAIN_PM_STATE_DEFAULT = 0,
+ VIR_DOMAIN_PM_STATE_ON,
+ VIR_DOMAIN_PM_STATE_OFF,
+
+ VIR_DOMAIN_PM_STATE_LAST,
+};
+
enum virDomainBIOSUseserial {
VIR_DOMAIN_BIOS_USESERIAL_DEFAULT = 0,
VIR_DOMAIN_BIOS_USESERIAL_YES,
@@ -1619,6 +1627,12 @@ struct _virDomainDef {
int onPoweroff;
int onCrash;
+ struct {
+ /* These options are actually type of enum virDomainPMState */
+ int s3;
+ int s4;
+ } pm;
+
virDomainOSDef os;
char *emulator;
int features;
@@ -2166,6 +2180,7 @@ VIR_ENUM_DECL(virDomainBoot)
VIR_ENUM_DECL(virDomainFeature)
VIR_ENUM_DECL(virDomainLifecycle)
VIR_ENUM_DECL(virDomainLifecycleCrash)
+VIR_ENUM_DECL(virDomainPMState)
VIR_ENUM_DECL(virDomainDevice)
VIR_ENUM_DECL(virDomainDeviceAddress)
VIR_ENUM_DECL(virDomainDeviceAddressPciMulti)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 79b4a18..d8f409a 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -437,6 +437,8 @@ virDomainPausedReasonTypeFromString;
virDomainPausedReasonTypeToString;
virDomainPciRombarModeTypeFromString;
virDomainPciRombarModeTypeToString;
+virDomainPMStateTypeFromString;
+virDomainPMStateTypeToString;
virDomainRedirdevBusTypeFromString;
virDomainRedirdevBusTypeToString;
virDomainRemoveInactive;
--
1.7.8.6