summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPavel Březina <pbrezina@redhat.com>2016-09-21 12:25:43 +0200
committerJakub Hrozek <jhrozek@redhat.com>2016-10-11 14:31:35 +0200
commitf4f2edba5c555773d7c9adfa95562b96b0c0cdb2 (patch)
tree406c739cdbc315531d454870dba5acbc4c8e6350
parent03713a6444fdecd01465b9d5fbfead9601adce6e (diff)
downloadsssd-f4f2edba5c555773d7c9adfa95562b96b0c0cdb2.tar.gz
sssd-f4f2edba5c555773d7c9adfa95562b96b0c0cdb2.tar.xz
sssd-f4f2edba5c555773d7c9adfa95562b96b0c0cdb2.zip
sssctl: use systemd D-Bus API
If systemd is used we leverage it's D-Bus API instead of running systemctl. Resolves: https://fedorahosted.org/sssd/ticket/3056 Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
-rw-r--r--Makefile.am1
-rw-r--r--src/tools/sssctl/sssctl.c23
-rw-r--r--src/tools/sssctl/sssctl.h4
-rw-r--r--src/tools/sssctl/sssctl_systemd.c136
4 files changed, 154 insertions, 10 deletions
diff --git a/Makefile.am b/Makefile.am
index 1ea8f5066..b5f300a37 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1573,6 +1573,7 @@ sss_override_CFLAGS = \
sssctl_SOURCES = \
src/tools/sssctl/sssctl.c \
+ src/tools/sssctl/sssctl_systemd.c \
src/tools/sssctl/sssctl_cache.c \
src/tools/sssctl/sssctl_data.c \
src/tools/sssctl/sssctl_logs.c \
diff --git a/src/tools/sssctl/sssctl.c b/src/tools/sssctl/sssctl.c
index 20ea26f8f..2ccb30eb1 100644
--- a/src/tools/sssctl/sssctl.c
+++ b/src/tools/sssctl/sssctl.c
@@ -26,12 +26,6 @@
#include "tools/common/sss_tools.h"
#include "tools/common/sss_process.h"
-#ifdef HAVE_SYSTEMD
- #define SSSD_SVC_CMD(cmd) "systemctl " cmd " sssd.service"
-#else
- #define SSSD_SVC_CMD(cmd) "service sssd " cmd
-#endif
-
static const char *
sssctl_prompt_str(enum sssctl_prompt_result result)
{
@@ -125,14 +119,23 @@ errno_t sssctl_run_command(const char *command)
static errno_t sssctl_manage_service(enum sssctl_svc_action action)
{
-#if defined(HAVE_SYSTEMD) || defined(HAVE_SERVICE)
+#ifdef HAVE_SYSTEMD
+ switch (action) {
+ case SSSCTL_SVC_START:
+ return sssctl_systemd_start();
+ case SSSCTL_SVC_STOP:
+ return sssctl_systemd_stop();
+ case SSSCTL_SVC_RESTART:
+ return sssctl_systemd_restart();
+ }
+#elif HAVE_SERVICE
switch (action) {
case SSSCTL_SVC_START:
- return sssctl_run_command(SSSD_SVC_CMD("start"));
+ return sssctl_run_command("service sssd start");
case SSSCTL_SVC_STOP:
- return sssctl_run_command(SSSD_SVC_CMD("stop"));
+ return sssctl_run_command("service sssd stop");
case SSSCTL_SVC_RESTART:
- return sssctl_run_command(SSSD_SVC_CMD("restart"));
+ return sssctl_run_command("service sssd restart");
}
#endif
diff --git a/src/tools/sssctl/sssctl.h b/src/tools/sssctl/sssctl.h
index d4e3359b0..5270a9ec6 100644
--- a/src/tools/sssctl/sssctl.h
+++ b/src/tools/sssctl/sssctl.h
@@ -70,6 +70,10 @@ sss_sifp_error _sssctl_sifp_send(TALLOC_CTX *mem_ctx,
_sssctl_sifp_send(mem_ctx, sifp, reply, path, iface, method, \
##__VA_ARGS__, DBUS_TYPE_INVALID);
+errno_t sssctl_systemd_start(void);
+errno_t sssctl_systemd_stop(void);
+errno_t sssctl_systemd_restart(void);
+
errno_t sssctl_domain_list(struct sss_cmdline *cmdline,
struct sss_tool_ctx *tool_ctx,
void *pvt);
diff --git a/src/tools/sssctl/sssctl_systemd.c b/src/tools/sssctl/sssctl_systemd.c
new file mode 100644
index 000000000..d5ce3b6f5
--- /dev/null
+++ b/src/tools/sssctl/sssctl_systemd.c
@@ -0,0 +1,136 @@
+/*
+ Authors:
+ Pavel Březina <pbrezina@redhat.com>
+
+ Copyright (C) 2016 Red Hat
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <talloc.h>
+#include <dbus/dbus.h>
+#include <errno.h>
+
+#include "util/util.h"
+#include "tools/sssctl/sssctl.h"
+
+#define SSS_SYSTEMD_BUS "org.freedesktop.systemd1"
+#define SSS_SYSTEMD_PATH "/org/freedesktop/systemd1"
+#define SSS_SYSTEMD_IFACE "org.freedesktop.systemd1.Manager"
+#define SSS_SYSTEMD_UNIT "sssd.service"
+#define SSS_SYSTEMD_MODE "replace" /* replace queued job if present */
+
+static DBusConnection *
+sssctl_systemd_connect(void)
+{
+ DBusConnection *conn;
+ DBusError error;
+
+ dbus_error_init(&error);
+
+ conn = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
+ if (dbus_error_is_set(&error)) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to connect to systemd D-Bus "
+ "[%s]: %s\n", error.name, error.message);
+ conn = NULL;
+ goto done;
+ }
+
+done:
+ dbus_error_free(&error);
+ return conn;
+}
+
+static errno_t sssctl_systemd_call(const char *method)
+{
+ DBusConnection *conn = NULL;
+ DBusMessage *reply = NULL;
+ DBusMessage *msg = NULL;
+ DBusError error;
+ const char *unit = SSS_SYSTEMD_UNIT;
+ const char *mode = SSS_SYSTEMD_MODE;
+ const char *job;
+ errno_t ret;
+
+ dbus_error_init(&error);
+
+ conn = sssctl_systemd_connect();
+ if (conn == NULL) {
+ ret = EIO;
+ goto done;
+ }
+
+ msg = sbus_create_message(NULL, SSS_SYSTEMD_BUS, SSS_SYSTEMD_PATH,
+ SSS_SYSTEMD_IFACE, method,
+ DBUS_TYPE_STRING, &unit,
+ DBUS_TYPE_STRING, &mode);
+ if (msg == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create D-Bus Message!\n");
+ ret = ENOMEM;
+ goto done;
+ }
+
+ reply = dbus_connection_send_with_reply_and_block(conn, msg, 5000, &error);
+ if (dbus_error_is_set(&error)) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to send D-Bus message "
+ "[%s]: %s\n", error.name, error.message);
+ ret = EIO;
+ goto done;
+ }
+
+ ret = sbus_parse_message(reply, DBUS_TYPE_OBJECT_PATH, &job);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to get D-Bus reply [%d]: %s!\n",
+ ret, sss_strerror(ret));
+ goto done;
+ }
+
+ DEBUG(SSSDBG_TRACE_FUNC, "New systemd job created: %s\n", job);
+
+done:
+ if (msg != NULL) {
+ dbus_message_unref(msg);
+ }
+
+ if (reply != NULL) {
+ dbus_message_unref(reply);
+ }
+
+ if (conn != NULL) {
+ dbus_connection_unref(conn);
+ }
+
+ return ret;
+}
+
+errno_t sssctl_systemd_start(void)
+{
+ DEBUG(SSSDBG_TRACE_FUNC, "Starting SSSD via systemd...\n");
+
+ return sssctl_systemd_call("StartUnit");
+}
+
+errno_t sssctl_systemd_stop(void)
+{
+ DEBUG(SSSDBG_TRACE_FUNC, "Stopping SSSD via systemd...\n");
+
+ return sssctl_systemd_call("StopUnit");
+}
+
+errno_t sssctl_systemd_restart(void)
+{
+ DEBUG(SSSDBG_TRACE_FUNC, "Restarting SSSD via systemd...\n");
+
+ return sssctl_systemd_call("RestartUnit");
+}