[libvirt] [PATCH v3] Introduce --without-pm-utils to get rid of pm-is-supported dependency

This uses the dbus api of systemd to check the power management capabilities of the node. --- Diff with v2: * Fixed a few dbus call problems configure.ac | 11 +++++++++ libvirt.spec.in | 9 ++++++++ src/libvirt_private.syms | 3 +++ src/util/virnodesuspend.c | 32 +++++++++++++++++++++++++ src/util/virsystemd.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++ src/util/virsystemd.h | 6 +++++ 6 files changed, 120 insertions(+) diff --git a/configure.ac b/configure.ac index 73efffa..807cf0f 100644 --- a/configure.ac +++ b/configure.ac @@ -563,6 +563,10 @@ AC_ARG_WITH([chrdev-lock-files], [location for UUCP style lock files for character devices (use auto for default paths on some platforms) @<:@default=auto@:>@])]) m4_divert_text([DEFAULTS], [with_chrdev_lock_files=auto]) +AC_ARG_WITH([pm-utils], + [AS_HELP_STRING([--with-pm-utils], + [use pm-utils for power management @<:@default=yes@:>@])]) +m4_divert_text([DEFAULTS], [with_pm_utils=yes]) dnl dnl in case someone want to build static binaries @@ -1621,6 +1625,12 @@ fi AM_CONDITIONAL([WITH_PHYP],[test "$with_phyp" = "yes"]) +dnl Should we build with pm-utils support? +if test "$with_pm_utils" = "yes"; then + AC_DEFINE_UNQUOTED([WITH_PM_UTILS], 1, [whether to use pm-utils]) +fi +AM_CONDITIONAL([WITH_PM_UTILS], [test "$with_pm_utils" = "yes"]) + dnl virsh libraries VIRSH_LIBS="$VIRSH_LIBS $READLINE_LIBS" AC_SUBST([VIRSH_LIBS]) @@ -2845,6 +2855,7 @@ AC_MSG_NOTICE([ rbd: $LIBRBD_LIBS]) else AC_MSG_NOTICE([ rbd: no]) fi +AC_MSG_NOTICE([pm-utils: $with_pm_utils]) AC_MSG_NOTICE([]) AC_MSG_NOTICE([Test suite]) diff --git a/libvirt.spec.in b/libvirt.spec.in index eab9b23..5c20955 100644 --- a/libvirt.spec.in +++ b/libvirt.spec.in @@ -132,6 +132,7 @@ %define with_libssh2 0%{!?_without_libssh2:0} %define with_wireshark 0%{!?_without_wireshark:0} %define with_systemd_daemon 0%{!?_without_systemd_daemon:0} +%define with_pm_utils 1 # Non-server/HV driver defaults which are always enabled %define with_sasl 0%{!?_without_sasl:1} @@ -182,6 +183,7 @@ %if 0%{?fedora} >= 17 || 0%{?rhel} >= 7 %define with_systemd 1 %define with_systemd_daemon 1 + %define with_pm_utils 0 %endif # Fedora 18 / RHEL-7 are first where firewalld support is enabled @@ -1138,8 +1140,10 @@ Requires: nc Requires: gettext # Needed by virt-pki-validate script. Requires: gnutls-utils +%if %{with_pm_utils} # Needed for probing the power management features of the host. Requires: pm-utils +%{endif} %if %{with_sasl} Requires: cyrus-sasl # Not technically required, but makes 'out-of-box' config @@ -1395,6 +1399,10 @@ driver %define _without_systemd_daemon --without-systemd-daemon %endif +%if ! %{with_pm_utils} + %define _without_pm_utils --without-pm-utils +%endif + %define when %(date +"%%F-%%T") %define where %(hostname) %define who %{?packager}%{!?packager:Unknown} @@ -1471,6 +1479,7 @@ rm -f po/stamp-po %{?_with_firewalld} \ %{?_without_wireshark} \ %{?_without_systemd_daemon} \ + %{?_without_pm_utils} \ %{with_packager} \ %{with_packager_version} \ --with-qemu-user=%{qemu_user} \ diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 38fbf63..ce51bdf 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1879,6 +1879,9 @@ virSysinfoSetup; # util/virsystemd.h +virSystemdCanHibernate; +virSystemdCanHybridSleep; +virSystemdCanSuspend; virSystemdCreateMachine; virSystemdMakeMachineName; virSystemdMakeScopeName; diff --git a/src/util/virnodesuspend.c b/src/util/virnodesuspend.c index 8088931..ba4a338 100644 --- a/src/util/virnodesuspend.c +++ b/src/util/virnodesuspend.c @@ -22,6 +22,9 @@ #include <config.h> #include "virnodesuspend.h" +#ifndef WITH_PM_UTILS +# include "virsystemd.h" +#endif #include "vircommand.h" #include "virthread.h" #include "datatypes.h" @@ -260,6 +263,7 @@ int nodeSuspendForDuration(unsigned int target, * * Returns 0 if the query was successful, -1 on failure. */ +#ifdef WITH_PM_UTILS static int virNodeSuspendSupportsTarget(unsigned int target, bool *supported) { @@ -300,6 +304,34 @@ virNodeSuspendSupportsTarget(unsigned int target, bool *supported) virCommandFree(cmd); return ret; } +#else /* ! WITH_PM_UTILS */ +static int +virNodeSuspendSupportsTarget(unsigned int target, bool *supported) +{ + int ret = -1; + + if (virNodeSuspendInitialize() < 0) + return -1; + + *supported = false; + + switch (target) { + case VIR_NODE_SUSPEND_TARGET_MEM: + ret = virSystemdCanSuspend(supported); + break; + case VIR_NODE_SUSPEND_TARGET_DISK: + ret = virSystemdCanHibernate(supported); + break; + case VIR_NODE_SUSPEND_TARGET_HYBRID: + ret = virSystemdCanHybridSleep(supported); + break; + default: + return ret; + } + + return ret; +} +#endif /* WITH_PM_UTILS */ /** * virNodeSuspendGetTargetMask: diff --git a/src/util/virsystemd.c b/src/util/virsystemd.c index 93b3f9c..d144d12 100644 --- a/src/util/virsystemd.c +++ b/src/util/virsystemd.c @@ -325,3 +325,62 @@ virSystemdNotifyStartup(void) sd_notify(0, "READY=1"); #endif } + +static int +virSystemdPMSupportTarget(const char *methodName, bool *result) +{ + int ret; + DBusConnection *conn; + DBusMessage *message = NULL; + char *response; + + ret = virDBusIsServiceEnabled("org.freedesktop.login1"); + if (ret < 0) + return ret; + + if ((ret = virDBusIsServiceRegistered("org.freedesktop.login1")) < 0) + return ret; + + if (!(conn = virDBusGetSystemBus())) + return -1; + + ret = -1; + + if (virDBusCallMethod(conn, + &message, + NULL, + "org.freedesktop.login1", + "/org/freedesktop/login1", + "org.freedesktop.login1.Manager", + methodName, + NULL) < 0) + return ret; + + if ((ret = virDBusMessageRead(message, "s", &response)) < 0) + goto cleanup; + + *result = STRNEQ("no", response); + + ret = 0; + + cleanup: + dbus_message_unref(message); + VIR_FREE(response); + + return ret; +} + +int virSystemdCanSuspend(bool *result) +{ + return virSystemdPMSupportTarget("CanSuspend", result); +} + +int virSystemdCanHibernate(bool *result) +{ + return virSystemdPMSupportTarget("CanHibernate", result); +} + +int virSystemdCanHybridSleep(bool *result) +{ + return virSystemdPMSupportTarget("CanHybridSleep", result); +} diff --git a/src/util/virsystemd.h b/src/util/virsystemd.h index 7fed456..491c9b7 100644 --- a/src/util/virsystemd.h +++ b/src/util/virsystemd.h @@ -48,4 +48,10 @@ int virSystemdTerminateMachine(const char *name, void virSystemdNotifyStartup(void); +int virSystemdCanSuspend(bool *result); + +int virSystemdCanHibernate(bool *result); + +int virSystemdCanHybridSleep(bool *result); + #endif /* __VIR_SYSTEMD_H__ */ -- 1.8.4.5

