
On 09.08.2012 10:26, Martin Kletzander wrote:
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(-)
As I've mentioned in one of previous series - I'd like to see documentation and XML extension in one patch as it's advised here: http://libvirt.org/api_extension.html But then again, having a separate patch within set is okay too.
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> + <!--
Let's hope we won't need any other configurable knobs for s3/s4; otherwise we should move from attributes to elements: <pm> <s3 enabled='yes'/> <s4 enabled='no'/> </pm>
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); + } + } +
vir*TypeFromString() may fail and return < 0 value. We should not silently ignore not allowed values here. NB please don't use VIR_ERR_INTERNAL_ERROR as it is not an internal error but VIR_ERR_CONFIG_UNSUPPORTED.
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) {
This is useless. Libvirt must validate its inputs (esp. those from user). Outputs are believed to be trusted - that is - once we validate input and set def->pm.s3 to one of allowed values, nobody will hop into our address space and change it. It he will anyway, it's problem.
+ 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;
Otherwise looking good. Michal