Add vip-generator program 80/150780/4
authorKonrad Kuchciak <k.kuchciak@samsung.com>
Wed, 13 Sep 2017 09:56:54 +0000 (11:56 +0200)
committerKonrad Kuchciak <k.kuchciak@samsung.com>
Wed, 11 Oct 2017 07:42:01 +0000 (09:42 +0200)
It is meant to be used by systemd to create overrides for VIP
services. The override contains two lines:

[Service]
Restart=no

and prevents service from restarting itself automatically after
failure in order to enter 'failed' state, which is then handled
by faultd.

The override is generated based on config files found
in "/etc/faultd/conf.d/" and placed under
"/run/systemd/generator.early/service_name.service.d/"

Change-Id: I10919964cb8bf0ae304c3771de864c654ee93e93
Signed-off-by: Konrad Kuchciak <k.kuchciak@samsung.com>
Makefile.am
generators/vip-generator.c [new file with mode: 0644]
packaging/faultd.spec
systemd-service.d/display-manager.service.conf [deleted file]

index 1b84322fd2a1ffee6b6274830b41afde0253046f..95efa0ad49e36e0aa569405a8a1320ed7f0d7390 100644 (file)
@@ -153,8 +153,6 @@ install-data-local:
        $(MKDIR_P) $(DESTDIR)$(pkglibdir)/available-modules
        $(MKDIR_P) $(DESTDIR)$(sysconfdir)/faultd/available-modules
        $(MKDIR_P) $(DESTDIR)$(sysconfdir)/faultd/enabled-modules
-       $(MKDIR_P) $(DESTDIR)$(unitdir)/display-manager.service.d
-       $(INSTALL) systemd-service.d/display-manager.service.conf $(DESTDIR)/$(unitdir)/display-manager.service.d/faultd.conf
 
 
 if BUILD_TEST_PROGRAMS
@@ -219,3 +217,16 @@ test_SOURCES = \
 
 TESTS = $(check_PROGRAMS)
 endif
