]> xenbits.xensource.com Git - libvirt.git/commitdiff
Introduce --without-pm-utils to get rid of pm-is-supported dependency
authorCédric Bosdonnat <cbosdonnat@suse.com>
Fri, 11 Apr 2014 07:20:48 +0000 (09:20 +0200)
committerJim Fehlig <jfehlig@suse.com>
Fri, 11 Apr 2014 21:51:10 +0000 (15:51 -0600)
This uses the dbus api of systemd to check the power management
capabilities of the node.

configure.ac
libvirt.spec.in
src/libvirt_private.syms
src/util/virnodesuspend.c
src/util/virsystemd.c
src/util/virsystemd.h
tests/virsystemdtest.c

index 52c50df6a7141fe87b31ede4bcc3933fd7f2ccca..ea85851eb0ab77e24351f16a7a6b322287837789 100644 (file)
@@ -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=check])
 
 dnl
 dnl in case someone want to build static binaries
@@ -1621,6 +1625,23 @@ fi
 
 AM_CONDITIONAL([WITH_PHYP],[test "$with_phyp" = "yes"])
 
+dnl
+dnl Should we build with pm-utils support?
+dnl
+if test "$with_pm_utils" = "check"; then
+    with_pm_utils=yes
+    if test "$with_dbus" = "yes"; then
+        if test "$init_systemd" = "yes"; then
+            with_pm_utils=no
+        fi
+    fi
+fi
+
+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])
@@ -2853,6 +2874,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])
index 8e83fb3e0dc88ecd10c4fd111ce32c02a47142de..4e70a41486eb69dddfd11e4e7b1ef15d69b2ec7a 100644 (file)
 %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}
 %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} \
index cd4333548dc7ddc2e38cb7ceeae3a0603c45ef4c..6e807c49195f3a0f48959027553c729557c1c81c 100644 (file)
@@ -1888,6 +1888,9 @@ virSysinfoSetup;
 
 
 # util/virsystemd.h
+virSystemdCanHibernate;
+virSystemdCanHybridSleep;
+virSystemdCanSuspend;
 virSystemdCreateMachine;
 virSystemdMakeMachineName;
 virSystemdMakeScopeName;
index 08c47aa20f18a7d92908d4978b10695c07c30ebe..59b84effe2b218a9a5acd7a72fa6d166e92ec9ba 100644 (file)
@@ -22,6 +22,7 @@
 #include <config.h>
 #include "virnodesuspend.h"
 
+#include "virsystemd.h"
 #include "vircommand.h"
 #include "virthread.h"
 #include "datatypes.h"
@@ -228,23 +229,9 @@ int nodeSuspendForDuration(unsigned int target,
     return ret;
 }
 
-
-/**
- * virNodeSuspendSupportsTarget:
- * @target: The power management target to check whether it is supported
- *           by the host. Values could be:
- *           VIR_NODE_SUSPEND_TARGET_MEM
- *           VIR_NODE_SUSPEND_TARGET_DISK
- *           VIR_NODE_SUSPEND_TARGET_HYBRID
- * @supported: set to true if supported, false otherwise
- *
- * Run the script 'pm-is-supported' (from the pm-utils package)
- * to find out if @target is supported by the host.
- *
- * Returns 0 if the query was successful, -1 on failure.
- */
+#ifdef WITH_PM_UTILS
 static int
-virNodeSuspendSupportsTarget(unsigned int target, bool *supported)
+virNodeSuspendSupportsTargetPMUtils(unsigned int target, bool *supported)
 {
     virCommandPtr cmd;
     int status;
@@ -280,6 +267,59 @@ virNodeSuspendSupportsTarget(unsigned int target, bool *supported)
     virCommandFree(cmd);
     return ret;
 }
