[libvirt] [RFC v2] Export KVM Host Power Management capabilities

Srivatsa S. Bhat srivatsa.bhat at linux.vnet.ibm.com
Fri Aug 5 11:54:13 UTC 2011


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 host does not support any power management feature,
then the XML will not contain the <power_management> tag.

The initial discussion about this patch was done in [1]. And the choice
to name the new tag as "power_management" was discussed in [2].

Please let me know your comments and feedback.

References:
----------
[1] Exporting KVM host power saving capabilities through libvirt
    http://thread.gmane.org/gmane.comp.emulators.libvirt/40886

[2] http://article.gmane.org/gmane.comp.emulators.libvirt/41688

Signed-off-by: Srivatsa S. Bhat <srivatsa.bhat at linux.vnet.ibm.com>
---

 src/conf/capabilities.c      |   34 +++++++++++++++++++++++++++
 src/conf/capabilities.h      |    7 ++++++
 src/libvirt_private.syms     |    2 ++
 src/qemu/qemu_capabilities.c |   10 ++++++++
 src/util/util.c              |   52 ++++++++++++++++++++++++++++++++++++++++++
 src/util/util.h              |    7 ++++++
 6 files changed, 112 insertions(+), 0 deletions(-)

diff --git a/src/conf/capabilities.c b/src/conf/capabilities.c
index 2f243ae..94423dc 100644
--- a/src/conf/capabilities.c
+++ b/src/conf/capabilities.c
@@ -166,6 +166,10 @@ virCapabilitiesFree(virCapsPtr caps) {
 
     virCapabilitiesFreeNUMAInfo(caps);
 
+    for(i = 0; i < caps->host.npowerMgmt ; i++)
+        VIR_FREE(caps->host.powerMgmt[i]);
+    VIR_FREE(caps->host.powerMgmt);
+
     for (i = 0 ; i < caps->host.nmigrateTrans ; i++)
         VIR_FREE(caps->host.migrateTrans[i]);
     VIR_FREE(caps->host.migrateTrans);
@@ -201,6 +205,27 @@ virCapabilitiesAddHostFeature(virCapsPtr caps,
     return 0;
 }
 
+/**
+ * virCapabilitiesAddHostPowerManagement:
+ * @caps: capabilities to extend
+ * @name: name of power management feature
+ *
+ * Registers a new host power management feature, eg: 'S3' or 'S4'
+ */
+int
+virCapabilitiesAddHostPowerManagement(virCapsPtr caps,
+                                      const char *name)
+{
+    if(VIR_RESIZE_N(caps->host.powerMgmt, caps->host.npowerMgmt_max,
+                   caps->host.npowerMgmt, 1) < 0)
+        return -1;
+
+    if((caps->host.powerMgmt[caps->host.npowerMgmt] = strdup(name)) == NULL)
+        return -1;
+    caps->host.npowerMgmt++;
+
+    return 0;
+}
 
 /**
  * virCapabilitiesAddHostMigrateTransport:
@@ -686,6 +711,15 @@ virCapabilitiesFormatXML(virCapsPtr caps)
 
     virBufferAddLit(&xml, "    </cpu>\n");
 
+    if(caps->host.npowerMgmt) {
+        virBufferAddLit(&xml, "    <power_management>\n");
+        for (i = 0; i < caps->host.npowerMgmt ; i++) {
+            virBufferAsprintf(&xml, "      <%s/>\n",
+                              caps->host.powerMgmt[i]);
+        }
+        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 e2fa1d6..eb6e561 100644
--- a/src/conf/capabilities.h
+++ b/src/conf/capabilities.h
@@ -105,6 +105,9 @@ struct _virCapsHost {
     size_t nfeatures;
     size_t nfeatures_max;
     char **features;
+    size_t npowerMgmt;
+    size_t npowerMgmt_max;
+    char **powerMgmt;
     int offlineMigrate;
     int liveMigrate;
     size_t nmigrateTrans;
@@ -186,6 +189,10 @@ virCapabilitiesAddHostFeature(virCapsPtr caps,
                               const char *name);
 
 extern int
+virCapabilitiesAddHostPowerManagement(virCapsPtr caps,
+                                      const char *name);
+
+extern int
 virCapabilitiesAddHostMigrateTransport(virCapsPtr caps,
                                        const char *name);
 
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 830222b..5754fdd 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -41,6 +41,7 @@ virCapabilitiesAddGuestFeature;
 virCapabilitiesAddHostFeature;
 virCapabilitiesAddHostMigrateTransport;
 virCapabilitiesAddHostNUMACell;
+virCapabilitiesAddHostPowerManagement;
 virCapabilitiesAllocMachines;
 virCapabilitiesDefaultGuestArch;
 virCapabilitiesDefaultGuestEmulator;
@@ -1025,6 +1026,7 @@ safezero;
 virArgvToString;
 virAsprintf;
 virBuildPathInternal;
+virCheckPMCapability;
 virDirCreate;
 virEmitXMLWarning;
 virEnumFromString;
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index 3f36212..6e969a7 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -824,6 +824,16 @@ virCapsPtr qemuCapsInit(virCapsPtr old_caps)
         old_caps->host.cpu = NULL;
     }
 
+    /* Add the power management features of the host */
+
+    /* Check for Suspend-to-RAM support (S3) */
+    if(virCheckPMCapability(HOST_PM_S3) == 0)
+        virCapabilitiesAddHostPowerManagement(caps, "S3");
+
+    /* Check for Suspend-to-Disk support (S4) */
+    if(virCheckPMCapability(HOST_PM_S4) == 0)
+        virCapabilitiesAddHostPowerManagement(caps, "S4");
+
     virCapabilitiesAddHostMigrateTransport(caps,
                                            "tcp");
 
diff --git a/src/util/util.c b/src/util/util.c
index 03a9e1a..9893597 100644
--- a/src/util/util.c
+++ b/src/util/util.c
@@ -2641,3 +2641,55 @@ or other application using the libvirt API.\n\
 
     return 0;
 }