On Wed, Apr 02, 2014 at 03:35:51PM +0200, Cédric Bosdonnat wrote:
This uses the dbus api of systemd to check the power management capabilities of the node. --- Diff with v2: * Fixed a few dbus call problems
configure.ac | 11 +++++++++ libvirt.spec.in | 9 ++++++++ src/libvirt_private.syms | 3 +++ src/util/virnodesuspend.c | 32 +++++++++++++++++++++++++ src/util/virsystemd.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++ src/util/virsystemd.h | 6 +++++ 6 files changed, 120 insertions(+)
Could you also add a test to tests/virsystemdtest.c to exercuse these hekper APIs.
diff --git a/src/util/virnodesuspend.c b/src/util/virnodesuspend.c index 8088931..ba4a338 100644 --- a/src/util/virnodesuspend.c +++ b/src/util/virnodesuspend.c @@ -22,6 +22,9 @@ #include <config.h> #include "virnodesuspend.h"
+#ifndef WITH_PM_UTILS +# include "virsystemd.h" +#endif #include "vircommand.h" #include "virthread.h" #include "datatypes.h" @@ -260,6 +263,7 @@ int nodeSuspendForDuration(unsigned int target, * * Returns 0 if the query was successful, -1 on failure. */ +#ifdef WITH_PM_UTILS static int virNodeSuspendSupportsTarget(unsigned int target, bool *supported) { @@ -300,6 +304,34 @@ virNodeSuspendSupportsTarget(unsigned int target, bool *supported) virCommandFree(cmd); return ret; } +#else /* ! WITH_PM_UTILS */ +static int +virNodeSuspendSupportsTarget(unsigned int target, bool *supported) +{ + int ret = -1; + + if (virNodeSuspendInitialize() < 0) + return -1; + + *supported = false; + + switch (target) { + case VIR_NODE_SUSPEND_TARGET_MEM: + ret = virSystemdCanSuspend(supported); + break; + case VIR_NODE_SUSPEND_TARGET_DISK: + ret = virSystemdCanHibernate(supported); + break; + case VIR_NODE_SUSPEND_TARGET_HYBRID: + ret = virSystemdCanHybridSleep(supported); + break; + default: + return ret; + } + + return ret; +} +#endif /* WITH_PM_UTILS */
Rather than having a hardcoded choice of pm-utils vs systemd I think we should check if the systemd service is running and if so use it, otherwise fallback to pm-utils. That way if someone has systemd installed, but is not running it as their init, things would still work Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

