17 #include <sys/types.h>
20 #include <sys/utsname.h>
32 #include <qb/qbdefs.h>
43 #include <libxml2/libxml/relaxng.h>
54 # define PW_BUFFER_LEN 500
67 static struct crm_option *crm_long_options = NULL;
68 static const char *crm_app_description = NULL;
69 static char *crm_short_options = NULL;
70 static const char *crm_app_usage = NULL;
161 if(stat(value, &st) != 0) {
162 crm_err(
"Script %s does not exist", value);
166 if(S_ISREG(st.st_mode) == 0) {
167 crm_err(
"Script %s is not a regular file", value);
171 if( (st.st_mode & (S_IXUSR | S_IXGRP )) == 0) {
172 crm_err(
"Script %s is not executable", value);
183 long number = strtol(value, &end, 10);
185 if(end && end[0] !=
'%') {
187 }
else if(number < 0) {
197 free(crm_short_options);
198 crm_short_options = NULL;
262 return crm_itoa(score);
267 const char *name,
const char *old_name,
const char *def_value)
269 const char *value = NULL;
270 char *new_value = NULL;
275 value = g_hash_table_lookup(options, name);
277 if ((value == NULL) && old_name) {
278 value = g_hash_table_lookup(options, old_name);
281 " is deprecated and will be removed in a future release",
285 new_value = strdup(value);
286 g_hash_table_insert(options, strdup(name), new_value);
291 if (value && validate && (validate(value) == FALSE)) {
292 crm_config_err(
"Resetting cluster option '%s' to default: value '%s' is invalid",
306 crm_trace(
"No value or default provided for cluster option '%s'",
313 crm_err(
"Bug: default value for cluster option '%s' is invalid", name);
317 crm_trace(
"Using default value '%s' for cluster option '%s'",
320 new_value = strdup(value);
321 g_hash_table_insert(options, strdup(name), new_value);
330 const char *value = NULL;
332 for (
int lpc = 0; lpc < len; lpc++) {
335 option_list[lpc].is_valid,
336 option_list[lpc].name,
337 option_list[lpc].alt_name,
338 option_list[lpc].default_value);
352 fprintf(stdout,
"<?xml version=\"1.0\"?>"
353 "<!DOCTYPE resource-agent SYSTEM \"ra-api-1.dtd\">\n"
354 "<resource-agent name=\"%s\">\n"
355 " <version>%s</version>\n"
356 " <longdesc lang=\"en\">%s</longdesc>\n"
357 " <shortdesc lang=\"en\">%s</shortdesc>\n"
358 " <parameters>\n", name,
version, desc_long, desc_short);
360 for (lpc = 0; lpc < len; lpc++) {
361 if (option_list[lpc].description_long == NULL && option_list[lpc].description_short == NULL) {
364 fprintf(stdout,
" <parameter name=\"%s\" unique=\"0\">\n"
365 " <shortdesc lang=\"en\">%s</shortdesc>\n"
366 " <content type=\"%s\" default=\"%s\"/>\n"
367 " <longdesc lang=\"en\">%s%s%s</longdesc>\n"
369 option_list[lpc].name,
370 option_list[lpc].description_short,
371 option_list[lpc].
type,
372 option_list[lpc].default_value,
373 option_list[lpc].description_long ? option_list[lpc].
374 description_long : option_list[lpc].description_short,
375 option_list[lpc].values ?
" Allowed values: " :
"",
376 option_list[lpc].values ? option_list[lpc].values :
"");
378 fprintf(stdout,
" </parameters>\n</resource-agent>\n");
386 for (lpc = 0; lpc < len; lpc++) {
388 option_list[lpc].is_valid,
389 option_list[lpc].name,
390 option_list[lpc].alt_name, option_list[lpc].default_value);
397 char *hash_key = crm_concat(sys ? sys :
"none", crm_msg_reference,
'_');
399 crm_trace(
"created hash key: (%s)", hash_key);
410 struct passwd *pwentry = NULL;
413 rc = getpwnam_r(name, &pwd, buffer,
PW_BUFFER_LEN, &pwentry);
416 *uid = pwentry->pw_uid;
419 *gid = pwentry->pw_gid;
421 crm_trace(
"User %s has uid=%d gid=%d", name, pwentry->pw_uid, pwentry->pw_gid);
424 rc = rc? -rc : -EINVAL;
433 crm_version_helper(
const char *text,
const char **end_text)
435 int atoi_result = -1;
441 if (text != NULL && text[0] != 0) {
448 atoi_result = (int) strtol(text, (
char **) end_text, 10);
450 if (errno == EINVAL) {
451 crm_err(
"Conversion of '%s' %c failed", text, text[0]);
468 const char *ver1_iter, *ver2_iter;
470 if (version1 == NULL && version2 == NULL) {
472 }
else if (version1 == NULL) {
474 }
else if (version2 == NULL) {
478 ver1_iter = version1;
479 ver2_iter = version2;
487 if (ver1_iter == ver2_iter) {
491 if (ver1_iter != NULL) {
492 digit1 = crm_version_helper(ver1_iter, &ver1_iter);
495 if (ver2_iter != NULL) {
496 digit2 = crm_version_helper(ver2_iter, &ver2_iter);
499 if (digit1 < digit2) {
503 }
else if (digit1 > digit2) {
508 if (ver1_iter != NULL && *ver1_iter ==
'.') {
511 if (ver1_iter != NULL && *ver1_iter ==
'\0') {
515 if (ver2_iter != NULL && *ver2_iter ==
'.') {
518 if (ver2_iter != NULL && *ver2_iter == 0) {
524 crm_trace(
"%s == %s (%d)", version1, version2, lpc);
526 crm_trace(
"%s < %s (%d)", version1, version2, lpc);
528 crm_trace(
"%s > %s (%d)", version1, version2, lpc);
537 # define NUMCHARS "0123456789."
541 # define WHITESPACE " \t\n\r\f"
552 }
else if (input[0] !=
'P') {
567 crm_warn(
"Using 0 instead of '%s'", input);
571 return (msec <= 0)? 0 : ((msec >= G_MAXUINT)? G_MAXUINT : (guint) msec);
577 const char *cp = input;
579 long long multiplier = 1000;
580 long long divisor = 1;
582 char *end_text = NULL;
594 if (strchr(
NUMCHARS, *cp) == NULL) {
598 if (strncasecmp(units,
"ms", 2) == 0 || strncasecmp(units,
"msec", 4) == 0) {
601 }
else if (strncasecmp(units,
"us", 2) == 0 || strncasecmp(units,
"usec", 4) == 0) {
604 }
else if (strncasecmp(units,
"s", 1) == 0 || strncasecmp(units,
"sec", 3) == 0) {
607 }
else if (strncasecmp(units,
"m", 1) == 0 || strncasecmp(units,
"min", 3) == 0) {
608 multiplier = 60 * 1000;
610 }
else if (strncasecmp(units,
"h", 1) == 0 || strncasecmp(units,
"hr", 2) == 0) {
611 multiplier = 60 * 60 * 1000;
613 }
else if (*units !=
EOS && *units !=
'\n' && *units !=
'\r') {
618 if (msec > LLONG_MAX/multiplier) {
633 crm_abort(
const char *file,
const char *
function,
int line,
634 const char *assert_condition, gboolean do_core, gboolean do_fork)
651 if (do_core == FALSE) {
652 crm_err(
"%s: Triggered assert at %s:%d : %s",
function, file, line, assert_condition);
655 }
else if (do_fork) {
659 crm_err(
"%s: Triggered fatal assert at %s:%d : %s",
function, file, line, assert_condition);
663 crm_crit(
"%s: Cannot create core for non-fatal assert at %s:%d : %s",
664 function, file, line, assert_condition);
667 }
else if(
pid == 0) {
674 crm_err(
"%s: Forked child %d to record non-fatal assert at %s:%d : %s",
675 function,
pid, file, line, assert_condition);
679 rc = waitpid(
pid, &status, 0);
684 }
while(errno == EINTR);
686 if (errno == ECHILD) {
688 crm_trace(
"Cannot wait on forked child %d - SIGCHLD is probably set to SIG_IGN",
pid);
699 const char *devnull =
"/dev/null";
701 if (daemonize == FALSE) {
707 if(rc <
pcmk_ok && rc != -ENOENT) {
709 crm_err(
"%s: already running [pid %ld in %s]", name,
pid, pidfile);
710 printf(
"%s: already running [pid %ld in %s]\n", name,
pid, pidfile);
716 fprintf(stderr,
"%s: could not start daemon\n", name);
720 }
else if (
pid > 0) {
727 printf(
"Could not lock '%s' for %s: %s (%d)\n", pidfile, name,
pcmk_strerror(rc), rc);
731 umask(S_IWGRP | S_IWOTH | S_IROTH);
734 (void)open(devnull, O_RDONLY);
735 close(STDOUT_FILENO);
736 (void)open(devnull, O_WRONLY);
737 close(STDERR_FILENO);
738 (void)open(devnull, O_WRONLY);
746 char *crm_name = NULL;
749 crm_name = crm_concat(
CRM_META, field,
'_');
752 max = strlen(crm_name);
753 for (; lpc < max; lpc++) {
754 switch (crm_name[lpc]) {
767 const char *value = NULL;
771 value = g_hash_table_lookup(hash, key);
778 static struct option *
779 crm_create_long_opts(
struct crm_option *long_options)
781 struct option *long_opts = NULL;
784 int index = 0, lpc = 0;
793 long_opts = realloc_safe(long_opts, (index + 1) *
sizeof(
struct option));
794 long_opts[index].name =
"__dummmy__";
795 long_opts[index].has_arg = 0;
796 long_opts[index].flag = 0;
797 long_opts[index].val =
'_';
800 for (lpc = 0; long_options[lpc].
name != NULL; lpc++) {
801 if (long_options[lpc].name[0] ==
'-') {
805 long_opts = realloc_safe(long_opts, (index + 1) *
sizeof(
struct option));
808 long_opts[index].name = long_options[lpc].
name;
809 long_opts[index].has_arg = long_options[lpc].
has_arg;
810 long_opts[index].flag = long_options[lpc].
flag;
811 long_opts[index].val = long_options[lpc].
val;
816 long_opts = realloc_safe(long_opts, (index + 1) *
sizeof(
struct option));
817 long_opts[index].name = NULL;
818 long_opts[index].has_arg = 0;
819 long_opts[index].flag = 0;
820 long_opts[index].val = 0;
828 const char *app_desc)
831 crm_short_options = strdup(short_options);
833 }
else if (long_options) {
835 int opt_string_len = 0;
836 char *local_short_options = NULL;
838 for (lpc = 0; long_options[lpc].
name != NULL; lpc++) {
839 if (long_options[lpc].val && long_options[lpc].val !=
'-' && long_options[lpc].val < UCHAR_MAX) {
840 local_short_options = realloc_safe(local_short_options, opt_string_len + 4);
841 local_short_options[opt_string_len++] = long_options[lpc].
val;
843 if (long_options[lpc].has_arg == optional_argument) {
844 local_short_options[opt_string_len++] =
':';
846 if (long_options[lpc].has_arg >= required_argument) {
847 local_short_options[opt_string_len++] =
':';
849 local_short_options[opt_string_len] = 0;
852 crm_short_options = local_short_options;
853 crm_trace(
"Generated short option string: '%s'", local_short_options);
857 crm_long_options = long_options;
860 crm_app_description = app_desc;
863 crm_app_usage = app_usage;
877 static struct option *long_opts = NULL;
879 if (long_opts == NULL && crm_long_options) {
880 long_opts = crm_create_long_opts(crm_long_options);
885 int flag = getopt_long(argc, argv, crm_short_options, long_opts, index);
889 if (long_opts[*index].val) {
890 return long_opts[*index].val;
891 }
else if (longname) {
892 *longname = long_opts[*index].name;
894 crm_notice(
"Unhandled option --%s", long_opts[*index].name);
911 if (crm_short_options) {
912 return getopt(argc, argv, crm_short_options);
922 FILE *stream = (exit_code ? stderr : stdout);
924 if (cmd ==
'v' || cmd ==
'$') {
926 fprintf(stream,
"Written by Andrew Beekhof\n");
941 if (crm_long_options) {
942 fprintf(stream,
"Options:\n");
943 for (i = 0; crm_long_options[i].
name != NULL; i++) {
947 fprintf(stream,
"%s\n\n", crm_long_options[i].desc);
950 fprintf(stream,
"\t#%s\n\n", crm_long_options[i].desc);
952 }
else if (crm_long_options[i].val ==
'-' && crm_long_options[i].desc) {
953 fprintf(stream,
"%s\n", crm_long_options[i].desc);
957 if (crm_long_options[i].val && crm_long_options[i].val <= UCHAR_MAX) {
958 fprintf(stream,
" -%c,", crm_long_options[i].val);
962 fprintf(stream,
" --%s%s\t%s\n", crm_long_options[i].name,
963 crm_long_options[i].has_arg == optional_argument ?
"[=value]" :
964 crm_long_options[i].has_arg == required_argument ?
"=value" :
"",
965 crm_long_options[i].desc ? crm_long_options[i].desc :
"");
969 }
else if (crm_short_options) {
970 fprintf(stream,
"Usage: %s - %s\n",
crm_system_name, crm_app_description);
971 for (i = 0; crm_short_options[i] != 0; i++) {
972 int has_arg = no_argument ;
974 if (crm_short_options[i + 1] ==
':') {
975 if (crm_short_options[i + 2] ==
':')
976 has_arg = optional_argument ;
978 has_arg = required_argument ;
981 fprintf(stream,
" -%c %s\n", crm_short_options[i],
982 has_arg == optional_argument ?
"[value]" :
983 has_arg == required_argument ?
"{value}" :
"");
996 qb_ipcs_service_t **ipcs_rw,
997 qb_ipcs_service_t **ipcs_shm,
998 struct qb_ipcs_service_handlers *ro_cb,
999 struct qb_ipcs_service_handlers *rw_cb)
1005 if (*ipcs_ro == NULL || *ipcs_rw == NULL || *ipcs_shm == NULL) {
1006 crm_err(
"Failed to create the CIB manager: exiting and inhibiting respawn");
1007 crm_warn(
"Verify pacemaker and pacemaker_remote are not both enabled");
1013 qb_ipcs_service_t *ipcs_rw,
1014 qb_ipcs_service_t *ipcs_shm)
1016 qb_ipcs_destroy(ipcs_ro);
1017 qb_ipcs_destroy(ipcs_rw);
1018 qb_ipcs_destroy(ipcs_shm);
1032 if (*ipcs == NULL) {
1033 crm_err(
"Failed to create pacemaker-attrd server: exiting and inhibiting respawn");
1034 crm_warn(
"Verify pacemaker and pacemaker_remote are not both enabled.");
1045 if (*ipcs == NULL) {
1046 crm_err(
"Failed to create fencer: exiting and inhibiting respawn.");
1047 crm_warn(
"Verify pacemaker and pacemaker_remote are not both enabled.");
1058 if (*handle == NULL) {
1059 *handle = dlopen(lib, RTLD_LAZY);
1063 crm_err(
"%sCould not open %s: %s", fatal ?
"Fatal: " :
"", lib, dlerror());
1070 a_function = dlsym(*handle, fn);
1071 if (a_function == NULL) {
1073 crm_err(
"%sCould not find %s in %s: %s", fatal ?
"Fatal: " :
"", fn, lib, error);
1082 #ifdef HAVE_UUID_UUID_H
1083 # include <uuid/uuid.h>
1089 unsigned char uuid[16];
1090 char *buffer = malloc(37);
1092 uuid_generate(uuid);
1093 uuid_unparse(uuid, buffer);
1114 }
else if (!strcmp(name,
"pacemaker-attrd")) {
1117 }
else if (!strcmp(name,
"pacemaker-based")) {
1120 }
else if (!strcmp(name,
"pacemaker-controld")) {
1123 }
else if (!strcmp(name,
"pacemaker-execd")) {
1126 }
else if (!strcmp(name,
"pacemaker-fenced")) {
1127 return "stonith-ng";
1129 }
else if (!strcmp(name,
"pacemaker-schedulerd")) {
1150 || !strcmp(name,
"stonith-ng")
1151 || !strcmp(name,
"attrd")
1164 int lpc = 0, len = 0;
1165 char *digest = NULL;
1168 if (buffer == NULL) {
1171 len = strlen(buffer);
1173 crm_trace(
"Beginning digest of %d bytes", len);
1178 sprintf(digest + (2 * lpc),
"%02x", raw_digest[lpc]);
1184 crm_err(
"Could not create digest");
1189 #ifdef HAVE_GNUTLS_GNUTLS_H
1191 crm_gnutls_global_init(
void)
1193 signal(SIGPIPE, SIG_IGN);
1194 gnutls_global_init();
1206 struct utsname hostinfo;
1208 return (
uname(&hostinfo) < 0)? NULL : strdup(hostinfo.nodename);