+
+/**
+ * Check the Power Management Capabilities of the host system.
+ * The script 'pm-is-supported' (from the pm-utils package) is run
+ * to find out if the capability is supported by the host.
+ *
+ * @capability: capability to check for
+ * HOST_PM_S3: Check for Suspend-to-RAM support
+ * HOST_PM_S4: Check for Suspend-to-Disk support
+ *
+ * Returns 0 if supported, -1 if not supported.
+ */
+int
+virCheckPMCapability(int capability)
+{
+
+    char *path = NULL;
+    int status = -1, ret = -1;
+    virCommandPtr cmd;
+
+    if((path = virFindFileInPath("pm-is-supported")) == NULL)
+        return -1;
+
+    cmd = virCommandNew(path);
+    switch(capability) {
+    case HOST_PM_S3:
+        /* Check support for suspend (S3) */
+        virCommandAddArg(cmd, "--suspend");
+        break;
+
+    case HOST_PM_S4:
+        /* Check support for hibernation (S4) */
+        virCommandAddArg(cmd, "--hibernate");
+        break;
+
+    default:
+        goto cleanup;
+    }
+
+    if(virCommandRun(cmd, &status) < 0)
+        goto cleanup;
+
+    /* Check return code of command == 0 for success */
+    if(status == 0)
+        ret = 0;
+
+cleanup:
+    virCommandFree(cmd);
+    VIR_FREE(path);
+    return ret;
+}
+
diff --git a/src/util/util.h b/src/util/util.h
index af8b15d..c428eb4 100644
--- a/src/util/util.h
+++ b/src/util/util.h
@@ -272,4 +272,11 @@ bool virIsDevMapperDevice(const char *devname) 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 */
+# define HOST_PM_S3          1    /* Suspend-to-RAM */
+# define HOST_PM_S4          2    /* Suspend-to-Disk */
+
+int virCheckPMCapability(int capability);
+
 #endif /* __VIR_UTIL_H__ */




More information about the libvir-list mailing list