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;
158 if(stat(value, &st) != 0) {
159 crm_err(
"Script %s does not exist", value);
163 if(S_ISREG(st.st_mode) == 0) {
164 crm_err(
"Script %s is not a regular file", value);
168 if( (st.st_mode & (S_IXUSR | S_IXGRP )) == 0) {
169 crm_err(
"Script %s is not executable", value);
180 long number = strtol(value, &end, 10);
182 if(end && end[0] !=
'%') {
184 }
else if(number < 0) {
194 free(crm_short_options);
195 crm_short_options = NULL;
259 return crm_itoa(score);
264 const char *name,
const char *old_name,
const char *def_value)
266 const char *value = NULL;
267 char *new_value = NULL;
272 value = g_hash_table_lookup(options, name);
274 if ((value == NULL) && old_name) {
275 value = g_hash_table_lookup(options, old_name);
278 " is deprecated and will be removed in a future release",
282 new_value = strdup(value);
283 g_hash_table_insert(options, strdup(name), new_value);
288 if (value && validate && (validate(value) == FALSE)) {
289 crm_config_err(
"Resetting cluster option '%s' to default: value '%s' is invalid",
303 crm_trace(
"No value or default provided for cluster option '%s'",
310 crm_err(
"Bug: default value for cluster option '%s' is invalid", name);
314 crm_trace(
"Using default value '%s' for cluster option '%s'",
317 new_value = strdup(value);
318 g_hash_table_insert(options, strdup(name), new_value);
327 const char *value = NULL;
329 for (
int lpc = 0; lpc < len; lpc++) {
332 option_list[lpc].is_valid,
333 option_list[lpc].name,
334 option_list[lpc].alt_name,
335 option_list[lpc].default_value);
349 fprintf(stdout,
"<?xml version=\"1.0\"?>"
350 "<!DOCTYPE resource-agent SYSTEM \"ra-api-1.dtd\">\n"
351 "<resource-agent name=\"%s\">\n"
352 " <version>%s</version>\n"
353 " <longdesc lang=\"en\">%s</longdesc>\n"
354 " <shortdesc lang=\"en\">%s</shortdesc>\n"
355 " <parameters>\n", name, version, desc_long, desc_short);
357 for (lpc = 0; lpc < len; lpc++) {
358 if (option_list[lpc].description_long == NULL && option_list[lpc].description_short == NULL) {
361 fprintf(stdout,
" <parameter name=\"%s\" unique=\"0\">\n"
362 " <shortdesc lang=\"en\">%s</shortdesc>\n"
363 " <content type=\"%s\" default=\"%s\"/>\n"
364 " <longdesc lang=\"en\">%s%s%s</longdesc>\n"
366 option_list[lpc].name,
367 option_list[lpc].description_short,
368 option_list[lpc].
type,
369 option_list[lpc].default_value,
370 option_list[lpc].description_long ? option_list[lpc].
371 description_long : option_list[lpc].description_short,
372 option_list[lpc].values ?
" Allowed values: " :
"",
373 option_list[lpc].values ? option_list[lpc].values :
"");
375 fprintf(stdout,
" </parameters>\n</resource-agent>\n");
383 for (lpc = 0; lpc < len; lpc++) {
385 option_list[lpc].is_valid,
386 option_list[lpc].name,
387 option_list[lpc].alt_name, option_list[lpc].default_value);
394 char *hash_key = crm_concat(sys ? sys :
"none", crm_msg_reference,
'_');
396 crm_trace(
"created hash key: (%s)", hash_key);
407 struct passwd *pwentry = NULL;
410 rc = getpwnam_r(name, &pwd, buffer,
PW_BUFFER_LEN, &pwentry);
413 *uid = pwentry->pw_uid;
416 *gid = pwentry->pw_gid;
418 crm_trace(
"User %s has uid=%d gid=%d", name, pwentry->pw_uid, pwentry->pw_gid);
421 rc = rc? -rc : -EINVAL;
430 crm_version_helper(
const char *text,
const char **end_text)
432 int atoi_result = -1;
438 if (text != NULL && text[0] != 0) {
445 atoi_result = (int) strtol(text, (
char **) end_text, 10);
447 if (errno == EINVAL) {
448 crm_err(
"Conversion of '%s' %c failed", text, text[0]);
465 const char *ver1_iter, *ver2_iter;
467 if (version1 == NULL && version2 == NULL) {
469 }
else if (version1 == NULL) {
471 }
else if (version2 == NULL) {
475 ver1_iter = version1;
476 ver2_iter = version2;
484 if (ver1_iter == ver2_iter) {
488 if (ver1_iter != NULL) {
489 digit1 = crm_version_helper(ver1_iter, &ver1_iter);
492 if (ver2_iter != NULL) {
493 digit2 = crm_version_helper(ver2_iter, &ver2_iter);
496 if (digit1 < digit2) {
500 }
else if (digit1 > digit2) {
505 if (ver1_iter != NULL && *ver1_iter ==
'.') {
508 if (ver1_iter != NULL && *ver1_iter ==
'\0') {
512 if (ver2_iter != NULL && *ver2_iter ==
'.') {
515 if (ver2_iter != NULL && *ver2_iter == 0) {
521 crm_trace(
"%s == %s (%d)", version1, version2, lpc);
523 crm_trace(
"%s < %s (%d)", version1, version2, lpc);
525 crm_trace(
"%s > %s (%d)", version1, version2, lpc);
534 # define NUMCHARS "0123456789."
538 # define WHITESPACE " \t\n\r\f"
549 }
else if (input[0] !=
'P') {
563 return (msec <= 0)? 0 : ((msec >= G_MAXUINT)? G_MAXUINT : (guint) msec);
569 const char *cp = input;
571 long long multiplier = 1000;
572 long long divisor = 1;
574 char *end_text = NULL;
586 if (strchr(
NUMCHARS, *cp) == NULL) {
590 if (strncasecmp(units,
"ms", 2) == 0 || strncasecmp(units,
"msec", 4) == 0) {
593 }
else if (strncasecmp(units,
"us", 2) == 0 || strncasecmp(units,
"usec", 4) == 0) {
596 }
else if (strncasecmp(units,
"s", 1) == 0 || strncasecmp(units,
"sec", 3) == 0) {
599 }
else if (strncasecmp(units,
"m", 1) == 0 || strncasecmp(units,
"min", 3) == 0) {
600 multiplier = 60 * 1000;
602 }
else if (strncasecmp(units,
"h", 1) == 0 || strncasecmp(units,
"hr", 2) == 0) {
603 multiplier = 60 * 60 * 1000;
605 }
else if (*units !=
EOS && *units !=
'\n' && *units !=
'\r') {
610 if (msec > LLONG_MAX/multiplier) {
625 crm_abort(
const char *file,
const char *
function,
int line,
626 const char *assert_condition, gboolean do_core, gboolean do_fork)
635 if(crm_is_daemon == FALSE) {
643 if (do_core == FALSE) {
644 crm_err(
"%s: Triggered assert at %s:%d : %s",
function, file, line, assert_condition);
647 }
else if (do_fork) {
651 crm_err(
"%s: Triggered fatal assert at %s:%d : %s",
function, file, line, assert_condition);
655 crm_crit(
"%s: Cannot create core for non-fatal assert at %s:%d : %s",
656 function, file, line, assert_condition);
659 }
else if(pid == 0) {
666 crm_err(
"%s: Forked child %d to record non-fatal assert at %s:%d : %s",
667 function, pid, file, line, assert_condition);
671 rc = waitpid(pid, &status, 0);
676 }
while(errno == EINTR);
678 if (errno == ECHILD) {
680 crm_trace(
"Cannot wait on forked child %d - SIGCHLD is probably set to SIG_IGN", pid);
683 crm_perror(LOG_ERR,
"Cannot wait on forked child %d", pid);
691 const char *devnull =
"/dev/null";
693 if (daemonize == FALSE) {
699 if(rc <
pcmk_ok && rc != -ENOENT) {
701 crm_err(
"%s: already running [pid %ld in %s]", name, pid, pidfile);
702 printf(
"%s: already running [pid %ld in %s]\n", name, pid, pidfile);
708 fprintf(stderr,
"%s: could not start daemon\n", name);
712 }
else if (pid > 0) {
719 printf(
"Could not lock '%s' for %s: %s (%d)\n", pidfile, name,
pcmk_strerror(rc), rc);
723 umask(S_IWGRP | S_IWOTH | S_IROTH);
726 (void)open(devnull, O_RDONLY);
727 close(STDOUT_FILENO);
728 (void)open(devnull, O_WRONLY);
729 close(STDERR_FILENO);
730 (void)open(devnull, O_WRONLY);
738 char *crm_name = NULL;
741 crm_name = crm_concat(
CRM_META, field,
'_');
744 max = strlen(crm_name);
745 for (; lpc < max; lpc++) {
746 switch (crm_name[lpc]) {
759 const char *value = NULL;
763 value = g_hash_table_lookup(hash, key);
770 static struct option *
771 crm_create_long_opts(
struct crm_option *long_options)
773 struct option *long_opts = NULL;
776 int index = 0, lpc = 0;
785 long_opts = realloc_safe(long_opts, (index + 1) *
sizeof(
struct option));
786 long_opts[index].name =
"__dummmy__";
787 long_opts[index].has_arg = 0;
788 long_opts[index].flag = 0;
789 long_opts[index].val =
'_';
792 for (lpc = 0; long_options[lpc].
name != NULL; lpc++) {
793 if (long_options[lpc].name[0] ==
'-') {
797 long_opts = realloc_safe(long_opts, (index + 1) *
sizeof(
struct option));
800 long_opts[index].name = long_options[lpc].
name;
801 long_opts[index].has_arg = long_options[lpc].
has_arg;
802 long_opts[index].flag = long_options[lpc].
flag;
803 long_opts[index].val = long_options[lpc].
val;
808 long_opts = realloc_safe(long_opts, (index + 1) *
sizeof(
struct option));
809 long_opts[index].name = NULL;
810 long_opts[index].has_arg = 0;
811 long_opts[index].flag = 0;
812 long_opts[index].val = 0;
820 const char *app_desc)
823 crm_short_options = strdup(short_options);
825 }
else if (long_options) {
827 int opt_string_len = 0;
828 char *local_short_options = NULL;
830 for (lpc = 0; long_options[lpc].
name != NULL; lpc++) {
831 if (long_options[lpc].val && long_options[lpc].val !=
'-' && long_options[lpc].val < UCHAR_MAX) {
832 local_short_options = realloc_safe(local_short_options, opt_string_len + 4);
833 local_short_options[opt_string_len++] = long_options[lpc].
val;
835 if (long_options[lpc].has_arg == optional_argument) {
836 local_short_options[opt_string_len++] =
':';
838 if (long_options[lpc].has_arg >= required_argument) {
839 local_short_options[opt_string_len++] =
':';
841 local_short_options[opt_string_len] = 0;
844 crm_short_options = local_short_options;
845 crm_trace(
"Generated short option string: '%s'", local_short_options);
849 crm_long_options = long_options;
852 crm_app_description = app_desc;
855 crm_app_usage = app_usage;
869 static struct option *long_opts = NULL;
871 if (long_opts == NULL && crm_long_options) {
872 long_opts = crm_create_long_opts(crm_long_options);
877 int flag = getopt_long(argc, argv, crm_short_options, long_opts, index);
881 if (long_opts[*index].val) {
882 return long_opts[*index].val;
883 }
else if (longname) {
884 *longname = long_opts[*index].name;
886 crm_notice(
"Unhandled option --%s", long_opts[*index].name);
903 if (crm_short_options) {
904 return getopt(argc, argv, crm_short_options);
914 FILE *stream = (exit_code ? stderr : stdout);
916 if (cmd ==
'v' || cmd ==
'$') {
918 fprintf(stream,
"Written by Andrew Beekhof\n");
933 if (crm_long_options) {
934 fprintf(stream,
"Options:\n");
935 for (i = 0; crm_long_options[i].
name != NULL; i++) {
939 fprintf(stream,
"%s\n\n", crm_long_options[i].desc);
942 fprintf(stream,
"\t#%s\n\n", crm_long_options[i].desc);
944 }
else if (crm_long_options[i].val ==
'-' && crm_long_options[i].desc) {
945 fprintf(stream,
"%s\n", crm_long_options[i].desc);
949 if (crm_long_options[i].val && crm_long_options[i].val <= UCHAR_MAX) {
950 fprintf(stream,
" -%c,", crm_long_options[i].val);
954 fprintf(stream,
" --%s%s\t%s\n", crm_long_options[i].name,
955 crm_long_options[i].has_arg == optional_argument ?
"[=value]" :
956 crm_long_options[i].has_arg == required_argument ?
"=value" :
"",
957 crm_long_options[i].desc ? crm_long_options[i].desc :
"");
961 }
else if (crm_short_options) {
962 fprintf(stream,
"Usage: %s - %s\n",
crm_system_name, crm_app_description);
963 for (i = 0; crm_short_options[i] != 0; i++) {
964 int has_arg = no_argument ;
966 if (crm_short_options[i + 1] ==
':') {
967 if (crm_short_options[i + 2] ==
':')
968 has_arg = optional_argument ;
970 has_arg = required_argument ;
973 fprintf(stream,
" -%c %s\n", crm_short_options[i],
974 has_arg == optional_argument ?
"[value]" :
975 has_arg == required_argument ?
"{value}" :
"");
988 qb_ipcs_service_t **ipcs_rw,
989 qb_ipcs_service_t **ipcs_shm,
990 struct qb_ipcs_service_handlers *ro_cb,
991 struct qb_ipcs_service_handlers *rw_cb)
997 if (*ipcs_ro == NULL || *ipcs_rw == NULL || *ipcs_shm == NULL) {
998 crm_err(
"Failed to create the CIB manager: exiting and inhibiting respawn");
999 crm_warn(
"Verify pacemaker and pacemaker_remote are not both enabled");
1005 qb_ipcs_service_t *ipcs_rw,
1006 qb_ipcs_service_t *ipcs_shm)
1008 qb_ipcs_destroy(ipcs_ro);
1009 qb_ipcs_destroy(ipcs_rw);
1010 qb_ipcs_destroy(ipcs_shm);
1024 if (*ipcs == NULL) {
1025 crm_err(
"Failed to create pacemaker-attrd server: exiting and inhibiting respawn");
1026 crm_warn(
"Verify pacemaker and pacemaker_remote are not both enabled.");
1036 if (*ipcs == NULL) {
1037 crm_err(
"Failed to create fencer: exiting and inhibiting respawn.");
1038 crm_warn(
"Verify pacemaker and pacemaker_remote are not both enabled.");
1049 if (*handle == NULL) {
1050 *handle = dlopen(lib, RTLD_LAZY);
1054 crm_err(
"%sCould not open %s: %s", fatal ?
"Fatal: " :
"", lib, dlerror());
1061 a_function = dlsym(*handle, fn);
1062 if (a_function == NULL) {
1064 crm_err(
"%sCould not find %s in %s: %s", fatal ?
"Fatal: " :
"", fn, lib, error);
1073 #ifdef HAVE_UUID_UUID_H
1074 # include <uuid/uuid.h>
1080 unsigned char uuid[16];
1081 char *buffer = malloc(37);
1083 uuid_generate(uuid);
1084 uuid_unparse(uuid, buffer);
1105 }
else if (!strcmp(name,
"pacemaker-attrd")) {
1108 }
else if (!strcmp(name,
"pacemaker-based")) {
1111 }
else if (!strcmp(name,
"pacemaker-controld")) {
1114 }
else if (!strcmp(name,
"pacemaker-execd")) {
1117 }
else if (!strcmp(name,
"pacemaker-fenced")) {
1118 return "stonith-ng";
1120 }
else if (!strcmp(name,
"pacemaker-schedulerd")) {
1141 || !strcmp(name,
"stonith-ng")
1142 || !strcmp(name,
"attrd")
1155 int lpc = 0, len = 0;
1156 char *digest = NULL;
1159 if (buffer == NULL) {
1162 len = strlen(buffer);
1164 crm_trace(
"Beginning digest of %d bytes", len);
1169 sprintf(digest + (2 * lpc),
"%02x", raw_digest[lpc]);
1175 crm_err(
"Could not create digest");
1180 #ifdef HAVE_GNUTLS_GNUTLS_H
1182 crm_gnutls_global_init(
void)
1184 signal(SIGPIPE, SIG_IGN);
1185 gnutls_global_init();
1197 struct utsname hostinfo;
1199 return (
uname(&hostinfo) < 0)? NULL : strdup(hostinfo.nodename);
#define CRM_CHECK(expr, failure_action)
void crm_write_blackbox(int nsig, struct qb_log_callsite *callsite)
void * find_library_function(void **handle, const char *lib, const char *fn, int fatal)
#define crm_notice(fmt, args...)
const char * pcmk_strerror(int rc)
void crm_enable_stderr(int enable)
bool crm_is_daemon_name(const char *name)
Check whether a string represents a cluster daemon name.
#define crm_crit(fmt, args...)
char * crm_generate_uuid(void)
int crm_lock_pidfile(const char *filename, const char *name)
_Noreturn crm_exit_t crm_exit(crm_exit_t rc)
struct crm_time_s crm_time_t
#define crm_config_err(fmt...)
long long crm_int_helper(const char *text, char **end_text)
int char2score(const char *score)
long long crm_get_msec(const char *input)
void crm_make_daemon(const char *name, gboolean daemonize, const char *pidfile)
char * score2char_stack(int score, char *buf, size_t len)
const char * crm_meta_value(GHashTable *hash, const char *field)
void stonith_ipc_server_init(qb_ipcs_service_t **ipcs, struct qb_ipcs_service_handlers *cb)
int crm_parse_int(const char *text, const char *default_text)
Parse an integer value from a string.
crm_time_t * crm_time_parse_duration(const char *duration_str)
enum crm_exit_e crm_exit_t
int crm_user_lookup(const char *name, uid_t *uid, gid_t *gid)
void crm_set_options(const char *short_options, const char *usage, struct crm_option *long_options, const char *app_desc)
guint crm_parse_interval_spec(const char *input)
gboolean check_number(const char *value)
#define PACEMAKER_VERSION
#define CRM_SCORE_INFINITY
Wrappers for and extensions to glib mainloop.
char * crm_meta_name(const char *field)
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)
#define CRM_TRACE_INIT_DATA(name)
gboolean crm_config_error
void config_metadata(const char *name, const char *version, const char *desc_short, const char *desc_long, pe_cluster_option *option_list, int len)
#define crm_warn(fmt, args...)
const char * pcmk_message_name(const char *name)
Get name to be used as identifier for cluster messages.
#define pcmk_option_example
gboolean check_quorum(const char *value)
#define crm_trace(fmt, args...)
#define pcmk_option_paragraph
#define CRM_SYSTEM_PENGINE
#define CRM_MINUS_INFINITY_S
Wrappers for and extensions to libxml2.
void cib_ipc_servers_destroy(qb_ipcs_service_t *ipcs_ro, qb_ipcs_service_t *ipcs_rw, qb_ipcs_service_t *ipcs_shm)
gboolean check_positive_number(const char *value)
long crm_pidfile_inuse(const char *filename, long mypid, const char *daemon)
gboolean check_time(const char *value)
gboolean check_boolean(const char *value)
char * crm_itoa_stack(int an_int, char *buf, size_t len)
int crm_get_option_long(int argc, char **argv, int *index, const char **longname)
long long int crm_time_get_seconds(crm_time_t *dt)
#define crm_config_warn(fmt...)
void attrd_ipc_server_init(qb_ipcs_service_t **ipcs, struct qb_ipcs_service_handlers *cb)
#define CRM_SYSTEM_STONITHD
int crm_str_to_boolean(const char *s, int *ret)
qb_ipcs_service_t * crmd_ipc_server_init(struct qb_ipcs_service_handlers *cb)
#define CRM_SYSTEM_TENGINE
const char * cluster_option(GHashTable *options, gboolean(*validate)(const char *), const char *name, const char *old_name, const char *def_value)
#define crm_perror(level, fmt, args...)
Log a system error message.
gboolean check_script(const char *value)
#define crm_err(fmt, args...)
gboolean check_utilization(const char *value)
gboolean crm_config_warning
int compare_version(const char *version1, const char *version2)
void verify_all_options(GHashTable *options, pe_cluster_option *option_list, int len)
#define pcmk_option_hidden
_Noreturn void crm_help(char cmd, crm_exit_t exit_code)
void * md5_buffer(const char *buffer, size_t len, void *resblock)
Wrappers for and extensions to libqb IPC.
char * generate_hash_key(const char *crm_msg_reference, const char *sys)
#define PACKAGE_BUGREPORT
#define CRM_PLUS_INFINITY_S
char * crm_md5sum(const char *buffer)
gboolean check_timer(const char *value)
int crm_get_option(int argc, char **argv, int *index)
char * pcmk_hostname(void)
Get the local hostname.
#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)
void crm_abort(const char *file, const char *function, int line, const char *condition, gboolean do_core, gboolean do_fork)
const char * get_cluster_pref(GHashTable *options, pe_cluster_option *option_list, int len, const char *name)
#define crm_info(fmt, args...)
long crm_read_pidfile(const char *filename)
enum crm_ais_msg_types type
char * score2char(int score)
void crm_time_free(crm_time_t *dt)