+#endif
+
+static int
+virNodeSuspendSupportsTargetSystemd(unsigned int target, bool *supported)
+{
+    int ret = -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;
+}
+
+/**
+ * virNodeSuspendSupportsTarget:
+ * @target: The power management target to check whether it is supported
+ *           by the host. Values could be:
+ *           VIR_NODE_SUSPEND_TARGET_MEM
+ *           VIR_NODE_SUSPEND_TARGET_DISK
+ *           VIR_NODE_SUSPEND_TARGET_HYBRID
+ * @supported: set to true if supported, false otherwise
+ *
+ * Run the script 'pm-is-supported' (from the pm-utils package)
+ * to find out if @target is supported by the host.
+ *
+ * Returns 0 if the query was successful, -1 on failure.
+ */
+static int
+virNodeSuspendSupportsTarget(unsigned int target, bool *supported)
+{
+    int ret;
+
+    ret = virNodeSuspendSupportsTargetSystemd(target, supported);
+#ifdef WITH_PM_UTILS
+    if (ret < 0)
+        ret = virNodeSuspendSupportsTargetPMUtils(target, supported);
+#endif
+
+    return ret;
+}
 
 /**
  * virNodeSuspendGetTargetMask:
index 93b3f9c98a2e2731003581b6f1bb1716537fa4c5..e9ca564e82cc9b8f46c27afb377a1c0628d550e3 100644 (file)
@@ -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 = STREQ("yes", response) || STREQ("challenge", 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);
+}
index 7fed456270347e3574ae108f205f2342ab507de4..491c9b7de3be6cc5089563b4d41ad510c2aa4ea9 100644 (file)
@@ -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__ */
index 2b014ccdd1f88731be865897f30e17a60089e13b..0fcd4e8447c0b50265c82ae5e79098651a63be13 100644 (file)
@@ -55,10 +55,21 @@ VIR_MOCK_IMPL_RET_ARGS(dbus_connection_send_with_reply_and_block,
         } else {
             reply = dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_RETURN);
         }
+    } else if (STREQ(service, "org.freedesktop.login1")) {
+        char *supported = getenv("RESULT_SUPPORT");
+        DBusMessageIter iter;
+        reply = dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_RETURN);
+        dbus_message_iter_init_append(reply, &iter);
+
+        if (!dbus_message_iter_append_basic(&iter,
+                                            DBUS_TYPE_STRING,
+                                            &supported))
+            goto error;
     } else if (STREQ(service, "org.freedesktop.DBus") &&
                STREQ(member, "ListActivatableNames")) {
         const char *svc1 = "org.foo.bar.wizz";
         const char *svc2 = "org.freedesktop.machine1";
+        const char *svc3 = "org.freedesktop.login1";
         DBusMessageIter iter;
         DBusMessageIter sub;
         reply = dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_RETURN);
@@ -75,11 +86,17 @@ VIR_MOCK_IMPL_RET_ARGS(dbus_connection_send_with_reply_and_block,
                                             DBUS_TYPE_STRING,
                                             &svc2))
             goto error;
+        if (!getenv("FAIL_NO_SERVICE") &&
+            !dbus_message_iter_append_basic(&sub,
+                                            DBUS_TYPE_STRING,
+                                            &svc3))
+            goto error;
         dbus_message_iter_close_container(&iter, &sub);
     } else if (STREQ(service, "org.freedesktop.DBus") &&
                STREQ(member, "ListNames")) {
         const char *svc1 = "org.foo.bar.wizz";
         const char *svc2 = "org.freedesktop.systemd1";
+        const char *svc3 = "org.freedesktop.login1";
         DBusMessageIter iter;
         DBusMessageIter sub;
         reply = dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_RETURN);
@@ -96,6 +113,11 @@ VIR_MOCK_IMPL_RET_ARGS(dbus_connection_send_with_reply_and_block,
                                             DBUS_TYPE_STRING,
                                             &svc2))
             goto error;
+        if ((!getenv("FAIL_NO_SERVICE") && !getenv("FAIL_NOT_REGISTERED")) &&
+            !dbus_message_iter_append_basic(&sub,
+                                            DBUS_TYPE_STRING,
+                                            &svc3))
+            goto error;
         dbus_message_iter_close_container(&iter, &sub);
     } else {
         reply = dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_RETURN);
