pacemaker  1.1.16-94ff4df
Scalable High-Availability cluster resource manager
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Modules
services.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2010-2016 Andrew Beekhof <andrew@beekhof.net>
3  *
4  * This source code is licensed under the GNU Lesser General Public License
5  * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
6  */
7 
8 #include <crm_internal.h>
9 
10 #ifndef _GNU_SOURCE
11 # define _GNU_SOURCE
12 #endif
13 
14 #include <sys/types.h>
15 #include <sys/stat.h>
16 #include <stdio.h>
17 
18 #include <errno.h>
19 #include <unistd.h>
20 #include <dirent.h>
21 #include <fcntl.h>
22 
23 #include <crm/crm.h>
24 #include <crm/common/mainloop.h>
25 #include <crm/services.h>
26 #include <crm/msg_xml.h>
27 #include "services_private.h"
28 
29 #if SUPPORT_UPSTART
30 # include <upstart.h>
31 #endif
32 
33 #if SUPPORT_SYSTEMD
34 # include <systemd.h>
35 #endif
36 
37 /* TODO: Develop a rollover strategy */
38 
39 static int operations = 0;
40 GHashTable *recurring_actions = NULL;
41 
42 /* ops waiting to run async because of conflicting active
43  * pending ops*/
44 GList *blocked_ops = NULL;
45 
46 /* ops currently active (in-flight) */
47 GList *inflight_ops = NULL;
48 
50 services_action_create(const char *name, const char *action, int interval, int timeout)
51 {
52  return resources_action_create(name, "lsb", NULL, name, action, interval, timeout, NULL, 0);
53 }
54 
55 const char *
56 resources_find_service_class(const char *agent)
57 {
58  /* Priority is:
59  * - lsb
60  * - systemd
61  * - upstart
62  */
63  int rc = 0;
64  struct stat st;
65  char *path = NULL;
66 
67 #ifdef LSB_ROOT_DIR
68  rc = asprintf(&path, "%s/%s", LSB_ROOT_DIR, agent);
69  if (rc > 0 && stat(path, &st) == 0) {
70  free(path);
71  return "lsb";
72  }
73  free(path);
74 #endif
75 
76 #if SUPPORT_SYSTEMD
77  if (systemd_unit_exists(agent)) {
78  return "systemd";
79  }
80 #endif
81 
82 #if SUPPORT_UPSTART
83  if (upstart_job_exists(agent)) {
84  return "upstart";
85  }
86 #endif
87  return NULL;
88 }
89 
90 
92 resources_action_create(const char *name, const char *standard, const char *provider,
93  const char *agent, const char *action, int interval, int timeout,
94  GHashTable * params, enum svc_action_flags flags)
95 {
96  svc_action_t *op = NULL;
97 
98  /*
99  * Do some up front sanity checks before we go off and
100  * build the svc_action_t instance.
101  */
102 
103  if (crm_strlen_zero(name)) {
104  crm_err("A service or resource action must have a name.");
105  goto return_error;
106  }
107 
108  if (crm_strlen_zero(standard)) {
109  crm_err("A service action must have a valid standard.");
110  goto return_error;
111  }
112 
113  if (!strcasecmp(standard, "ocf") && crm_strlen_zero(provider)) {
114  crm_err("An OCF resource action must have a provider.");
115  goto return_error;
116  }
117 
118  if (crm_strlen_zero(agent)) {
119  crm_err("A service or resource action must have an agent.");
120  goto return_error;
121  }
122 
123  if (crm_strlen_zero(action)) {
124  crm_err("A service or resource action must specify an action.");
125  goto return_error;
126  }
127 
128  if (safe_str_eq(action, "monitor") && (
130  safe_str_eq(standard, "heartbeat") ||
131 #endif
132  safe_str_eq(standard, "lsb") || safe_str_eq(standard, "service"))) {
133  action = "status";
134  }
135 
136  /*
137  * Sanity checks passed, proceed!
138  */
139 
140  op = calloc(1, sizeof(svc_action_t));
141  op->opaque = calloc(1, sizeof(svc_action_private_t));
142  op->rsc = strdup(name);
143  op->action = strdup(action);
144  op->interval = interval;
145  op->timeout = timeout;
146  op->standard = strdup(standard);
147  op->agent = strdup(agent);
148  op->sequence = ++operations;
149  op->flags = flags;
150 
151  if (asprintf(&op->id, "%s_%s_%d", name, action, interval) == -1) {
152  goto return_error;
153  }
154 
155  if (strcasecmp(op->standard, "service") == 0) {
156  const char *expanded = resources_find_service_class(op->agent);
157 
158  if(expanded) {
159  crm_debug("Found a %s agent for %s/%s", expanded, op->rsc, op->agent);
160  free(op->standard);
161  op->standard = strdup(expanded);
162 
163  } else {
164  crm_info("Cannot determine the standard for %s (%s)", op->rsc, op->agent);
165  free(op->standard);
166  op->standard = strdup("lsb");
167  }
168  CRM_ASSERT(op->standard);
169  }
170 
171  if (strcasecmp(op->standard, "ocf") == 0) {
172  op->provider = strdup(provider);
173  op->params = params;
174  params = NULL;
175 
176  if (asprintf(&op->opaque->exec, "%s/resource.d/%s/%s", OCF_ROOT_DIR, provider, agent) == -1) {
177  crm_err("Internal error: cannot create agent path");
178  goto return_error;
179  }
180  op->opaque->args[0] = strdup(op->opaque->exec);
181  op->opaque->args[1] = strdup(action);
182 
183  } else if (strcasecmp(op->standard, "lsb") == 0) {
184  if (op->agent[0] == '/') {
185  /* if given an absolute path, use that instead
186  * of tacking on the LSB_ROOT_DIR path to the front */
187  op->opaque->exec = strdup(op->agent);
188  } else if (asprintf(&op->opaque->exec, "%s/%s", LSB_ROOT_DIR, op->agent) == -1) {
189  crm_err("Internal error: cannot create agent path");
190  goto return_error;
191  }
192  op->opaque->args[0] = strdup(op->opaque->exec);
193  op->opaque->args[1] = strdup(op->action);
194  op->opaque->args[2] = NULL;
195 #if SUPPORT_HEARTBEAT
196  } else if (strcasecmp(op->standard, "heartbeat") == 0) {
197  int index;
198  int param_num;
199  char buf_tmp[20];
200  void *value_tmp;
201 
202  if (op->agent[0] == '/') {
203  /* if given an absolute path, use that instead
204  * of tacking on the HB_RA_DIR path to the front */
205  op->opaque->exec = strdup(op->agent);
206  } else if (asprintf(&op->opaque->exec, "%s/%s", HB_RA_DIR, op->agent) == -1) {
207  crm_err("Internal error: cannot create agent path");
208  goto return_error;
209  }
210  op->opaque->args[0] = strdup(op->opaque->exec);
211 
212  /* The "heartbeat" agent class only has positional arguments,
213  * which we keyed by their decimal position number. */
214  param_num = 1;
215  for (index = 1; index <= MAX_ARGC - 3; index++ ) {
216  snprintf(buf_tmp, sizeof(buf_tmp), "%d", index);
217  value_tmp = g_hash_table_lookup(params, buf_tmp);
218  if (value_tmp == NULL) {
219  /* maybe: strdup("") ??
220  * But the old lrmd did simply continue as well. */
221  continue;
222  }
223  op->opaque->args[param_num++] = strdup(value_tmp);
224  }
225 
226  /* Add operation code as the last argument, */
227  /* and the teminating NULL pointer */
228  op->opaque->args[param_num++] = strdup(op->action);
229  op->opaque->args[param_num] = NULL;
230 #endif
231 #if SUPPORT_SYSTEMD
232  } else if (strcasecmp(op->standard, "systemd") == 0) {
233  op->opaque->exec = strdup("systemd-dbus");
234 #endif
235 #if SUPPORT_UPSTART
236  } else if (strcasecmp(op->standard, "upstart") == 0) {
237  op->opaque->exec = strdup("upstart-dbus");
238 #endif
239  } else if (strcasecmp(op->standard, "service") == 0) {
240  op->opaque->exec = strdup(SERVICE_SCRIPT);
241  op->opaque->args[0] = strdup(SERVICE_SCRIPT);
242  op->opaque->args[1] = strdup(agent);
243  op->opaque->args[2] = strdup(action);
244 
245 #if SUPPORT_NAGIOS
246  } else if (strcasecmp(op->standard, "nagios") == 0) {
247  int index = 0;
248 
249  if (op->agent[0] == '/') {
250  /* if given an absolute path, use that instead
251  * of tacking on the NAGIOS_PLUGIN_DIR path to the front */
252  op->opaque->exec = strdup(op->agent);
253 
254  } else if (asprintf(&op->opaque->exec, "%s/%s", NAGIOS_PLUGIN_DIR, op->agent) == -1) {
255  crm_err("Internal error: cannot create agent path");
256  goto return_error;
257  }
258 
259  op->opaque->args[0] = strdup(op->opaque->exec);
260  index = 1;
261 
262  if (safe_str_eq(op->action, "monitor") && op->interval == 0) {
263  /* Invoke --version for a nagios probe */
264  op->opaque->args[index] = strdup("--version");
265  index++;
266 
267  } else if (params) {
268  GHashTableIter iter;
269  char *key = NULL;
270  char *value = NULL;
271  static int args_size = sizeof(op->opaque->args) / sizeof(char *);
272 
273  g_hash_table_iter_init(&iter, params);
274 
275  while (g_hash_table_iter_next(&iter, (gpointer *) & key, (gpointer *) & value) &&
276  index <= args_size - 3) {
277  int len = 3;
278  char *long_opt = NULL;
279 
280  if (safe_str_eq(key, XML_ATTR_CRM_VERSION) || strstr(key, CRM_META "_")) {
281  continue;
282  }
283 
284  len += strlen(key);
285  long_opt = calloc(1, len);
286  sprintf(long_opt, "--%s", key);
287  long_opt[len - 1] = 0;
288 
289  op->opaque->args[index] = long_opt;
290  op->opaque->args[index + 1] = strdup(value);
291  index += 2;
292  }
293  }
294  op->opaque->args[index] = NULL;
295 #endif
296 
297  } else {
298  crm_err("Unknown resource standard: %s", op->standard);
300  op = NULL;
301  }
302 
303  if(params) {
304  g_hash_table_destroy(params);
305  }
306  return op;
307 
308  return_error:
309  if(params) {
310  g_hash_table_destroy(params);
311  }
313 
314  return NULL;
315 }
316 
317 svc_action_t *
318 services_action_create_generic(const char *exec, const char *args[])
319 {
320  svc_action_t *op;
321  unsigned int cur_arg;
322 
323  op = calloc(1, sizeof(*op));
324  op->opaque = calloc(1, sizeof(svc_action_private_t));
325 
326  op->opaque->exec = strdup(exec);
327  op->opaque->args[0] = strdup(exec);
328 
329  for (cur_arg = 1; args && args[cur_arg - 1]; cur_arg++) {
330  op->opaque->args[cur_arg] = strdup(args[cur_arg - 1]);
331 
332  if (cur_arg == DIMOF(op->opaque->args) - 1) {
333  crm_err("svc_action_t args list not long enough for '%s' execution request.", exec);
334  break;
335  }
336  }
337 
338  return op;
339 }
340 
341 #if SUPPORT_DBUS
342 
349 void
350 services_set_op_pending(svc_action_t *op, DBusPendingCall *pending)
351 {
352  if (op->opaque->pending && (op->opaque->pending != pending)) {
353  if (pending) {
354  crm_info("Lost pending %s DBus call (%p)", op->id, op->opaque->pending);
355  } else {
356  crm_trace("Done with pending %s DBus call (%p)", op->id, op->opaque->pending);
357  }
358  dbus_pending_call_unref(op->opaque->pending);
359  }
360  op->opaque->pending = pending;
361  if (pending) {
362  crm_trace("Updated pending %s DBus call (%p)", op->id, pending);
363  } else {
364  crm_trace("Cleared pending %s DBus call", op->id);
365  }
366 }
367 #endif
368 
369 void
371 {
372  if(op->opaque == NULL) {
373  return;
374  }
375 
376 #if SUPPORT_DBUS
377  if(op->opaque->timerid != 0) {
378  crm_trace("Removing timer for call %s to %s", op->action, op->rsc);
379  g_source_remove(op->opaque->timerid);
380  op->opaque->timerid = 0;
381  }
382 
383  if(op->opaque->pending) {
384  crm_trace("Cleaning up pending dbus call %p %s for %s", op->opaque->pending, op->action, op->rsc);
385  if(dbus_pending_call_get_completed(op->opaque->pending)) {
386  crm_warn("Pending dbus call %s for %s did not complete", op->action, op->rsc);
387  }
388  dbus_pending_call_cancel(op->opaque->pending);
389  dbus_pending_call_unref(op->opaque->pending);
390  op->opaque->pending = NULL;
391  }
392 #endif
393 
394  if (op->opaque->stderr_gsource) {
396  op->opaque->stderr_gsource = NULL;
397  }
398 
399  if (op->opaque->stdout_gsource) {
401  op->opaque->stdout_gsource = NULL;
402  }
403 }
404 
405 void
407 {
408  unsigned int i;
409 
410  if (op == NULL) {
411  return;
412  }
413 
415 
416  if (op->opaque->repeat_timer) {
417  g_source_remove(op->opaque->repeat_timer);
418  op->opaque->repeat_timer = 0;
419  }
420 
421  free(op->id);
422  free(op->opaque->exec);
423 
424  for (i = 0; i < DIMOF(op->opaque->args); i++) {
425  free(op->opaque->args[i]);
426  }
427 
428  free(op->opaque);
429  free(op->rsc);
430  free(op->action);
431 
432  free(op->standard);
433  free(op->agent);
434  free(op->provider);
435 
436  free(op->stdout_data);
437  free(op->stderr_data);
438 
439  if (op->params) {
440  g_hash_table_destroy(op->params);
441  op->params = NULL;
442  }
443 
444  free(op);
445 }
446 
447 gboolean
449 {
450  crm_info("Cancelling %s operation %s", op->standard, op->id);
451 
452  if (recurring_actions) {
453  g_hash_table_remove(recurring_actions, op->id);
454  }
455 
456  if (op->opaque->repeat_timer) {
457  g_source_remove(op->opaque->repeat_timer);
458  op->opaque->repeat_timer = 0;
459  }
460 
461  return TRUE;
462 }
463 
464 gboolean
465 services_action_cancel(const char *name, const char *action, int interval)
466 {
467  svc_action_t *op = NULL;
468  char id[512];
469 
470  snprintf(id, sizeof(id), "%s_%s_%d", name, action, interval);
471 
472  if (!(op = g_hash_table_lookup(recurring_actions, id))) {
473  return FALSE;
474  }
475 
476  /* Always kill the recurring timer */
478 
479  if (op->pid == 0) {
481  if (op->opaque->callback) {
482  op->opaque->callback(op);
483  }
484 
485  blocked_ops = g_list_remove(blocked_ops, op);
487 
488  } else {
489  crm_info("Cancelling in-flight op: performing early termination of %s (pid=%d)", id, op->pid);
490  op->cancel = 1;
491  if (mainloop_child_kill(op->pid) == FALSE) {
492  /* even though the early termination failed,
493  * the op will be marked as cancelled once it completes. */
494  crm_err("Termination of %s (pid=%d) failed", id, op->pid);
495  return FALSE;
496  }
497  }
498 
499  return TRUE;
500 }
501 
502 gboolean
503 services_action_kick(const char *name, const char *action, int interval /* ms */)
504 {
505  svc_action_t * op = NULL;
506  char *id = NULL;
507 
508  if (asprintf(&id, "%s_%s_%d", name, action, interval) == -1) {
509  return FALSE;
510  }
511 
512  op = g_hash_table_lookup(recurring_actions, id);
513  free(id);
514 
515  if (op == NULL) {
516  return FALSE;
517  }
518 
519  if (op->pid) {
520  return TRUE;
521  } else {
522  if (op->opaque->repeat_timer) {
523  g_source_remove(op->opaque->repeat_timer);
524  op->opaque->repeat_timer = 0;
525  }
527  return TRUE;
528  }
529 
530 }
531 
532 /* add new recurring operation, check for duplicates.
533  * - if duplicate found, return TRUE, immediately reschedule op.
534  * - if no dup, return FALSE, inserve into recurring op list.*/
535 static gboolean
536 handle_duplicate_recurring(svc_action_t * op, void (*action_callback) (svc_action_t *))
537 {
538  svc_action_t * dup = NULL;
539 
540  if (recurring_actions == NULL) {
541  recurring_actions = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL);
542  return FALSE;
543  }
544 
545  /* check for duplicates */
546  dup = g_hash_table_lookup(recurring_actions, op->id);
547 
548  if (dup && (dup != op)) {
549  /* update user data */
550  if (op->opaque->callback) {
551  dup->opaque->callback = op->opaque->callback;
552  dup->cb_data = op->cb_data;
553  op->cb_data = NULL;
554  }
555  /* immediately execute the next interval */
556  if (dup->pid != 0) {
557  if (op->opaque->repeat_timer) {
558  g_source_remove(op->opaque->repeat_timer);
559  op->opaque->repeat_timer = 0;
560  }
562  }
563  /* free the dup. */
565  return TRUE;
566  }
567 
568  return FALSE;
569 }
570 
571 static gboolean
572 action_async_helper(svc_action_t * op)
573 {
574  if (op->standard && strcasecmp(op->standard, "upstart") == 0) {
575 #if SUPPORT_UPSTART
576  return upstart_job_exec(op, FALSE);
577 #endif
578  } else if (op->standard && strcasecmp(op->standard, "systemd") == 0) {
579 #if SUPPORT_SYSTEMD
580  return systemd_unit_exec(op);
581 #endif
582  } else {
583  return services_os_action_execute(op, FALSE);
584  }
585  /* The 'op' has probably been freed if the execution functions return TRUE. */
586  /* Avoid using the 'op' in here. */
587 
588  return FALSE;
589 }
590 
591 void
593 {
594  if (op == NULL) {
595  return;
596  }
597 
598  CRM_ASSERT(op->synchronous == FALSE);
599 
600  /* keep track of ops that are in-flight to avoid collisions in the same namespace */
601  if (op->rsc) {
602  inflight_ops = g_list_append(inflight_ops, op);
603  }
604 }
605 
606 gboolean
607 services_action_async(svc_action_t * op, void (*action_callback) (svc_action_t *))
608 {
609  op->synchronous = false;
610  if (action_callback) {
611  op->opaque->callback = action_callback;
612  }
613 
614  if (op->interval > 0) {
615  if (handle_duplicate_recurring(op, action_callback) == TRUE) {
616  /* entry rescheduled, dup freed */
617  /* exit early */
618  return TRUE;
619  }
620  g_hash_table_replace(recurring_actions, op->id, op);
621  }
622 
623  if (op->rsc && is_op_blocked(op->rsc)) {
624  blocked_ops = g_list_append(blocked_ops, op);
625  return TRUE;
626  }
627 
628  return action_async_helper(op);
629 }
630 
631 
632 static gboolean processing_blocked_ops = FALSE;
633 
634 gboolean
635 is_op_blocked(const char *rsc)
636 {
637  GList *gIter = NULL;
638  svc_action_t *op = NULL;
639 
640  for (gIter = inflight_ops; gIter != NULL; gIter = gIter->next) {
641  op = gIter->data;
642  if (safe_str_eq(op->rsc, rsc)) {
643  return TRUE;
644  }
645  }
646 
647  return FALSE;
648 }
649 
650 void
652 {
653  GList *executed_ops = NULL;
654  GList *gIter = NULL;
655  svc_action_t *op = NULL;
656  gboolean res = FALSE;
657 
658  if (processing_blocked_ops) {
659  /* avoid nested calling of this function */
660  return;
661  }
662 
663  processing_blocked_ops = TRUE;
664 
665  /* n^2 operation here, but blocked ops are incredibly rare. this list
666  * will be empty 99% of the time. */
667  for (gIter = blocked_ops; gIter != NULL; gIter = gIter->next) {
668  op = gIter->data;
669  if (is_op_blocked(op->rsc)) {
670  continue;
671  }
672  executed_ops = g_list_append(executed_ops, op);
673  res = action_async_helper(op);
674  if (res == FALSE) {
676  /* this can cause this function to be called recursively
677  * which is why we have processing_blocked_ops static variable */
678  operation_finalize(op);
679  }
680  }
681 
682  for (gIter = executed_ops; gIter != NULL; gIter = gIter->next) {
683  op = gIter->data;
684  blocked_ops = g_list_remove(blocked_ops, op);
685  }
686  g_list_free(executed_ops);
687 
688  processing_blocked_ops = FALSE;
689 }
690 
691 gboolean
693 {
694  gboolean rc = TRUE;
695 
696  if (op == NULL) {
697  crm_trace("No operation to execute");
698  return FALSE;
699  }
700 
701  op->synchronous = true;
702  if (op->standard && strcasecmp(op->standard, "upstart") == 0) {
703 #if SUPPORT_UPSTART
704  rc = upstart_job_exec(op, TRUE);
705 #endif
706  } else if (op->standard && strcasecmp(op->standard, "systemd") == 0) {
707 #if SUPPORT_SYSTEMD
708  rc = systemd_unit_exec(op);
709 #endif
710  } else {
711  rc = services_os_action_execute(op, TRUE);
712  }
713  crm_trace(" > %s_%s_%d: %s = %d", op->rsc, op->action, op->interval, op->opaque->exec, op->rc);
714  if (op->stdout_data) {
715  crm_trace(" > stdout: %s", op->stdout_data);
716  }
717  if (op->stderr_data) {
718  crm_trace(" > stderr: %s", op->stderr_data);
719  }
720  return rc;
721 }
722 
723 GList *
724 get_directory_list(const char *root, gboolean files, gboolean executable)
725 {
726  return services_os_get_directory_list(root, files, executable);
727 }
728 
729 GList *
731 {
732  return resources_list_agents("lsb", NULL);
733 }
734 
735 #if SUPPORT_HEARTBEAT
736 static GList *
737 resources_os_list_hb_agents(void)
738 {
739  return services_os_get_directory_list(HB_RA_DIR, TRUE, TRUE);
740 }
741 #endif
742 
743 GList *
745 {
746  GList *standards = NULL;
747  GList *agents = NULL;
748 
749  standards = g_list_append(standards, strdup("ocf"));
750  standards = g_list_append(standards, strdup("lsb"));
751  standards = g_list_append(standards, strdup("service"));
752 
753 #if SUPPORT_SYSTEMD
754  agents = systemd_unit_listall();
755  if (agents) {
756  standards = g_list_append(standards, strdup("systemd"));
757  g_list_free_full(agents, free);
758  }
759 #endif
760 
761 #if SUPPORT_UPSTART
762  agents = upstart_job_listall();
763  if (agents) {
764  standards = g_list_append(standards, strdup("upstart"));
765  g_list_free_full(agents, free);
766  }
767 #endif
768 
769 #if SUPPORT_NAGIOS
771  if (agents) {
772  standards = g_list_append(standards, strdup("nagios"));
773  g_list_free_full(agents, free);
774  }
775 #endif
776 
777 #if SUPPORT_HEARTBEAT
778  standards = g_list_append(standards, strdup("heartbeat"));
779 #endif
780 
781  return standards;
782 }
783 
784 GList *
785 resources_list_providers(const char *standard)
786 {
787  if (strcasecmp(standard, "ocf") == 0) {
789  }
790 
791  return NULL;
792 }
793 
794 GList *
795 resources_list_agents(const char *standard, const char *provider)
796 {
797  if (standard == NULL || strcasecmp(standard, "service") == 0) {
798  GList *tmp1;
799  GList *tmp2;
800  GList *result = resources_os_list_lsb_agents();
801 
802  if (standard == NULL) {
803  tmp1 = result;
804  tmp2 = resources_os_list_ocf_agents(NULL);
805  if (tmp2) {
806  result = g_list_concat(tmp1, tmp2);
807  }
808  }
809 #if SUPPORT_SYSTEMD
810  tmp1 = result;
811  tmp2 = systemd_unit_listall();
812  if (tmp2) {
813  result = g_list_concat(tmp1, tmp2);
814  }
815 #endif
816 
817 #if SUPPORT_UPSTART
818  tmp1 = result;
819  tmp2 = upstart_job_listall();
820  if (tmp2) {
821  result = g_list_concat(tmp1, tmp2);
822  }
823 #endif
824 
825  return result;
826 
827  } else if (strcasecmp(standard, "ocf") == 0) {
828  return resources_os_list_ocf_agents(provider);
829  } else if (strcasecmp(standard, "lsb") == 0) {
831 #if SUPPORT_HEARTBEAT
832  } else if (strcasecmp(standard, "heartbeat") == 0) {
833  return resources_os_list_hb_agents();
834 #endif
835 #if SUPPORT_SYSTEMD
836  } else if (strcasecmp(standard, "systemd") == 0) {
837  return systemd_unit_listall();
838 #endif
839 #if SUPPORT_UPSTART
840  } else if (strcasecmp(standard, "upstart") == 0) {
841  return upstart_job_listall();
842 #endif
843 #if SUPPORT_NAGIOS
844  } else if (strcasecmp(standard, "nagios") == 0) {
846 #endif
847  }
848 
849  return NULL;
850 }
gboolean services_action_cancel(const char *name, const char *action, int interval)
Definition: services.c:465
Services API.
A dumping ground.
GList * resources_list_providers(const char *standard)
Get a list of providers.
Definition: services.c:785
char * standard
Definition: services.h:157
#define SERVICE_SCRIPT
Definition: services.h:51
gboolean upstart_job_exists(const char *name)
Definition: upstart.c:230
gboolean mainloop_child_kill(pid_t pid)
Definition: mainloop.c:1042
char * id
Definition: services.h:152
svc_action_t * resources_action_create(const char *name, const char *standard, const char *provider, const char *agent, const char *action, int interval, int timeout, GHashTable *params, enum svc_action_flags flags)
Create a new resource action.
Definition: services.c:92
mainloop_io_t * stderr_gsource
GList * resources_os_list_ocf_agents(const char *provider)
GList * resources_os_list_ocf_providers(void)
gboolean recurring_action_timer(gpointer data)
GList * services_os_get_directory_list(const char *root, gboolean files, gboolean executable)
gboolean services_action_async(svc_action_t *op, void(*action_callback)(svc_action_t *))
Definition: services.c:607
char * rsc
Definition: services.h:153
int interval
Definition: services.h:155
svc_action_flags
Definition: services.h:143
gboolean is_op_blocked(const char *rsc)
Definition: services.c:635
Wrappers for and extensions to glib mainloop.
svc_action_t * services_action_create_generic(const char *exec, const char *args[])
Definition: services.c:318
GList * resources_os_list_lsb_agents(void)
GList * blocked_ops
Definition: services.c:44
gboolean upstart_job_exec(svc_action_t *op, gboolean synchronous)
Definition: upstart.c:417
enum svc_action_flags flags
Definition: services.h:171
gboolean services_os_action_execute(svc_action_t *op, gboolean synchronous)
#define crm_warn(fmt, args...)
Definition: logging.h:249
GList * services_list(void)
Definition: services.c:730
gboolean cancel_recurring_action(svc_action_t *op)
Definition: services.c:448
svc_action_private_t * opaque
Definition: services.h:184
GList * upstart_job_listall(void)
Definition: upstart.c:149
#define OCF_ROOT_DIR
Definition: services.h:38
#define crm_debug(fmt, args...)
Definition: logging.h:253
gboolean operation_finalize(svc_action_t *op)
char * stdout_data
Definition: services.h:174
gboolean systemd_unit_exists(const char *name)
Definition: systemd.c:434
GHashTable * params
Definition: services.h:162
#define crm_trace(fmt, args...)
Definition: logging.h:254
void(* callback)(svc_action_t *op)
char * agent
Definition: services.h:159
GList * inflight_ops
Definition: services.c:47
int synchronous
Definition: services.h:170
gboolean services_action_sync(svc_action_t *op)
Definition: services.c:692
#define SUPPORT_HEARTBEAT
Definition: config.h:611
#define LSB_ROOT_DIR
Definition: services.h:42
int sequence
Definition: services.h:168
gboolean services_action_kick(const char *name, const char *action, int interval)
Definition: services.c:503
GList * systemd_unit_listall(void)
Definition: systemd.c:358
const char * resources_find_service_class(const char *agent)
Definition: services.c:56
GList * resources_list_agents(const char *standard, const char *provider)
Get a list of resource agents.
Definition: services.c:795
#define MAX_ARGC
char * args[MAX_ARGC]
void services_add_inflight_op(svc_action_t *op)
Definition: services.c:592
GList * resources_list_standards(void)
Definition: services.c:744
char * action
Definition: services.h:154
GList * get_directory_list(const char *root, gboolean files, gboolean executable)
Get a list of files or directories in a given path.
Definition: services.c:724
#define NAGIOS_PLUGIN_DIR
Definition: config.h:503
#define CRM_META
Definition: crm.h:53
#define crm_err(fmt, args...)
Definition: logging.h:248
GList * resources_os_list_nagios_agents(void)
#define DIMOF(a)
Definition: crm.h:39
GHashTable * recurring_actions
Definition: services.c:40
mainloop_io_t * stdout_gsource
#define CRM_ASSERT(expr)
Definition: error.h:35
#define XML_ATTR_CRM_VERSION
Definition: msg_xml.h:83
void mainloop_del_fd(mainloop_io_t *client)
Definition: mainloop.c:854
void * cb_data
Definition: services.h:182
void services_action_cleanup(svc_action_t *op)
Definition: services.c:370
#define safe_str_eq(a, b)
Definition: util.h:63
void handle_blocked_ops(void)
Definition: services.c:651
void services_action_free(svc_action_t *op)
Definition: services.c:406
char * provider
Definition: services.h:158
gboolean systemd_unit_exec(svc_action_t *op)
Definition: systemd.c:723
#define crm_info(fmt, args...)
Definition: logging.h:251
uint64_t flags
Definition: remote.c:121
svc_action_t * services_action_create(const char *name, const char *action, int interval, int timeout)
Definition: services.c:50
char * stderr_data
Definition: services.h:173