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(a)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(a)veillard.com | Rpmfind RPM search engine
http://rpmfind.net/
http://veillard.com/ | virtualization library
http://libvirt.org/