@@ -313,6 +335,86 @@ testScopeName(const void *opaque)
     return ret;
 }
 
+typedef int (*virSystemdCanHelper)(bool * result);
+struct testPMSupportData {
+    virSystemdCanHelper tested;
+};
+
+static int testPMSupportHelper(const void *opaque)
+{
+    int rv;
+    bool result;
+    size_t i;
+    const char *results[4] = {"yes", "no", "na", "challenge"};
+    int expected[4] = {1, 0, 0, 1};
+    const struct testPMSupportData *data = opaque;
+
+    for (i = 0; i < 4; i++) {
+        setenv("RESULT_SUPPORT",  results[i], 1);
+        if ((rv = data->tested(&result)) < 0) {
+            fprintf(stderr, "%s", "Unexpected canSuspend error\n");
+            return -1;
+        }
+
+        if (result != expected[i]) {
+            fprintf(stderr, "Unexpected result for answer '%s'\n", results[i]);
+            goto error;
+        }
+        unsetenv("RESULT_SUPPORT");
+    }
+
+    return 0;
+ error:
+    unsetenv("RESULT_SUPPORT");
+    return -1;
+}
+
+static int testPMSupportHelperNoSystemd(const void *opaque)
+{
+    int rv;
+    bool result;
+    const struct testPMSupportData *data = opaque;
+
+    setenv("FAIL_NO_SERVICE", "1", 1);
+
+    if ((rv = data->tested(&result)) == 0) {
+        unsetenv("FAIL_NO_SERVICE");
+        fprintf(stderr, "%s", "Unexpected canSuspend success\n");
+        return -1;
+    }
+    unsetenv("FAIL_NO_SERVICE");
+
+    if (rv != -2) {
+        fprintf(stderr, "%s", "Unexpected canSuspend error\n");
+        return -1;
+    }
+
+    return 0;
+}
+
+static int testPMSupportSystemdNotRunning(const void *opaque)
+{
+    int rv;
+    bool result;
+    const struct testPMSupportData *data = opaque;
+
+    setenv("FAIL_NOT_REGISTERED", "1", 1);
+
+    if ((rv = data->tested(&result)) == 0) {
+        unsetenv("FAIL_NOT_REGISTERED");
+        fprintf(stderr, "%s", "Unexpected canSuspend success\n");
+        return -1;
+    }
+    unsetenv("FAIL_NOT_REGISTERED");
+
+    if (rv != -2) {
+        fprintf(stderr, "%s", "Unexpected canSuspend error\n");
+        return -1;
+    }
+
+    return 0;
+}
+
 static int
 mymain(void)
 {
@@ -351,6 +453,25 @@ mymain(void)
     TEST_SCOPE("demo", "/machine/eng-dept/testing!stuff",
                "machine-eng\\x2ddept-testing\\x21stuff-lxc\\x2ddemo.scope");
 
+# define TESTS_PM_SUPPORT_HELPER(name, function)                        \
+    do {                                                                \
+        struct testPMSupportData data = {                               \
+            function                                                    \
+        };                                                              \
+        if (virtTestRun("Test " name " ", testPMSupportHelper, &data) < 0)  \
+            ret = -1;                                                   \
+        if (virtTestRun("Test " name " no systemd ",                    \
+                        testPMSupportHelperNoSystemd, &data) < 0)       \
+            ret = -1;                                                   \
+        if (virtTestRun("Test systemd " name " not running ",           \
+                        testPMSupportSystemdNotRunning, &data) < 0)     \
+            ret = -1;                                                   \
+    } while (0)
+
+    TESTS_PM_SUPPORT_HELPER("canSuspend", &virSystemdCanSuspend);
+    TESTS_PM_SUPPORT_HELPER("canHibernate", &virSystemdCanHibernate);
+    TESTS_PM_SUPPORT_HELPER("canHybridSleep", &virSystemdCanHybridSleep);
+
     return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
 }