diff --git a/AUTHORS b/AUTHORS
index 272a82869e..9d5f8b52f6 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -206,6 +206,7 @@ Patches have also been contributed by:
Eli Qiao
Michael Wood
Bharata B Rao
+ Srivatsa S. Bhat
[....send patches to get your name here....]
diff --git a/docs/formatcaps.html.in b/docs/formatcaps.html.in
index a4297cefa1..ce6f9a644a 100644
--- a/docs/formatcaps.html.in
+++ b/docs/formatcaps.html.in
@@ -28,6 +28,10 @@ BIOS you will see
<feature name='xtpr'/>
...
</cpu>
+ <power_management>
+ <S3/>
+ <S4/>
+ <power_management/>
</host>
<!-- xen-3.0-x86_64 -->
@@ -61,11 +65,16 @@ BIOS you will see
...
</capabilities>
The first block (in red) indicates the host hardware capabilities, currently
-it is limited to the CPU properties but other information may be available,
-it shows the CPU architecture, topology, model name, and additional features
-which are not included in the model but the CPU provides them. Features of the
-chip are shown within the feature block (the block is similar to what you will
-find in a Xen fully virtualized domain description).
+it is limited to the CPU properties and the power management features of
+the host platform, but other information may be available, it shows the CPU architecture,
+topology, model name, and additional features which are not included in the model but the
+CPU provides them. Features of the chip are shown within the feature block (the block is
+similar to what you will find in a Xen fully virtualized domain description). Further,
+the power management features supported by the host are shown, such as Suspend-to-RAM (S3)
+and Suspend-to-Disk (S4). In case the query for power management features succeeded but the
+host does not support any such feature, then an empty <power_management/>
+tag will be shown. Otherwise, if the query itself failed, no such tag will
+be displayed (i.e., there will not be any power_management block or empty tag in the XML).
The second block (in blue) indicates the paravirtualization support of the
Xen support, you will see the os_type of xen to indicate a paravirtual
kernel, then architecture information and potential features.
diff --git a/docs/schemas/capability.rng b/docs/schemas/capability.rng
index 0a63a1c6a1..645769e330 100644
--- a/docs/schemas/capability.rng
+++ b/docs/schemas/capability.rng
@@ -34,6 +34,9 @@
+
+
+
@@ -105,6 +108,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h
index a8549b784f..7063ef6a8e 100644
--- a/include/libvirt/virterror.h
+++ b/include/libvirt/virterror.h
@@ -84,6 +84,7 @@ typedef enum {
VIR_FROM_LIBXL = 41, /* Error from libxenlight driver */
VIR_FROM_LOCKING = 42, /* Error from lock manager */
VIR_FROM_HYPERV = 43, /* Error from Hyper-V driver */
+ VIR_FROM_CAPABILITIES = 44, /* Error from capabilities */
} virErrorDomain;
diff --git a/libvirt.spec.in b/libvirt.spec.in
index ce541a7cc8..f61a243acb 100644
--- a/libvirt.spec.in
+++ b/libvirt.spec.in
@@ -506,6 +506,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
%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 40e297678a..87b60b0c3e 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, " \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, " \n");
+ while (pm) {
+ int bit = ffs(pm) - 1;
+ virBufferAsprintf(&xml, " <%s/>\n",
+ virHostPMCapabilityTypeToString(bit));
+ pm &= ~(1U << bit);
+ }
+ virBufferAddLit(&xml, " \n");
+ } else {
+ /* The host does not support any PM feature. */
+ virBufferAddLit(&xml, " \n");
+ }
+ }
+
if (caps->host.offlineMigrate) {
virBufferAddLit(&xml, " \n");
if (caps->host.liveMigrate)
diff --git a/src/conf/capabilities.h b/src/conf/capabilities.h
index dd4a8279b3..148c7cc939 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 e5784f579c..2cf50d30b0 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1094,6 +1094,7 @@ virFormatMacAddr;
virGenerateMacAddr;
virGetGroupID;
virGetHostname;
+virGetPMCapabilities;
virGetUserDirectory;
virGetUserID;
virGetUserName;
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index 26a7f11a67..c5fe41d9a8 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -848,6 +848,14 @@ 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");
+ caps->host.powerMgmt_valid = false;
+ } else
+ caps->host.powerMgmt_valid = true; /* The PM query succeeded. */
+
virCapabilitiesAddHostMigrateTransport(caps,
"tcp");
diff --git a/src/util/util.c b/src/util/util.c
index 9ecfa9dee8..ce697fb7b4 100644
--- a/src/util/util.c
+++ b/src/util/util.c
@@ -2621,3 +2621,53 @@ virTypedParameterArrayClear(virTypedParameterPtr params, int nparams)
VIR_FREE(params[i].value.s);
}
}
+
+/**
+ * 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 3295ce8b55..5afcf58dcc 100644
--- a/src/util/util.h
+++ b/src/util/util.h
@@ -260,4 +260,18 @@ int virEmitXMLWarning(int fd,
const char *cmd) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
void virTypedParameterArrayClear(virTypedParameterPtr params, int nparams);
+
+/* 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 5006fa27ed..44a276a9db 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);
}