diff options
author | Vitezslav Crhonek <vcrhonek@redhat.com> | 2013-05-13 16:37:48 +0200 |
---|---|---|
committer | Vitezslav Crhonek <vcrhonek@redhat.com> | 2013-05-13 16:37:48 +0200 |
commit | 78244e3db39e98e3243f82f153cf9ca350904879 (patch) | |
tree | 9a7a05ac236cc66b0a920a6ce1ab52860755e22b /src/service-dbus/util | |
parent | 41d6143573157a999ce0ef8f5854a1f4bacd4a69 (diff) | |
download | openlmi-providers-78244e3db39e98e3243f82f153cf9ca350904879.tar.gz openlmi-providers-78244e3db39e98e3243f82f153cf9ca350904879.tar.xz openlmi-providers-78244e3db39e98e3243f82f153cf9ca350904879.zip |
service: added dbus based service provider
Diffstat (limited to 'src/service-dbus/util')
-rw-r--r-- | src/service-dbus/util/serviceutil.c | 290 | ||||
-rw-r--r-- | src/service-dbus/util/serviceutil.h | 61 |
2 files changed, 351 insertions, 0 deletions
diff --git a/src/service-dbus/util/serviceutil.c b/src/service-dbus/util/serviceutil.c new file mode 100644 index 0000000..32bd76a --- /dev/null +++ b/src/service-dbus/util/serviceutil.c @@ -0,0 +1,290 @@ +/* + * Copyright (C) 2012-2013 Red Hat, Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Authors: Vitezslav Crhonek <vcrhonek@redhat.com> + * Radek Novacek <rnovacek@redhat.com> + */ + + +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/types.h> +#include <dirent.h> +#include <gio/gio.h> + +#include "serviceutil.h" + +#define MAX_SLIST_CNT 1000 + +#define MANAGER_NAME "org.freedesktop.systemd1" +#define MANAGER_OP "/org/freedesktop/systemd1" +#define MANAGER_INTERFACE "org.freedesktop.systemd1.Manager" +#define UNIT_INTERFACE "org.freedesktop.systemd1.Unit" +#define SERVICE_INTERFACE "org.freedesktop.systemd1.Service" +#define PROPERTY_INTERFACE "org.freedesktop.DBus.Properties" + +void service_free_slist(SList *slist) +{ + int i; + + if (!slist) + return; + + for(i = 0; i < slist->cnt; i++) + free(slist->name[i]); + free(slist->name); + free(slist); + + return; +} + +SList *service_find_all(void) +{ + GDBusProxy *manager_proxy = NULL; + GVariantIter *arr = NULL; + GVariant *result = NULL; + GError *error = NULL; + SList *slist = NULL; + gchar *primary_unit_name = NULL; + char *tmps = NULL; + + g_type_init(); + + manager_proxy = g_dbus_proxy_new_for_bus_sync(G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, + NULL, MANAGER_NAME, MANAGER_OP, MANAGER_INTERFACE, NULL, &error); + if (!manager_proxy) { + g_error_free(error); + return NULL; + } + + error = NULL; + result = g_dbus_proxy_call_sync(manager_proxy, "ListUnitFiles", NULL, + G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); + if (error) { + g_error_free(error); + g_object_unref(manager_proxy); + return NULL; + } + + slist = malloc(sizeof(SList)); + if (!slist) return NULL; + slist->name = malloc(MAX_SLIST_CNT * sizeof(char *)); + if (!slist->name) { + free(slist); + return NULL; + } + slist->cnt = 0; + + g_variant_get(result, "(a(ss))", &arr); + while (g_variant_iter_loop(arr, "(ss)", &primary_unit_name, NULL)) { + if (strstr(primary_unit_name, ".service")) { + tmps = strdup(primary_unit_name); + if (!tmps) + continue; + slist->name[slist->cnt] = strndup(basename(tmps), strlen(basename(tmps))); + if (!slist->name[slist->cnt]) { + free(tmps); + continue; + } + free(tmps); + slist->cnt++; + } + } + g_variant_iter_free(arr); + + g_object_unref(manager_proxy); + return slist; +} + + +int service_get_properties( + Service *svc, + const char *service) +{ + GDBusProxy *manager_proxy = NULL; + GDBusProxy *proxy = NULL; + GVariantIter *arr = NULL; + GVariant *result = NULL; + GVariant *result2 = NULL; + GError *error = NULL; + gchar *fragment_path = NULL, *unit_file_state = NULL; + gchar *unit, *value_str; + unsigned long value_long; + + g_type_init(); + + svc->svName = strdup(service); + if (!svc->svName) return 0; + + manager_proxy = g_dbus_proxy_new_for_bus_sync(G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, + NULL, MANAGER_NAME, MANAGER_OP, MANAGER_INTERFACE, NULL, &error); + if (!manager_proxy) goto error; + + error = NULL; + result = g_dbus_proxy_call_sync(manager_proxy, "ListUnitFiles", NULL, + G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); + if (error) goto error; + + svc->svEnabledDefault = NOT_APPLICABLE; + g_variant_get(result, "(a(ss))", &arr); + while (g_variant_iter_loop(arr, "(ss)", &fragment_path, &unit_file_state)) { + if (strstr(fragment_path, service) && strcmp(strstr(fragment_path, service), service) == 0) { + if (strncmp(unit_file_state, "enabled", 7) == 0) + svc->svEnabledDefault = ENABLED; + if (strncmp(unit_file_state, "disabled", 8) == 0) + svc->svEnabledDefault = DISABLED; + } + } + g_variant_iter_free(arr); + arr = NULL; + + error = NULL; + result = g_dbus_proxy_call_sync(manager_proxy, "LoadUnit", g_variant_new("(s)", service), + G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); + if (error) goto error; + + g_object_unref(manager_proxy); + manager_proxy = NULL; + g_variant_get(result, "(o)", &unit); + + proxy = g_dbus_proxy_new_for_bus_sync(G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, + NULL, MANAGER_NAME, unit, PROPERTY_INTERFACE, NULL, &error); + if (!proxy) goto error; + + error = NULL; + result = g_dbus_proxy_call_sync(proxy, "Get", g_variant_new("(ss)", UNIT_INTERFACE, "Description"), + G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); + if (error) goto error; + + g_variant_get(result, "(v)", &result2); + g_variant_get(result2, "s", &value_str); + svc->svCaption = strdup(value_str); + if (!svc->svCaption) goto error; + + error = NULL; + result = g_dbus_proxy_call_sync(proxy, "Get", g_variant_new("(ss)", SERVICE_INTERFACE, "MainPID"), + G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); + if (error) goto error; + + g_variant_get(result, "(v)", &result2); + g_variant_get(result2, "u", &value_long); + svc->pid = value_long; + + error = NULL; + result = g_dbus_proxy_call_sync(proxy, "Get", g_variant_new("(ss)", UNIT_INTERFACE, "ActiveState"), + G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); + if (error) goto error; + + g_variant_get(result, "(v)", &result2); + g_variant_get(result2, "s", &value_str); + + if (!strcmp(value_str, "active")) { + svc->svOperationalStatus[0] = OS_OK; + svc->svOperationalStatusCnt = 1; + } + else if (!strcmp(value_str, "inactive")) { + svc->svOperationalStatus[0] = OS_COMPLETED; + svc->svOperationalStatus[1] = OS_OK; + svc->svOperationalStatusCnt = 2; + } + else if (!strcmp(value_str, "failed")) { + svc->svOperationalStatus[0] = OS_COMPLETED; + svc->svOperationalStatus[1] = OS_ERROR; + svc->svOperationalStatusCnt = 2; + } + else if (!strcmp(value_str, "activating")) { + svc->svOperationalStatus[0] = OS_STARTING; + svc->svOperationalStatusCnt = 1; + } + else if (!strcmp(value_str, "deactivating")) { + svc->svOperationalStatus[0] = OS_STOPPING; + svc->svOperationalStatusCnt = 1; + } + + if (svc->pid) { + svc->svStarted = 1; + svc->svStatus = strdup("OK"); + } else { + svc->svStarted = 0; + svc->svStatus = strdup("Stopped"); + } + if (!svc->svStatus) goto error; + + g_object_unref(proxy); + return 1; + +error: + if (svc->svName) free(svc->svName); + if (error) g_error_free(error); + if (manager_proxy) g_object_unref(manager_proxy); + if (proxy) g_object_unref(proxy); + if (svc->svCaption) free(svc->svCaption); + + return 0; +} + +unsigned int service_operation( + const char *service, + const char *method, + char *output, + int output_len) +{ + GDBusProxy *manager_proxy = NULL; + GVariant *result = NULL; + GError *error = NULL; + GVariantBuilder *builder; + + g_type_init(); + + manager_proxy = g_dbus_proxy_new_for_bus_sync(G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, + NULL, MANAGER_NAME, MANAGER_OP, MANAGER_INTERFACE, NULL, &error); + if (!manager_proxy) { + g_error_free(error); + return -1; + } + + error = NULL; + if (!strcasecmp(method, "EnableUnitFiles") || !strcasecmp(method, "DisableUnitFiles")) { + builder = g_variant_builder_new(G_VARIANT_TYPE ("as")); + g_variant_builder_add(builder, "s", service); + if (!strcasecmp(method, "EnableUnitFiles")) { + result = g_dbus_proxy_call_sync(manager_proxy, method, g_variant_new("(asbb)", builder, FALSE, TRUE), + G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); + } else { + result = g_dbus_proxy_call_sync(manager_proxy, method, g_variant_new("(asb)", builder, FALSE), + G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); + } + if (error) { + g_error_free(error); + g_object_unref(manager_proxy); + return -1; + } + } else { + result = g_dbus_proxy_call_sync(manager_proxy, method, g_variant_new("(ss)", service, "replace"), + G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); + if (error) { + g_error_free(error); + g_object_unref(manager_proxy); + return -1; + } + } + + g_object_unref(manager_proxy); + return 0; +} diff --git a/src/service-dbus/util/serviceutil.h b/src/service-dbus/util/serviceutil.h new file mode 100644 index 0000000..d3dcc33 --- /dev/null +++ b/src/service-dbus/util/serviceutil.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2012-2013 Red Hat, Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Authors: Vitezslav Crhonek <vcrhonek@redhat.com> + */ + + +#ifndef SERVICEUTIL_H +#define SERVICEUTIL_H + +#include <stdio.h> + +#define ARRAY_SIZE(name) (sizeof(name) / sizeof(name[0])) + +enum OperationalStatus {OS_UNKNOWN = 0, OS_OK = 2, OS_ERROR = 6, OS_STARTING = 8, OS_STOPPING = 9, OS_STOPPED = 10, OS_COMPLETED = 17}; +enum ServiceEnabledDefault {ENABLED = 2, DISABLED = 3, NOT_APPLICABLE = 5}; + +struct _Service { + char *svSystemCCname; + char *svSystemname; + char *svCCname; + char *svName; /* "rsyslog.service", "httpd.service", ... */ + char *svCaption; /* "Description" field from unit file */ + enum OperationalStatus svOperationalStatus[2]; /* see enum definition - current status of the element */ + int svOperationalStatusCnt; + char *svStatus; /* "Stopped", "OK" - deprecated, but recommended to fill */ + enum ServiceEnabledDefault svEnabledDefault; + int svStarted; /* 0, 1 */ + int pid; /* PID */ +}; + +struct _SList { + char **name; + int cnt; +}; + +typedef struct _Service Service; +typedef struct _SList SList; + +void service_free_slist(SList *slist); +SList *service_find_all(void); + +int service_get_properties(Service *svc, const char *service); + +unsigned int service_operation(const char *service, const char *method, char *output, int output_len); + +#endif |