On Wed, 2014-04-02 at 15:52 +0200, Daniel P. Berrange wrote:
On Wed, Apr 02, 2014 at 03:35:51PM +0200, Cédric Bosdonnat wrote:
This uses the dbus api of systemd to check the power management capabilities of the node. --- Diff with v2: * Fixed a few dbus call problems
configure.ac | 11 +++++++++ libvirt.spec.in | 9 ++++++++ src/libvirt_private.syms | 3 +++ src/util/virnodesuspend.c | 32 +++++++++++++++++++++++++ src/util/virsystemd.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++ src/util/virsystemd.h | 6 +++++ 6 files changed, 120 insertions(+)
Could you also add a test to tests/virsystemdtest.c to exercuse these hekper APIs.
Will do it.
diff --git a/src/util/virnodesuspend.c b/src/util/virnodesuspend.c index 8088931..ba4a338 100644 --- a/src/util/virnodesuspend.c +++ b/src/util/virnodesuspend.c @@ -22,6 +22,9 @@ #include <config.h> #include "virnodesuspend.h"
+#ifndef WITH_PM_UTILS +# include "virsystemd.h" +#endif #include "vircommand.h" #include "virthread.h" #include "datatypes.h" @@ -260,6 +263,7 @@ int nodeSuspendForDuration(unsigned int target, * * Returns 0 if the query was successful, -1 on failure. */ +#ifdef WITH_PM_UTILS static int virNodeSuspendSupportsTarget(unsigned int target, bool *supported) { @@ -300,6 +304,34 @@ virNodeSuspendSupportsTarget(unsigned int target, bool *supported) virCommandFree(cmd); return ret; } +#else /* ! WITH_PM_UTILS */ +static int +virNodeSuspendSupportsTarget(unsigned int target, bool *supported) +{ + int ret = -1; + + if (virNodeSuspendInitialize() < 0) + return -1; + + *supported = false; + + switch (target) { + case VIR_NODE_SUSPEND_TARGET_MEM: + ret = virSystemdCanSuspend(supported); + break; + case VIR_NODE_SUSPEND_TARGET_DISK: + ret = virSystemdCanHibernate(supported); + break; + case VIR_NODE_SUSPEND_TARGET_HYBRID: + ret = virSystemdCanHybridSleep(supported); + break; + default: + return ret; + } + + return ret; +} +#endif /* WITH_PM_UTILS */
Rather than having a hardcoded choice of pm-utils vs systemd I think we should check if the systemd service is running and if so use it, otherwise fallback to pm-utils. That way if someone has systemd installed, but is not running it as their init, things would still work
The idea is also to be able to drop the Requires: pm-utils in the spec file... so a runtime check wouldn't help this. -- Cedric

