diff --git a/lib/common/utils.c b/lib/common/utils.c index d5c2b63392..7a9dc6b9aa 100644 --- a/lib/common/utils.c +++ b/lib/common/utils.c @@ -1,2640 +1,2587 @@ /* * Copyright (C) 2004 Andrew Beekhof * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #ifndef _GNU_SOURCE # define _GNU_SOURCE #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if HAVE_HB_CONFIG_H #include /* for HB_COREDIR */ #endif #if HAVE_GLUE_CONFIG_H #include /* for HB_COREDIR */ #endif #ifndef MAXLINE # define MAXLINE 512 #endif #ifdef HAVE_GETOPT_H # include #endif CRM_TRACE_INIT_DATA(common); static uint ref_counter = 0; unsigned int crm_log_level = LOG_INFO; gboolean crm_config_error = FALSE; gboolean crm_config_warning = FALSE; const char *crm_system_name = "unknown"; int node_score_red = 0; int node_score_green = 0; int node_score_yellow = 0; int node_score_infinity = INFINITY; void crm_set_env_options(void); gboolean check_time(const char *value) { - if(crm_get_msec(value) < 5000) { - return FALSE; - } - return TRUE; + if(crm_get_msec(value) < 5000) { + return FALSE; + } + return TRUE; } gboolean check_timer(const char *value) { - if(crm_get_msec(value) < 0) { - return FALSE; - } - return TRUE; + if(crm_get_msec(value) < 0) { + return FALSE; + } + return TRUE; } gboolean check_boolean(const char *value) { - int tmp = FALSE; - if(crm_str_to_boolean(value, &tmp) != 1) { - return FALSE; - } - return TRUE; + int tmp = FALSE; + if(crm_str_to_boolean(value, &tmp) != 1) { + return FALSE; + } + return TRUE; } gboolean check_number(const char *value) { - errno = 0; - if(value == NULL) { - return FALSE; + errno = 0; + if(value == NULL) { + return FALSE; - } else if(safe_str_eq(value, MINUS_INFINITY_S)) { + } else if(safe_str_eq(value, MINUS_INFINITY_S)) { - } else if(safe_str_eq(value, INFINITY_S)) { + } else if(safe_str_eq(value, INFINITY_S)) { - } else { - crm_int_helper(value, NULL); - } + } else { + crm_int_helper(value, NULL); + } - if(errno != 0) { - return FALSE; - } - return TRUE; + if(errno != 0) { + return FALSE; + } + return TRUE; } int char2score(const char *score) { - int score_f = 0; + int score_f = 0; - if(score == NULL) { + if(score == NULL) { - } else if(safe_str_eq(score, MINUS_INFINITY_S)) { - score_f = -node_score_infinity; + } else if(safe_str_eq(score, MINUS_INFINITY_S)) { + score_f = -node_score_infinity; - } else if(safe_str_eq(score, INFINITY_S)) { - score_f = node_score_infinity; + } else if(safe_str_eq(score, INFINITY_S)) { + score_f = node_score_infinity; - } else if(safe_str_eq(score, "+"INFINITY_S)) { - score_f = node_score_infinity; + } else if(safe_str_eq(score, "+"INFINITY_S)) { + score_f = node_score_infinity; - } else if(safe_str_eq(score, "red")) { - score_f = node_score_red; + } else if(safe_str_eq(score, "red")) { + score_f = node_score_red; - } else if(safe_str_eq(score, "yellow")) { - score_f = node_score_yellow; + } else if(safe_str_eq(score, "yellow")) { + score_f = node_score_yellow; - } else if(safe_str_eq(score, "green")) { - score_f = node_score_green; + } else if(safe_str_eq(score, "green")) { + score_f = node_score_green; - } else { - score_f = crm_parse_int(score, NULL); - if(score_f > 0 && score_f > node_score_infinity) { - score_f = node_score_infinity; + } else { + score_f = crm_parse_int(score, NULL); + if(score_f > 0 && score_f > node_score_infinity) { + score_f = node_score_infinity; - } else if(score_f < 0 && score_f < -node_score_infinity) { - score_f = -node_score_infinity; - } + } else if(score_f < 0 && score_f < -node_score_infinity) { + score_f = -node_score_infinity; } + } - return score_f; + return score_f; } char * score2char(int score) { - if(score >= node_score_infinity) { - return crm_strdup(INFINITY_S); + if(score >= node_score_infinity) { + return crm_strdup(INFINITY_S); - } else if(score <= -node_score_infinity) { - return crm_strdup("-"INFINITY_S); - } - return crm_itoa(score); + } else if(score <= -node_score_infinity) { + return crm_strdup("-"INFINITY_S); + } + return crm_itoa(score); } const char * cluster_option(GHashTable* options, gboolean(*validate)(const char*), const char *name, const char *old_name, const char *def_value) { - const char *value = NULL; - CRM_ASSERT(name != NULL); + const char *value = NULL; + CRM_ASSERT(name != NULL); - if(options != NULL) { - value = g_hash_table_lookup(options, name); - } + if(options != NULL) { + value = g_hash_table_lookup(options, name); + } - if(value == NULL && old_name && options != NULL) { - value = g_hash_table_lookup(options, old_name); - if(value != NULL) { - crm_config_warn("Using deprecated name '%s' for" - " cluster option '%s'", old_name, name); - g_hash_table_insert( - options, crm_strdup(name), crm_strdup(value)); - value = g_hash_table_lookup(options, old_name); - } + if(value == NULL && old_name && options != NULL) { + value = g_hash_table_lookup(options, old_name); + if(value != NULL) { + crm_config_warn("Using deprecated name '%s' for" + " cluster option '%s'", old_name, name); + g_hash_table_insert( + options, crm_strdup(name), crm_strdup(value)); + value = g_hash_table_lookup(options, old_name); } + } - if(value == NULL) { - crm_debug_2("Using default value '%s' for cluster option '%s'", - def_value, name); + if(value == NULL) { + crm_debug_2("Using default value '%s' for cluster option '%s'", + def_value, name); - if(options == NULL) { - return def_value; - } - - g_hash_table_insert( - options, crm_strdup(name), crm_strdup(def_value)); - value = g_hash_table_lookup(options, name); + if(options == NULL) { + return def_value; } + + g_hash_table_insert( + options, crm_strdup(name), crm_strdup(def_value)); + value = g_hash_table_lookup(options, name); + } - if(validate && validate(value) == FALSE) { - crm_config_err("Value '%s' for cluster option '%s' is invalid." - " Defaulting to %s", value, name, def_value); - g_hash_table_replace(options, crm_strdup(name), - crm_strdup(def_value)); - value = g_hash_table_lookup(options, name); - } + if(validate && validate(value) == FALSE) { + crm_config_err("Value '%s' for cluster option '%s' is invalid." + " Defaulting to %s", value, name, def_value); + g_hash_table_replace(options, crm_strdup(name), + crm_strdup(def_value)); + value = g_hash_table_lookup(options, name); + } - return value; + return value; } const char * get_cluster_pref(GHashTable *options, pe_cluster_option *option_list, int len, const char *name) { - int lpc = 0; - const char *value = NULL; - gboolean found = FALSE; - for(lpc = 0; lpc < len; lpc++) { - if(safe_str_eq(name, option_list[lpc].name)) { - found = TRUE; - value = cluster_option(options, - option_list[lpc].is_valid, - option_list[lpc].name, - option_list[lpc].alt_name, - option_list[lpc].default_value); - } + int lpc = 0; + const char *value = NULL; + gboolean found = FALSE; + for(lpc = 0; lpc < len; lpc++) { + if(safe_str_eq(name, option_list[lpc].name)) { + found = TRUE; + value = cluster_option(options, + option_list[lpc].is_valid, + option_list[lpc].name, + option_list[lpc].alt_name, + option_list[lpc].default_value); } - CRM_CHECK(found, crm_err("No option named: %s", name)); - CRM_ASSERT(value != NULL); - return value; + } + CRM_CHECK(found, crm_err("No option named: %s", name)); + CRM_ASSERT(value != NULL); + return value; } void config_metadata(const char *name, const char *version, const char *desc_short, const char *desc_long, pe_cluster_option *option_list, int len) { - int lpc = 0; + int lpc = 0; - fprintf(stdout, "" - "\n" - "\n" - " %s\n" - " %s\n" - " %s\n" - " \n", name, version, desc_long, desc_short); - - for(lpc = 0; lpc < len; lpc++) { - if(option_list[lpc].description_long == NULL - && option_list[lpc].description_short == NULL) { - continue; - } - fprintf(stdout, " \n" - " %s\n" - " \n" - " %s%s%s\n" - " \n", - option_list[lpc].name, - option_list[lpc].description_short, - option_list[lpc].type, - option_list[lpc].default_value, - option_list[lpc].description_long?option_list[lpc].description_long:option_list[lpc].description_short, - option_list[lpc].values?" Allowed values: ":"", - option_list[lpc].values?option_list[lpc].values:""); + fprintf(stdout, "" + "\n" + "\n" + " %s\n" + " %s\n" + " %s\n" + " \n", name, version, desc_long, desc_short); + + for(lpc = 0; lpc < len; lpc++) { + if(option_list[lpc].description_long == NULL + && option_list[lpc].description_short == NULL) { + continue; } - fprintf(stdout, " \n\n"); + fprintf(stdout, " \n" + " %s\n" + " \n" + " %s%s%s\n" + " \n", + option_list[lpc].name, + option_list[lpc].description_short, + option_list[lpc].type, + option_list[lpc].default_value, + option_list[lpc].description_long?option_list[lpc].description_long:option_list[lpc].description_short, + option_list[lpc].values?" Allowed values: ":"", + option_list[lpc].values?option_list[lpc].values:""); + } + fprintf(stdout, " \n\n"); } void verify_all_options(GHashTable *options, pe_cluster_option *option_list, int len) { - int lpc = 0; - for(lpc = 0; lpc < len; lpc++) { - cluster_option(options, - option_list[lpc].is_valid, - option_list[lpc].name, - option_list[lpc].alt_name, - option_list[lpc].default_value); - } + int lpc = 0; + for(lpc = 0; lpc < len; lpc++) { + cluster_option(options, + option_list[lpc].is_valid, + option_list[lpc].name, + option_list[lpc].alt_name, + option_list[lpc].default_value); + } } char * generateReference(const char *custom1, const char *custom2) { - const char *local_cust1 = custom1; - const char *local_cust2 = custom2; - int reference_len = 4; - char *since_epoch = NULL; + const char *local_cust1 = custom1; + const char *local_cust2 = custom2; + int reference_len = 4; + char *since_epoch = NULL; - reference_len += 20; /* too big */ - reference_len += 40; /* too big */ + reference_len += 20; /* too big */ + reference_len += 40; /* too big */ - if(local_cust1 == NULL) { local_cust1 = "_empty_"; } - reference_len += strlen(local_cust1); + if(local_cust1 == NULL) { local_cust1 = "_empty_"; } + reference_len += strlen(local_cust1); - if(local_cust2 == NULL) { local_cust2 = "_empty_"; } - reference_len += strlen(local_cust2); + if(local_cust2 == NULL) { local_cust2 = "_empty_"; } + reference_len += strlen(local_cust2); - crm_malloc0(since_epoch, reference_len); + crm_malloc0(since_epoch, reference_len); - if(since_epoch != NULL) { - sprintf(since_epoch, "%s-%s-%ld-%u", - local_cust1, local_cust2, - (unsigned long)time(NULL), ref_counter++); - } + if(since_epoch != NULL) { + sprintf(since_epoch, "%s-%s-%ld-%u", + local_cust1, local_cust2, + (unsigned long)time(NULL), ref_counter++); + } - return since_epoch; + return since_epoch; } gboolean decodeNVpair(const char *srcstring, char separator, char **name, char **value) { - int lpc = 0; - int len = 0; - const char *temp = NULL; - - CRM_ASSERT(name != NULL && value != NULL); - *name = NULL; - *value = NULL; - - crm_debug_4("Attempting to decode: [%s]", srcstring); - if (srcstring != NULL) { - len = strlen(srcstring); - while(lpc <= len) { - if (srcstring[lpc] == separator) { - crm_malloc0(*name, lpc+1); - if(*name == NULL) { - break; /* and return FALSE */ - } - strncpy(*name, srcstring, lpc); - (*name)[lpc] = '\0'; + int lpc = 0; + int len = 0; + const char *temp = NULL; + + CRM_ASSERT(name != NULL && value != NULL); + *name = NULL; + *value = NULL; + + crm_debug_4("Attempting to decode: [%s]", srcstring); + if (srcstring != NULL) { + len = strlen(srcstring); + while(lpc <= len) { + if (srcstring[lpc] == separator) { + crm_malloc0(*name, lpc+1); + if(*name == NULL) { + break; /* and return FALSE */ + } + strncpy(*name, srcstring, lpc); + (*name)[lpc] = '\0'; /* this sucks but as the strtok manpage says.. * it *is* a bug */ - len = len-lpc; len--; - if(len <= 0) { - *value = NULL; - } else { - - crm_malloc0(*value, len+1); - if(*value == NULL) { - crm_free(*name); - break; /* and return FALSE */ - } - temp = srcstring+lpc+1; - strncpy(*value, temp, len); - (*value)[len] = '\0'; - } - return TRUE; - } - lpc++; + len = len-lpc; len--; + if(len <= 0) { + *value = NULL; + } else { + + crm_malloc0(*value, len+1); + if(*value == NULL) { + crm_free(*name); + break; /* and return FALSE */ + } + temp = srcstring+lpc+1; + strncpy(*value, temp, len); + (*value)[len] = '\0'; } + return TRUE; + } + lpc++; } + } - if(*name != NULL) { - crm_free(*name); - } - *name = NULL; - *value = NULL; + if(*name != NULL) { + crm_free(*name); + } + *name = NULL; + *value = NULL; - return FALSE; + return FALSE; } char * crm_concat(const char *prefix, const char *suffix, char join) { - int len = 0; - char *new_str = NULL; - CRM_ASSERT(prefix != NULL); - CRM_ASSERT(suffix != NULL); - len = strlen(prefix) + strlen(suffix) + 2; + int len = 0; + char *new_str = NULL; + CRM_ASSERT(prefix != NULL); + CRM_ASSERT(suffix != NULL); + len = strlen(prefix) + strlen(suffix) + 2; - crm_malloc0(new_str, (len)); - sprintf(new_str, "%s%c%s", prefix, join, suffix); - new_str[len-1] = 0; - return new_str; + crm_malloc0(new_str, (len)); + sprintf(new_str, "%s%c%s", prefix, join, suffix); + new_str[len-1] = 0; + return new_str; } char * generate_hash_key(const char *crm_msg_reference, const char *sys) { - char *hash_key = crm_concat(sys?sys:"none", crm_msg_reference, '_'); - crm_debug_3("created hash key: (%s)", hash_key); - return hash_key; + char *hash_key = crm_concat(sys?sys:"none", crm_msg_reference, '_'); + crm_debug_3("created hash key: (%s)", hash_key); + return hash_key; } char * generate_hash_value(const char *src_node, const char *src_subsys) { - char *hash_value = NULL; + char *hash_value = NULL; - if (src_node == NULL || src_subsys == NULL) { - return NULL; - } + if (src_node == NULL || src_subsys == NULL) { + return NULL; + } - if (strcasecmp(CRM_SYSTEM_DC, src_subsys) == 0) { - hash_value = crm_strdup(src_subsys); - CRM_ASSERT(hash_value); - return hash_value; - } - - hash_value = crm_concat(src_node, src_subsys, '_'); - crm_info("created hash value: (%s)", hash_value); + if (strcasecmp(CRM_SYSTEM_DC, src_subsys) == 0) { + hash_value = crm_strdup(src_subsys); + CRM_ASSERT(hash_value); return hash_value; + } + + hash_value = crm_concat(src_node, src_subsys, '_'); + crm_info("created hash value: (%s)", hash_value); + return hash_value; } char * crm_itoa(int an_int) { - int len = 32; - char *buffer = NULL; + int len = 32; + char *buffer = NULL; - crm_malloc0(buffer, (len+1)); - if(buffer != NULL) { - snprintf(buffer, len, "%d", an_int); - } + crm_malloc0(buffer, (len+1)); + if(buffer != NULL) { + snprintf(buffer, len, "%d", an_int); + } - return buffer; + return buffer; } extern int LogToLoggingDaemon(int priority, const char * buf, int bstrlen, gboolean use_pri_str); #ifdef HAVE_G_LOG_SET_DEFAULT_HANDLER GLogFunc glib_log_default; static void crm_glib_handler(const gchar *log_domain, GLogLevelFlags flags, const gchar *message, gpointer user_data) { - int log_level = LOG_WARNING; - GLogLevelFlags msg_level = (flags & G_LOG_LEVEL_MASK); + int log_level = LOG_WARNING; + GLogLevelFlags msg_level = (flags & G_LOG_LEVEL_MASK); - switch(msg_level) { - case G_LOG_LEVEL_CRITICAL: - /* log and record how we got here */ - crm_abort(__FILE__,__PRETTY_FUNCTION__,__LINE__, message, TRUE, TRUE); - return; + switch(msg_level) { + case G_LOG_LEVEL_CRITICAL: + /* log and record how we got here */ + crm_abort(__FILE__,__PRETTY_FUNCTION__,__LINE__, message, TRUE, TRUE); + return; - case G_LOG_LEVEL_ERROR: log_level = LOG_ERR; break; - case G_LOG_LEVEL_MESSAGE: log_level = LOG_NOTICE; break; - case G_LOG_LEVEL_INFO: log_level = LOG_INFO; break; - case G_LOG_LEVEL_DEBUG: log_level = LOG_DEBUG; break; + case G_LOG_LEVEL_ERROR: log_level = LOG_ERR; break; + case G_LOG_LEVEL_MESSAGE: log_level = LOG_NOTICE; break; + case G_LOG_LEVEL_INFO: log_level = LOG_INFO; break; + case G_LOG_LEVEL_DEBUG: log_level = LOG_DEBUG; break; - case G_LOG_LEVEL_WARNING: - case G_LOG_FLAG_RECURSION: - case G_LOG_FLAG_FATAL: - case G_LOG_LEVEL_MASK: - log_level = LOG_WARNING; - break; - } + case G_LOG_LEVEL_WARNING: + case G_LOG_FLAG_RECURSION: + case G_LOG_FLAG_FATAL: + case G_LOG_LEVEL_MASK: + log_level = LOG_WARNING; + break; + } - do_crm_log(log_level, "%s: %s", log_domain, message); + do_crm_log(log_level, "%s: %s", log_domain, message); } #endif void crm_log_deinit(void) { #ifdef HAVE_G_LOG_SET_DEFAULT_HANDLER g_log_set_default_handler(glib_log_default, NULL); #endif } gboolean crm_log_init( const char *entity, int level, gboolean coredir, gboolean to_stderr, int argc, char **argv) { return crm_log_init_worker(entity, level, coredir, to_stderr, argc, argv, FALSE); } gboolean crm_log_init_quiet( const char *entity, int level, gboolean coredir, gboolean to_stderr, int argc, char **argv) { return crm_log_init_worker(entity, level, coredir, to_stderr, argc, argv, TRUE); } #if SUPPORT_TRACING static int update_trace_data(struct _pcmk_ddebug_query *query, struct _pcmk_ddebug *start, struct _pcmk_ddebug *stop) { int lpc = 0; unsigned nfound = 0; struct _pcmk_ddebug *dp; const char *match = "unknown"; CRM_ASSERT(stop != NULL); CRM_ASSERT(start != NULL); for (dp = start; dp != stop; dp++) { gboolean bump = FALSE; lpc++; /* fprintf(stderr, "checking: %-12s %20s:%u fmt:%s\n", */ /* dp->function, dp->filename, dp->lineno, dp->format); */ if (query->functions && strstr(query->functions, dp->function) != NULL) { match = "function"; bump = TRUE; } if (query->files && strstr(query->files, dp->filename) != NULL) { match = "file"; bump = TRUE; } if (query->formats && strstr(query->formats, dp->format) != NULL) { match = "format"; bump = TRUE; } if(bump) { nfound++; dp->bump = LOG_NOTICE; do_crm_log_always(LOG_INFO, "Detected '%s' match: %-12s %20s:%u fmt:%s", match, dp->function, dp->filename, dp->lineno, dp->format); } } query->total += lpc; query->matches += nfound; return nfound; } #define _GNU_SOURCE #include #include #include static int ddebug_callback(struct dl_phdr_info *info, size_t size, void *data) { if(strlen(info->dlpi_name) > 0) { struct _pcmk_ddebug_query *query = data; void *handle; void *start; void *stop; char *error; handle = dlopen (info->dlpi_name, RTLD_LAZY); error = dlerror(); if (!handle || error) { crm_err("%s", error); if(handle) { dlclose(handle); } return 0; } start = dlsym(handle, "__start___verbose"); error = dlerror(); if (error) { goto done; } stop = dlsym(handle, "__stop___verbose"); error = dlerror(); if (error) { goto done; } else { unsigned long int len = (unsigned long int)stop - (unsigned long int)start; crm_info("Checking for query matches in %lu trace symbols from: %s (offset: %p)", len/sizeof(struct _pcmk_ddebug), info->dlpi_name, start); update_trace_data(query, start, stop); } done: dlclose(handle); } return 0; } #endif void update_all_trace_data(void) { #if SUPPORT_TRACING gboolean search = FALSE; const char *env_value = NULL; struct _pcmk_ddebug_query query; memset(&query, 0, sizeof(struct _pcmk_ddebug_query)); env_value = getenv("PCMK_trace_files"); if(env_value) { search = TRUE; query.files = env_value; } env_value = getenv("PCMK_trace_formats"); if(env_value) { search = TRUE; query.formats = env_value; } env_value = getenv("PCMK_trace_functions"); if(env_value) { search = TRUE; query.functions = env_value; } if(search) { update_trace_data(&query, __start___verbose, __stop___verbose); dl_iterate_phdr(ddebug_callback, &query); if(query.matches == 0) { do_crm_log_always(LOG_DEBUG, "no matches for query: {fn='%s', file='%s', fmt='%s'} in %llu entries", crm_str(query.functions), crm_str(query.files), crm_str(query.formats), query.total); } else { do_crm_log_always(LOG_INFO, "%llu matches for query: {fn='%s', file='%s', fmt='%s'} in %llu entries", query.matches, crm_str(query.functions), crm_str(query.files), crm_str(query.formats), query.total); } } /* return query.matches; */ #endif } gboolean crm_log_init_worker( const char *entity, int level, gboolean coredir, gboolean to_stderr, int argc, char **argv, gboolean quiet) { - /* Redirect messages from glib functions to our handler */ + /* Redirect messages from glib functions to our handler */ /* cl_malloc_forced_for_glib(); */ #ifdef HAVE_G_LOG_SET_DEFAULT_HANDLER - glib_log_default = g_log_set_default_handler(crm_glib_handler, NULL); + glib_log_default = g_log_set_default_handler(crm_glib_handler, NULL); #endif - /* and for good measure... - this enum is a bit field (!) */ - g_log_set_always_fatal((GLogLevelFlags)0); /*value out of range*/ + /* and for good measure... - this enum is a bit field (!) */ + g_log_set_always_fatal((GLogLevelFlags)0); /*value out of range*/ - if(entity) { - crm_system_name = entity; + if(entity) { + crm_system_name = entity; - } else if(argc > 0 && argv != NULL) { - crm_system_name = basename(argv[0]); - if(strstr(crm_system_name, "lt-") == crm_system_name) { - crm_system_name += 3; - } - - } else if(crm_system_name == NULL) { - crm_system_name = "Unknown"; + } else if(argc > 0 && argv != NULL) { + crm_system_name = basename(argv[0]); + if(strstr(crm_system_name, "lt-") == crm_system_name) { + crm_system_name += 3; } + + } else if(crm_system_name == NULL) { + crm_system_name = "Unknown"; + } - setenv("PCMK_service", crm_system_name, 1); - cl_log_set_entity(crm_system_name); - set_crm_log_level(level); - crm_set_env_options(); + setenv("PCMK_service", crm_system_name, 1); + cl_log_set_entity(crm_system_name); + set_crm_log_level(level); + crm_set_env_options(); - if(quiet) { - /* Nuke any syslog activity */ - unsetenv("HA_logfacility"); + if(quiet) { + /* Nuke any syslog activity */ + unsetenv("HA_logfacility"); - } else { - cl_log_args(argc, argv); - if(getenv("HA_logfacility") == NULL) { - /* Set a default */ - cl_log_set_facility(HA_LOG_FACILITY); - } /* else: picked up by crm_set_env_options() */ - } + } else { + cl_log_args(argc, argv); + if(getenv("HA_logfacility") == NULL) { + /* Set a default */ + cl_log_set_facility(HA_LOG_FACILITY); + } /* else: picked up by crm_set_env_options() */ + } - cl_log_enable_stderr(to_stderr); + cl_log_enable_stderr(to_stderr); - if(coredir) { - const char *user = getenv("USER"); - if(user != NULL && safe_str_neq(user, "root") && safe_str_neq(user, CRM_DAEMON_USER)) { - crm_info("Not switching to corefile directory for %s", user); - coredir = FALSE; - } + if(coredir) { + const char *user = getenv("USER"); + if(user != NULL && safe_str_neq(user, "root") && safe_str_neq(user, CRM_DAEMON_USER)) { + crm_info("Not switching to corefile directory for %s", user); + coredir = FALSE; } + } - if(coredir) { - int user = getuid(); - const char *base = HA_COREDIR; - struct passwd *pwent = getpwuid(user); + if(coredir) { + int user = getuid(); + const char *base = HA_COREDIR; + struct passwd *pwent = getpwuid(user); - if (pwent == NULL) { - crm_perror(LOG_ERR, "Cannot get name for uid: %d", user); + if (pwent == NULL) { + crm_perror(LOG_ERR, "Cannot get name for uid: %d", user); - } else if(safe_str_neq(pwent->pw_name, "root") - && safe_str_neq(pwent->pw_name, "nobody") - && safe_str_neq(pwent->pw_name, CRM_DAEMON_USER)) { - crm_debug("Don't change active directory for regular user: %s", pwent->pw_name); + } else if(safe_str_neq(pwent->pw_name, "root") + && safe_str_neq(pwent->pw_name, "nobody") + && safe_str_neq(pwent->pw_name, CRM_DAEMON_USER)) { + crm_debug("Don't change active directory for regular user: %s", pwent->pw_name); - } else if (chdir(base) < 0) { - crm_perror(LOG_ERR, "Cannot change active directory to %s", base); + } else if (chdir(base) < 0) { + crm_perror(LOG_ERR, "Cannot change active directory to %s", base); - } else if (chdir(pwent->pw_name) < 0) { - crm_perror(LOG_ERR, "Cannot change active directory to %s/%s", base, pwent->pw_name); - } else { - crm_info("Changed active directory to %s/%s", base, pwent->pw_name); + } else if (chdir(pwent->pw_name) < 0) { + crm_perror(LOG_ERR, "Cannot change active directory to %s/%s", base, pwent->pw_name); + } else { + crm_info("Changed active directory to %s/%s", base, pwent->pw_name); #if 0 - { - char path[512]; - snprintf(path, 512, "%s-%d", crm_system_name, getpid()); - mkdir(path, 0750); - chdir(path); - crm_info("Changed active directory to %s/%s/%s", - base, pwent->pw_name, path); - } -#endif + { + char path[512]; + snprintf(path, 512, "%s-%d", crm_system_name, getpid()); + mkdir(path, 0750); + chdir(path); + crm_info("Changed active directory to %s/%s/%s", + base, pwent->pw_name, path); } +#endif } + } - update_all_trace_data(); + update_all_trace_data(); - crm_signal(DEBUG_INC, alter_debug); - crm_signal(DEBUG_DEC, alter_debug); + crm_signal(DEBUG_INC, alter_debug); + crm_signal(DEBUG_DEC, alter_debug); - return TRUE; + return TRUE; } /* returns the old value */ unsigned int set_crm_log_level(unsigned int level) { - unsigned int old = crm_log_level; - crm_log_level = level; - return old; + unsigned int old = crm_log_level; + crm_log_level = level; + return old; } unsigned int get_crm_log_level(void) { - return crm_log_level; + return crm_log_level; } static int crm_version_helper(const char *text, char **end_text) { - int atoi_result = -1; - CRM_ASSERT(end_text != NULL); + int atoi_result = -1; + CRM_ASSERT(end_text != NULL); - errno = 0; + errno = 0; - if(text != NULL && text[0] != 0) { - atoi_result = (int)strtol(text, end_text, 10); + if(text != NULL && text[0] != 0) { + atoi_result = (int)strtol(text, end_text, 10); - if(errno == EINVAL) { - crm_err("Conversion of '%s' %c failed", text, text[0]); - atoi_result = -1; - } + if(errno == EINVAL) { + crm_err("Conversion of '%s' %c failed", text, text[0]); + atoi_result = -1; } - return atoi_result; + } + return atoi_result; } /* * version1 < version2 : -1 * version1 = version2 : 0 * version1 > version2 : 1 */ int compare_version(const char *version1, const char *version2) { - int rc = 0; - int lpc = 0; - char *ver1_copy = NULL, *ver2_copy = NULL; - char *rest1 = NULL, *rest2 = NULL; - - if(version1 == NULL && version2 == NULL) { - return 0; - } else if(version1 == NULL) { - return -1; - } else if(version2 == NULL) { - return 1; - } + int rc = 0; + int lpc = 0; + char *ver1_copy = NULL, *ver2_copy = NULL; + char *rest1 = NULL, *rest2 = NULL; + + if(version1 == NULL && version2 == NULL) { + return 0; + } else if(version1 == NULL) { + return -1; + } else if(version2 == NULL) { + return 1; + } - ver1_copy = crm_strdup(version1); - ver2_copy = crm_strdup(version2); - rest1 = ver1_copy; - rest2 = ver2_copy; + ver1_copy = crm_strdup(version1); + ver2_copy = crm_strdup(version2); + rest1 = ver1_copy; + rest2 = ver2_copy; - while(1) { - int digit1 = 0; - int digit2 = 0; + while(1) { + int digit1 = 0; + int digit2 = 0; - lpc++; + lpc++; - if(rest1 == rest2) { - break; - } + if(rest1 == rest2) { + break; + } - if(rest1 != NULL) { - digit1 = crm_version_helper(rest1, &rest1); - } + if(rest1 != NULL) { + digit1 = crm_version_helper(rest1, &rest1); + } - if(rest2 != NULL) { - digit2 = crm_version_helper(rest2, &rest2); - } + if(rest2 != NULL) { + digit2 = crm_version_helper(rest2, &rest2); + } - if(digit1 < digit2){ - rc = -1; - crm_debug_5("%d < %d", digit1, digit2); - break; + if(digit1 < digit2){ + rc = -1; + crm_debug_5("%d < %d", digit1, digit2); + break; - } else if (digit1 > digit2){ - rc = 1; - crm_debug_5("%d > %d", digit1, digit2); - break; - } + } else if (digit1 > digit2){ + rc = 1; + crm_debug_5("%d > %d", digit1, digit2); + break; + } - if(rest1 != NULL && rest1[0] == '.') { - rest1++; - } - if(rest1 != NULL && rest1[0] == 0) { - rest1 = NULL; - } + if(rest1 != NULL && rest1[0] == '.') { + rest1++; + } + if(rest1 != NULL && rest1[0] == 0) { + rest1 = NULL; + } - if(rest2 != NULL && rest2[0] == '.') { - rest2++; - } - if(rest2 != NULL && rest2[0] == 0) { - rest2 = NULL; - } + if(rest2 != NULL && rest2[0] == '.') { + rest2++; + } + if(rest2 != NULL && rest2[0] == 0) { + rest2 = NULL; } + } - crm_free(ver1_copy); - crm_free(ver2_copy); + crm_free(ver1_copy); + crm_free(ver2_copy); - if(rc == 0) { - crm_debug_3("%s == %s (%d)", version1, version2, lpc); - } else if(rc < 0) { - crm_debug_3("%s < %s (%d)", version1, version2, lpc); - } else if(rc > 0) { - crm_debug_3("%s > %s (%d)", version1, version2, lpc); - } + if(rc == 0) { + crm_debug_3("%s == %s (%d)", version1, version2, lpc); + } else if(rc < 0) { + crm_debug_3("%s < %s (%d)", version1, version2, lpc); + } else if(rc > 0) { + crm_debug_3("%s > %s (%d)", version1, version2, lpc); + } - return rc; + return rc; } gboolean do_stderr = FALSE; void alter_debug(int nsig) { - crm_signal(DEBUG_INC, alter_debug); - crm_signal(DEBUG_DEC, alter_debug); - - switch(nsig) { - case DEBUG_INC: - if (crm_log_level < 100) { - crm_log_level++; - } - break; - - case DEBUG_DEC: - if (crm_log_level > 0) { - crm_log_level--; - } - break; - - default: - fprintf(stderr, "Unknown signal %d\n", nsig); - cl_log(LOG_ERR, "Unknown signal %d", nsig); - break; - } + crm_signal(DEBUG_INC, alter_debug); + crm_signal(DEBUG_DEC, alter_debug); + + switch(nsig) { + case DEBUG_INC: + if (crm_log_level < 100) { + crm_log_level++; + } + break; + + case DEBUG_DEC: + if (crm_log_level > 0) { + crm_log_level--; + } + break; + + default: + fprintf(stderr, "Unknown signal %d\n", nsig); + cl_log(LOG_ERR, "Unknown signal %d", nsig); + break; + } } void g_hash_destroy_str(gpointer data) { - crm_free(data); + crm_free(data); } #include /* #include */ /* #include */ long long crm_int_helper(const char *text, char **end_text) { long long result = -1; char *local_end_text = NULL; int saved_errno = 0; errno = 0; if(text != NULL) { #ifdef ANSI_ONLY if(end_text != NULL) { result = strtol(text, end_text, 10); } else { result = strtol(text, &local_end_text, 10); } #else if(end_text != NULL) { result = strtoll(text, end_text, 10); } else { result = strtoll(text, &local_end_text, 10); } #endif saved_errno = errno; /* CRM_CHECK(errno != EINVAL); */ if(errno == EINVAL) { crm_err("Conversion of %s failed", text); result = -1; } else if(errno == ERANGE) { crm_err("Conversion of %s was clipped: %lld", text, result); } else if(errno != 0) { crm_perror(LOG_ERR,"Conversion of %s failed:", text); } if(local_end_text != NULL && local_end_text[0] != '\0') { crm_err("Characters left over after parsing '%s': '%s'", text, local_end_text); } errno = saved_errno; } return result; } int crm_parse_int(const char *text, const char *default_text) { - int atoi_result = -1; - if(text != NULL) { - atoi_result = crm_int_helper(text, NULL); - if(errno == 0) { - return atoi_result; - } + int atoi_result = -1; + if(text != NULL) { + atoi_result = crm_int_helper(text, NULL); + if(errno == 0) { + return atoi_result; } + } - if(default_text != NULL) { - atoi_result = crm_int_helper(default_text, NULL); - if(errno == 0) { - return atoi_result; - } - - } else { - crm_err("No default conversion value supplied"); + if(default_text != NULL) { + atoi_result = crm_int_helper(default_text, NULL); + if(errno == 0) { + return atoi_result; } - return -1; + } else { + crm_err("No default conversion value supplied"); + } + + return -1; } gboolean safe_str_neq(const char *a, const char *b) { - if(a == b) { - return FALSE; - - } else if(a==NULL || b==NULL) { - return TRUE; + if(a == b) { + return FALSE; - } else if(strcasecmp(a, b) == 0) { - return FALSE; - } + } else if(a==NULL || b==NULL) { return TRUE; + + } else if(strcasecmp(a, b) == 0) { + return FALSE; + } + return TRUE; } char * crm_strdup_fn(const char *src, const char *file, const char *fn, int line) { - char *dup = NULL; - CRM_CHECK(src != NULL, - crm_err("Could not perform copy at %s:%d (%s)", file, line, fn); - return NULL); - crm_malloc0(dup, strlen(src) + 1); - return strcpy(dup, src); + char *dup = NULL; + CRM_CHECK(src != NULL, + crm_err("Could not perform copy at %s:%d (%s)", file, line, fn); + return NULL); + crm_malloc0(dup, strlen(src) + 1); + return strcpy(dup, src); } #define ENV_PREFIX "HA_" void crm_set_env_options(void) { - cl_inherit_logging_environment(500); - cl_log_set_logd_channel_source(NULL, NULL); + cl_inherit_logging_environment(500); + cl_log_set_logd_channel_source(NULL, NULL); - if(debug_level > 0 && (debug_level+LOG_INFO) > (int)crm_log_level) { - set_crm_log_level(LOG_INFO + debug_level); - } + if(debug_level > 0 && (debug_level+LOG_INFO) > (int)crm_log_level) { + set_crm_log_level(LOG_INFO + debug_level); + } } gboolean crm_is_true(const char * s) { - gboolean ret = FALSE; - if(s != NULL) { - crm_str_to_boolean(s, &ret); - } - return ret; + gboolean ret = FALSE; + if(s != NULL) { + crm_str_to_boolean(s, &ret); + } + return ret; } int crm_str_to_boolean(const char * s, int * ret) { - if(s == NULL) { - return -1; - - } else if (strcasecmp(s, "true") == 0 - || strcasecmp(s, "on") == 0 - || strcasecmp(s, "yes") == 0 - || strcasecmp(s, "y") == 0 - || strcasecmp(s, "1") == 0){ - *ret = TRUE; - return 1; - - } else if (strcasecmp(s, "false") == 0 - || strcasecmp(s, "off") == 0 - || strcasecmp(s, "no") == 0 - || strcasecmp(s, "n") == 0 - || strcasecmp(s, "0") == 0){ - *ret = FALSE; - return 1; - } + if(s == NULL) { return -1; + + } else if (strcasecmp(s, "true") == 0 + || strcasecmp(s, "on") == 0 + || strcasecmp(s, "yes") == 0 + || strcasecmp(s, "y") == 0 + || strcasecmp(s, "1") == 0){ + *ret = TRUE; + return 1; + + } else if (strcasecmp(s, "false") == 0 + || strcasecmp(s, "off") == 0 + || strcasecmp(s, "no") == 0 + || strcasecmp(s, "n") == 0 + || strcasecmp(s, "0") == 0){ + *ret = FALSE; + return 1; + } + return -1; } #ifndef NUMCHARS # define NUMCHARS "0123456789." #endif #ifndef WHITESPACE # define WHITESPACE " \t\n\r\f" #endif unsigned long long crm_get_interval(const char * input) { ha_time_t *interval = NULL; char *input_copy = crm_strdup(input); char *input_copy_mutable = input_copy; unsigned long long msec = 0; if(input == NULL) { return 0; } else if(input[0] != 'P') { crm_free(input_copy); return crm_get_msec(input); } interval = parse_time_duration(&input_copy_mutable); msec = date_in_seconds(interval); free_ha_date(interval); crm_free(input_copy); return msec * 1000; } long long crm_get_msec(const char * input) { - const char *cp = input; - const char *units; - long long multiplier = 1000; - long long divisor = 1; - long long msec = -1; - char *end_text = NULL; - /* double dret; */ + const char *cp = input; + const char *units; + long long multiplier = 1000; + long long divisor = 1; + long long msec = -1; + char *end_text = NULL; + /* double dret; */ - if(input == NULL) { - return msec; - } + if(input == NULL) { + return msec; + } - cp += strspn(cp, WHITESPACE); - units = cp + strspn(cp, NUMCHARS); - units += strspn(units, WHITESPACE); + cp += strspn(cp, WHITESPACE); + units = cp + strspn(cp, NUMCHARS); + units += strspn(units, WHITESPACE); - if (strchr(NUMCHARS, *cp) == NULL) { - return msec; - } + if (strchr(NUMCHARS, *cp) == NULL) { + return msec; + } - if (strncasecmp(units, "ms", 2) == 0 - || strncasecmp(units, "msec", 4) == 0) { - multiplier = 1; - divisor = 1; - } else if (strncasecmp(units, "us", 2) == 0 - || strncasecmp(units, "usec", 4) == 0) { - multiplier = 1; - divisor = 1000; - } else if (strncasecmp(units, "s", 1) == 0 - || strncasecmp(units, "sec", 3) == 0) { - multiplier = 1000; - divisor = 1; - } else if (strncasecmp(units, "m", 1) == 0 - || strncasecmp(units, "min", 3) == 0) { - multiplier = 60*1000; - divisor = 1; - } else if (strncasecmp(units, "h", 1) == 0 - || strncasecmp(units, "hr", 2) == 0) { - multiplier = 60*60*1000; - divisor = 1; - } else if (*units != EOS && *units != '\n' && *units != '\r') { - return msec; - } - - msec = crm_int_helper(cp, &end_text); - msec *= multiplier; - msec /= divisor; - /* dret += 0.5; */ - /* msec = (long long)dret; */ + if (strncasecmp(units, "ms", 2) == 0 + || strncasecmp(units, "msec", 4) == 0) { + multiplier = 1; + divisor = 1; + } else if (strncasecmp(units, "us", 2) == 0 + || strncasecmp(units, "usec", 4) == 0) { + multiplier = 1; + divisor = 1000; + } else if (strncasecmp(units, "s", 1) == 0 + || strncasecmp(units, "sec", 3) == 0) { + multiplier = 1000; + divisor = 1; + } else if (strncasecmp(units, "m", 1) == 0 + || strncasecmp(units, "min", 3) == 0) { + multiplier = 60*1000; + divisor = 1; + } else if (strncasecmp(units, "h", 1) == 0 + || strncasecmp(units, "hr", 2) == 0) { + multiplier = 60*60*1000; + divisor = 1; + } else if (*units != EOS && *units != '\n' && *units != '\r') { return msec; + } + + msec = crm_int_helper(cp, &end_text); + msec *= multiplier; + msec /= divisor; + /* dret += 0.5; */ + /* msec = (long long)dret; */ + return msec; } const char * op_status2text(op_status_t status) { - switch(status) { - case LRM_OP_PENDING: - return "pending"; - break; - case LRM_OP_DONE: - return "complete"; - break; - case LRM_OP_ERROR: - return "Error"; - break; - case LRM_OP_TIMEOUT: - return "Timed Out"; - break; - case LRM_OP_NOTSUPPORTED: - return "NOT SUPPORTED"; - break; - case LRM_OP_CANCELLED: - return "Cancelled"; - break; - } - crm_err("Unknown status: %d", status); - return "UNKNOWN!"; + switch(status) { + case LRM_OP_PENDING: + return "pending"; + break; + case LRM_OP_DONE: + return "complete"; + break; + case LRM_OP_ERROR: + return "Error"; + break; + case LRM_OP_TIMEOUT: + return "Timed Out"; + break; + case LRM_OP_NOTSUPPORTED: + return "NOT SUPPORTED"; + break; + case LRM_OP_CANCELLED: + return "Cancelled"; + break; + } + crm_err("Unknown status: %d", status); + return "UNKNOWN!"; } char * generate_op_key(const char *rsc_id, const char *op_type, int interval) { - int len = 35; - char *op_id = NULL; + int len = 35; + char *op_id = NULL; - CRM_CHECK(rsc_id != NULL, return NULL); - CRM_CHECK(op_type != NULL, return NULL); + CRM_CHECK(rsc_id != NULL, return NULL); + CRM_CHECK(op_type != NULL, return NULL); - len += strlen(op_type); - len += strlen(rsc_id); - crm_malloc0(op_id, len); - CRM_CHECK(op_id != NULL, return NULL); - sprintf(op_id, "%s_%s_%d", rsc_id, op_type, interval); - return op_id; + len += strlen(op_type); + len += strlen(rsc_id); + crm_malloc0(op_id, len); + CRM_CHECK(op_id != NULL, return NULL); + sprintf(op_id, "%s_%s_%d", rsc_id, op_type, interval); + return op_id; } gboolean parse_op_key(const char *key, char **rsc_id, char **op_type, int *interval) { - char *mutable_key = NULL; - char *mutable_key_ptr = NULL; - int len = 0, offset = 0, ch = 0; + char *mutable_key = NULL; + char *mutable_key_ptr = NULL; + int len = 0, offset = 0, ch = 0; - CRM_CHECK(key != NULL, return FALSE); + CRM_CHECK(key != NULL, return FALSE); - *interval = 0; - len = strlen(key); - offset = len-1; + *interval = 0; + len = strlen(key); + offset = len-1; - crm_debug_3("Source: %s", key); + crm_debug_3("Source: %s", key); - while(offset > 0 && isdigit(key[offset])) { - int digits = len-offset; - ch = key[offset] - '0'; - CRM_CHECK(ch < 10, return FALSE); - CRM_CHECK(ch >= 0, return FALSE); - while(digits > 1) { - digits--; - ch = ch * 10; - } - *interval += ch; - offset--; + while(offset > 0 && isdigit(key[offset])) { + int digits = len-offset; + ch = key[offset] - '0'; + CRM_CHECK(ch < 10, return FALSE); + CRM_CHECK(ch >= 0, return FALSE); + while(digits > 1) { + digits--; + ch = ch * 10; } + *interval += ch; + offset--; + } - crm_debug_3(" Interval: %d", *interval); - CRM_CHECK(key[offset] == '_', return FALSE); + crm_debug_3(" Interval: %d", *interval); + CRM_CHECK(key[offset] == '_', return FALSE); - mutable_key = crm_strdup(key); - mutable_key_ptr = mutable_key_ptr; - mutable_key[offset] = 0; - offset--; + mutable_key = crm_strdup(key); + mutable_key_ptr = mutable_key_ptr; + mutable_key[offset] = 0; + offset--; - while(offset > 0 && key[offset] != '_') { - offset--; - } + while(offset > 0 && key[offset] != '_') { + offset--; + } - CRM_CHECK(key[offset] == '_', - crm_free(mutable_key); return FALSE); + CRM_CHECK(key[offset] == '_', + crm_free(mutable_key); return FALSE); - mutable_key_ptr = mutable_key+offset+1; + mutable_key_ptr = mutable_key+offset+1; - crm_debug_3(" Action: %s", mutable_key_ptr); + crm_debug_3(" Action: %s", mutable_key_ptr); - *op_type = crm_strdup(mutable_key_ptr); + *op_type = crm_strdup(mutable_key_ptr); - mutable_key[offset] = 0; - offset--; + mutable_key[offset] = 0; + offset--; - CRM_CHECK(mutable_key != mutable_key_ptr, - crm_free(mutable_key); return FALSE); + CRM_CHECK(mutable_key != mutable_key_ptr, + crm_free(mutable_key); return FALSE); - crm_debug_3(" Resource: %s", mutable_key); - *rsc_id = crm_strdup(mutable_key); + crm_debug_3(" Resource: %s", mutable_key); + *rsc_id = crm_strdup(mutable_key); - crm_free(mutable_key); - return TRUE; + crm_free(mutable_key); + return TRUE; } char * generate_notify_key(const char *rsc_id, const char *notify_type, const char *op_type) { - int len = 12; - char *op_id = NULL; + int len = 12; + char *op_id = NULL; - CRM_CHECK(rsc_id != NULL, return NULL); - CRM_CHECK(op_type != NULL, return NULL); - CRM_CHECK(notify_type != NULL, return NULL); + CRM_CHECK(rsc_id != NULL, return NULL); + CRM_CHECK(op_type != NULL, return NULL); + CRM_CHECK(notify_type != NULL, return NULL); - len += strlen(op_type); - len += strlen(rsc_id); - len += strlen(notify_type); - crm_malloc0(op_id, len); - if(op_id != NULL) { - sprintf(op_id, "%s_%s_notify_%s_0", rsc_id, notify_type, op_type); - } - return op_id; + len += strlen(op_type); + len += strlen(rsc_id); + len += strlen(notify_type); + crm_malloc0(op_id, len); + if(op_id != NULL) { + sprintf(op_id, "%s_%s_notify_%s_0", rsc_id, notify_type, op_type); + } + return op_id; } char * generate_transition_magic_v202(const char *transition_key, int op_status) { - int len = 80; - char *fail_state = NULL; + int len = 80; + char *fail_state = NULL; - CRM_CHECK(transition_key != NULL, return NULL); + CRM_CHECK(transition_key != NULL, return NULL); - len += strlen(transition_key); + len += strlen(transition_key); - crm_malloc0(fail_state, len); - if(fail_state != NULL) { - snprintf(fail_state, len, "%d:%s", op_status,transition_key); - } - return fail_state; + crm_malloc0(fail_state, len); + if(fail_state != NULL) { + snprintf(fail_state, len, "%d:%s", op_status,transition_key); + } + return fail_state; } char * generate_transition_magic(const char *transition_key, int op_status, int op_rc) { - int len = 80; - char *fail_state = NULL; + int len = 80; + char *fail_state = NULL; - CRM_CHECK(transition_key != NULL, return NULL); + CRM_CHECK(transition_key != NULL, return NULL); - len += strlen(transition_key); + len += strlen(transition_key); - crm_malloc0(fail_state, len); - if(fail_state != NULL) { - snprintf(fail_state, len, "%d:%d;%s", - op_status, op_rc, transition_key); - } - return fail_state; + crm_malloc0(fail_state, len); + if(fail_state != NULL) { + snprintf(fail_state, len, "%d:%d;%s", + op_status, op_rc, transition_key); + } + return fail_state; } gboolean decode_transition_magic( - const char *magic, char **uuid, int *transition_id, int *action_id, - int *op_status, int *op_rc, int *target_rc) + const char *magic, char **uuid, int *transition_id, int *action_id, + int *op_status, int *op_rc, int *target_rc) { int res = 0; char *key = NULL; gboolean result = TRUE; CRM_CHECK(magic != NULL, return FALSE); CRM_CHECK(op_rc != NULL, return FALSE); CRM_CHECK(op_status != NULL, return FALSE); crm_malloc0(key, strlen(magic)+1); res = sscanf(magic, "%d:%d;%s", op_status, op_rc, key); if(res != 3) { crm_crit("Only found %d items in: %s", res, magic); result = FALSE; goto bail; } CRM_CHECK(decode_transition_key(key, uuid, transition_id, action_id, target_rc), result = FALSE; goto bail; ); bail: crm_free(key); return result; } char * generate_transition_key(int transition_id, int action_id, int target_rc, const char *node) { - int len = 40; - char *fail_state = NULL; + int len = 40; + char *fail_state = NULL; - CRM_CHECK(node != NULL, return NULL); + CRM_CHECK(node != NULL, return NULL); - len += strlen(node); + len += strlen(node); - crm_malloc0(fail_state, len); - if(fail_state != NULL) { - snprintf(fail_state, len, "%d:%d:%d:%s", - action_id, transition_id, target_rc, node); - } - return fail_state; + crm_malloc0(fail_state, len); + if(fail_state != NULL) { + snprintf(fail_state, len, "%d:%d:%d:%s", + action_id, transition_id, target_rc, node); + } + return fail_state; } gboolean decode_transition_key( - const char *key, char **uuid, int *transition_id, int *action_id, int *target_rc) -{ - int res = 0; - gboolean done = FALSE; - - CRM_CHECK(uuid != NULL, return FALSE); - CRM_CHECK(target_rc != NULL, return FALSE); - CRM_CHECK(action_id != NULL, return FALSE); - CRM_CHECK(transition_id != NULL, return FALSE); - - crm_malloc0(*uuid, strlen(key)+1); - res = sscanf(key, "%d:%d:%d:%s", action_id, transition_id, target_rc, *uuid); - switch(res) { - case 4: - /* Post Pacemaker 0.6 */ - done = TRUE; - break; - case 3: - case 2: - /* this can be tricky - the UUID might start with an integer */ - - /* Until Pacemaker 0.6 */ - done = TRUE; - *target_rc = -1; - res = sscanf(key, "%d:%d:%s", action_id, transition_id, *uuid); - if(res == 2) { - *action_id = -1; - res = sscanf(key, "%d:%s", transition_id, *uuid); - CRM_CHECK(res == 2, done = FALSE); - - } else if(res != 3) { - CRM_CHECK(res == 3, done = FALSE); - } - break; - - case 1: - /* Prior to Heartbeat 2.0.8 */ - done = TRUE; + const char *key, char **uuid, int *transition_id, int *action_id, int *target_rc) +{ + int res = 0; + gboolean done = FALSE; + + CRM_CHECK(uuid != NULL, return FALSE); + CRM_CHECK(target_rc != NULL, return FALSE); + CRM_CHECK(action_id != NULL, return FALSE); + CRM_CHECK(transition_id != NULL, return FALSE); + + crm_malloc0(*uuid, strlen(key)+1); + res = sscanf(key, "%d:%d:%d:%s", action_id, transition_id, target_rc, *uuid); + switch(res) { + case 4: + /* Post Pacemaker 0.6 */ + done = TRUE; + break; + case 3: + case 2: + /* this can be tricky - the UUID might start with an integer */ + + /* Until Pacemaker 0.6 */ + done = TRUE; + *target_rc = -1; + res = sscanf(key, "%d:%d:%s", action_id, transition_id, *uuid); + if(res == 2) { *action_id = -1; - *target_rc = -1; res = sscanf(key, "%d:%s", transition_id, *uuid); CRM_CHECK(res == 2, done = FALSE); - break; - default: - crm_crit("Unhandled sscanf result (%d) for %s", res, key); + + } else if(res != 3) { + CRM_CHECK(res == 3, done = FALSE); + } + break; - } + case 1: + /* Prior to Heartbeat 2.0.8 */ + done = TRUE; + *action_id = -1; + *target_rc = -1; + res = sscanf(key, "%d:%s", transition_id, *uuid); + CRM_CHECK(res == 2, done = FALSE); + break; + default: + crm_crit("Unhandled sscanf result (%d) for %s", res, key); + + } - if(strlen(*uuid) != 36) { - crm_warn("Bad UUID (%s) in sscanf result (%d) for %s", *uuid, res, key); - } + if(strlen(*uuid) != 36) { + crm_warn("Bad UUID (%s) in sscanf result (%d) for %s", *uuid, res, key); + } - if(done == FALSE) { - crm_err("Cannot decode '%s' rc=%d", key, res); + if(done == FALSE) { + crm_err("Cannot decode '%s' rc=%d", key, res); - crm_free(*uuid); - *uuid = NULL; - *target_rc = -1; - *action_id = -1; - *transition_id = -1; - } + crm_free(*uuid); + *uuid = NULL; + *target_rc = -1; + *action_id = -1; + *transition_id = -1; + } - return done; + return done; } void filter_action_parameters(xmlNode *param_set, const char *version) { - char *key = NULL; - char *timeout = NULL; - char *interval = NULL; -#if CRM_DEPRECATED_SINCE_2_0_5 - const char *filter_205[] = { - XML_ATTR_TE_TARGET_RC, - XML_ATTR_LRM_PROBE, - XML_RSC_ATTR_START, - XML_RSC_ATTR_NOTIFY, - XML_RSC_ATTR_UNIQUE, - XML_RSC_ATTR_MANAGED, - XML_RSC_ATTR_PRIORITY, - XML_RSC_ATTR_MULTIPLE, - XML_RSC_ATTR_STICKINESS, - XML_RSC_ATTR_FAIL_STICKINESS, - XML_RSC_ATTR_TARGET_ROLE, - -/* ignore clone fields */ - XML_RSC_ATTR_INCARNATION, - XML_RSC_ATTR_INCARNATION_MAX, - XML_RSC_ATTR_INCARNATION_NODEMAX, - XML_RSC_ATTR_MASTER_MAX, - XML_RSC_ATTR_MASTER_NODEMAX, - -/* old field names */ - "role", - "crm_role", - "te-target-rc", - -/* ignore notify fields */ - "notify_stop_resource", - "notify_stop_uname", - "notify_start_resource", - "notify_start_uname", - "notify_active_resource", - "notify_active_uname", - "notify_inactive_resource", - "notify_inactive_uname", - "notify_promote_resource", - "notify_promote_uname", - "notify_demote_resource", - "notify_demote_uname", - "notify_master_resource", - "notify_master_uname", - "notify_slave_resource", - "notify_slave_uname" - }; -#endif + char *key = NULL; + char *timeout = NULL; + char *interval = NULL; - const char *attr_filter[] = { - XML_ATTR_ID, - XML_ATTR_CRM_VERSION, - XML_LRM_ATTR_OP_DIGEST, - }; - - gboolean do_delete = FALSE; - int lpc = 0; - static int meta_len = 0; - if(meta_len == 0) { - meta_len = strlen(CRM_META); - } - - if(param_set == NULL) { - return; - } + const char *attr_filter[] = { + XML_ATTR_ID, + XML_ATTR_CRM_VERSION, + XML_LRM_ATTR_OP_DIGEST, + }; -#if CRM_DEPRECATED_SINCE_2_0_5 - if(version == NULL || compare_version("1.0.5", version) > 0) { - for(lpc = 0; lpc < DIMOF(filter_205); lpc++) { - xml_remove_prop(param_set, filter_205[lpc]); - } - } -#endif + gboolean do_delete = FALSE; + int lpc = 0; + static int meta_len = 0; + if(meta_len == 0) { + meta_len = strlen(CRM_META); + } + + if(param_set == NULL) { + return; + } - for(lpc = 0; lpc < DIMOF(attr_filter); lpc++) { - xml_remove_prop(param_set, attr_filter[lpc]); - } + for(lpc = 0; lpc < DIMOF(attr_filter); lpc++) { + xml_remove_prop(param_set, attr_filter[lpc]); + } - key = crm_meta_name(XML_LRM_ATTR_INTERVAL); - interval = crm_element_value_copy(param_set, key); - crm_free(key); + key = crm_meta_name(XML_LRM_ATTR_INTERVAL); + interval = crm_element_value_copy(param_set, key); + crm_free(key); - key = crm_meta_name(XML_ATTR_TIMEOUT); - timeout = crm_element_value_copy(param_set, key); + key = crm_meta_name(XML_ATTR_TIMEOUT); + timeout = crm_element_value_copy(param_set, key); - xml_prop_name_iter(param_set, prop_name, - do_delete = FALSE; - if(strncasecmp(prop_name, CRM_META, meta_len) == 0) { - do_delete = TRUE; - } + xml_prop_name_iter(param_set, prop_name, + do_delete = FALSE; + if(strncasecmp(prop_name, CRM_META, meta_len) == 0) { + do_delete = TRUE; + } - if(do_delete) { - xml_remove_prop(param_set, prop_name); - } - ); + if(do_delete) { + xml_remove_prop(param_set, prop_name); + } + ); - if(crm_get_msec(interval) > 0 && compare_version(version, "1.0.8") > 0) { - /* Re-instate the operation's timeout value */ - if(timeout != NULL) { - crm_xml_add(param_set, key, timeout); - } + if(crm_get_msec(interval) > 0 && compare_version(version, "1.0.8") > 0) { + /* Re-instate the operation's timeout value */ + if(timeout != NULL) { + crm_xml_add(param_set, key, timeout); } + } - crm_free(interval); - crm_free(timeout); - crm_free(key); + crm_free(interval); + crm_free(timeout); + crm_free(key); } void filter_reload_parameters(xmlNode *param_set, const char *restart_string) { - int len = 0; - char *name = NULL; - char *match = NULL; + int len = 0; + char *name = NULL; + char *match = NULL; - if(param_set == NULL) { - return; - } + if(param_set == NULL) { + return; + } - xml_prop_name_iter(param_set, prop_name, - name = NULL; - len = strlen(prop_name) + 3; + xml_prop_name_iter(param_set, prop_name, + name = NULL; + len = strlen(prop_name) + 3; - crm_malloc0(name, len); - sprintf(name, " %s ", prop_name); - name[len-1] = 0; + crm_malloc0(name, len); + sprintf(name, " %s ", prop_name); + name[len-1] = 0; - match = strstr(restart_string, name); - if(match == NULL) { - crm_debug_3("%s not found in %s", - prop_name, restart_string); - xml_remove_prop(param_set, prop_name); - } - crm_free(name); - ); + match = strstr(restart_string, name); + if(match == NULL) { + crm_debug_3("%s not found in %s", + prop_name, restart_string); + xml_remove_prop(param_set, prop_name); + } + crm_free(name); + ); } void crm_abort(const char *file, const char *function, int line, const char *assert_condition, gboolean do_core, gboolean do_fork) { - int rc = 0; - int pid = 0; - int status = 0; + int rc = 0; + int pid = 0; + int status = 0; - if(do_core == FALSE) { - do_crm_log(LOG_ERR, "%s: Triggered assert at %s:%d : %s", - function, file, line, assert_condition); - return; + if(do_core == FALSE) { + do_crm_log(LOG_ERR, "%s: Triggered assert at %s:%d : %s", + function, file, line, assert_condition); + return; - } else if(do_fork) { - pid=fork(); + } else if(do_fork) { + pid=fork(); - } else { - do_crm_log(LOG_ERR, "%s: Triggered fatal assert at %s:%d : %s", - function, file, line, assert_condition); - } + } else { + do_crm_log(LOG_ERR, "%s: Triggered fatal assert at %s:%d : %s", + function, file, line, assert_condition); + } - switch(pid) { - case -1: - do_crm_log(LOG_CRIT, "%s: Cannot create core for non-fatal assert at %s:%d : %s", - function, file, line, assert_condition); - return; - - default: /* Parent */ - do_crm_log(LOG_ERR, - "%s: Forked child %d to record non-fatal assert at %s:%d : %s", - function, pid, file, line, assert_condition); - do { - rc = waitpid(pid, &status, 0); - if(rc < 0 && errno != EINTR) { - crm_perror(LOG_ERR,"%s: Cannot wait on forked child %d", function, pid); - } + switch(pid) { + case -1: + do_crm_log(LOG_CRIT, "%s: Cannot create core for non-fatal assert at %s:%d : %s", + function, file, line, assert_condition); + return; + + default: /* Parent */ + do_crm_log(LOG_ERR, + "%s: Forked child %d to record non-fatal assert at %s:%d : %s", + function, pid, file, line, assert_condition); + do { + rc = waitpid(pid, &status, 0); + if(rc < 0 && errno != EINTR) { + crm_perror(LOG_ERR,"%s: Cannot wait on forked child %d", function, pid); + } - } while(rc < 0 && errno == EINTR); + } while(rc < 0 && errno == EINTR); - return; + return; - case 0: /* Child */ - abort(); - break; - } + case 0: /* Child */ + abort(); + break; + } } char * generate_series_filename( - const char *directory, const char *series, int sequence, gboolean bzip) + const char *directory, const char *series, int sequence, gboolean bzip) { - int len = 40; - char *filename = NULL; - const char *ext = "raw"; + int len = 40; + char *filename = NULL; + const char *ext = "raw"; - CRM_CHECK(directory != NULL, return NULL); - CRM_CHECK(series != NULL, return NULL); + CRM_CHECK(directory != NULL, return NULL); + CRM_CHECK(series != NULL, return NULL); - len += strlen(directory); - len += strlen(series); - crm_malloc0(filename, len); - CRM_CHECK(filename != NULL, return NULL); + len += strlen(directory); + len += strlen(series); + crm_malloc0(filename, len); + CRM_CHECK(filename != NULL, return NULL); - if(bzip) { - ext = "bz2"; - } - sprintf(filename, "%s/%s-%d.%s", directory, series, sequence, ext); + if(bzip) { + ext = "bz2"; + } + sprintf(filename, "%s/%s-%d.%s", directory, series, sequence, ext); - return filename; + return filename; } int get_last_sequence(const char *directory, const char *series) { - FILE *file_strm = NULL; - int start = 0, length = 0, read_len = 0; - char *series_file = NULL; - char *buffer = NULL; - int seq = 0; - int len = 36; - - CRM_CHECK(directory != NULL, return 0); - CRM_CHECK(series != NULL, return 0); - - len += strlen(directory); - len += strlen(series); - crm_malloc0(series_file, len); - CRM_CHECK(series_file != NULL, return 0); - sprintf(series_file, "%s/%s.last", directory, series); - - file_strm = fopen(series_file, "r"); - if(file_strm == NULL) { - crm_debug("Series file %s does not exist", series_file); - crm_free(series_file); - return 0; - } + FILE *file_strm = NULL; + int start = 0, length = 0, read_len = 0; + char *series_file = NULL; + char *buffer = NULL; + int seq = 0; + int len = 36; + + CRM_CHECK(directory != NULL, return 0); + CRM_CHECK(series != NULL, return 0); + + len += strlen(directory); + len += strlen(series); + crm_malloc0(series_file, len); + CRM_CHECK(series_file != NULL, return 0); + sprintf(series_file, "%s/%s.last", directory, series); + + file_strm = fopen(series_file, "r"); + if(file_strm == NULL) { + crm_debug("Series file %s does not exist", series_file); + crm_free(series_file); + return 0; + } - /* see how big the file is */ - start = ftell(file_strm); - fseek(file_strm, 0L, SEEK_END); - length = ftell(file_strm); - fseek(file_strm, 0L, start); + /* see how big the file is */ + start = ftell(file_strm); + fseek(file_strm, 0L, SEEK_END); + length = ftell(file_strm); + fseek(file_strm, 0L, start); - CRM_ASSERT(length >= 0); - CRM_ASSERT(start == ftell(file_strm)); + CRM_ASSERT(length >= 0); + CRM_ASSERT(start == ftell(file_strm)); - crm_debug_3("Reading %d bytes from file", length); - crm_malloc0(buffer, (length+1)); - read_len = fread(buffer, 1, length, file_strm); + crm_debug_3("Reading %d bytes from file", length); + crm_malloc0(buffer, (length+1)); + read_len = fread(buffer, 1, length, file_strm); - if(read_len != length) { - crm_err("Calculated and read bytes differ: %d vs. %d", - length, read_len); - crm_free(buffer); - buffer = NULL; + if(read_len != length) { + crm_err("Calculated and read bytes differ: %d vs. %d", + length, read_len); + crm_free(buffer); + buffer = NULL; - } else if(length <= 0) { - crm_info("%s was not valid", series_file); - crm_free(buffer); - buffer = NULL; - } - - crm_free(series_file); - seq = crm_parse_int(buffer, "0"); + } else if(length <= 0) { + crm_info("%s was not valid", series_file); crm_free(buffer); - fclose(file_strm); - return seq; + buffer = NULL; + } + + crm_free(series_file); + seq = crm_parse_int(buffer, "0"); + crm_free(buffer); + fclose(file_strm); + return seq; } void write_last_sequence( - const char *directory, const char *series, int sequence, int max) + const char *directory, const char *series, int sequence, int max) { - int rc = 0; - int len = 36; - FILE *file_strm = NULL; - char *series_file = NULL; + int rc = 0; + int len = 36; + FILE *file_strm = NULL; + char *series_file = NULL; - CRM_CHECK(directory != NULL, return); - CRM_CHECK(series != NULL, return); + CRM_CHECK(directory != NULL, return); + CRM_CHECK(series != NULL, return); - if(max == 0) { - return; - } - while(max > 0 && sequence > max) { - sequence -= max; - } + if(max == 0) { + return; + } + while(max > 0 && sequence > max) { + sequence -= max; + } - len += strlen(directory); - len += strlen(series); - crm_malloc0(series_file, len); - sprintf(series_file, "%s/%s.last", directory, series); + len += strlen(directory); + len += strlen(series); + crm_malloc0(series_file, len); + sprintf(series_file, "%s/%s.last", directory, series); - file_strm = fopen(series_file, "w"); - if(file_strm == NULL) { - crm_err("Cannout open series file %s for writing", series_file); - goto bail; - } + file_strm = fopen(series_file, "w"); + if(file_strm == NULL) { + crm_err("Cannout open series file %s for writing", series_file); + goto bail; + } - rc = fprintf(file_strm, "%d", sequence); - if(rc < 0) { - crm_perror(LOG_ERR,"Cannot write to series file %s", series_file); - } + rc = fprintf(file_strm, "%d", sequence); + if(rc < 0) { + crm_perror(LOG_ERR,"Cannot write to series file %s", series_file); + } bail: - if(file_strm != NULL) { - fflush(file_strm); - fclose(file_strm); - } + if(file_strm != NULL) { + fflush(file_strm); + fclose(file_strm); + } - crm_free(series_file); + crm_free(series_file); } #define LOCKSTRLEN 11 int crm_pid_active(long pid) { int rc = 0; int running = 0; char proc_path[PATH_MAX], exe_path[PATH_MAX], myexe_path[PATH_MAX]; if(pid <= 0) { return -1; } else if (kill(pid, 0) < 0 && errno == ESRCH) { return 0; } #ifndef HAVE_PROC_PID return 1; #endif /* check to make sure pid hasn't been reused by another process */ snprintf(proc_path, sizeof(proc_path), "/proc/%lu/exe", pid); rc = readlink(proc_path, exe_path, PATH_MAX-1); if(rc < 0) { crm_perror(LOG_ERR, "Could not read from %s", proc_path); goto bail; } exe_path[rc] = 0; snprintf(proc_path, sizeof(proc_path), "/proc/%lu/exe", (long unsigned int)getpid()); rc = readlink(proc_path, myexe_path, PATH_MAX-1); if(rc < 0) { crm_perror(LOG_ERR, "Could not read from %s", proc_path); goto bail; } myexe_path[rc] = 0; if(strcmp(exe_path, myexe_path) == 0) { running = 1; } bail: return running; } int crm_read_pidfile(const char *filename) { int fd; long pid = -1; char buf[LOCKSTRLEN+1]; if ((fd = open(filename, O_RDONLY)) < 0) { goto bail; } if (read(fd, buf, sizeof(buf)) < 1) { goto bail; } if (sscanf(buf, "%lu", &pid) > 0) { if (pid <= 0){ pid = -LSB_STATUS_STOPPED; } } bail: if(fd >= 0) { close(fd); } return pid; } int crm_lock_pidfile(const char *filename) { struct stat sbuf; int fd = 0, rc = 0; long pid = 0, mypid = 0; char lf_name[256], tf_name[256], buf[LOCKSTRLEN+1]; mypid = (unsigned long) getpid(); snprintf(lf_name, sizeof(lf_name), "%s",filename); snprintf(tf_name, sizeof(tf_name), "%s.%lu", filename, mypid); if ((fd = open(lf_name, O_RDONLY)) >= 0) { if (fstat(fd, &sbuf) >= 0 && sbuf.st_size < LOCKSTRLEN) { sleep(1); /* if someone was about to create one, * give'm a sec to do so * Though if they follow our protocol, * this won't happen. They should really * put the pid in, then link, not the * other way around. */ } if (read(fd, buf, sizeof(buf)) > 0) { if (sscanf(buf, "%lu", &pid) > 0) { if (pid > 1 && pid != getpid() && crm_pid_active(pid)) { /* locked by existing process - give up */ close(fd); return -1; } } } unlink(lf_name); close(fd); } if ((fd = open(tf_name, O_CREAT | O_WRONLY | O_EXCL, 0644)) < 0) { /* Hmmh, why did we fail? Anyway, nothing we can do about it */ return -3; } /* Slight overkill with the %*d format ;-) */ snprintf(buf, sizeof(buf), "%*lu\n", LOCKSTRLEN-1, mypid); if (write(fd, buf, LOCKSTRLEN) != LOCKSTRLEN) { /* Again, nothing we can do about this */ rc = -3; close(fd); goto out; } close(fd); switch (link(tf_name, lf_name)) { case 0: if (stat(tf_name, &sbuf) < 0) { /* something weird happened */ rc = -3; } else if (sbuf.st_nlink < 2) { /* somehow, it didn't get through - NFS trouble? */ rc = -2; } else { rc = 0; } break; case EEXIST: rc = -1; break; default: rc = -3; } out: unlink(tf_name); return rc; } void crm_make_daemon(const char *name, gboolean daemonize, const char *pidfile) { long pid; const char *devnull = "/dev/null"; if(daemonize == FALSE) { return; } pid = fork(); if (pid < 0) { fprintf(stderr, "%s: could not start daemon\n", name); crm_perror(LOG_ERR,"fork"); exit(LSB_EXIT_GENERIC); } else if (pid > 0) { exit(LSB_EXIT_OK); } if (crm_lock_pidfile(pidfile) < 0 ) { pid = crm_read_pidfile(pidfile); if(crm_pid_active(pid) > 0) { crm_warn("%s: already running [pid %ld] (%s).\n", name, pid, pidfile); exit(LSB_EXIT_OK); } } umask(022); close(STDIN_FILENO); (void)open(devnull, O_RDONLY); /* Stdin: fd 0 */ close(STDOUT_FILENO); (void)open(devnull, O_WRONLY); /* Stdout: fd 1 */ close(STDERR_FILENO); (void)open(devnull, O_WRONLY); /* Stderr: fd 2 */ } gboolean crm_is_writable(const char *dir, const char *file, const char *user, const char *group, gboolean need_both) { - int s_res = -1; - struct stat buf; - char *full_file = NULL; - const char *target = NULL; - - gboolean pass = TRUE; - gboolean readwritable = FALSE; - - CRM_ASSERT(dir != NULL); - if(file != NULL) { - full_file = crm_concat(dir, file, '/'); - target = full_file; - s_res = stat(full_file, &buf); - if( s_res == 0 && S_ISREG(buf.st_mode) == FALSE ) { - crm_err("%s must be a regular file", target); - pass = FALSE; - goto out; - } + int s_res = -1; + struct stat buf; + char *full_file = NULL; + const char *target = NULL; + + gboolean pass = TRUE; + gboolean readwritable = FALSE; + + CRM_ASSERT(dir != NULL); + if(file != NULL) { + full_file = crm_concat(dir, file, '/'); + target = full_file; + s_res = stat(full_file, &buf); + if( s_res == 0 && S_ISREG(buf.st_mode) == FALSE ) { + crm_err("%s must be a regular file", target); + pass = FALSE; + goto out; } + } - if (s_res != 0) { - target = dir; - s_res = stat(dir, &buf); - if(s_res != 0) { - crm_err("%s must exist and be a directory", dir); - pass = FALSE; - goto out; - - } else if( S_ISDIR(buf.st_mode) == FALSE ) { - crm_err("%s must be a directory", dir); - pass = FALSE; - } + if (s_res != 0) { + target = dir; + s_res = stat(dir, &buf); + if(s_res != 0) { + crm_err("%s must exist and be a directory", dir); + pass = FALSE; + goto out; + + } else if( S_ISDIR(buf.st_mode) == FALSE ) { + crm_err("%s must be a directory", dir); + pass = FALSE; } + } - if(user) { - struct passwd *sys_user = NULL; - sys_user = getpwnam(user); - readwritable = (sys_user != NULL - && buf.st_uid == sys_user->pw_uid - && (buf.st_mode & (S_IRUSR|S_IWUSR))); - if(readwritable == FALSE) { - crm_err("%s must be owned and r/w by user %s", - target, user); - if(need_both) { - pass = FALSE; - } - } - } - - if(group) { - struct group *sys_grp = getgrnam(group); - readwritable = ( - sys_grp != NULL - && buf.st_gid == sys_grp->gr_gid - && (buf.st_mode & (S_IRGRP|S_IWGRP))); - if(readwritable == FALSE) { - if(need_both || user == NULL) { - pass = FALSE; - crm_err("%s must be owned and r/w by group %s", - target, group); - } else { - crm_warn("%s should be owned and r/w by group %s", - target, group); - } - } + if(user) { + struct passwd *sys_user = NULL; + sys_user = getpwnam(user); + readwritable = (sys_user != NULL + && buf.st_uid == sys_user->pw_uid + && (buf.st_mode & (S_IRUSR|S_IWUSR))); + if(readwritable == FALSE) { + crm_err("%s must be owned and r/w by user %s", + target, user); + if(need_both) { + pass = FALSE; + } } + } + + if(group) { + struct group *sys_grp = getgrnam(group); + readwritable = ( + sys_grp != NULL + && buf.st_gid == sys_grp->gr_gid + && (buf.st_mode & (S_IRGRP|S_IWGRP))); + if(readwritable == FALSE) { + if(need_both || user == NULL) { + pass = FALSE; + crm_err("%s must be owned and r/w by group %s", + target, group); + } else { + crm_warn("%s should be owned and r/w by group %s", + target, group); + } + } + } out: - crm_free(full_file); - return pass; + crm_free(full_file); + return pass; } static unsigned long long crm_bit_filter = 0; /* 0x00000002ULL; */ static unsigned int bit_log_level = LOG_DEBUG_5; long long crm_clear_bit(const char *function, long long word, long long bit) { - unsigned int level = bit_log_level; - if(bit & crm_bit_filter) { - level = LOG_ERR; - } + unsigned int level = bit_log_level; + if(bit & crm_bit_filter) { + level = LOG_ERR; + } - do_crm_log_unlikely(level, "Bit 0x%.16llx cleared by %s", bit, function); - word &= ~bit; + do_crm_log_unlikely(level, "Bit 0x%.16llx cleared by %s", bit, function); + word &= ~bit; - return word; + return word; } long long crm_set_bit(const char *function, long long word, long long bit) { - unsigned int level = bit_log_level; - if(bit & crm_bit_filter) { - level = LOG_ERR; - } + unsigned int level = bit_log_level; + if(bit & crm_bit_filter) { + level = LOG_ERR; + } - do_crm_log_unlikely(level, "Bit 0x%.16llx set by %s", bit, function); - word |= bit; - return word; + do_crm_log_unlikely(level, "Bit 0x%.16llx set by %s", bit, function); + word |= bit; + return word; } const char * name_for_cluster_type(enum cluster_type_e type) { switch(type) { case pcmk_cluster_classic_ais: return "classic openais (with plugin)"; case pcmk_cluster_cman: return "cman"; case pcmk_cluster_corosync: return "corosync"; case pcmk_cluster_heartbeat: return "heartbeat"; case pcmk_cluster_unknown: return "unknown"; case pcmk_cluster_invalid: return "invalid"; } crm_err("Invalid cluster type: %d", type); return "invalid"; } /* Do not expose these two */ int set_cluster_type(enum cluster_type_e type); static enum cluster_type_e cluster_type = pcmk_cluster_unknown; int set_cluster_type(enum cluster_type_e type) { if(cluster_type == pcmk_cluster_unknown) { crm_info("Cluster type set to: %s", name_for_cluster_type(cluster_type)); cluster_type = type; return 0; } else if(cluster_type == type) { return 0; } else if(pcmk_cluster_unknown == type) { cluster_type = type; return 0; } crm_err("Cluster type already set to %s", name_for_cluster_type(cluster_type)); return -1; } enum cluster_type_e get_cluster_type(void) { if(cluster_type == pcmk_cluster_unknown) { const char *cluster = getenv("HA_cluster_type"); cluster_type = pcmk_cluster_invalid; if(cluster) { crm_info("Cluster type is: '%s'.", cluster); } if(cluster == NULL || safe_str_eq(cluster, "heartbeat")) { #if SUPPORT_HEARTBEAT cluster_type = pcmk_cluster_heartbeat; #else crm_crit("This installation of Pacemaker does not support the '%s' cluster infrastructure. Terminating.", cluster); exit(100); #endif } else if(safe_str_eq(cluster, "openais")) { #if SUPPORT_COROSYNC cluster_type = pcmk_cluster_classic_ais; #else crm_crit("This installation of Pacemaker does not support the '%s' cluster infrastructure. Terminating.", cluster); exit(100); #endif } else if(safe_str_eq(cluster, "corosync")) { #if SUPPORT_COROSYNC cluster_type = pcmk_cluster_corosync; #else crm_crit("This installation of Pacemaker does not support the '%s' cluster infrastructure. Terminating.", cluster); exit(100); #endif } else if(safe_str_eq(cluster, "cman")) { #if SUPPORT_CMAN cluster_type = pcmk_cluster_cman; #else crm_crit("This installation of Pacemaker does not support the '%s' cluster infrastructure. Terminating.", cluster); exit(100); #endif } else { crm_crit("Unknown cluster type: '%s'. Terminating.", cluster); exit(100); } } return cluster_type; } gboolean is_cman_cluster(void) { return get_cluster_type() == pcmk_cluster_cman; } gboolean is_corosync_cluster(void) { return get_cluster_type() == pcmk_cluster_corosync; } gboolean is_classic_ais_cluster(void) { return get_cluster_type() == pcmk_cluster_classic_ais; } gboolean is_openais_cluster(void) { enum cluster_type_e type = get_cluster_type(); if(type == pcmk_cluster_classic_ais) { return TRUE; } else if(type == pcmk_cluster_corosync) { return TRUE; } else if(type == pcmk_cluster_cman) { return TRUE; } return FALSE; } gboolean is_heartbeat_cluster(void) { return get_cluster_type() == pcmk_cluster_heartbeat; } gboolean crm_str_eq(const char *a, const char *b, gboolean use_case) { if(a == b) { return TRUE; } else if(a == NULL || b == NULL) { /* shouldn't be comparing NULLs */ return FALSE; } else if(use_case && a[0] != b[0]) { return FALSE; } else if(strcasecmp(a, b) == 0) { return TRUE; } return FALSE; } char *crm_meta_name(const char *field) { int lpc = 0; int max = 0; char *crm_name = NULL; CRM_CHECK(field != NULL, return NULL); crm_name = crm_concat(CRM_META, field, '_'); /* Massage the names so they can be used as shell variables */ max = strlen(crm_name); for(; lpc < max; lpc++) { switch(crm_name[lpc]) { case '-': crm_name[lpc] = '_'; break; } } return crm_name; } const char *crm_meta_value(GHashTable *hash, const char *field) { char *key = NULL; const char *value = NULL; key = crm_meta_name(field); if(key) { value = g_hash_table_lookup(hash, key); crm_free(key); } return value; } static struct crm_option *crm_long_options = NULL; static const char *crm_app_description = NULL; static const char *crm_short_options = NULL; static const char *crm_app_usage = NULL; static struct option *crm_create_long_opts(struct crm_option *long_options) { struct option *long_opts = NULL; #ifdef HAVE_GETOPT_H int index = 0, lpc = 0; /* * A previous, possibly poor, choice of '?' as the short form of --help * means that getopt_long() returns '?' for both --help and for "unknown option" * * This dummy entry allows us to differentiate between the two in crm_get_option() * and exit with the correct error code */ crm_realloc(long_opts, (index+1) * sizeof(struct option)); long_opts[index].name = "__dummmy__"; long_opts[index].has_arg = 0; long_opts[index].flag = 0; long_opts[index].val = '_'; index++; for(lpc = 0; long_options[lpc].name != NULL; lpc++) { if(long_options[lpc].name[0] == '-') { continue; } crm_realloc(long_opts, (index+1) * sizeof(struct option)); /*fprintf(stderr, "Creating %d %s = %c\n", index, * long_options[lpc].name, long_options[lpc].val); */ long_opts[index].name = long_options[lpc].name; long_opts[index].has_arg = long_options[lpc].has_arg; long_opts[index].flag = long_options[lpc].flag; long_opts[index].val = long_options[lpc].val; index++; } /* Now create the list terminator */ crm_realloc(long_opts, (index+1) * sizeof(struct option)); long_opts[index].name = NULL; long_opts[index].has_arg = 0; long_opts[index].flag = 0; long_opts[index].val = 0; #endif return long_opts; } void crm_set_options(const char *short_options, const char *app_usage, struct crm_option *long_options, const char *app_desc) { if(short_options) { crm_short_options = short_options; } if(long_options) { crm_long_options = long_options; } if(app_desc) { crm_app_description = app_desc; } if(app_usage) { crm_app_usage = app_usage; } } int crm_get_option(int argc, char **argv, int *index) { #ifdef HAVE_GETOPT_H static struct option *long_opts = NULL; if(long_opts == NULL && crm_long_options) { long_opts = crm_create_long_opts(crm_long_options); } if(long_opts) { int flag = getopt_long(argc, argv, crm_short_options, long_opts, index); switch(flag) { case 0: return long_opts[*index].val; case -1: /* End of option processing */ break; case ':': crm_debug_2("Missing argument"); crm_help('?', 1); break; case '?': crm_help('?', *index?0:1); break; } return flag; } #endif if(crm_short_options) { return getopt(argc, argv, crm_short_options); } return -1; } void crm_help(char cmd, int exit_code) { int i = 0; FILE *stream = (exit_code ? stderr : stdout); if(cmd == 'v' || cmd == '$') { fprintf(stream, "Pacemaker %s\n", VERSION); fprintf(stream, "Written by Andrew Beekhof\n"); goto out; } if(cmd == '!') { fprintf(stream, "Pacemaker %s (Build: %s): %s\n", VERSION, BUILD_VERSION, CRM_FEATURES); goto out; } fprintf(stream, "%s - %s\n", crm_system_name, crm_app_description); if(crm_app_usage) { fprintf(stream, "Usage: %s %s\n", crm_system_name, crm_app_usage); } if(crm_long_options) { fprintf(stream, "Options:\n"); for(i = 0; crm_long_options[i].name != NULL; i++) { if(crm_long_options[i].flags & pcmk_option_hidden) { } else if(crm_long_options[i].flags & pcmk_option_paragraph) { fprintf(stream, "%s\n\n", crm_long_options[i].desc); } else if(crm_long_options[i].flags & pcmk_option_example) { fprintf(stream, "\t#%s\n\n", crm_long_options[i].desc); } else if(crm_long_options[i].val == '-' && crm_long_options[i].desc) { fprintf(stream, "%s\n", crm_long_options[i].desc); } else { fprintf(stream, " -%c, --%s%c%s\t%s\n", crm_long_options[i].val, crm_long_options[i].name, crm_long_options[i].has_arg?'=':' ',crm_long_options[i].has_arg?"value":"", crm_long_options[i].desc?crm_long_options[i].desc:""); } } } else if(crm_short_options) { fprintf(stream, "Usage: %s - %s\n", crm_system_name, crm_app_description); for(i = 0; crm_short_options[i] != 0; i++) { int has_arg = FALSE; if(crm_short_options[i+1] == ':') { has_arg = TRUE; } fprintf(stream, " -%c %s\n", crm_short_options[i], has_arg?"{value}":""); if(has_arg) { i++; } } } fprintf(stream, "\nReport bugs to %s\n", PACKAGE_BUGREPORT); out: if(exit_code >= 0) { exit(exit_code); } } #include <../../tools/attrd.h> gboolean attrd_update(IPC_Channel *cluster, char command, const char *host, const char *name, const char *value, const char *section, const char *set, const char *dampen) { gboolean success = FALSE; const char *reason = "Cluster connection failed"; /* remap common aliases */ if(safe_str_eq(section, "reboot")) { section = XML_CIB_TAG_STATUS; } else if(safe_str_eq(section, "forever")) { section = XML_CIB_TAG_NODES; } if(cluster == NULL) { reason = "No connection to the cluster"; } else { xmlNode *update = create_xml_node(NULL, __FUNCTION__); crm_xml_add(update, F_TYPE, T_ATTRD); crm_xml_add(update, F_ORIG, crm_system_name); if(name == NULL && command == 'U') { command = 'R'; } switch(command) { case 'D': case 'U': case 'v': crm_xml_add(update, F_ATTRD_TASK, "update"); crm_xml_add(update, F_ATTRD_ATTRIBUTE, name); break; case 'R': crm_xml_add(update, F_ATTRD_TASK, "refresh"); break; case 'q': crm_xml_add(update, F_ATTRD_TASK, "query"); break; } crm_xml_add(update, F_ATTRD_VALUE, value); crm_xml_add(update, F_ATTRD_DAMPEN, dampen); crm_xml_add(update, F_ATTRD_SECTION, section); crm_xml_add(update, F_ATTRD_HOST, host); crm_xml_add(update, F_ATTRD_SET, set); success = send_ipc_message(cluster, update); free_xml(update); } if(success) { crm_debug("Sent update: %s=%s for %s", name, value, host?host:"localhost"); return TRUE; } crm_info("Could not send update: %s=%s for %s", name, value, host?host:"localhost"); return FALSE; } gboolean attrd_lazy_update(char command, const char *host, const char *name, const char *value, const char *section, const char *set, const char *dampen) { int max = 5; gboolean updated = FALSE; static IPC_Channel *cluster = NULL; while(updated == 0 && max > 0) { if(cluster == NULL) { crm_info("Connecting to cluster... %d retries remaining", max); cluster = init_client_ipc_comms_nodispatch(T_ATTRD); } if(cluster != NULL) { updated = attrd_update(cluster, command, host, name, value, section, set, dampen); } if(updated == 0) { cluster = NULL; sleep(2); max--; } } return updated; } gboolean attrd_update_no_mainloop(int *connection, char command, const char *host, const char *name, const char *value, const char *section, const char *set, const char *dampen) { int max = 5; gboolean updated = FALSE; static IPC_Channel *cluster = NULL; if(connection && *connection == 0 && cluster) { crm_info("Forcing a new connection to the cluster"); cluster = NULL; } while(updated == 0 && max > 0) { if(cluster == NULL) { crm_info("Connecting to cluster... %d retries remaining", max); cluster = init_client_ipc_comms_nodispatch(T_ATTRD); } if(connection) { if(cluster != NULL) { *connection = cluster->ops->get_recv_select_fd(cluster); } else { *connection = 0; } } if(cluster != NULL) { updated = attrd_update(cluster, command, host, name, value, section, set, dampen); } if(updated == 0) { cluster = NULL; sleep(2); max--; } } return updated; } #define FAKE_TE_ID "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" static void append_digest(lrm_op_t *op, xmlNode *update, const char *version, const char *magic, int level) { /* this will enable us to later determine that the * resource's parameters have changed and we should force * a restart */ char *digest = NULL; xmlNode *args_xml = NULL; if(op->params == NULL) { return; } args_xml = create_xml_node(NULL, XML_TAG_PARAMS); g_hash_table_foreach(op->params, hash2field, args_xml); filter_action_parameters(args_xml, version); digest = calculate_operation_digest(args_xml, version); #if 0 if(level < crm_log_level && op->interval == 0 && crm_str_eq(op->op_type, CRMD_ACTION_START, TRUE)) { char *digest_source = dump_xml_unformatted(args_xml); do_crm_log(level, "Calculated digest %s for %s (%s). Source: %s\n", digest, ID(update), magic, digest_source); crm_free(digest_source); } #endif crm_xml_add(update, XML_LRM_ATTR_OP_DIGEST, digest); free_xml(args_xml); crm_free(digest); } xmlNode * create_operation_update( xmlNode *parent, lrm_op_t *op, const char *caller_version, int target_rc, const char *origin, int level) { char *magic = NULL; const char *task = NULL; xmlNode *xml_op = NULL; char *op_id = NULL; char *local_user_data = NULL; gboolean dc_munges_migrate_ops = (compare_version(caller_version, "3.0.3") < 0); CRM_CHECK(op != NULL, return NULL); do_crm_log(level, "%s: Updating resouce %s after %s %s op (interval=%d)", origin, op->rsc_id, op_status2text(op->op_status), op->op_type, op->interval); if(op->op_status == LRM_OP_CANCELLED) { crm_debug_3("Ignoring cancelled op"); return NULL; } crm_debug_3("DC version: %s", caller_version); task = op->op_type; /* remap the task name under various scenarios * this makes life easier for the PE when its trying determin the current state */ if(crm_str_eq(task, "reload", TRUE)) { if(op->op_status == LRM_OP_DONE) { task = CRMD_ACTION_START; } else { task = CRMD_ACTION_STATUS; } } else if(dc_munges_migrate_ops && crm_str_eq(task, CRMD_ACTION_MIGRATE, TRUE)) { /* if the migrate_from fails it will have enough info to do the right thing */ if(op->op_status == LRM_OP_DONE) { task = CRMD_ACTION_STOP; } else { task = CRMD_ACTION_STATUS; } } else if(dc_munges_migrate_ops && op->op_status == LRM_OP_DONE && crm_str_eq(task, CRMD_ACTION_MIGRATED, TRUE)) { task = CRMD_ACTION_START; } else if(crm_str_eq(task, CRMD_ACTION_NOTIFY, TRUE)) { const char *n_type = crm_meta_value(op->params, "notify_type"); const char *n_task = crm_meta_value(op->params, "notify_operation"); CRM_LOG_ASSERT(n_type != NULL); CRM_LOG_ASSERT(n_task != NULL); op_id = generate_notify_key(op->rsc_id, n_type, n_task); /* these are not yet allowed to fail */ op->op_status = LRM_OP_DONE; op->rc = 0; } if (op_id == NULL) { op_id = generate_op_key(op->rsc_id, task, op->interval); } xml_op = find_entity(parent, XML_LRM_TAG_RSC_OP, op_id); if(xml_op != NULL) { crm_log_xml(LOG_DEBUG, "Replacing existing entry", xml_op); } else { xml_op = create_xml_node(parent, XML_LRM_TAG_RSC_OP); } if(op->user_data == NULL) { crm_debug("Generating fake transition key for:" " %s_%s_%d %d from %s", op->rsc_id, op->op_type, op->interval, op->call_id, op->app_name); local_user_data = generate_transition_key(-1, op->call_id, target_rc, FAKE_TE_ID); op->user_data = local_user_data; } magic = generate_transition_magic(op->user_data, op->op_status, op->rc); crm_xml_add(xml_op, XML_ATTR_ID, op_id); crm_xml_add(xml_op, XML_LRM_ATTR_TASK, task); crm_xml_add(xml_op, XML_ATTR_ORIGIN, origin); crm_xml_add(xml_op, XML_ATTR_CRM_VERSION, caller_version); crm_xml_add(xml_op, XML_ATTR_TRANSITION_KEY, op->user_data); crm_xml_add(xml_op, XML_ATTR_TRANSITION_MAGIC, magic); crm_xml_add_int(xml_op, XML_LRM_ATTR_CALLID, op->call_id); crm_xml_add_int(xml_op, XML_LRM_ATTR_RC, op->rc); crm_xml_add_int(xml_op, XML_LRM_ATTR_OPSTATUS, op->op_status); crm_xml_add_int(xml_op, XML_LRM_ATTR_INTERVAL, op->interval); if(compare_version("2.1", caller_version) <= 0) { if(op->t_run || op->t_rcchange || op->exec_time || op->queue_time) { crm_debug_2("Timing data (%s_%s_%d): last=%lu change=%lu exec=%lu queue=%lu", op->rsc_id, op->op_type, op->interval, op->t_run, op->t_rcchange, op->exec_time, op->queue_time); crm_xml_add_int(xml_op, "last-run", op->t_run); crm_xml_add_int(xml_op, "last-rc-change", op->t_rcchange); crm_xml_add_int(xml_op, "exec-time", op->exec_time); crm_xml_add_int(xml_op, "queue-time", op->queue_time); } } if(crm_str_eq(op->op_type, CRMD_ACTION_MIGRATE, TRUE) || crm_str_eq(op->op_type, CRMD_ACTION_MIGRATED, TRUE)) { /* * Record migrate_source and migrate_target always for migrate ops. */ const char *name = XML_LRM_ATTR_MIGRATE_SOURCE; crm_xml_add(xml_op, name, crm_meta_value(op->params, name)); name = XML_LRM_ATTR_MIGRATE_TARGET; crm_xml_add(xml_op, name, crm_meta_value(op->params, name)); } append_digest(op, xml_op, caller_version, magic, LOG_DEBUG); if(local_user_data) { crm_free(local_user_data); op->user_data = NULL; } crm_free(magic); crm_free(op_id); return xml_op; } void free_lrm_op(lrm_op_t *op) { - g_hash_table_destroy(op->params); - crm_free(op->user_data); - crm_free(op->output); - crm_free(op->rsc_id); - crm_free(op->op_type); - crm_free(op->app_name); - crm_free(op); + g_hash_table_destroy(op->params); + crm_free(op->user_data); + crm_free(op->output); + crm_free(op->rsc_id); + crm_free(op->op_type); + crm_free(op->app_name); + crm_free(op); } diff --git a/tools/crm_verify.c b/tools/crm_verify.c index fa92a06709..deeeee5746 100644 --- a/tools/crm_verify.c +++ b/tools/crm_verify.c @@ -1,302 +1,291 @@ /* * Copyright (C) 2004 Andrew Beekhof * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include gboolean USE_LIVE_CIB = FALSE; char *cib_save = NULL; void usage(const char *cmd, int exit_status); extern gboolean stage0(pe_working_set_t *data_set); extern void cleanup_alloc_calculations(pe_working_set_t *data_set); extern xmlNode * do_calculations( pe_working_set_t *data_set, xmlNode *xml_input, ha_time_t *now); static struct crm_option long_options[] = { /* Top-level Options */ {"help", 0, 0, '?', "\tThis text"}, {"version", 0, 0, '$', "\tVersion information" }, {"verbose", 0, 0, 'V', "\tIncrease debug output\n"}, {"-spacer-", 1, 0, '-', "\nData sources:"}, {"live-check", 0, 0, 'L', "Check the configuration used by the running cluster\n"}, {"xml-file", 1, 0, 'x', "Check the configuration in the named file"}, {"xml-text", 1, 0, 'X', "Check the configuration in the supplied string"}, {"xml-pipe", 0, 0, 'p', "Check the configuration piped in via stdin"}, {"-spacer-", 1, 0, '-', "\nAdditional Options:"}, {"save-xml", 1, 0, 'S', "Save the verified XML to the named file. Most useful with -L"}, {"-spacer-", 1, 0, '-', "\nExamples:", pcmk_option_paragraph}, {"-spacer-", 1, 0, '-', "Check the consistency of the configuration in the running cluster:", pcmk_option_paragraph}, {"-spacer-", 1, 0, '-', " crm_verify --live-check", pcmk_option_example}, {"-spacer-", 1, 0, '-', "Check the consistency of the configuration in a given file and produce verbose output:", pcmk_option_paragraph}, {"-spacer-", 1, 0, '-', " crm_verify --xml-file file.xml --verbose", pcmk_option_example}, {F_CRM_DATA, 1, 0, 'X', NULL, 1}, /* legacy */ {0, 0, 0, 0} }; int main(int argc, char **argv) { xmlNode *cib_object = NULL; xmlNode *status = NULL; int argerr = 0; int flag; int option_index = 0; pe_working_set_t data_set; cib_t * cib_conn = NULL; int rc = cib_ok; gboolean xml_stdin = FALSE; const char *xml_tag = NULL; const char *xml_file = NULL; const char *xml_string = NULL; g_log_set_handler(NULL, G_LOG_LEVEL_ERROR | G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING | G_LOG_LEVEL_MESSAGE | G_LOG_LEVEL_INFO | G_LOG_LEVEL_DEBUG | G_LOG_FLAG_RECURSION | G_LOG_FLAG_FATAL, cl_glib_msg_handler, NULL); /* and for good measure... - this enum is a bit field (!) */ g_log_set_always_fatal((GLogLevelFlags)0); /*value out of range*/ crm_log_init_quiet(NULL, LOG_ERR, FALSE, TRUE, argc, argv); crm_set_options("V?$X:x:pLS:", "[modifiers] data_source", long_options, "Check a (complete) confiuration for syntax and common conceptual errors." "\n\nChecks the well-formedness of an XML configuration, its conformance to the configured DTD/schema and for the presence of common misconfigurations." "\n\nIt reports two classes of problems, errors and warnings." " Errors must be fixed before the cluster will work properly." " However, it is left up to the administrator to decide if the warnings should also be fixed."); while (1) { flag = crm_get_option(argc, argv, &option_index); if (flag == -1) break; switch(flag) { #ifdef HAVE_GETOPT_H case 0: printf("option %s", long_options[option_index].name); if (optarg) printf(" with arg %s", optarg); printf("\n"); break; #endif case 'X': crm_debug_2("Option %c => %s", flag, optarg); xml_string = crm_strdup(optarg); break; case 'x': crm_debug_2("Option %c => %s", flag, optarg); xml_file = crm_strdup(optarg); break; case 'p': xml_stdin = TRUE; break; case 'S': cib_save = crm_strdup(optarg); break; case 'V': alter_debug(DEBUG_INC); break; case 'L': USE_LIVE_CIB = TRUE; break; case '$': case '?': crm_help(flag, LSB_EXIT_OK); break; default: fprintf(stderr, "Option -%c is not yet supported\n", flag); ++argerr; break; } } if (optind < argc) { printf("non-option ARGV-elements: "); while (optind < argc) { printf("%s ", argv[optind++]); } printf("\n"); } if (optind > argc) { ++argerr; } if (argerr) { crm_err("%d errors in option parsing", argerr); crm_help(flag, LSB_EXIT_GENERIC); } crm_info("=#=#=#=#= Getting XML =#=#=#=#="); if(USE_LIVE_CIB) { cib_conn = cib_new(); rc = cib_conn->cmds->signon(cib_conn, crm_system_name, cib_command); } if(USE_LIVE_CIB) { if(rc == cib_ok) { int options = cib_scope_local|cib_sync_call; crm_info("Reading XML from: live cluster"); rc = cib_conn->cmds->query( cib_conn, NULL, &cib_object, options); } if(rc != cib_ok) { fprintf(stderr, "Live CIB query failed: %s\n", cib_error2string(rc)); return 3; } if(cib_object == NULL) { fprintf(stderr, "Live CIB query failed: empty result\n"); return 3; } } else if(xml_file != NULL) { cib_object = filename2xml(xml_file); if(cib_object == NULL) { fprintf(stderr, "Couldn't parse input file: %s\n", xml_file); return 4; } } else if(xml_string != NULL) { cib_object = string2xml(xml_string); if(cib_object == NULL) { fprintf(stderr, "Couldn't parse input string: %s\n", xml_string); return 4; } } else if(xml_stdin) { cib_object = stdin2xml(); if(cib_object == NULL) { fprintf(stderr, "Couldn't parse input from STDIN.\n"); return 4; } } else { fprintf(stderr, "No configuration source specified." " Use --help for usage information.\n"); return 5; } xml_tag = crm_element_name(cib_object); if(safe_str_neq(xml_tag, XML_TAG_CIB)) { fprintf(stderr, "This tool can only check complete configurations (ie. those starting with ).\n"); return 6; } if(cib_save != NULL) { write_xml_file(cib_object, cib_save, FALSE); } status = get_object_root(XML_CIB_TAG_STATUS, cib_object); if(status == NULL) { create_xml_node(cib_object, XML_CIB_TAG_STATUS); } -#if CRM_DEPRECATED_SINCE_2_0_4 - { - xmlNode *node_state = NULL; - for(node_state = status; node_state != NULL; node_state = node_state->next) { - if(crm_str_eq((const char *)node_state->name, XML_CIB_TAG_STATE, TRUE)) { - xml_remove_prop(node_state, XML_CIB_TAG_LRM); - } - } - } -#endif - if(validate_xml(cib_object, NULL, FALSE) == FALSE) { crm_config_err("CIB did not pass DTD/schema validation"); free_xml(cib_object); cib_object = NULL; } else if(cli_config_update(&cib_object, NULL, FALSE) == FALSE) { crm_config_error = TRUE; free_xml(cib_object); cib_object = NULL; fprintf(stderr, "The cluster will NOT be able to use this configuration.\n"); fprintf(stderr, "Please manually update the configuration to conform to the %s syntax.\n", LATEST_SCHEMA_VERSION); } set_working_set_defaults(&data_set); if(cib_object == NULL) { } else if(USE_LIVE_CIB) { /* we will always have a status section and can do a full simulation */ do_calculations(&data_set, cib_object, NULL); cleanup_alloc_calculations(&data_set); } else { data_set.now = new_ha_date(TRUE); data_set.input = cib_object; stage0(&data_set); cleanup_alloc_calculations(&data_set); } if(crm_config_error) { fprintf(stderr, "Errors found during check: config not valid\n"); if(crm_log_level < LOG_WARNING) { fprintf(stderr, " -V may provide more details\n"); } rc = 2; } else if(crm_config_warning) { fprintf(stderr, "Warnings found during check: config may not be valid\n"); if(crm_log_level < LOG_WARNING) { fprintf(stderr, " Use -V for more details\n"); } rc = 1; } if(USE_LIVE_CIB) { cib_conn->cmds->signoff(cib_conn); cib_delete(cib_conn); } return rc; }