Add systemd as a standard for Resources. It uses systemctl command to list
services and invoke actions.
List of supported standards has been moved from agents to services
library. It's now function instead of global list.
Signed-off-by: Radek Novacek <rnovacek(a)redhat.com>
---
src/include/matahari/services.h | 11 +++++++++
src/lib/services.c | 27 +++++++++++++++++++++++
src/lib/services_linux.c | 38 ++++++++++++++++++++++++++++++++
src/lib/services_private.h | 3 ++
src/service/service-dbus.c | 45 +++++++++++++++++---------------------
src/service/service-qmf.cpp | 44 ++++++++++++++++---------------------
6 files changed, 118 insertions(+), 50 deletions(-)
diff --git a/src/include/matahari/services.h b/src/include/matahari/services.h
index 82d0aa9..56d07d4 100644
--- a/src/include/matahari/services.h
+++ b/src/include/matahari/services.h
@@ -33,6 +33,8 @@
#define OCF_ROOT "/usr/lib/ocf"
#define LSB_ROOT "/etc/init.d"
+#define SYSTEMCTL "/bin/systemctl"
+
enum lsb_exitcode {
LSB_OK = 0,
LSB_UNKNOWN_ERROR = 1,
@@ -180,6 +182,15 @@ resources_list_providers(const char *standard);
GList *
resources_list_agents(const char *standard, const char *provider);
+/**
+ * Get list of available standards
+ *
+ * \return a list of resource standards. The list items are gchar *. This list _must_
+ * be destroyed using g_list_free_full(list, free).
+ */
+GList *
+resources_list_standards();
+
svc_action_t *
services_action_create(const char *name, const char *action,
int interval /* ms */, int timeout /* ms */);
diff --git a/src/lib/services.c b/src/lib/services.c
index 6ab5a66..e6270cc 100644
--- a/src/lib/services.c
+++ b/src/lib/services.c
@@ -108,6 +108,13 @@ svc_action_t *resources_action_create(
} else if(strcmp(standard, "lsb") == 0 || strcmp(standard,
"windows") == 0) {
services_os_set_exec(op);
+ } else if(strcmp(standard, "systemd") == 0) {
+ char *service;
+ op->opaque->exec = strdup(SYSTEMCTL);
+ op->opaque->args[0] = strdup(SYSTEMCTL);
+ op->opaque->args[1] = strdup(action);
+ asprintf(&service, "%s.service", agent);
+ op->opaque->args[2] = service;
} else {
mh_err("Unknown resource standard: %s", standard);
services_action_free(op);
@@ -253,6 +260,22 @@ services_list(void)
}
GList *
+resources_list_standards(void)
+{
+ GList *standards = NULL;
+#ifdef __linux__
+ standards = g_list_append(standards, strdup("ofc"));
+ standards = g_list_append(standards, strdup("lsb"));
+ if (g_file_test(SYSTEMCTL, G_FILE_TEST_IS_REGULAR))
+ standards = g_list_append(standards, strdup("systemd"));
+#endif
+#ifdef WIN32
+ standards = g_list_append(standards, strdup("windows"));
+#endif
+ return standards;
+}
+
+GList *
resources_list_providers(const char *standard)
{
if(strcmp(standard, "ocf") == 0) {
@@ -271,6 +294,10 @@ resources_list_agents(const char *standard, const char *provider)
} else if(strcmp(standard, "lsb") == 0
|| strcmp(standard, "windows") == 0) {
return services_os_list();
+#ifdef __linux__
+ } else if(strcmp(standard, "systemd") == 0) {
+ return resources_os_list_systemd_services();
+#endif
}
return NULL;
diff --git a/src/lib/services_linux.c b/src/lib/services_linux.c
index 7760913..c50bdef 100644
--- a/src/lib/services_linux.c
+++ b/src/lib/services_linux.c
@@ -503,3 +503,41 @@ resources_os_list_ocf_agents(const char *provider)
}
return NULL;
}
+
+GList *
+resources_os_list_systemd_services(void)
+{
+ GList *list = NULL;
+ char *ptr, *service, *end;
+ svc_action_t *action;
+ int len;
+ const char *args[] = { "list-units", "--all",
+ "--type=service", "--full",
"--no-pager" };
+
+ if (!(action = mh_services_action_create_generic(SYSTEMCTL, args))) {
+ return NULL;
+ }
+ if (!services_action_sync(action)) {
+ return NULL;
+ }
+ ptr = action->stdout_data;
+ // Skip first line with column labels
+ while ((ptr = strchr(ptr, '\n')) != NULL)
+ {
+ // Skip the line break
+ ptr++;
+
+ // Read beggining of the line until ".service"
+ if (!(end = strstr(ptr, ".service")))
+ break;
+ // Length of service name
+ len = end - ptr;
+ // Append the name to the list of services
+ service = malloc(sizeof(char) * (len + 1));
+ service = strncpy(service, ptr, len);
+ service[len] = '\0';
+ list = g_list_append(list, service);
+ }
+ services_action_free(action);
+ return list;
+}
diff --git a/src/lib/services_private.h b/src/lib/services_private.h
index d7931dc..6406b17 100644
--- a/src/lib/services_private.h
+++ b/src/lib/services_private.h
@@ -51,4 +51,7 @@ resources_os_list_ocf_providers(void);
GList *
resources_os_list_ocf_agents(const char *provider);
+GList *
+resources_os_list_systemd_services(void);
+
#endif /* __MH_SERVICES_PRIVATE_H__ */
diff --git a/src/service/service-dbus.c b/src/service/service-dbus.c
index aefb842..95ea986 100644
--- a/src/service/service-dbus.c
+++ b/src/service/service-dbus.c
@@ -229,22 +229,14 @@ Services_describe(Matahari *matahari, const char *name,
return TRUE;
}
-// TODO: This and same code in service-qmf.cpp should go to the library
-const char *standards[] = {
-#ifdef __linux__
- "ocf",
-#endif
- "lsb",
-#ifndef WIN32
- "windows",
-#endif
- NULL};
-
-
gboolean
Resources_list_standards(Matahari *matahari, DBusGMethodInvocation *context)
{
GError* error = NULL;
+ gchar **list;
+ int i = 0;
+ GList *standards;
+
if (!check_authorization(RESOURCES_INTERFACE_NAME ".list_standards",
&error, context)) {
dbus_g_method_return_error(context, error);
@@ -252,7 +244,17 @@ Resources_list_standards(Matahari *matahari, DBusGMethodInvocation
*context)
return FALSE;
}
- dbus_g_method_return(context, standards);
+ standards = resources_list_standards();
+
+ // Convert GList to (char **)
+ list = g_new(char *, g_list_length(standards) + 1);
+ for (; standards != NULL; standards = standards->next)
+ list[i++] = strdup(standards->data);
+ list[i] = NULL; // Sentinel
+
+ dbus_g_method_return(context, list);
+ g_strfreev(list);
+ g_list_free_full(standards, free);
return TRUE;
}
@@ -350,10 +352,9 @@ Resources_invoke(Matahari *matahari, const char *name, const char
*standard,
unsigned int timeout, unsigned int expected_rc,
const char *userdata_in, DBusGMethodInvocation *context)
{
- int i = 0;
GError* error = NULL;
svc_action_t *op = NULL;
- gboolean valid_standard = FALSE;
+ GList *standards;
if (!check_authorization(RESOURCES_INTERFACE_NAME ".invoke",
&error, context)) {
@@ -363,16 +364,9 @@ Resources_invoke(Matahari *matahari, const char *name, const char
*standard,
}
// Check if standard is valid
- while (standards[i] != NULL)
- {
- if (strcmp(standard, standards[i]) == 0)
- {
- valid_standard = TRUE;
- break;
- }
- i++;
- }
- if (!valid_standard) {
+ standards = resources_list_standards();
+
+ if (g_list_find_custom(standards, standard, (GCompareFunc) strcmp) == NULL) {
mh_err("%s is not a known resource standard", standard);
error = g_error_new(MATAHARI_ERROR, MH_RES_NOT_IMPLEMENTED,
"%s is not a known resource standard", standard);
@@ -387,6 +381,7 @@ Resources_invoke(Matahari *matahari, const char *name, const char
*standard,
services_action_sync(op); //TODO: maybe async
dbus_g_method_return(context, op->rc, op->sequence, userdata_in);
+ g_list_free_full(standards, free);
return TRUE;
}
diff --git a/src/service/service-qmf.cpp b/src/service/service-qmf.cpp
index 63f5db2..b40f2ce 100644
--- a/src/service/service-qmf.cpp
+++ b/src/service/service-qmf.cpp
@@ -55,8 +55,6 @@ private:
qmf::Data _resources;
static const char RESOURCES_NAME[];
- _qtype::Variant::List standards;
-
gboolean invoke_services(qmf::AgentSession session,
qmf::AgentEvent event, gpointer user_data);
gboolean invoke_resources(qmf::AgentSession session,
@@ -219,14 +217,6 @@ SrvAgent::raiseEvent(svc_action_t *op, enum service_id service, const
std::strin
int
SrvAgent::setup(qmf::AgentSession session)
{
-#ifdef __linux__
- standards.push_back("ocf");
- standards.push_back("lsb");
-#endif
-#ifndef WIN32
- standards.push_back("windows");
-#endif
-
_package.configure(session);
_services = qmf::Data(_package.data_Services);
@@ -347,7 +337,17 @@ SrvAgent::invoke_resources(qmf::AgentSession session, qmf::AgentEvent
event,
qpid::types::Variant::Map& args = event.getArguments();
if (methodName == "list_standards") {
- event.addReturnArgument("standards", standards);
+ GList *gIter = NULL;
+ GList *standards = NULL;
+ _qtype::Variant::List s_list;
+
+ standards = resources_list_standards();
+ for (gIter = standards; gIter != NULL; gIter = gIter->next) {
+ s_list.push_back((const char *) gIter->data);
+ }
+ g_list_free_full(standards, free);
+
+ event.addReturnArgument("standards", s_list);
} else if (methodName == "list_providers") {
GList *gIter = NULL;
@@ -387,7 +387,6 @@ SrvAgent::invoke_resources(qmf::AgentSession session, qmf::AgentEvent
event,
} else if (methodName == "invoke") {
svc_action_t *op = NULL;
- bool valid_standard = false;
_qtype::Variant::List::iterator iter;
_qtype::Variant::Map map;
@@ -403,19 +402,6 @@ SrvAgent::invoke_resources(qmf::AgentSession session, qmf::AgentEvent
event,
std::string standard("ocf");
std::string provider("heartbeat");
- for ( iter=standards.begin() ; iter != standards.end(); iter++ ) {
- if(args["standard"].asString() == (*iter).asString()) {
- valid_standard = true;
- break;
- }
- }
-
- if(valid_standard == false) {
- mh_err("%s is not a known resource standard",
args["standard"].asString().c_str());
- session.raiseException(event, mh_result_to_str(MH_RES_NOT_IMPLEMENTED));
- return TRUE;
- }
-
if (args.count("standard")) {
standard = args["standard"].asString();
}
@@ -435,6 +421,14 @@ SrvAgent::invoke_resources(qmf::AgentSession session, qmf::AgentEvent
event,
timeout = args["timeout"].asInt32();
}
+ GList *standards = resources_list_standards();
+
+ if (g_list_find_custom(standards, standard.c_str(), (GCompareFunc) strcmp) ==
NULL) {
+ mh_err("%s is not a known resource standard", standard.c_str());
+ session.raiseException(event, mh_result_to_str(MH_RES_NOT_IMPLEMENTED));
+ return TRUE;
+ }
+
op = resources_action_create(
args["name"].asString().c_str(),
standard.c_str(), provider.c_str(), agent.c_str(),
--
1.7.6.4