On Wed, Nov 09, 2011 at 04:38:02PM +0530, Srivatsa S. Bhat wrote:
This patch exports KVM Host Power Management capabilities as XML so that higher-level systems management software can make use of these features available in the host.
The script "pm-is-supported" (from pm-utils package) is run to discover if Suspend-to-RAM (S3) or Suspend-to-Disk (S4) is supported by the host. If either of them are supported, then a new tag "<power_management>" is introduced in the XML under the <host> tag.
Eg: When the host supports both S3 and S4, the XML looks like this:
<capabilities>
<host> <uuid>dc699581-48a2-11cb-b8a8-9a0265a79bbe</uuid> <cpu> <arch>i686</arch> <model>coreduo</model> <vendor>Intel</vendor> <topology sockets='1' cores='2' threads='1'/> <feature name='xtpr'/> <feature name='tm2'/> <feature name='est'/> <feature name='vmx'/> <feature name='pbe'/> <feature name='tm'/> <feature name='ht'/> <feature name='ss'/> <feature name='acpi'/> <feature name='ds'/> </cpu> <power_management> <<<=== New host power management features <S3/> <S4/> </power_management> <migration_features> <live/> <uri_transports> <uri_transport>tcp</uri_transport> </uri_transports> </migration_features> </host> . . .
However in case the query to check for power management features succeeded, but the host does not support any such feature, then the XML will contain an empty <power_management/> tag. In the event that the PM query itself failed, the XML will not contain any "power_management" tag.
To use this, new APIs could be implemented in libvirt to exploit power management features such as S3/S4. This was discussed in [1] and [2].
Changelog: --------- This version v5: Some redundant error messages were removed and the code was streamlined.
v4: http://www.redhat.com/archives/libvir-list/2011-August/msg00316.html v3: http://www.redhat.com/archives/libvir-list/2011-August/msg00282.html v2: http://www.redhat.com/archives/libvir-list/2011-August/msg00238.html v1: http://thread.gmane.org/gmane.comp.emulators.libvirt/40886
References: ---------- [1] http://www.redhat.com/archives/libvir-list/2011-August/msg00248.html [2] http://www.redhat.com/archives/libvir-list/2011-August/msg00302.html
Signed-off-by: Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com> [...] index 0a63a1c..eac1d02 100644 --- a/docs/schemas/capability.rng +++ b/docs/schemas/capability.rng @@ -35,6 +35,9 @@ </optional> </element> <optional> + <ref name='power_management'/> + </optional> + <optional> <ref name='migration'/> </optional> <optional> @@ -105,6 +108,21 @@ </zeroOrMore> </define>
+ <define name='power_management'> + <element name='power_management'>
Seems to me you don't care about S3 and S4 order so <interleave>
+ <optional> + <element name='S3'> + <empty/> + </element> + </optional> + <optional> + <element name='S4'> + <empty/> + </element> + </optional>
</interleave> should be added, but that's minor.
+ </element> + </define> + [...] diff --git a/libvirt.spec.in b/libvirt.spec.in index c74b0ea..23487e3 100644 --- a/libvirt.spec.in +++ b/libvirt.spec.in @@ -493,6 +493,8 @@ Requires: nc Requires: gettext # Needed by virt-pki-validate script. Requires: gnutls-utils +# Needed for probing the power management features of the host. +Requires: pm-utils
Okay that seems present even on RHEL-5
%if %{with_sasl} Requires: cyrus-sasl # Not technically required, but makes 'out-of-box' config diff --git a/src/conf/capabilities.c b/src/conf/capabilities.c index 40e2976..87b60b0 100644 --- a/src/conf/capabilities.c +++ b/src/conf/capabilities.c @@ -29,6 +29,13 @@ #include "util.h" #include "uuid.h" #include "cpu_conf.h" +#include "virterror_internal.h" + + +#define VIR_FROM_THIS VIR_FROM_CAPABILITIES + +VIR_ENUM_IMPL(virHostPMCapability, VIR_HOST_PM_LAST, + "S3", "S4")
/** * virCapabilitiesNew: @@ -201,7 +208,6 @@ virCapabilitiesAddHostFeature(virCapsPtr caps, return 0; }
- /** * virCapabilitiesAddHostMigrateTransport: * @caps: capabilities to extend @@ -687,6 +693,25 @@ virCapabilitiesFormatXML(virCapsPtr caps)
virBufferAddLit(&xml, " </cpu>\n");
+ if (caps->host.powerMgmt_valid) { + /* The PM query was successful. */ + if (caps->host.powerMgmt) { + /* The host supports some PM features. */ + unsigned int pm = caps->host.powerMgmt; + virBufferAddLit(&xml, " <power_management>\n"); + while (pm) { + int bit = ffs(pm) - 1; + virBufferAsprintf(&xml, " <%s/>\n", + virHostPMCapabilityTypeToString(bit)); + pm &= ~(1U << bit); + } + virBufferAddLit(&xml, " </power_management>\n"); + } else { + /* The host does not support any PM feature. */ + virBufferAddLit(&xml, " <power_management/>\n"); + } + } + if (caps->host.offlineMigrate) { virBufferAddLit(&xml, " <migration_features>\n"); if (caps->host.liveMigrate) diff --git a/src/conf/capabilities.h b/src/conf/capabilities.h index dd4a827..148c7cc 100644 --- a/src/conf/capabilities.h +++ b/src/conf/capabilities.h @@ -105,6 +105,10 @@ struct _virCapsHost { size_t nfeatures; size_t nfeatures_max; char **features; + bool powerMgmt_valid; + unsigned int powerMgmt; /* Bitmask of the PM capabilities. + * See enum virHostPMCapability. + */ int offlineMigrate; int liveMigrate; size_t nmigrateTrans; diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 6a1562e..4d366d4 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1128,6 +1128,7 @@ virFormatMacAddr; virGenerateMacAddr; virGetGroupID; virGetHostname; +virGetPMCapabilities; virGetUserDirectory; virGetUserID; virGetUserName; diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 26a7f11..e1cc760 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -848,6 +848,13 @@ virCapsPtr qemuCapsInit(virCapsPtr old_caps) old_caps->host.cpu = NULL; }
+ /* Add the power management features of the host */ + + if (virGetPMCapabilities(&caps->host.powerMgmt) < 0) + VIR_WARN("Failed to get host power management capabilities"); + else + caps->host.powerMgmt_valid = true; /* The PM query succeeded. */ + virCapabilitiesAddHostMigrateTransport(caps, "tcp");
I would probably explicitely set caps->host.powerMgmt_valid to false if that failed instead of relying on "false" being 0 ...
diff --git a/src/util/util.c b/src/util/util.c index 959c224..6f0f84a 100644 --- a/src/util/util.c +++ b/src/util/util.c @@ -2607,3 +2607,54 @@ or other application using the libvirt API.\n\
return 0; } + +/** + * Get the Power Management Capabilities of the host system. + * The script 'pm-is-supported' (from the pm-utils package) is run + * to find out all the power management features supported by the host, + * such as Suspend-to-RAM (S3) and Suspend-to-Disk (S4). + * + * @bitmask: Pointer to the bitmask which will be set appropriately to + * indicate all the supported host power management features. + * + * Returns 0 if the query was successful, -1 upon failure. + */ +int +virGetPMCapabilities(unsigned int *bitmask) +{ + int ret = -1; + int status; + virCommandPtr cmd; + + *bitmask = 0; + + /* Check support for Suspend-to-RAM (S3) */ + cmd = virCommandNewArgList("pm-is-supported", "--suspend", NULL); + if (virCommandRun(cmd, &status) < 0) + goto cleanup; + + /* Check return code of command == 0 for success + * (i.e., the PM capability is supported) + */ + if (status == 0) + *bitmask |= 1U << VIR_HOST_PM_S3; + virCommandFree(cmd); + + /* Check support for Suspend-to-Disk (S4) */ + cmd = virCommandNewArgList("pm-is-supported", "--hibernate", NULL); + if (virCommandRun(cmd, &status) < 0) + goto cleanup; + + /* Check return code of command == 0 for success + * (i.e., the PM capability is supported) + */ + if (status == 0) + *bitmask |= 1U << VIR_HOST_PM_S4; + + ret = 0; + +cleanup: + virCommandFree(cmd); + return ret; +} + diff --git a/src/util/util.h b/src/util/util.h index d8176a8..b1c4847 100644 --- a/src/util/util.h +++ b/src/util/util.h @@ -258,4 +258,18 @@ bool virIsDevMapperDevice(const char *dev_name) ATTRIBUTE_NONNULL(1); int virEmitXMLWarning(int fd, const char *name, const char *cmd) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3); + +/* Power Management Capabilities of the host system */ + +enum virHostPMCapability { + VIR_HOST_PM_S3, /* Suspend-to-RAM */ + VIR_HOST_PM_S4, /* Suspend-to-Disk */ + + VIR_HOST_PM_LAST +}; + +VIR_ENUM_DECL(virHostPMCapability) + +int virGetPMCapabilities(unsigned int *); + #endif /* __VIR_UTIL_H__ */ diff --git a/src/util/virterror.c b/src/util/virterror.c index 5006fa2..44a276a 100644 --- a/src/util/virterror.c +++ b/src/util/virterror.c @@ -175,6 +175,9 @@ static const char *virErrorDomainName(virErrorDomain domain) { case VIR_FROM_HYPERV: dom = "Hyper-V "; break; + case VIR_FROM_CAPABILITIES: + dom = "Capabilities "; + break; } return(dom); }
ACK, I made the couple of modifications above, cleaned up "make syntax-check" and fixed a small issue in applying the patch to util.h, then commited it, thanks a lot ! Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/