On Wed, Apr 02, 2014 at 03:57:44PM +0200, Cedric Bosdonnat wrote:
On Wed, 2014-04-02 at 15:52 +0200, Daniel P. Berrange wrote:
On Wed, Apr 02, 2014 at 03:35:51PM +0200, Cédric Bosdonnat wrote:
This uses the dbus api of systemd to check the power management capabilities of the node. --- Diff with v2: * Fixed a few dbus call problems
configure.ac | 11 +++++++++ libvirt.spec.in | 9 ++++++++ src/libvirt_private.syms | 3 +++ src/util/virnodesuspend.c | 32 +++++++++++++++++++++++++ src/util/virsystemd.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++ src/util/virsystemd.h | 6 +++++ 6 files changed, 120 insertions(+)
Could you also add a test to tests/virsystemdtest.c to exercuse these hekper APIs.
Will do it.
diff --git a/src/util/virnodesuspend.c b/src/util/virnodesuspend.c index 8088931..ba4a338 100644 --- a/src/util/virnodesuspend.c +++ b/src/util/virnodesuspend.c @@ -22,6 +22,9 @@ #include <config.h> #include "virnodesuspend.h"
+#ifndef WITH_PM_UTILS +# include "virsystemd.h" +#endif #include "vircommand.h" #include "virthread.h" #include "datatypes.h" @@ -260,6 +263,7 @@ int nodeSuspendForDuration(unsigned int target, * * Returns 0 if the query was successful, -1 on failure. */ +#ifdef WITH_PM_UTILS static int virNodeSuspendSupportsTarget(unsigned int target, bool *supported) { @@ -300,6 +304,34 @@ virNodeSuspendSupportsTarget(unsigned int target, bool *supported) virCommandFree(cmd); return ret; } +#else /* ! WITH_PM_UTILS */ +static int +virNodeSuspendSupportsTarget(unsigned int target, bool *supported) +{ + int ret = -1; + + if (virNodeSuspendInitialize() < 0) + return -1; + + *supported = false; + + switch (target) { + case VIR_NODE_SUSPEND_TARGET_MEM: + ret = virSystemdCanSuspend(supported); + break; + case VIR_NODE_SUSPEND_TARGET_DISK: + ret = virSystemdCanHibernate(supported); + break; + case VIR_NODE_SUSPEND_TARGET_HYBRID: + ret = virSystemdCanHybridSleep(supported); + break; + default: + return ret; + } + + return ret; +} +#endif /* WITH_PM_UTILS */
Rather than having a hardcoded choice of pm-utils vs systemd I think we should check if the systemd service is running and if so use it, otherwise fallback to pm-utils. That way if someone has systemd installed, but is not running it as their init, things would still work
The idea is also to be able to drop the Requires: pm-utils in the spec file... so a runtime check wouldn't help this.
Oh, i mean you can still have WITH_PM_UTILS conditional in the RPM spec / configure check. Downstream user can thus have the option to have both enabled at build time, or to disable pm-utils and only rely on systemd. ie we'd default to everything enabled and fully dynamic at runtime, but we'd set the RPM builds to disable pm-utils on Fedora >= 20 Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

On 04/02/2014 08:06 AM, Daniel P. Berrange wrote:
Rather than having a hardcoded choice of pm-utils vs systemd I think we should check if the systemd service is running and if so use it, otherwise fallback to pm-utils. That way if someone has systemd installed, but is not running it as their init, things would still work
The idea is also to be able to drop the Requires: pm-utils in the spec file... so a runtime check wouldn't help this.
Oh, i mean you can still have WITH_PM_UTILS conditional in the RPM spec / configure check. Downstream user can thus have the option to have both enabled at build time, or to disable pm-utils and only rely on systemd. ie we'd default to everything enabled and fully dynamic at runtime, but we'd set the RPM builds to disable pm-utils on Fedora >= 20
More or less this pseudo-code: #if SYSTEMD && DBUS try dbus calls; if successful return result #endif #if PM_UTILS try pm-utils calls; if successful return result #endif return failure and then it is possible for downstream to support both methods depending on configure arguments. That way, the spec file can control configure flags to create an ideal situation for Fedora (enforcesystemd only) while avoiding bitrot for developers (developers can enable both systemd and pm-utils code to make sure both branches compile) -- Eric Blake eblake redhat com +1-919-301-3266 Libvirt virtualization library http://libvirt.org

On 04/02/2014 07:35 AM, Cédric Bosdonnat wrote:
This uses the dbus api of systemd to check the power management capabilities of the node. --- Diff with v2: * Fixed a few dbus call problems
+++ b/configure.ac @@ -563,6 +563,10 @@ AC_ARG_WITH([chrdev-lock-files], [location for UUCP style lock files for character devices (use auto for default paths on some platforms) @<:@default=auto@:>@])]) m4_divert_text([DEFAULTS], [with_chrdev_lock_files=auto]) +AC_ARG_WITH([pm-utils], + [AS_HELP_STRING([--with-pm-utils], + [use pm-utils for power management @<:@default=yes@:>@])]) +m4_divert_text([DEFAULTS], [with_pm_utils=yes])
Should the default really be yes? On systems where dbus is not in use, 'yes' as the default makes sense. But on systems where dbus is active, and where we know we are using systemd for other configure options, wouldn't it make more sense to default pm-utils to no in that case? Or in other words, set default=check, then use other configure options to decide whether to flip check to no (systemd and dbus detected) or to yes (all other cases), rather than hard-coding to yes. -- Eric Blake eblake redhat com +1-919-301-3266 Libvirt virtualization library http://libvirt.org
participants (4)
-
Cedric Bosdonnat
-
Cédric Bosdonnat
-
Daniel P. Berrange
-
Eric Blake