pacemaker  2.0.3-4b1f869f0f
Scalable High-Availability cluster resource manager
services_linux.c
Go to the documentation of this file.
1 /*
2  * Copyright 2010-2019 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 <sys/wait.h>
17 #include <errno.h>
18 #include <unistd.h>
19 #include <dirent.h>
20 #include <grp.h>
21 #include <string.h>
22 #include <sys/time.h>
23 #include <sys/resource.h>
24 
25 #ifdef HAVE_SYS_SIGNALFD_H
26 #include <sys/signalfd.h>
27 #endif
28 
29 #include "crm/crm.h"
30 #include "crm/common/mainloop.h"
31 #include "crm/services.h"
32 
33 #include "services_private.h"
34 
35 #if SUPPORT_CIBSECRETS
36 # include "crm/common/cib_secrets.h"
37 #endif
38 
39 static gboolean
40 svc_read_output(int fd, svc_action_t * op, bool is_stderr)
41 {
42  char *data = NULL;
43  int rc = 0, len = 0;
44  char buf[500];
45  static const size_t buf_read_len = sizeof(buf) - 1;
46 
47 
48  if (fd < 0) {
49  crm_trace("No fd for %s", op->id);
50  return FALSE;
51  }
52 
53  if (is_stderr && op->stderr_data) {
54  len = strlen(op->stderr_data);
55  data = op->stderr_data;
56  crm_trace("Reading %s stderr into offset %d", op->id, len);
57 
58  } else if (is_stderr == FALSE && op->stdout_data) {
59  len = strlen(op->stdout_data);
60  data = op->stdout_data;
61  crm_trace("Reading %s stdout into offset %d", op->id, len);
62 
63  } else {
64  crm_trace("Reading %s %s into offset %d", op->id, is_stderr?"stderr":"stdout", len);
65  }
66 
67  do {
68  rc = read(fd, buf, buf_read_len);
69  if (rc > 0) {
70  buf[rc] = 0;
71  crm_trace("Got %d chars: %.80s", rc, buf);
72  data = realloc_safe(data, len + rc + 1);
73  len += sprintf(data + len, "%s", buf);
74 
75  } else if (errno != EINTR) {
76  /* error or EOF
77  * Cleanup happens in pipe_done()
78  */
79  rc = FALSE;
80  break;
81  }
82 
83  } while (rc == buf_read_len || rc < 0);
84 
85  if (is_stderr) {
86  op->stderr_data = data;
87  } else {
88  op->stdout_data = data;
89  }
90 
91  return rc;
92 }
93 
94 static int
95 dispatch_stdout(gpointer userdata)
96 {
97  svc_action_t *op = (svc_action_t *) userdata;
98 
99  return svc_read_output(op->opaque->stdout_fd, op, FALSE);
100 }
101 
102 static int
103 dispatch_stderr(gpointer userdata)
104 {
105  svc_action_t *op = (svc_action_t *) userdata;
106 
107  return svc_read_output(op->opaque->stderr_fd, op, TRUE);
108 }
109 
110 static void
111 pipe_out_done(gpointer user_data)
112 {
113  svc_action_t *op = (svc_action_t *) user_data;
114 
115  crm_trace("%p", op);
116 
117  op->opaque->stdout_gsource = NULL;
118  if (op->opaque->stdout_fd > STDOUT_FILENO) {
119  close(op->opaque->stdout_fd);
120  }
121  op->opaque->stdout_fd = -1;
122 }
123 
124 static void
125 pipe_err_done(gpointer user_data)
126 {
127  svc_action_t *op = (svc_action_t *) user_data;
128 
129  op->opaque->stderr_gsource = NULL;
130  if (op->opaque->stderr_fd > STDERR_FILENO) {
131  close(op->opaque->stderr_fd);
132  }
133  op->opaque->stderr_fd = -1;
134 }
135 
136 static struct mainloop_fd_callbacks stdout_callbacks = {
137  .dispatch = dispatch_stdout,
138  .destroy = pipe_out_done,
139 };
140 
141 static struct mainloop_fd_callbacks stderr_callbacks = {
142  .dispatch = dispatch_stderr,
143  .destroy = pipe_err_done,
144 };
145 
146 static void
147 set_ocf_env(const char *key, const char *value, gpointer user_data)
148 {
149  if (setenv(key, value, 1) != 0) {
150  crm_perror(LOG_ERR, "setenv failed for key:%s and value:%s", key, value);
151  }
152 }
153 
154 static void
155 set_ocf_env_with_prefix(gpointer key, gpointer value, gpointer user_data)
156 {
157  char buffer[500];
158 
159  snprintf(buffer, sizeof(buffer), "OCF_RESKEY_%s", (char *)key);
160  set_ocf_env(buffer, value, user_data);
161 }
162 
163 static void
164 set_alert_env(gpointer key, gpointer value, gpointer user_data)
165 {
166  int rc;
167 
168  if (value != NULL) {
169  rc = setenv(key, value, 1);
170  } else {
171  rc = unsetenv(key);
172  }
173 
174  if (rc < 0) {
175  crm_perror(LOG_ERR, "setenv %s=%s",
176  (char*)key, (value? (char*)value : ""));
177  } else {
178  crm_trace("setenv %s=%s", (char*)key, (value? (char*)value : ""));
179  }
180 }
181 
188 static void
189 add_action_env_vars(const svc_action_t *op)
190 {
191  void (*env_setter)(gpointer, gpointer, gpointer) = NULL;
192  if (op->agent == NULL) {
193  env_setter = set_alert_env; /* we deal with alert handler */
194 
195  } else if (safe_str_eq(op->standard, PCMK_RESOURCE_CLASS_OCF)) {
196  env_setter = set_ocf_env_with_prefix;
197  }
198 
199  if (env_setter != NULL && op->params != NULL) {
200  g_hash_table_foreach(op->params, env_setter, NULL);
201  }
202 
203  if (env_setter == NULL || env_setter == set_alert_env) {
204  return;
205  }
206 
207  set_ocf_env("OCF_RA_VERSION_MAJOR", "1", NULL);
208  set_ocf_env("OCF_RA_VERSION_MINOR", "0", NULL);
209  set_ocf_env("OCF_ROOT", OCF_ROOT_DIR, NULL);
210  set_ocf_env("OCF_EXIT_REASON_PREFIX", PCMK_OCF_REASON_PREFIX, NULL);
211 
212  if (op->rsc) {
213  set_ocf_env("OCF_RESOURCE_INSTANCE", op->rsc, NULL);
214  }
215 
216  if (op->agent != NULL) {
217  set_ocf_env("OCF_RESOURCE_TYPE", op->agent, NULL);
218  }
219 
220  /* Notes: this is not added to specification yet. Sept 10,2004 */
221  if (op->provider != NULL) {
222  set_ocf_env("OCF_RESOURCE_PROVIDER", op->provider, NULL);
223  }
224 }
225 
226 static void
227 pipe_in_single_parameter(gpointer key, gpointer value, gpointer user_data)
228 {
229  svc_action_t *op = user_data;
230  char *buffer = crm_strdup_printf("%s=%s\n", (char *)key, (char *) value);
231  int ret, total = 0, len = strlen(buffer);
232 
233  do {
234  errno = 0;
235  ret = write(op->opaque->stdin_fd, buffer + total, len - total);
236  if (ret > 0) {
237  total += ret;
238  }
239 
240  } while ((errno == EINTR) && (total < len));
241  free(buffer);
242 }
243 
250 static void
251 pipe_in_action_stdin_parameters(const svc_action_t *op)
252 {
253  crm_debug("sending args");
254  if (op->params) {
255  g_hash_table_foreach(op->params, pipe_in_single_parameter, (gpointer) op);
256  }
257 }
258 
259 gboolean
261 {
262  svc_action_t *op = data;
263 
264  crm_debug("Scheduling another invocation of %s", op->id);
265 
266  /* Clean out the old result */
267  free(op->stdout_data);
268  op->stdout_data = NULL;
269  free(op->stderr_data);
270  op->stderr_data = NULL;
271  op->opaque->repeat_timer = 0;
272 
273  services_action_async(op, NULL);
274  return FALSE;
275 }
276 
277 /* Returns FALSE if 'op' should be free'd by the caller */
278 gboolean
280 {
281  int recurring = 0;
282 
283  if (op->interval_ms) {
284  if (op->cancel) {
287  } else {
288  recurring = 1;
289  op->opaque->repeat_timer = g_timeout_add(op->interval_ms,
290  recurring_action_timer, (void *)op);
291  }
292  }
293 
294  if (op->opaque->callback) {
295  op->opaque->callback(op);
296  }
297 
298  op->pid = 0;
299 
301 
302  if (!recurring && op->synchronous == FALSE) {
303  /*
304  * If this is a recurring action, do not free explicitly.
305  * It will get freed whenever the action gets cancelled.
306  */
308  return TRUE;
309  }
310 
312  return FALSE;
313 }
314 
315 static void
316 operation_finished(mainloop_child_t * p, pid_t pid, int core, int signo, int exitcode)
317 {
319  char *prefix = crm_strdup_printf("%s:%d", op->id, op->pid);
320 
322  op->status = PCMK_LRM_OP_DONE;
323  CRM_ASSERT(op->pid == pid);
324 
325  crm_trace("%s %p %p", prefix, op->opaque->stderr_gsource, op->opaque->stdout_gsource);
326  if (op->opaque->stderr_gsource) {
327  /* Make sure we have read everything from the buffer.
328  * Depending on the priority mainloop gives the fd, operation_finished
329  * could occur before all the reads are done. Force the read now.*/
330  crm_trace("%s dispatching stderr", prefix);
331  dispatch_stderr(op);
332  crm_trace("%s: %p", op->id, op->stderr_data);
334  op->opaque->stderr_gsource = NULL;
335  }
336 
337  if (op->opaque->stdout_gsource) {
338  /* Make sure we have read everything from the buffer.
339  * Depending on the priority mainloop gives the fd, operation_finished
340  * could occur before all the reads are done. Force the read now.*/
341  crm_trace("%s dispatching stdout", prefix);
342  dispatch_stdout(op);
343  crm_trace("%s: %p", op->id, op->stdout_data);
345  op->opaque->stdout_gsource = NULL;
346  }
347 
348  if (op->opaque->stdin_fd >= 0) {
349  close(op->opaque->stdin_fd);
350  }
351 
352  if (signo) {
353  if (mainloop_child_timeout(p)) {
354  crm_warn("%s - timed out after %dms", prefix, op->timeout);
356  op->rc = PCMK_OCF_TIMEOUT;
357 
358  } else if (op->cancel) {
359  /* If an in-flight recurring operation was killed because it was
360  * cancelled, don't treat that as a failure.
361  */
362  crm_info("%s - terminated with signal %d", prefix, signo);
364  op->rc = PCMK_OCF_OK;
365 
366  } else {
367  crm_warn("%s - terminated with signal %d", prefix, signo);
369  op->rc = PCMK_OCF_SIGNAL;
370  }
371 
372  } else {
373  op->rc = exitcode;
374  crm_debug("%s - exited with rc=%d", prefix, exitcode);
375  }
376 
377  free(prefix);
378  prefix = crm_strdup_printf("%s:%d:stderr", op->id, op->pid);
379  crm_log_output(LOG_NOTICE, prefix, op->stderr_data);
380 
381  free(prefix);
382  prefix = crm_strdup_printf("%s:%d:stdout", op->id, op->pid);
383  crm_log_output(LOG_DEBUG, prefix, op->stdout_data);
384 
385  free(prefix);
386  operation_finalize(op);
387 }
388 
398 static void
399 services_handle_exec_error(svc_action_t * op, int error)
400 {
401  int rc_not_installed, rc_insufficient_priv, rc_exec_error;
402 
403  /* Mimic the return codes for each standard as that's what we'll convert back from in get_uniform_rc() */
405  && safe_str_eq(op->action, "status")) {
406 
407  rc_not_installed = PCMK_LSB_STATUS_NOT_INSTALLED;
408  rc_insufficient_priv = PCMK_LSB_STATUS_INSUFFICIENT_PRIV;
409  rc_exec_error = PCMK_LSB_STATUS_UNKNOWN;
410 
411 #if SUPPORT_NAGIOS
413  rc_not_installed = NAGIOS_NOT_INSTALLED;
414  rc_insufficient_priv = NAGIOS_INSUFFICIENT_PRIV;
415  rc_exec_error = PCMK_OCF_EXEC_ERROR;
416 #endif
417 
418  } else {
419  rc_not_installed = PCMK_OCF_NOT_INSTALLED;
420  rc_insufficient_priv = PCMK_OCF_INSUFFICIENT_PRIV;
421  rc_exec_error = PCMK_OCF_EXEC_ERROR;
422  }
423 
424  switch (error) { /* see execve(2), stat(2) and fork(2) */
425  case ENOENT: /* No such file or directory */
426  case EISDIR: /* Is a directory */
427  case ENOTDIR: /* Path component is not a directory */
428  case EINVAL: /* Invalid executable format */
429  case ENOEXEC: /* Invalid executable format */
430  op->rc = rc_not_installed;
432  break;
433  case EACCES: /* permission denied (various errors) */
434  case EPERM: /* permission denied (various errors) */
435  op->rc = rc_insufficient_priv;
437  break;
438  default:
439  op->rc = rc_exec_error;
441  }
442 }
443 
444 static void
445 action_launch_child(svc_action_t *op)
446 {
447  /* SIGPIPE is ignored (which is different from signal blocking) by the gnutls library.
448  * Depending on the libqb version in use, libqb may set SIGPIPE to be ignored as well.
449  * We do not want this to be inherited by the child process. By resetting this the signal
450  * to the default behavior, we avoid some potential odd problems that occur during OCF
451  * scripts when SIGPIPE is ignored by the environment. */
452  signal(SIGPIPE, SIG_DFL);
453 
454 #if defined(HAVE_SCHED_SETSCHEDULER)
455  if (sched_getscheduler(0) != SCHED_OTHER) {
456  struct sched_param sp;
457 
458  memset(&sp, 0, sizeof(sp));
459  sp.sched_priority = 0;
460 
461  if (sched_setscheduler(0, SCHED_OTHER, &sp) == -1) {
462  crm_perror(LOG_ERR, "Could not reset scheduling policy to SCHED_OTHER for %s", op->id);
463  }
464  }
465 #endif
466  if (setpriority(PRIO_PROCESS, 0, 0) == -1) {
467  crm_perror(LOG_ERR, "Could not reset process priority to 0 for %s", op->id);
468  }
469 
470  /* Man: The call setpgrp() is equivalent to setpgid(0,0)
471  * _and_ compiles on BSD variants too
472  * need to investigate if it works the same too.
473  */
474  setpgid(0, 0);
475 
477 
478 #if SUPPORT_CIBSECRETS
479  if (replace_secret_params(op->rsc, op->params) < 0) {
480  /* replacing secrets failed! */
481  if (safe_str_eq(op->action,"stop")) {
482  /* don't fail on stop! */
483  crm_info("proceeding with the stop operation for %s", op->rsc);
484 
485  } else {
486  crm_err("failed to get secrets for %s, "
487  "considering resource not configured", op->rsc);
489  }
490  }
491 #endif
492 
493  add_action_env_vars(op);
494 
495  /* Become the desired user */
496  if (op->opaque->uid && (geteuid() == 0)) {
497 
498  // If requested, set effective group
499  if (op->opaque->gid && (setgid(op->opaque->gid) < 0)) {
500  crm_perror(LOG_ERR, "Could not set child group to %d", op->opaque->gid);
502  }
503 
504  // Erase supplementary group list
505  // (We could do initgroups() if we kept a copy of the username)
506  if (setgroups(0, NULL) < 0) {
507  crm_perror(LOG_ERR, "Could not set child groups");
509  }
510 
511  // Set effective user
512  if (setuid(op->opaque->uid) < 0) {
513  crm_perror(LOG_ERR, "setting user to %d", op->opaque->uid);
515  }
516  }
517 
518  /* execute the RA */
519  execvp(op->opaque->exec, op->opaque->args);
520 
521  /* Most cases should have been already handled by stat() */
522  services_handle_exec_error(op, errno);
523 
524  _exit(op->rc);
525 }
526 
527 #ifndef HAVE_SYS_SIGNALFD_H
528 static int sigchld_pipe[2] = { -1, -1 };
529 
530 static void
531 sigchld_handler()
532 {
533  if ((sigchld_pipe[1] >= 0) && (write(sigchld_pipe[1], "", 1) == -1)) {
534  crm_perror(LOG_TRACE, "Could not poke SIGCHLD self-pipe");
535  }
536 }
537 #endif
538 
539 static void
540 action_synced_wait(svc_action_t * op, sigset_t *mask)
541 {
542  int status = 0;
543  int timeout = op->timeout;
544  int sfd = -1;
545  time_t start = -1;
546  struct pollfd fds[3];
547  int wait_rc = 0;
548 
549 #ifdef HAVE_SYS_SIGNALFD_H
550  // mask is always non-NULL in practice, but this makes static analysis happy
551  if (mask) {
552  sfd = signalfd(-1, mask, SFD_NONBLOCK);
553  if (sfd < 0) {
554  crm_perror(LOG_ERR, "signalfd() failed");
555  }
556  }
557 #else
558  sfd = sigchld_pipe[0];
559 #endif
560 
561  fds[0].fd = op->opaque->stdout_fd;
562  fds[0].events = POLLIN;
563  fds[0].revents = 0;
564 
565  fds[1].fd = op->opaque->stderr_fd;
566  fds[1].events = POLLIN;
567  fds[1].revents = 0;
568 
569  fds[2].fd = sfd;
570  fds[2].events = POLLIN;
571  fds[2].revents = 0;
572 
573  crm_trace("Waiting for %d", op->pid);
574  start = time(NULL);
575  do {
576  int poll_rc = poll(fds, 3, timeout);
577 
578  if (poll_rc > 0) {
579  if (fds[0].revents & POLLIN) {
580  svc_read_output(op->opaque->stdout_fd, op, FALSE);
581  }
582 
583  if (fds[1].revents & POLLIN) {
584  svc_read_output(op->opaque->stderr_fd, op, TRUE);
585  }
586 
587  if (fds[2].revents & POLLIN) {
588 #ifdef HAVE_SYS_SIGNALFD_H
589  struct signalfd_siginfo fdsi;
590  ssize_t s;
591 
592  s = read(sfd, &fdsi, sizeof(struct signalfd_siginfo));
593  if (s != sizeof(struct signalfd_siginfo)) {
594  crm_perror(LOG_ERR, "Read from signal fd %d failed", sfd);
595 
596  } else if (fdsi.ssi_signo == SIGCHLD) {
597 #else
598  if (1) {
599  /* Clear out the sigchld pipe. */
600  char ch;
601  while (read(sfd, &ch, 1) == 1) /*omit*/;
602 #endif
603  wait_rc = waitpid(op->pid, &status, WNOHANG);
604 
605  if (wait_rc > 0) {
606  break;
607 
608  } else if (wait_rc < 0){
609  if (errno == ECHILD) {
610  /* Here, don't dare to kill and bail out... */
611  break;
612 
613  } else {
614  /* ...otherwise pretend process still runs. */
615  wait_rc = 0;
616  }
617  crm_perror(LOG_ERR, "waitpid() for %d failed", op->pid);
618  }
619  }
620  }
621 
622  } else if (poll_rc == 0) {
623  timeout = 0;
624  break;
625 
626  } else if (poll_rc < 0) {
627  if (errno != EINTR) {
628  crm_perror(LOG_ERR, "poll() failed");
629  break;
630  }
631  }
632 
633  timeout = op->timeout - (time(NULL) - start) * 1000;
634 
635  } while ((op->timeout < 0 || timeout > 0));
636 
637  crm_trace("Child done: %d", op->pid);
638  if (wait_rc <= 0) {
640 
641  if (op->timeout > 0 && timeout <= 0) {
643  crm_warn("%s:%d - timed out after %dms", op->id, op->pid, op->timeout);
644 
645  } else {
647  }
648 
649  /* If only child hasn't been successfully waited for, yet.
650  This is to limit killing wrong target a bit more. */
651  if (wait_rc == 0 && waitpid(op->pid, &status, WNOHANG) == 0) {
652  if (kill(op->pid, SIGKILL)) {
653  crm_err("kill(%d, KILL) failed: %d", op->pid, errno);
654  }
655  /* Safe to skip WNOHANG here as we sent non-ignorable signal. */
656  while (waitpid(op->pid, &status, 0) == (pid_t) -1 && errno == EINTR) /*omit*/;
657  }
658 
659  } else if (WIFEXITED(status)) {
660  op->status = PCMK_LRM_OP_DONE;
661  op->rc = WEXITSTATUS(status);
662  crm_info("Managed %s process %d exited with rc=%d", op->id, op->pid, op->rc);
663 
664  } else if (WIFSIGNALED(status)) {
665  int signo = WTERMSIG(status);
666 
668  crm_err("Managed %s process %d exited with signal=%d", op->id, op->pid, signo);
669  }
670 #ifdef WCOREDUMP
671  if (WCOREDUMP(status)) {
672  crm_err("Managed %s process %d dumped core", op->id, op->pid);
673  }
674 #endif
675 
676  svc_read_output(op->opaque->stdout_fd, op, FALSE);
677  svc_read_output(op->opaque->stderr_fd, op, TRUE);
678 
679  close(op->opaque->stdout_fd);
680  close(op->opaque->stderr_fd);
681  if (op->opaque->stdin_fd >= 0) {
682  close(op->opaque->stdin_fd);
683  }
684 
685 #ifdef HAVE_SYS_SIGNALFD_H
686  close(sfd);
687 #endif
688 }
689 
690 /* For an asynchronous 'op', returns FALSE if 'op' should be free'd by the caller */
691 /* For a synchronous 'op', returns FALSE if 'op' fails */
692 gboolean
694 {
695  int stdout_fd[2];
696  int stderr_fd[2];
697  int stdin_fd[2] = {-1, -1};
698  int rc;
699  struct stat st;
700  sigset_t *pmask = NULL;
701 
702 #ifdef HAVE_SYS_SIGNALFD_H
703  sigset_t mask;
704  sigset_t old_mask;
705 #define sigchld_cleanup() do { \
706  if (sigismember(&old_mask, SIGCHLD) == 0) { \
707  if (sigprocmask(SIG_UNBLOCK, &mask, NULL) < 0) { \
708  crm_perror(LOG_ERR, "sigprocmask() failed to unblock sigchld"); \
709  } \
710  } \
711 } while (0)
712 #else
713  struct sigaction sa;
714  struct sigaction old_sa;
715 #define sigchld_cleanup() do { \
716  if (sigaction(SIGCHLD, &old_sa, NULL) < 0) { \
717  crm_perror(LOG_ERR, "sigaction() failed to remove sigchld handler"); \
718  } \
719  close(sigchld_pipe[0]); \
720  close(sigchld_pipe[1]); \
721  sigchld_pipe[0] = sigchld_pipe[1] = -1; \
722 } while(0)
723 #endif
724 
725  /* Fail fast */
726  if(stat(op->opaque->exec, &st) != 0) {
727  rc = errno;
728  crm_warn("Cannot execute '%s': %s (%d)", op->opaque->exec, pcmk_strerror(rc), rc);
729  services_handle_exec_error(op, rc);
730  if (!op->synchronous) {
731  return operation_finalize(op);
732  }
733  return FALSE;
734  }
735 
736  if (pipe(stdout_fd) < 0) {
737  rc = errno;
738 
739  crm_err("pipe(stdout_fd) failed. '%s': %s (%d)", op->opaque->exec, pcmk_strerror(rc), rc);
740 
741  services_handle_exec_error(op, rc);
742  if (!op->synchronous) {
743  return operation_finalize(op);
744  }
745  return FALSE;
746  }
747 
748  if (pipe(stderr_fd) < 0) {
749  rc = errno;
750 
751  close(stdout_fd[0]);
752  close(stdout_fd[1]);
753 
754  crm_err("pipe(stderr_fd) failed. '%s': %s (%d)", op->opaque->exec, pcmk_strerror(rc), rc);
755 
756  services_handle_exec_error(op, rc);
757  if (!op->synchronous) {
758  return operation_finalize(op);
759  }
760  return FALSE;
761  }
762 
764  if (pipe(stdin_fd) < 0) {
765  rc = errno;
766 
767  close(stdout_fd[0]);
768  close(stdout_fd[1]);
769  close(stderr_fd[0]);
770  close(stderr_fd[1]);
771 
772  crm_err("pipe(stdin_fd) failed. '%s': %s (%d)", op->opaque->exec, pcmk_strerror(rc), rc);
773 
774  services_handle_exec_error(op, rc);
775  if (!op->synchronous) {
776  return operation_finalize(op);
777  }
778  return FALSE;
779  }
780  }
781 
782  if (op->synchronous) {
783 #ifdef HAVE_SYS_SIGNALFD_H
784  sigemptyset(&mask);
785  sigaddset(&mask, SIGCHLD);
786  sigemptyset(&old_mask);
787 
788  if (sigprocmask(SIG_BLOCK, &mask, &old_mask) < 0) {
789  crm_perror(LOG_ERR, "sigprocmask() failed to block sigchld");
790  }
791 
792  pmask = &mask;
793 #else
794  if(pipe(sigchld_pipe) == -1) {
795  crm_perror(LOG_ERR, "pipe() failed");
796  }
797 
798  rc = crm_set_nonblocking(sigchld_pipe[0]);
799  if (rc < 0) {
800  crm_warn("Could not set pipe input non-blocking: %s " CRM_XS " rc=%d",
801  pcmk_strerror(rc), rc);
802  }
803  rc = crm_set_nonblocking(sigchld_pipe[1]);
804  if (rc < 0) {
805  crm_warn("Could not set pipe output non-blocking: %s " CRM_XS " rc=%d",
806  pcmk_strerror(rc), rc);
807  }
808 
809  sa.sa_handler = sigchld_handler;
810  sa.sa_flags = 0;
811  sigemptyset(&sa.sa_mask);
812  if (sigaction(SIGCHLD, &sa, &old_sa) < 0) {
813  crm_perror(LOG_ERR, "sigaction() failed to set sigchld handler");
814  }
815 
816  pmask = NULL;
817 #endif
818  }
819 
820  op->pid = fork();
821  switch (op->pid) {
822  case -1:
823  rc = errno;
824 
825  close(stdout_fd[0]);
826  close(stdout_fd[1]);
827  close(stderr_fd[0]);
828  close(stderr_fd[1]);
829  if (stdin_fd[0] >= 0) {
830  close(stdin_fd[0]);
831  close(stdin_fd[1]);
832  }
833 
834  crm_err("Could not execute '%s': %s (%d)", op->opaque->exec, pcmk_strerror(rc), rc);
835  services_handle_exec_error(op, rc);
836  if (!op->synchronous) {
837  return operation_finalize(op);
838  }
839 
840  sigchld_cleanup();
841  return FALSE;
842 
843  case 0: /* Child */
844  close(stdout_fd[0]);
845  close(stderr_fd[0]);
846  if (stdin_fd[1] >= 0) {
847  close(stdin_fd[1]);
848  }
849  if (STDOUT_FILENO != stdout_fd[1]) {
850  if (dup2(stdout_fd[1], STDOUT_FILENO) != STDOUT_FILENO) {
851  crm_err("dup2() failed (stdout)");
852  }
853  close(stdout_fd[1]);
854  }
855  if (STDERR_FILENO != stderr_fd[1]) {
856  if (dup2(stderr_fd[1], STDERR_FILENO) != STDERR_FILENO) {
857  crm_err("dup2() failed (stderr)");
858  }
859  close(stderr_fd[1]);
860  }
861  if ((stdin_fd[0] >= 0) &&
862  (STDIN_FILENO != stdin_fd[0])) {
863  if (dup2(stdin_fd[0], STDIN_FILENO) != STDIN_FILENO) {
864  crm_err("dup2() failed (stdin)");
865  }
866  close(stdin_fd[0]);
867  }
868 
869  if (op->synchronous) {
870  sigchld_cleanup();
871  }
872 
873  action_launch_child(op);
874  CRM_ASSERT(0); /* action_launch_child is effectively noreturn */
875  }
876 
877  /* Only the parent reaches here */
878  close(stdout_fd[1]);
879  close(stderr_fd[1]);
880  if (stdin_fd[0] >= 0) {
881  close(stdin_fd[0]);
882  }
883 
884  op->opaque->stdout_fd = stdout_fd[0];
886  if (rc < 0) {
887  crm_warn("Could not set child output non-blocking: %s "
888  CRM_XS " rc=%d",
889  pcmk_strerror(rc), rc);
890  }
891 
892  op->opaque->stderr_fd = stderr_fd[0];
894  if (rc < 0) {
895  crm_warn("Could not set child error output non-blocking: %s "
896  CRM_XS " rc=%d",
897  pcmk_strerror(rc), rc);
898  }
899 
900  op->opaque->stdin_fd = stdin_fd[1];
901  if (op->opaque->stdin_fd >= 0) {
902  // using buffer behind non-blocking-fd here - that could be improved
903  // as long as no other standard uses stdin_fd assume stonith
905  if (rc < 0) {
906  crm_warn("Could not set child input non-blocking: %s "
907  CRM_XS " fd=%d,rc=%d",
908  pcmk_strerror(rc), op->opaque->stdin_fd, rc);
909  }
910  pipe_in_action_stdin_parameters(op);
911  // as long as we are handling parameters directly in here just close
912  close(op->opaque->stdin_fd);
913  op->opaque->stdin_fd = -1;
914  }
915 
916  // after fds are setup properly and before we plug anything into mainloop
917  if (op->opaque->fork_callback) {
918  op->opaque->fork_callback(op);
919  }
920 
921  if (op->synchronous) {
922  action_synced_wait(op, pmask);
923  sigchld_cleanup();
924  } else {
925 
926  crm_trace("Async waiting for %d - %s", op->pid, op->opaque->exec);
928  op->timeout,
929  op->id,
930  op,
932  operation_finished);
933 
934 
936  G_PRIORITY_LOW,
937  op->opaque->stdout_fd, op, &stdout_callbacks);
938 
940  G_PRIORITY_LOW,
941  op->opaque->stderr_fd, op, &stderr_callbacks);
942 
944  }
945 
946  return TRUE;
947 }
948 
949 GList *
950 services_os_get_directory_list(const char *root, gboolean files, gboolean executable)
951 {
952  GList *list = NULL;
953  struct dirent **namelist;
954  int entries = 0, lpc = 0;
955  char buffer[PATH_MAX];
956 
957  entries = scandir(root, &namelist, NULL, alphasort);
958  if (entries <= 0) {
959  return list;
960  }
961 
962  for (lpc = 0; lpc < entries; lpc++) {
963  struct stat sb;
964 
965  if ('.' == namelist[lpc]->d_name[0]) {
966  free(namelist[lpc]);
967  continue;
968  }
969 
970  snprintf(buffer, sizeof(buffer), "%s/%s", root, namelist[lpc]->d_name);
971 
972  if (stat(buffer, &sb)) {
973  continue;
974  }
975 
976  if (S_ISDIR(sb.st_mode)) {
977  if (files) {
978  free(namelist[lpc]);
979  continue;
980  }
981 
982  } else if (S_ISREG(sb.st_mode)) {
983  if (files == FALSE) {
984  free(namelist[lpc]);
985  continue;
986 
987  } else if (executable
988  && (sb.st_mode & S_IXUSR) == 0
989  && (sb.st_mode & S_IXGRP) == 0 && (sb.st_mode & S_IXOTH) == 0) {
990  free(namelist[lpc]);
991  continue;
992  }
993  }
994 
995  list = g_list_append(list, strdup(namelist[lpc]->d_name));
996 
997  free(namelist[lpc]);
998  }
999 
1000  free(namelist);
1001  return list;
1002 }
1003 
1004 GList *
1006 {
1007  return get_directory_list(OCF_ROOT_DIR "/resource.d", FALSE, TRUE);
1008 }
1009 
1010 GList *
1011 resources_os_list_ocf_agents(const char *provider)
1012 {
1013  GList *gIter = NULL;
1014  GList *result = NULL;
1015  GList *providers = NULL;
1016 
1017  if (provider) {
1018  char buffer[500];
1019 
1020  snprintf(buffer, sizeof(buffer), "%s/resource.d/%s", OCF_ROOT_DIR, provider);
1021  return get_directory_list(buffer, TRUE, TRUE);
1022  }
1023 
1024  providers = resources_os_list_ocf_providers();
1025  for (gIter = providers; gIter != NULL; gIter = gIter->next) {
1026  GList *tmp1 = result;
1027  GList *tmp2 = resources_os_list_ocf_agents(gIter->data);
1028 
1029  if (tmp2) {
1030  result = g_list_concat(tmp1, tmp2);
1031  }
1032  }
1033  g_list_free_full(providers, free);
1034  return result;
1035 }
1036 
1037 gboolean
1038 services__ocf_agent_exists(const char *provider, const char *agent)
1039 {
1040  char *buf = NULL;
1041  gboolean rc = FALSE;
1042  struct stat st;
1043 
1044  if (provider == NULL || agent == NULL) {
1045  return rc;
1046  }
1047 
1048  buf = crm_strdup_printf(OCF_ROOT_DIR "/resource.d/%s/%s", provider, agent);
1049  if (stat(buf, &st) == 0) {
1050  rc = TRUE;
1051  }
1052 
1053  free(buf);
1054  return rc;
1055 }
1056 
1057 #if SUPPORT_NAGIOS
1058 GList *
1060 {
1061  GList *plugin_list = NULL;
1062  GList *result = NULL;
1063  GList *gIter = NULL;
1064 
1065  plugin_list = get_directory_list(NAGIOS_PLUGIN_DIR, TRUE, TRUE);
1066 
1067  /* Make sure both the plugin and its metadata exist */
1068  for (gIter = plugin_list; gIter != NULL; gIter = gIter->next) {
1069  const char *plugin = gIter->data;
1070  char *metadata = crm_strdup_printf(NAGIOS_METADATA_DIR "/%s.xml", plugin);
1071  struct stat st;
1072 
1073  if (stat(metadata, &st) == 0) {
1074  result = g_list_append(result, strdup(plugin));
1075  }
1076 
1077  free(metadata);
1078  }
1079  g_list_free_full(plugin_list, free);
1080  return result;
1081 }
1082 
1083 gboolean
1084 services__nagios_agent_exists(const char *name)
1085 {
1086  char *buf = NULL;
1087  gboolean rc = FALSE;
1088  struct stat st;
1089 
1090  if (name == NULL) {
1091  return rc;
1092  }
1093 
1094  buf = crm_strdup_printf(NAGIOS_PLUGIN_DIR "/%s", name);
1095  if (stat(buf, &st) == 0) {
1096  rc = TRUE;
1097  }
1098 
1099  free(buf);
1100  return rc;
1101 }
1102 #endif
services_action_free
void services_action_free(svc_action_t *op)
Definition: services.c:463
PCMK_LSB_STATUS_INSUFFICIENT_PRIV
Definition: services.h:83
svc_action_s::opaque
svc_action_private_t * opaque
Definition: services.h:187
replace_secret_params
int replace_secret_params(const char *rsc_id, GHashTable *params)
Definition: cib_secrets.c:90
svc_action_private_s::stdin_fd
int stdin_fd
Definition: services_private.h:36
svc_action_private_s::gid
gid_t gid
Definition: services_private.h:24
svc_action_private_s::uid
uid_t uid
Definition: services_private.h:23
svc_action_s::provider
char * provider
Definition: services.h:158
alphasort
int alphasort(const void *dirent1, const void *dirent2)
data
char data[0]
Definition: internal.h:90
PCMK_LRM_OP_ERROR
Definition: services.h:125
mainloop_add_fd
mainloop_io_t * mainloop_add_fd(const char *name, int priority, int fd, void *userdata, struct mainloop_fd_callbacks *callbacks)
Definition: mainloop.c:941
LOG_TRACE
#define LOG_TRACE
Definition: logging.h:26
svc_action_s::flags
enum svc_action_flags flags
Definition: services.h:174
svc_action_s::action
char * action
Definition: services.h:154
services__nagios_agent_exists
G_GNUC_INTERNAL gboolean services__nagios_agent_exists(const char *agent)
PCMK_RESOURCE_CLASS_STONITH
#define PCMK_RESOURCE_CLASS_STONITH
Definition: services.h:49
PCMK_LRM_OP_CANCELLED
Definition: services.h:122
mainloop_child_userdata
void * mainloop_child_userdata(mainloop_child_t *child)
Definition: mainloop.c:1019
services_private.h
mainloop_fd_callbacks
Definition: mainloop.h:115
PCMK_RESOURCE_CLASS_OCF
#define PCMK_RESOURCE_CLASS_OCF
Definition: services.h:43
NAGIOS_NOT_INSTALLED
Definition: services.h:141
services__ocf_agent_exists
gboolean services__ocf_agent_exists(const char *provider, const char *agent)
Definition: services_linux.c:1038
svc_action_private_s::args
char * args[MAX_ARGC]
Definition: services_private.h:21
pcmk_strerror
const char * pcmk_strerror(int rc)
Definition: results.c:188
PCMK_OCF_TIMEOUT
Definition: services.h:114
crm_log_output
#define crm_log_output(level, prefix, output)
Definition: logging.h:85
OCF_ROOT_DIR
#define OCF_ROOT_DIR
Definition: services.h:30
crm_err
#define crm_err(fmt, args...)
Definition: logging.h:241
sigchld_cleanup
#define sigchld_cleanup()
PCMK_OCF_SIGNAL
Definition: services.h:110
crm_trace
#define crm_trace(fmt, args...)
Definition: logging.h:247
safe_str_eq
#define safe_str_eq(a, b)
Definition: util.h:61
resources_os_list_ocf_agents
GList * resources_os_list_ocf_agents(const char *provider)
Definition: services_linux.c:1011
crm_warn
#define crm_warn(fmt, args...)
Definition: logging.h:242
services_os_get_directory_list
GList * services_os_get_directory_list(const char *root, gboolean files, gboolean executable)
Definition: services_linux.c:950
svc_action_private_s::exec
char * exec
Definition: services_private.h:20
mainloop_child_timeout
int mainloop_child_timeout(mainloop_child_t *child)
Definition: mainloop.c:1013
svc_action_s::id
char * id
Definition: services.h:152
setenv
int setenv(const char *name, const char *value, int why)
svc_action_s::stderr_data
char * stderr_data
Definition: services.h:176
PCMK_LRM_OP_TIMEOUT
Definition: services.h:123
mainloop.h
Wrappers for and extensions to glib mainloop.
SVC_ACTION_LEAVE_GROUP
Definition: services.h:146
NAGIOS_PLUGIN_DIR
#define NAGIOS_PLUGIN_DIR
Definition: config.h:493
PCMK_LSB_STATUS_UNKNOWN
Definition: services.h:79
svc_action_s::params
GHashTable * params
Definition: services.h:162
services_os_action_execute
gboolean services_os_action_execute(svc_action_t *op)
Definition: services_linux.c:693
svc_action_private_s::stderr_fd
int stderr_fd
Definition: services_private.h:30
svc_action_private_s::stdout_fd
int stdout_fd
Definition: services_private.h:33
PCMK_RESOURCE_CLASS_NAGIOS
#define PCMK_RESOURCE_CLASS_NAGIOS
Definition: services.h:48
svc_action_s
Definition: services.h:151
crm_info
#define crm_info(fmt, args...)
Definition: logging.h:244
svc_action_s::timeout
int timeout
Definition: services.h:161
CRM_XS
#define CRM_XS
Definition: logging.h:34
resources_os_list_ocf_providers
GList * resources_os_list_ocf_providers(void)
Definition: services_linux.c:1005
svc_action_private_s::stdout_gsource
mainloop_io_t * stdout_gsource
Definition: services_private.h:34
crm_strdup_printf
char * crm_strdup_printf(char const *format,...) __attribute__((__format__(__printf__
svc_action_s::stdout_data
char * stdout_data
Definition: services.h:177
crm_debug
#define crm_debug(fmt, args...)
Definition: logging.h:246
PCMK_OCF_INSUFFICIENT_PRIV
Definition: services.h:94
resources_os_list_nagios_agents
G_GNUC_INTERNAL GList * resources_os_list_nagios_agents(void)
pid
uint32_t pid
Definition: internal.h:81
PCMK_OCF_EXEC_ERROR
Definition: services.h:108
PCMK_LRM_OP_NOT_INSTALLED
Definition: services.h:128
mainloop_leave_pid_group
Definition: mainloop.h:28
svc_action_s::pid
int pid
Definition: services.h:168
cancel_recurring_action
gboolean cancel_recurring_action(svc_action_t *op)
Definition: services.c:515
svc_action_private_s::fork_callback
void(* fork_callback)(svc_action_t *op)
Definition: services_private.h:28
svc_action_private_s::repeat_timer
guint repeat_timer
Definition: services_private.h:26
PCMK_OCF_UNKNOWN_ERROR
Definition: services.h:91
NAGIOS_METADATA_DIR
#define NAGIOS_METADATA_DIR
Definition: config.h:490
cib_secrets.h
svc_action_private_s::callback
void(* callback)(svc_action_t *op)
Definition: services_private.h:27
mainloop_clear_child_userdata
void mainloop_clear_child_userdata(mainloop_child_t *child)
Definition: mainloop.c:1025
pcmk__close_fds_in_child
void pcmk__close_fds_in_child(bool)
Definition: io.c:517
mainloop_fd_callbacks::dispatch
int(* dispatch)(gpointer userdata)
Definition: mainloop.h:116
crm_set_nonblocking
int crm_set_nonblocking(int fd)
Definition: io.c:485
PCMK_LSB_STATUS_NOT_INSTALLED
Definition: services.h:82
mainloop_child_t
struct mainloop_child_s mainloop_child_t
Definition: mainloop.h:33
crm_perror
#define crm_perror(level, fmt, args...)
Log a system error message.
Definition: logging.h:219
mainloop_del_fd
void mainloop_del_fd(mainloop_io_t *client)
Definition: mainloop.c:985
PCMK_OCF_NOT_CONFIGURED
Definition: services.h:96
services_add_inflight_op
void services_add_inflight_op(svc_action_t *op)
Definition: services.c:699
get_directory_list
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:954
PCMK_LRM_OP_DONE
Definition: services.h:121
svc_action_s::interval_ms
guint interval_ms
Definition: services.h:155
services.h
Services API.
svc_action_s::cancel
int cancel
Definition: services.h:169
mainloop_child_add_with_flags
void mainloop_child_add_with_flags(pid_t pid, int timeout, const char *desc, void *userdata, enum mainloop_child_flags, void(*callback)(mainloop_child_t *p, pid_t pid, int core, int signo, int exitcode))
Definition: mainloop.c:1237
services_action_cleanup
void services_action_cleanup(svc_action_t *op)
Definition: services.c:424
services_action_async
gboolean services_action_async(svc_action_t *op, void(*action_callback)(svc_action_t *))
Definition: services.c:763
NAGIOS_INSUFFICIENT_PRIV
Definition: services.h:140
PCMK_OCF_OK
Definition: services.h:90
services_untrack_op
void services_untrack_op(svc_action_t *op)
Definition: services.c:720
CRM_ASSERT
#define CRM_ASSERT(expr)
Definition: results.h:42
recurring_action_timer
gboolean recurring_action_timer(gpointer data)
Definition: services_linux.c:260
svc_action_s::status
int status
Definition: services.h:170
svc_action_s::agent
char * agent
Definition: services.h:159
svc_action_private_s::stderr_gsource
mainloop_io_t * stderr_gsource
Definition: services_private.h:31
svc_action_s::synchronous
int synchronous
Definition: services.h:173
PCMK_OCF_REASON_PREFIX
#define PCMK_OCF_REASON_PREFIX
Definition: services.h:55
svc_action_s::rc
int rc
Definition: services.h:167
operation_finalize
gboolean operation_finalize(svc_action_t *op)
Definition: services_linux.c:279
PCMK_OCF_NOT_INSTALLED
Definition: services.h:95
PCMK_RESOURCE_CLASS_LSB
#define PCMK_RESOURCE_CLASS_LSB
Definition: services.h:45
svc_action_s::standard
char * standard
Definition: services.h:157
crm_internal.h
crm.h
A dumping ground.
svc_action_s::rsc
char * rsc
Definition: services.h:153