26 #include <sys/param.h>
27 #include <sys/types.h>
30 #include <sys/utsname.h>
43 #include <qb/qbdefs.h>
56 #include <libxml2/libxml/relaxng.h>
67 # define PW_BUFFER_LEN 500
81 static struct crm_option *crm_long_options = NULL;
82 static const char *crm_app_description = NULL;
83 static char *crm_short_options = NULL;
84 static const char *crm_app_usage = NULL;
99 free(crm_short_options);
135 const char *env_value = getenv(
"SBD_WATCHDOG_TIMEOUT");
140 if(value == NULL || st_timeout <= 0) {
141 crm_notice(
"Watchdog may be enabled but stonith-watchdog-timeout is disabled: %s", value);
144 do_crm_log_always(LOG_EMERG,
"Shutting down: stonith-watchdog-timeout is configured (%ldms) but SBD is not active", st_timeout);
148 }
else if(st_timeout < sbd_timeout) {
149 do_crm_log_always(LOG_EMERG,
"Shutting down: stonith-watchdog-timeout (%ldms) is too short (must be greater than %ldms)",
150 st_timeout, sbd_timeout);
155 crm_info(
"Watchdog functionality is consistent: %s delay exceeds timeout of %s", value, env_value);
219 if(stat(value, &st) != 0) {
220 crm_err(
"Script %s does not exist", value);
224 if(S_ISREG(st.st_mode) == 0) {
225 crm_err(
"Script %s is not a regular file", value);
229 if( (st.st_mode & (S_IXUSR | S_IXGRP )) == 0) {
230 crm_err(
"Script %s is not executable", value);
241 long number = strtol(value, &end, 10);
243 if(end && end[0] !=
'%') {
245 }
else if(number < 0) {
318 const char *name,
const char *old_name,
const char *def_value)
320 const char *value = NULL;
324 if (options != NULL) {
325 value = g_hash_table_lookup(options, name);
328 if (value == NULL && old_name && options != NULL) {
329 value = g_hash_table_lookup(options, old_name);
332 " cluster option '%s'", old_name, name);
333 g_hash_table_insert(options, strdup(name), strdup(value));
334 value = g_hash_table_lookup(options, old_name);
339 crm_trace(
"Using default value '%s' for cluster option '%s'", def_value, name);
341 if (options == NULL) {
344 }
else if(def_value == NULL) {
348 g_hash_table_insert(options, strdup(name), strdup(def_value));
349 value = g_hash_table_lookup(options, name);
352 if (validate && validate(value) == FALSE) {
354 " Defaulting to %s", value, name, def_value);
355 g_hash_table_replace(options, strdup(name), strdup(def_value));
356 value = g_hash_table_lookup(options, name);
366 const char *value = NULL;
367 gboolean found = FALSE;
369 for (lpc = 0; lpc < len; lpc++) {
373 option_list[lpc].is_valid,
374 option_list[lpc].name,
375 option_list[lpc].alt_name, option_list[lpc].default_value);
388 fprintf(stdout,
"<?xml version=\"1.0\"?>"
389 "<!DOCTYPE resource-agent SYSTEM \"ra-api-1.dtd\">\n"
390 "<resource-agent name=\"%s\">\n"
391 " <version>%s</version>\n"
392 " <longdesc lang=\"en\">%s</longdesc>\n"
393 " <shortdesc lang=\"en\">%s</shortdesc>\n"
394 " <parameters>\n", name, version, desc_long, desc_short);
396 for (lpc = 0; lpc < len; lpc++) {
397 if (option_list[lpc].description_long == NULL && option_list[lpc].description_short == NULL) {
400 fprintf(stdout,
" <parameter name=\"%s\" unique=\"0\">\n"
401 " <shortdesc lang=\"en\">%s</shortdesc>\n"
402 " <content type=\"%s\" default=\"%s\"/>\n"
403 " <longdesc lang=\"en\">%s%s%s</longdesc>\n"
405 option_list[lpc].name,
406 option_list[lpc].description_short,
407 option_list[lpc].
type,
408 option_list[lpc].default_value,
409 option_list[lpc].description_long ? option_list[lpc].
410 description_long : option_list[lpc].description_short,
411 option_list[lpc].values ?
" Allowed values: " :
"",
412 option_list[lpc].values ? option_list[lpc].values :
"");
414 fprintf(stdout,
" </parameters>\n</resource-agent>\n");
422 for (lpc = 0; lpc < len; lpc++) {
424 option_list[lpc].is_valid,
425 option_list[lpc].name,
426 option_list[lpc].alt_name, option_list[lpc].default_value);
431 crm_concat(
const char *prefix,
const char *suffix,
char join)
434 char *new_str = NULL;
438 len = strlen(prefix) + strlen(suffix) + 2;
440 new_str = malloc(len);
442 sprintf(new_str,
"%s%c%s", prefix, join, suffix);
443 new_str[len - 1] = 0;
451 char *hash_key =
crm_concat(sys ? sys :
"none", crm_msg_reference,
'_');
453 crm_trace(
"created hash key: (%s)", hash_key);
461 if (buffer != NULL) {
462 snprintf(buffer, len,
"%d", an_int);
474 buffer = malloc(len + 1);
475 if (buffer != NULL) {
476 snprintf(buffer, len,
"%d", an_int);
488 struct passwd *pwentry = NULL;
495 *uid = pwentry->pw_uid;
498 *gid = pwentry->pw_gid;
500 crm_trace(
"Cluster user %s has uid=%d gid=%d", name, pwentry->pw_uid, pwentry->pw_gid);
503 crm_err(
"Cluster user %s does not exist", name);
511 crm_version_helper(
const char *text,
char **end_text)
513 int atoi_result = -1;
519 if (text != NULL && text[0] != 0) {
520 atoi_result = (int)strtol(text, end_text, 10);
522 if (errno == EINVAL) {
523 crm_err(
"Conversion of '%s' %c failed", text, text[0]);
540 char *ver1_copy = NULL, *ver2_copy = NULL;
541 char *rest1 = NULL, *rest2 = NULL;
543 if (version1 == NULL && version2 == NULL) {
545 }
else if (version1 == NULL) {
547 }
else if (version2 == NULL) {
551 ver1_copy = strdup(version1);
552 ver2_copy = strdup(version2);
562 if (rest1 == rest2) {
567 digit1 = crm_version_helper(rest1, &rest1);
571 digit2 = crm_version_helper(rest2, &rest2);
574 if (digit1 < digit2) {
578 }
else if (digit1 > digit2) {
583 if (rest1 != NULL && rest1[0] ==
'.') {
586 if (rest1 != NULL && rest1[0] == 0) {
590 if (rest2 != NULL && rest2[0] ==
'.') {
593 if (rest2 != NULL && rest2[0] == 0) {
602 crm_trace(
"%s == %s (%d)", version1, version2, lpc);
604 crm_trace(
"%s < %s (%d)", version1, version2, lpc);
606 crm_trace(
"%s > %s (%d)", version1, version2, lpc);
620 #include <sys/types.h>
627 long long result = -1;
628 char *local_end_text = NULL;
635 if (end_text != NULL) {
636 result = strtol(text, end_text, 10);
638 result = strtol(text, &local_end_text, 10);
641 if (end_text != NULL) {
642 result = strtoll(text, end_text, 10);
644 result = strtoll(text, &local_end_text, 10);
650 if (errno == EINVAL) {
651 crm_err(
"Conversion of %s failed", text);
654 }
else if (errno == ERANGE) {
655 crm_err(
"Conversion of %s was clipped: %lld", text, result);
657 }
else if (errno != 0) {
658 crm_perror(LOG_ERR,
"Conversion of %s failed:", text);
661 if (local_end_text != NULL && local_end_text[0] !=
'\0') {
662 crm_err(
"Characters left over after parsing '%s': '%s'", text, local_end_text);
673 int atoi_result = -1;
682 if (default_text != NULL) {
689 crm_err(
"No default conversion value supplied");
701 }
else if (a == NULL || b == NULL) {
704 }
else if (strcasecmp(a, b) == 0) {
713 gboolean ret = FALSE;
727 }
else if (strcasecmp(s,
"true") == 0
728 || strcasecmp(s,
"on") == 0
729 || strcasecmp(s,
"yes") == 0 || strcasecmp(s,
"y") == 0 || strcasecmp(s,
"1") == 0) {
733 }
else if (strcasecmp(s,
"false") == 0
734 || strcasecmp(s,
"off") == 0
735 || strcasecmp(s,
"no") == 0 || strcasecmp(s,
"n") == 0 || strcasecmp(s,
"0") == 0) {
743 # define NUMCHARS "0123456789."
747 # define WHITESPACE " \t\n\r\f"
753 unsigned long long msec = 0;
758 }
else if (input[0] !=
'P') {
778 const char *cp = input;
780 long long multiplier = 1000;
781 long long divisor = 1;
783 char *end_text = NULL;
795 if (strchr(
NUMCHARS, *cp) == NULL) {
799 if (strncasecmp(units,
"ms", 2) == 0 || strncasecmp(units,
"msec", 4) == 0) {
802 }
else if (strncasecmp(units,
"us", 2) == 0 || strncasecmp(units,
"usec", 4) == 0) {
805 }
else if (strncasecmp(units,
"s", 1) == 0 || strncasecmp(units,
"sec", 3) == 0) {
808 }
else if (strncasecmp(units,
"m", 1) == 0 || strncasecmp(units,
"min", 3) == 0) {
809 multiplier = 60 * 1000;
811 }
else if (strncasecmp(units,
"h", 1) == 0 || strncasecmp(units,
"hr", 2) == 0) {
812 multiplier = 60 * 60 * 1000;
814 }
else if (*units !=
EOS && *units !=
'\n' && *units !=
'\r') {
819 if (msec > LLONG_MAX/multiplier) {
839 len += strlen(op_type);
840 len += strlen(rsc_id);
843 sprintf(op_id,
"%s_%s_%d", rsc_id, op_type, interval);
848 parse_op_key(
const char *key,
char **rsc_id,
char **op_type,
int *interval)
851 char *mutable_key = NULL;
852 char *mutable_key_ptr = NULL;
853 int len = 0, offset = 0, ch = 0;
863 while (offset > 0 && isdigit(key[offset])) {
864 int digits = len - offset;
866 ch = key[offset] -
'0';
878 CRM_CHECK(key[offset] ==
'_',
return FALSE);
880 mutable_key = strdup(key);
881 mutable_key[offset] = 0;
884 while (offset > 0 && key[offset] !=
'_') {
888 CRM_CHECK(key[offset] ==
'_', free(mutable_key);
891 mutable_key_ptr = mutable_key + offset + 1;
893 crm_trace(
" Action: %s", mutable_key_ptr);
895 *op_type = strdup(mutable_key_ptr);
897 mutable_key[offset] = 0;
900 CRM_CHECK(mutable_key != mutable_key_ptr, free(mutable_key);
903 notify = strstr(mutable_key,
"_post_notify");
904 if (notify &&
safe_str_eq(notify,
"_post_notify")) {
908 notify = strstr(mutable_key,
"_pre_notify");
909 if (notify &&
safe_str_eq(notify,
"_pre_notify")) {
914 *rsc_id = mutable_key;
927 CRM_CHECK(notify_type != NULL,
return NULL);
929 len += strlen(op_type);
930 len += strlen(rsc_id);
931 len += strlen(notify_type);
936 sprintf(op_id,
"%s_%s_notify_%s_0", rsc_id, notify_type, op_type);
945 char *fail_state = NULL;
947 CRM_CHECK(transition_key != NULL,
return NULL);
949 len += strlen(transition_key);
951 fail_state = malloc(len);
952 if (fail_state != NULL) {
953 snprintf(fail_state, len,
"%d:%s", op_status, transition_key);
962 char *fail_state = NULL;
964 CRM_CHECK(transition_key != NULL,
return NULL);
966 len += strlen(transition_key);
968 fail_state = malloc(len);
969 if (fail_state != NULL) {
970 snprintf(fail_state, len,
"%d:%d;%s", op_status, op_rc, transition_key);
977 int *
op_status,
int *op_rc,
int *target_rc)
981 gboolean result = TRUE;
985 CRM_CHECK(op_status != NULL,
return FALSE);
987 key = calloc(1, strlen(magic) + 1);
988 res = sscanf(magic,
"%d:%d;%s", op_status, op_rc, key);
990 crm_warn(
"Only found %d items in: '%s'", res, magic);
1005 char *fail_state = NULL;
1009 len += strlen(node);
1011 fail_state = malloc(len);
1012 if (fail_state != NULL) {
1013 snprintf(fail_state, len,
"%d:%d:%d:%-*s", action_id, transition_id, target_rc, 36, node);
1023 gboolean done = FALSE;
1026 CRM_CHECK(target_rc != NULL,
return FALSE);
1027 CRM_CHECK(action_id != NULL,
return FALSE);
1028 CRM_CHECK(transition_id != NULL,
return FALSE);
1030 *uuid = calloc(1, 37);
1031 res = sscanf(key,
"%d:%d:%d:%36s", action_id, transition_id, target_rc, *uuid);
1044 res = sscanf(key,
"%d:%d:%36s", action_id, transition_id, *uuid);
1047 res = sscanf(key,
"%d:%36s", transition_id, *uuid);
1050 }
else if (res != 3) {
1060 res = sscanf(key,
"%d:%36s", transition_id, *uuid);
1064 crm_crit(
"Unhandled sscanf result (%d) for %s", res, key);
1067 if (strlen(*uuid) != 36) {
1068 crm_warn(
"Bad UUID (%s) in sscanf result (%d) for %s", *uuid, res, key);
1071 if (done == FALSE) {
1072 crm_err(
"Cannot decode '%s' rc=%d", key, res);
1078 *transition_id = -1;
1088 char *timeout = NULL;
1089 char *interval = NULL;
1091 const char *attr_filter[] = {
1097 gboolean do_delete = FALSE;
1099 static int meta_len = 0;
1101 if (meta_len == 0) {
1105 if (param_set == NULL) {
1109 for (lpc = 0; lpc <
DIMOF(attr_filter); lpc++) {
1121 xmlAttrPtr xIter = param_set->properties;
1124 const char *prop_name = (
const char *)xIter->name;
1126 xIter = xIter->next;
1128 if (strncasecmp(prop_name,
CRM_META, meta_len) == 0) {
1140 if (timeout != NULL) {
1155 const char *assert_condition, gboolean do_core, gboolean do_fork)
1164 if(crm_is_daemon == FALSE) {
1172 if (do_core == FALSE) {
1173 crm_err(
"%s: Triggered assert at %s:%d : %s",
function, file, line, assert_condition);
1176 }
else if (do_fork) {
1180 crm_err(
"%s: Triggered fatal assert at %s:%d : %s",
function, file, line, assert_condition);
1184 crm_crit(
"%s: Cannot create core for non-fatal assert at %s:%d : %s",
1185 function, file, line, assert_condition);
1188 }
else if(pid == 0) {
1195 crm_err(
"%s: Forked child %d to record non-fatal assert at %s:%d : %s",
1196 function, pid, file, line, assert_condition);
1200 rc = waitpid(pid, &status, 0);
1205 }
while(errno == EINTR);
1207 if (errno == ECHILD) {
1209 crm_trace(
"Cannot wait on forked child %d - SIGCHLD is probably set to SIG_IGN", pid);
1212 crm_perror(LOG_ERR,
"Cannot wait on forked child %d", pid);
1218 static int have_proc_pid = 0;
1220 if(have_proc_pid == 0) {
1221 char proc_path[PATH_MAX], exe_path[PATH_MAX];
1224 snprintf(proc_path,
sizeof(proc_path),
"/proc/%lu/exe", (
long unsigned int)getpid());
1227 if(readlink(proc_path, exe_path, PATH_MAX - 1) < 0) {
1235 }
else if (kill(pid, 0) < 0 && errno == ESRCH) {
1238 }
else if(daemon == NULL || have_proc_pid == -1) {
1243 char proc_path[PATH_MAX], exe_path[PATH_MAX], myexe_path[PATH_MAX];
1246 snprintf(proc_path,
sizeof(proc_path),
"/proc/%lu/exe", pid);
1248 rc = readlink(proc_path, exe_path, PATH_MAX - 1);
1249 if (rc < 0 && errno == EACCES) {
1250 crm_perror(LOG_INFO,
"Could not read from %s", proc_path);
1252 }
else if (rc < 0) {
1253 crm_perror(LOG_ERR,
"Could not read from %s", proc_path);
1260 if(daemon[0] !=
'/') {
1261 rc = snprintf(myexe_path,
sizeof(proc_path),
CRM_DAEMON_DIR"/%s", daemon);
1264 rc = snprintf(myexe_path,
sizeof(proc_path),
"%s", daemon);
1268 if (strcmp(exe_path, myexe_path) == 0) {
1276 #define LOCKSTRLEN 11
1286 if ((fd = open(filename, O_RDONLY)) < 0) {
1290 if (fstat(fd, &sbuf) >= 0 && sbuf.st_size <
LOCKSTRLEN) {
1296 if (read(fd, buf,
sizeof(buf)) < 1) {
1300 if (sscanf(buf,
"%lu", &pid) > 0) {
1304 crm_trace(
"Got pid %lu from %s\n", pid, filename);
1325 }
else if (mypid && pid == mypid) {
1334 }
else if (mypid && pid != mypid) {
1343 crm_lock_pidfile(
const char *filename,
const char *name)
1349 mypid = (
unsigned long)getpid();
1352 if (rc == -ENOENT) {
1360 if ((fd = open(filename, O_CREAT | O_WRONLY | O_EXCL, 0644)) < 0) {
1365 snprintf(buf,
sizeof(buf),
"%*lu\n",
LOCKSTRLEN - 1, mypid);
1370 crm_perror(LOG_ERR,
"Incomplete write to %s", filename);
1382 const char *devnull =
"/dev/null";
1384 if (daemonize == FALSE) {
1390 if(rc <
pcmk_ok && rc != -ENOENT) {
1392 crm_err(
"%s: already running [pid %ld in %s]", name, pid, pidfile);
1393 printf(
"%s: already running [pid %ld in %s]\n", name, pid, pidfile);
1399 fprintf(stderr,
"%s: could not start daemon\n", name);
1403 }
else if (pid > 0) {
1407 rc = crm_lock_pidfile(pidfile, name);
1410 printf(
"Could not lock '%s' for %s: %s (%d)\n", pidfile, name,
pcmk_strerror(rc), rc);
1414 umask(S_IWGRP | S_IWOTH | S_IROTH);
1416 close(STDIN_FILENO);
1417 (void)open(devnull, O_RDONLY);
1418 close(STDOUT_FILENO);
1419 (void)open(devnull, O_WRONLY);
1420 close(STDERR_FILENO);
1421 (void)open(devnull, O_WRONLY);
1433 for (len = strlen(str) - 1; len >= 0 && str[len] ==
'\n'; len--) {
1444 return g_strcmp0(a, b) == 0;
1447 }
else if (a == b) {
1450 }
else if (a == NULL || b == NULL) {
1454 }
else if (strcasecmp(a, b) == 0) {
1465 char *crm_name = NULL;
1471 max = strlen(crm_name);
1472 for (; lpc < max; lpc++) {
1473 switch (crm_name[lpc]) {
1475 crm_name[lpc] =
'_';
1486 const char *value = NULL;
1490 value = g_hash_table_lookup(hash, key);
1497 static struct option *
1498 crm_create_long_opts(
struct crm_option *long_options)
1500 struct option *long_opts = NULL;
1502 #ifdef HAVE_GETOPT_H
1503 int index = 0, lpc = 0;
1512 long_opts = realloc_safe(long_opts, (index + 1) *
sizeof(
struct option));
1513 long_opts[index].name =
"__dummmy__";
1514 long_opts[index].has_arg = 0;
1515 long_opts[index].flag = 0;
1516 long_opts[index].val =
'_';
1519 for (lpc = 0; long_options[lpc].
name != NULL; lpc++) {
1520 if (long_options[lpc].name[0] ==
'-') {
1524 long_opts = realloc_safe(long_opts, (index + 1) *
sizeof(
struct option));
1527 long_opts[index].name = long_options[lpc].
name;
1528 long_opts[index].has_arg = long_options[lpc].
has_arg;
1529 long_opts[index].flag = long_options[lpc].
flag;
1530 long_opts[index].val = long_options[lpc].
val;
1535 long_opts = realloc_safe(long_opts, (index + 1) *
sizeof(
struct option));
1536 long_opts[index].name = NULL;
1537 long_opts[index].has_arg = 0;
1538 long_opts[index].flag = 0;
1539 long_opts[index].val = 0;
1547 const char *app_desc)
1549 if (short_options) {
1550 crm_short_options = strdup(short_options);
1552 }
else if (long_options) {
1554 int opt_string_len = 0;
1555 char *local_short_options = NULL;
1557 for (lpc = 0; long_options[lpc].
name != NULL; lpc++) {
1558 if (long_options[lpc].val && long_options[lpc].val !=
'-' && long_options[lpc].val < UCHAR_MAX) {
1559 local_short_options = realloc_safe(local_short_options, opt_string_len + 4);
1560 local_short_options[opt_string_len++] = long_options[lpc].
val;
1562 if (long_options[lpc].has_arg == optional_argument) {
1563 local_short_options[opt_string_len++] =
':';
1565 if (long_options[lpc].has_arg >= required_argument) {
1566 local_short_options[opt_string_len++] =
':';
1568 local_short_options[opt_string_len] = 0;
1571 crm_short_options = local_short_options;
1572 crm_trace(
"Generated short option string: '%s'", local_short_options);
1576 crm_long_options = long_options;
1579 crm_app_description = app_desc;
1582 crm_app_usage = app_usage;
1595 #ifdef HAVE_GETOPT_H
1596 static struct option *long_opts = NULL;
1598 if (long_opts == NULL && crm_long_options) {
1599 long_opts = crm_create_long_opts(crm_long_options);
1604 int flag = getopt_long(argc, argv, crm_short_options, long_opts, index);
1608 if (long_opts[*index].val) {
1609 return long_opts[*index].val;
1610 }
else if (longname) {
1611 *longname = long_opts[*index].name;
1613 crm_notice(
"Unhandled option --%s", long_opts[*index].name);
1630 if (crm_short_options) {
1631 return getopt(argc, argv, crm_short_options);
1641 FILE *stream = (exit_code ? stderr : stdout);
1643 if (cmd ==
'v' || cmd ==
'$') {
1645 fprintf(stream,
"Written by Andrew Beekhof\n");
1656 if (crm_app_usage) {
1660 if (crm_long_options) {
1661 fprintf(stream,
"Options:\n");
1662 for (i = 0; crm_long_options[i].
name != NULL; i++) {
1666 fprintf(stream,
"%s\n\n", crm_long_options[i].desc);
1669 fprintf(stream,
"\t#%s\n\n", crm_long_options[i].desc);
1671 }
else if (crm_long_options[i].val ==
'-' && crm_long_options[i].desc) {
1672 fprintf(stream,
"%s\n", crm_long_options[i].desc);
1676 if (crm_long_options[i].val && crm_long_options[i].val <= UCHAR_MAX) {
1677 fprintf(stream,
" -%c,", crm_long_options[i].val);
1681 fprintf(stream,
" --%s%s\t%s\n", crm_long_options[i].name,
1682 crm_long_options[i].has_arg == optional_argument ?
"[=value]" :
1683 crm_long_options[i].has_arg == required_argument ?
"=value" :
"",
1684 crm_long_options[i].desc ? crm_long_options[i].desc :
"");
1688 }
else if (crm_short_options) {
1689 fprintf(stream,
"Usage: %s - %s\n",
crm_system_name, crm_app_description);
1690 for (i = 0; crm_short_options[i] != 0; i++) {
1691 int has_arg = no_argument ;
1693 if (crm_short_options[i + 1] ==
':') {
1694 if (crm_short_options[i + 2] ==
':')
1695 has_arg = optional_argument ;
1697 has_arg = required_argument ;
1700 fprintf(stream,
" -%c %s\n", crm_short_options[i],
1701 has_arg == optional_argument ?
"[value]" :
1702 has_arg == required_argument ?
"{value}" :
"");
1714 qb_ipcs_service_t **ipcs_rw,
1715 qb_ipcs_service_t **ipcs_shm,
1716 struct qb_ipcs_service_handlers *ro_cb,
1717 struct qb_ipcs_service_handlers *rw_cb)
1723 if (*ipcs_ro == NULL || *ipcs_rw == NULL || *ipcs_shm == NULL) {
1724 crm_err(
"Failed to create cib servers: exiting and inhibiting respawn.");
1725 crm_warn(
"Verify pacemaker and pacemaker_remote are not both enabled.");
1731 qb_ipcs_service_t *ipcs_rw,
1732 qb_ipcs_service_t *ipcs_shm)
1734 qb_ipcs_destroy(ipcs_ro);
1735 qb_ipcs_destroy(ipcs_rw);
1736 qb_ipcs_destroy(ipcs_shm);
1750 if (*ipcs == NULL) {
1751 crm_err(
"Failed to create attrd servers: exiting and inhibiting respawn.");
1752 crm_warn(
"Verify pacemaker and pacemaker_remote are not both enabled.");
1762 if (*ipcs == NULL) {
1763 crm_err(
"Failed to create stonith-ng servers: exiting and inhibiting respawn.");
1764 crm_warn(
"Verify pacemaker and pacemaker_remote are not both enabled.");
1771 const char *value,
const char *section,
const char *set,
const char *dampen,
1772 const char *user_name,
int options)
1776 const char *task = NULL;
1777 const char *name_as = NULL;
1780 static gboolean connected = TRUE;
1784 if (ipc == NULL && local_ipc == NULL) {
1805 if (name == NULL && command ==
'U') {
1840 if (name_as != NULL) {
1863 if (connected == FALSE) {
1864 crm_info(
"Connecting to cluster... %d retries remaining", max);
1871 crm_perror(LOG_INFO,
"Connection to cluster attribute manager failed");
1874 if (ipc != local_ipc) {
1877 }
else if (rc > 0) {
1880 }
else if (rc == -EAGAIN || rc == -EALREADY) {
1895 crm_debug(
"Sent update: %s=%s for %s", name, value, host ? host :
"localhost");
1899 crm_debug(
"Could not send update %s=%s for %s: %s (%d)", name, value,
1905 #define FAKE_TE_ID "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
1914 char *digest = NULL;
1915 xmlNode *args_xml = NULL;
1917 if (op->
params == NULL) {
1931 do_crm_log(level,
"Calculated digest %s for %s (%s). Source: %s\n",
1932 digest,
ID(update), magic, digest_source);
1933 free(digest_source);
1973 if (target_rc != op->
rc) {
1983 int target_rc,
const char * node,
const char * origin,
int level)
1988 char *op_id_additional = NULL;
1989 char *local_user_data = NULL;
1990 const char *exit_reason = NULL;
1992 xmlNode *xml_op = NULL;
1993 const char *task = NULL;
1994 gboolean dc_munges_migrate_ops = (
compare_version(caller_version,
"3.0.3") < 0);
1995 gboolean dc_needs_unique_ops = (
compare_version(caller_version,
"3.0.6") < 0);
1998 do_crm_log(level,
"%s: Updating resource %s after %s op %s (interval=%d)",
2002 crm_trace(
"DC version: %s", caller_version);
2023 }
else if (dc_munges_migrate_ops
2030 if (dc_needs_unique_ops && op->
interval > 0) {
2031 op_id = strdup(key);
2054 op_id = strdup(key);
2062 if (xml_op == NULL) {
2067 crm_debug(
"Generating fake transition key for:"
2068 " %s_%s_%d %d from %s",
2095 crm_trace(
"Timing data (%s_%s_%d): last=%u change=%u exec=%u queue=%u",
2131 append_digest(op, xml_op, caller_version, magic, LOG_DEBUG);
2133 if (op_id_additional) {
2135 op_id = op_id_additional;
2136 op_id_additional = NULL;
2140 if (local_user_data) {
2141 free(local_user_data);
2154 if(user == NULL || strlen(user) == 0) {
2161 }
else if (strcmp(user,
"root") == 0) {
2164 crm_trace(
"acls required for %s", user);
2176 struct passwd *pwent = getpwuid(uid);
2178 if (pwent == NULL) {
2179 crm_perror(LOG_ERR,
"Cannot get password entry of uid: %d", uid);
2183 return strdup(pwent->pw_name);
2191 static const char *effective_user = NULL;
2192 const char *requested_user = NULL;
2193 const char *user = NULL;
2195 if(effective_user == NULL) {
2200 if(requested_user == NULL) {
2204 if (is_privileged(effective_user) == FALSE) {
2206 user = effective_user;
2208 }
else if(peer_user == NULL && requested_user == NULL) {
2210 user = effective_user;
2212 }
else if(peer_user == NULL) {
2214 user = requested_user;
2216 }
else if (is_privileged(peer_user) == FALSE) {
2220 }
else if (requested_user == NULL) {
2226 user = requested_user;
2238 return requested_user;
2245 CRM_CHECK(user != NULL && request != NULL && field != NULL,
return);
2248 if (is_privileged(user) == FALSE) {
2279 const signed char *p;
2282 for (p = v; *p !=
'\0'; p++)
2283 h = (h << 5) - h + *p;
2291 const signed char *p;
2294 for (p = v; *p !=
'\0'; p++)
2295 h = (h << 5) - h + g_ascii_tolower(*p);
2306 if (*handle == NULL) {
2307 *handle = dlopen(lib, RTLD_LAZY);
2311 crm_err(
"%sCould not open %s: %s", fatal ?
"Fatal: " :
"", lib, dlerror());
2318 a_function = dlsym(*handle, fn);
2319 if (a_function == NULL) {
2321 crm_err(
"%sCould not find %s in %s: %s", fatal ?
"Fatal: " :
"", fn, lib, error);
2336 if (value == NULL) {
2340 last = strlen(list);
2343 len += strlen(value);
2344 list = realloc_safe(list, len);
2345 sprintf(list + last,
" %s", value);
2356 #ifdef HAVE_UUID_UUID_H
2357 # include <uuid/uuid.h>
2363 unsigned char uuid[16];
2364 char *buffer = malloc(37);
2366 uuid_generate(uuid);
2367 uuid_unparse(uuid, buffer);
2376 int lpc = 0, len = 0;
2377 char *digest = NULL;
2380 if (buffer == NULL) {
2383 len = strlen(buffer);
2385 crm_trace(
"Beginning digest of %d bytes", len);
2390 sprintf(digest + (2 * lpc),
"%02x", raw_digest[lpc]);
2396 crm_err(
"Could not create digest");
2408 char *compressed = NULL;
2409 char *uncompressed = strdup(data);
2410 struct timespec after_t;
2411 struct timespec before_t;
2414 max = (length * 1.1) + 600;
2417 #ifdef CLOCK_MONOTONIC
2418 clock_gettime(CLOCK_MONOTONIC, &before_t);
2422 compressed = malloc(max);
2425 rc = BZ2_bzBuffToBuffCompress(compressed, result_len, uncompressed, length,
CRM_BZ2_BLOCKS, 0,
2436 #ifdef CLOCK_MONOTONIC
2437 clock_gettime(CLOCK_MONOTONIC, &after_t);
2439 crm_info(
"Compressed %d bytes into %d (ratio %d:1) in %dms",
2440 length, *result_len, length / (*result_len),
2441 (after_t.tv_sec - before_t.tv_sec) * 1000 + (after_t.tv_nsec -
2442 before_t.tv_nsec) / 1000000);
2444 crm_info(
"Compressed %d bytes into %d (ratio %d:1)",
2445 length, *result_len, length / (*result_len));
2448 *result = compressed;
2452 #ifdef HAVE_GNUTLS_GNUTLS_H
2454 crm_gnutls_global_init(
void)
2456 signal(SIGPIPE, SIG_IGN);
2457 gnutls_global_init();
#define CRM_CHECK(expr, failure_action)
#define XML_RSC_OP_LAST_CHANGE
void * find_library_function(void **handle, const char *lib, const char *fn, gboolean fatal)
void verify_all_options(GHashTable *options, pe_cluster_option *option_list, int len)
gboolean parse_op_key(const char *key, char **rsc_id, char **op_type, int *interval)
void crm_write_blackbox(int nsig, struct qb_log_callsite *callsite)
bool crm_ipc_connect(crm_ipc_t *client)
Establish an IPC connection to a Pacemaker component.
long long crm_get_msec(const char *input)
int crm_get_option_long(int argc, char **argv, int *index, const char **longname)
#define crm_notice(fmt, args...)
int crm_user_lookup(const char *name, uid_t *uid, gid_t *gid)
#define CRMD_ACTION_MIGRATED
int attrd_update_delegate(crm_ipc_t *ipc, char command, const char *host, const char *name, const char *value, const char *section, const char *set, const char *dampen, const char *user_name, int options)
void crm_enable_stderr(int enable)
void * convert_const_pointer(const void *ptr)
bool crm_compress_string(const char *data, int length, int max, char **result, unsigned int *result_len)
#define crm_crit(fmt, args...)
gboolean check_utilization(const char *value)
const char * crm_meta_value(GHashTable *hash, const char *field)
#define XML_ATTR_TRANSITION_MAGIC
void cib_ipc_servers_destroy(qb_ipcs_service_t *ipcs_ro, qb_ipcs_service_t *ipcs_rw, qb_ipcs_service_t *ipcs_shm)
void attrd_ipc_server_init(qb_ipcs_service_t **ipcs, struct qb_ipcs_service_handlers *cb)
char * crm_concat(const char *prefix, const char *suffix, char join)
struct crm_time_s crm_time_t
const char * pcmk_strerror(int rc)
gboolean check_time(const char *value)
#define crm_config_err(fmt...)
void crm_make_daemon(const char *name, gboolean daemonize, const char *pidfile)
void crm_xml_cleanup(void)
gboolean decode_transition_key(const char *key, char **uuid, int *transition_id, int *action_id, int *target_rc)
void g_hash_destroy_str(gpointer data)
#define CRMD_ACTION_NOTIFY
void cib_ipc_servers_init(qb_ipcs_service_t **ipcs_ro, qb_ipcs_service_t **ipcs_rw, qb_ipcs_service_t **ipcs_shm, struct qb_ipcs_service_handlers *ro_cb, struct qb_ipcs_service_handlers *rw_cb)
char * crm_md5sum(const char *buffer)
xmlNode * find_entity(xmlNode *parent, const char *node_name, const char *id)
#define XML_RSC_OP_T_EXEC
gboolean check_sbd_timeout(const char *value)
char * generate_transition_key(int transition_id, int action_id, int target_rc, const char *node)
#define XML_LRM_ATTR_INTERVAL
gboolean safe_str_neq(const char *a, const char *b)
gboolean crm_config_warning
int crm_help(char cmd, int exit_code)
#define XML_LRM_ATTR_OP_DIGEST
void mainloop_cleanup(void)
char * crm_element_value_copy(xmlNode *data, const char *name)
crm_time_t * crm_time_parse_duration(const char *duration_str)
char * crm_itoa_stack(int an_int, char *buffer, size_t len)
#define CRM_LOG_ASSERT(expr)
void crm_set_options(const char *short_options, const char *app_usage, struct crm_option *long_options, const char *app_desc)
const char * get_cluster_pref(GHashTable *options, pe_cluster_option *option_list, int len, const char *name)
#define XML_RSC_OP_T_QUEUE
#define XML_CIB_TAG_NODES
#define PACEMAKER_VERSION
#define attrd_opt_private
Wrappers for and extensions to glib mainloop.
void config_metadata(const char *name, const char *version, const char *desc_short, const char *desc_long, pe_cluster_option *option_list, int len)
long crm_read_pidfile(const char *filename)
const char * crm_xml_replace(xmlNode *node, const char *name, const char *value)
#define ATTRD_OP_PEER_REMOVE
bool pcmk_acl_required(const char *user)
guint g_str_hash_traditional(gconstpointer v)
void stonith_ipc_server_init(qb_ipcs_service_t **ipcs, struct qb_ipcs_service_handlers *cb)
#define CRMD_ACTION_START
xmlNode * create_operation_update(xmlNode *parent, lrmd_event_data_t *op, const char *caller_version, int target_rc, const char *node, const char *origin, int level)
char * crm_meta_name(const char *field)
gboolean check_quorum(const char *value)
#define XML_LRM_ATTR_TASK_KEY
#define XML_LRM_ATTR_TASK
void hash2field(gpointer key, gpointer value, gpointer user_data)
char * calculate_operation_digest(xmlNode *local_cib, const char *version)
Calculate and return digest of XML operation.
#define crm_warn(fmt, args...)
int crm_pid_active(long pid, const char *daemon)
int daemon(int nochdir, int noclose)
#define F_ATTRD_ATTRIBUTE
char * generate_hash_key(const char *crm_msg_reference, const char *sys)
#define ATTRD_OP_UPDATE_BOTH
#define crm_debug(fmt, args...)
void determine_request_user(const char *user, xmlNode *request, const char *field)
struct crm_ipc_s crm_ipc_t
#define F_ATTRD_IS_PRIVATE
char * score2char(int score)
#define pcmk_option_example
unsigned long long crm_get_interval(const char *input)
gboolean did_rsc_op_fail(lrmd_event_data_t *op, int target_rc)
#define crm_trace(fmt, args...)
#define do_crm_log(level, fmt, args...)
Log a message.
const char * cluster_option(GHashTable *options, gboolean(*validate)(const char *), const char *name, const char *old_name, const char *def_value)
#define pcmk_option_paragraph
Wrappers for and extensions to libxml2.
xmlNode * create_xml_node(xmlNode *parent, const char *name)
const char * crm_element_value(xmlNode *data, const char *name)
long long crm_int_helper(const char *text, char **end_text)
char * crm_itoa(int an_int)
gboolean crm_is_true(const char *s)
#define F_ATTRD_IS_REMOTE
#define XML_LRM_ATTR_MIGRATE_TARGET
char * crm_generate_uuid(void)
#define XML_LRM_ATTR_EXIT_REASON
#define do_crm_log_always(level, fmt, args...)
Log a message using constant severity.
void free_xml(xmlNode *child)
void filter_action_parameters(xmlNode *param_set, const char *version)
CRM_TRACE_INIT_DATA(common)
gboolean decode_transition_magic(const char *magic, char **uuid, int *transition_id, int *action_id, int *op_status, int *op_rc, int *target_rc)
long long int crm_time_get_seconds(crm_time_t *dt)
#define DAEMON_RESPAWN_STOP
int compare_version(const char *version1, const char *version2)
gboolean check_script(const char *value)
#define crm_config_warn(fmt...)
#define XML_ATTR_TRANSITION_KEY
const char * crm_xml_add(xmlNode *node, const char *name, const char *value)
const char * crm_xml_add_int(xmlNode *node, const char *name, int value)
unsigned int get_crm_log_level(void)
void crm_abort(const char *file, const char *function, int line, const char *assert_condition, gboolean do_core, gboolean do_fork)
char * generate_notify_key(const char *rsc_id, const char *notify_type, const char *op_type)
gboolean check_timer(const char *value)
long crm_pidfile_inuse(const char *filename, long mypid, const char *daemon)
#define crm_perror(level, fmt, args...)
Log a system error message.
char * generate_transition_magic_v202(const char *transition_key, int op_status)
int char2score(const char *score)
#define crm_err(fmt, args...)
int crm_parse_int(const char *text, const char *default_text)
int crm_ipc_send(crm_ipc_t *client, xmlNode *message, enum crm_ipc_flags flags, int32_t ms_timeout, xmlNode **reply)
const char * bz2_strerror(int rc)
gboolean check_number(const char *value)
void xml_remove_prop(xmlNode *obj, const char *name)
int rsc_op_expected_rc(lrmd_event_data_t *op)
crm_ipc_t * crm_ipc_new(const char *name, size_t max_size)
char * dump_xml_unformatted(xmlNode *msg)
#define XML_LRM_ATTR_CALLID
#define CRMD_ACTION_MIGRATE
#define XML_LRM_ATTR_OPSTATUS
#define XML_ATTR_CRM_VERSION
#define pcmk_option_hidden
int crm_get_option(int argc, char **argv, int *index)
char * generate_op_key(const char *rsc_id, const char *op_type, int interval)
void * md5_buffer(const char *buffer, size_t len, void *resblock)
Wrappers for and extensions to libqb IPC.
#define PACKAGE_BUGREPORT
#define XML_CIB_TAG_STATUS
char * generate_transition_magic(const char *transition_key, int op_status, int op_rc)
int crm_str_to_boolean(const char *s, int *ret)
const char * crm_acl_get_set_user(xmlNode *request, const char *field, const char *peer_user)
pid_t pcmk_locate_sbd(void)
gboolean crm_config_error
#define XML_LRM_ATTR_TARGET
#define XML_LRM_TAG_RSC_OP
#define XML_RSC_OP_LAST_RUN
#define safe_str_eq(a, b)
qb_ipcs_service_t * mainloop_add_ipc_server(const char *name, enum qb_ipc_type type, struct qb_ipcs_service_handlers *callbacks)
#define XML_LRM_ATTR_MIGRATE_SOURCE
gboolean check_boolean(const char *value)
void crm_ipc_close(crm_ipc_t *client)
#define ATTRD_OP_UPDATE_DELAY
char * crm_strip_trailing_newline(char *str)
#define crm_info(fmt, args...)
gboolean crm_str_eq(const char *a, const char *b, gboolean use_case)
char * uid2username(uid_t uid)
char * score2char_stack(int score, char *buf, size_t len)
qb_ipcs_service_t * crmd_ipc_server_init(struct qb_ipcs_service_handlers *cb)
enum crm_ais_msg_types type
char * add_list_element(char *list, const char *value)
guint crm_strcase_hash(gconstpointer v)
#define CRMD_ACTION_STATUS
void crm_time_free(crm_time_t *dt)