On 10/19/2011 08:30 AM, Radek Novacek wrote:
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 Novacekrnovacek@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();
Can you add void to the arguments list? I thought I remembered getting compiler warnings without it at some point ... I don't remember what the circumstances were, though.
resources_list_standards(void);
The docs say the elements are gchar *, but they appear to just be char *.
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"));
typo: should be ocf instead of 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
Should we make all of these strcasecmp()? I think so ...
} 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" };
This needs to be NULL terminated.
- if (!(action = mh_services_action_create_generic(SYSTEMCTL, args))) {
return NULL;
- }
- if (!services_action_sync(action)) {
memory leak here. Free the services action.
return NULL;
- }
- ptr = action->stdout_data;
- // Skip first line with column labels
- while ((ptr = strchr(ptr, '\n')) != NULL)
- {
Move { up a line.
// 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';
mh_string_copy() will save you from having to manually set the terminator here.
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(),