[libvirt] [PATCH RESEND v5] Export KVM Host Power Management capabilities

Srivatsa S. Bhat srivatsa.bhat at linux.vnet.ibm.com
Mon Nov 14 05:29:14 UTC 2011


On 11/09/2011 04:38 PM, 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 at linux.vnet.ibm.com>

Any suggestions/comments on this patch?
As suggested in one of the earlier versions, I have posted the follow-on
patchset to add libvirt APIs to invoke suspend/resume in-band, here:
http://www.redhat.com/archives/libvir-list/2011-November/msg00381.html

Thanks,
Srivatsa S. Bhat

> ---
> 
>  docs/formatcaps.html.in      |   19 ++++++++++++----
>  docs/schemas/capability.rng  |   18 +++++++++++++++
>  include/libvirt/virterror.h  |    1 +
>  libvirt.spec.in              |    2 ++
>  src/conf/capabilities.c      |   27 +++++++++++++++++++++-
>  src/conf/capabilities.h      |    4 +++
>  src/libvirt_private.syms     |    1 +
>  src/qemu/qemu_capabilities.c |    7 ++++++
>  src/util/util.c              |   51 ++++++++++++++++++++++++++++++++++++++++++
>  src/util/util.h              |   14 ++++++++++++
>  src/util/virterror.c         |    3 ++
>  11 files changed, 141 insertions(+), 6 deletions(-)
> 
> diff --git a/docs/formatcaps.html.in b/docs/formatcaps.html.in
> index a4297ce..ce6f9a6 100644
> --- a/docs/formatcaps.html.in
> +++ b/docs/formatcaps.html.in
> @@ -28,6 +28,10 @@ BIOS you will see</p>
>        <feature name='xtpr'/>
>        ...
>      </cpu>
> +    <power_management>
> +      <S3/>
> +      <S4/>
> +    <power_management/>
>    </host></span>
> 
>    <!-- xen-3.0-x86_64 -->
> @@ -61,11 +65,16 @@ BIOS you will see</p>
>    ...
>  </capabilities></pre>
>          <p>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).</p>
> +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).</p>
>          <p>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.</p>
> diff --git a/docs/schemas/capability.rng b/docs/schemas/capability.rng
> 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'>
> +      <optional>
> +        <element name='S3'>
> +          <empty/>
> +        </element>
> +      </optional>
> +      <optional>
> +        <element name='S4'>
> +          <empty/>
> +        </element>
> +      </optional>
> +    </element>
> +  </define>
> +
>    <define name='migration'>
>      <element name='migration_features'>
>        <optional>
> diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h
> index a8549b7..7063ef6 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 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
>  %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");
> 
> 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);
>  }
> 




More information about the libvir-list mailing list