+
+generatorsdir = $(prefix)/lib/systemd/system-generators
+
+generators_PROGRAMS = vip-generator
+
+vip_generator_SOURCES = \
+    generators/vip-generator.c \
+    src/util/common.c \
+    src/util/systemd_dbus.c \
+    src/util/json-config.c \
+    src/util/log.c
+
+vip_generator_LDADD = $(LIBSYSTEMD_LIBS) $(JSON_C_LIBS)
diff --git a/generators/vip-generator.c b/generators/vip-generator.c
new file mode 100644 (file)
index 0000000..2e6cb7d
--- /dev/null
@@ -0,0 +1,193 @@
+/*
+ * This file is part of faultd.
+ *
+ * Copyright © 2017 Samsung Electronics
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <dirent.h>
+
+#include "service.h"
+#include "json-config.h"
+#include "log.h"
+
+static const char *dest_path = "/tmp/";
+
+static char *get_next_file(DIR *conf_dir)
+{
+       struct dirent *d;
+
+       while (1) {
+               d = readdir(conf_dir);
+               if (d == NULL)
+                       return NULL;
+
+               if (strcmp(d->d_name, ".") == 0 ||
+                       strcmp(d->d_name, "..") == 0) {
+
+                       continue;
+               }
+
+               return d->d_name;
+       }
+}
+
+static int create_dir(const char *path)
+{
+       if (mkdir(path, 0755) != 0) {
+               if (errno == EEXIST)
+                       return 0;
+               else
+                       return -errno;
+       }
+
+       return 0;
+}
+
+static char *get_service_name(char *conf_name)
+{
+       const char *suffix = ".conf";
+       int suffixlen = strlen(suffix);
+
+       int len = strlen(conf_name);
+       int prefixlen = len - suffixlen;
+
+       if (len > suffixlen && strcmp(&conf_name[prefixlen], suffix) == 0)
+               return strndup(conf_name, prefixlen);
+       else
+               return NULL;
+}
+
+static int create_vip_service_override(const char *service_name)
+{
+       FILE *fp;
+       char *location;
+       char *service_override;
+       int ret;
+
+       ret = asprintf(&location, "%s/%s.d", dest_path, service_name);
+       if (ret == -1)
+               return -errno;
+
+       ret = create_dir(location);
+       if (ret != 0) {
+               free(location);
+               return ret;
+       }
+
+       ret = asprintf(&service_override, "%s/faultd.conf", location);
+       free(location);
+       if (ret == -1)
+               return -errno;
+
+       fp = fopen(service_override, "w");
+       free(service_override);
+       if (fp == NULL)
+               return -errno;
+
+       fprintf(fp, "[Service]\n"
+                               "Restart=no\n");
+       fclose(fp);
+
+       return 0;
+}
+
+static void init_systemd_service(struct systemd_service *s)
+{
+       assert(s);
+
+       s->dbus_path = NULL;
+       s->service_type = NULL;
+       s->recovery_unit = NULL;
+}
+
+static void free_systemd_service(struct systemd_service *s)
+{
+       if (s) {
+               free(s->dbus_path);
+               free(s->service_type);
+               free(s->recovery_unit);
+       }
+}
+
+int main(int argc, char *argv[])
+{
+       DIR *config_dir;
+       struct systemd_service s;
+       char *service_name;
+       char *service_config;
+       int ret;
+
+       /*
+        * This program follows systemd generator specification, please see:
+        * https://www.freedesktop.org/software/systemd/man/systemd.generator.html
+        */
+
+       if (argc > 1 && argc != 4) {
+               log_error("This program takes three or no arguments");
+               return EXIT_FAILURE;
+       }
+
+       if (argc > 1)
+               dest_path = argv[2];
+
+       config_dir = opendir(FAULTD_SERVICES_CONFIG_PATH);
+       if (!config_dir) {
+               log_error("Unable to open directory %s: %m", FAULTD_SERVICES_CONFIG_PATH);
+               return EXIT_FAILURE;
+       }
+
+       while ((service_config = get_next_file(config_dir)) != NULL) {
+               init_systemd_service(&s);
+
+               service_name = get_service_name(service_config);
+               if (service_name == NULL) {
+                       log_error("Unable to get service name from config: %s", service_config);
+                       goto cleanup;
+               }
+
+               ret = asprintf(&service_config, FAULTD_SERVICES_CONFIG_PATH "%s", service_config);
+               if (ret == -1) {
+                       log_error("Unable to allocate string: %s", strerror(errno));
+                       goto cleanup;
+               }
+
+               ret = parse_service_config(service_config, &s);
+               if (ret != 0) {
+                       log_error("Unable to parse config file: %s", service_config);
+                       free(service_config);
+                       goto cleanup;
+               }
+
+               free(service_config);
+
+               if (systemd_service_is_of_type(&s, FAULTD_SERVICE_TYPE_VIP)) {
+                       ret = create_vip_service_override(service_name);
+                       if (ret != 0)
+                               log_error("Unable to create override for VIP service %s: %s\n",
+                                                 service_name, strerror(ret));
+               }
+
+       cleanup:
+               free(service_name);
+               free_systemd_service(&s);
+       }
+
+       closedir(config_dir);
+       return 0;
+}
index 18ffe5c15cb8265d689241fdb98e90950eec57bd..c988c2df0af109d7cc60bd40e39cb0f71b923f4d 100644 (file)
@@ -85,7 +85,7 @@ done
 %{_sysconfdir}/faultd/conf.d/display-manager.service.conf
 %{_unitdir}/faultd.service
 %{_unitdir}/multi-user.target.wants/faultd.service
-%{_unitdir}/display-manager.service.d/faultd.conf
+%{_prefix}/lib/systemd/system-generators/vip-generator
 
 %files extra -f faultd-extra-files
 
diff --git a/systemd-service.d/display-manager.service.conf b/systemd-service.d/display-manager.service.conf
deleted file mode 100644 (file)
index 3de2669..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-[Service]
-Restart=no