enum cib_errors cib_process_modify(const char *op, int options, const char *section, xmlNode * req, xmlNode * input, xmlNode * existing_cib, xmlNode ** result_cib, xmlNode ** answer) { xmlNode *obj_root = NULL; crm_debug_2("Processing \"%s\" event", op); if (options & cib_xpath) { return cib_process_xpath(op, options, section, req, input, existing_cib, result_cib, answer); } if (input == NULL) { crm_err("Cannot perform modification with no data"); return cib_NOOBJECT; } obj_root = get_object_root(section, *result_cib); crm_validate_data(input); crm_validate_data(*result_cib); if (obj_root == NULL) { xmlNode *tmp_section = NULL; const char *path = get_object_parent(section); if (path == NULL) { return cib_bad_section; } tmp_section = create_xml_node(NULL, section); cib_process_xpath(CIB_OP_CREATE, 0, path, NULL, tmp_section, NULL, result_cib, answer); free_xml(tmp_section); obj_root = get_object_root(section, *result_cib); } CRM_CHECK(obj_root != NULL, return cib_unknown); if (update_xml_child(obj_root, input) == FALSE) { if (options & cib_can_create) { add_node_copy(obj_root, input); } else { return cib_NOTEXISTS; } } return cib_ok; }
enum cib_errors updateList(crm_data_t *local_cib, crm_data_t *xml_section, crm_data_t *failed, int operation, const char *section) { int rc = cib_ok; crm_data_t *this_section = get_object_root(section, local_cib); if (section == NULL || xml_section == NULL) { crm_err("Section %s not found in message." " CIB update is corrupt, ignoring.", crm_str(section)); return cib_NOSECTION; } if((CIB_UPDATE_OP_NONE > operation) || (operation > CIB_UPDATE_OP_MAX)){ crm_err("Invalid operation on section %s", crm_str(section)); return cib_operation; } if(safe_str_eq(crm_element_name(xml_section), section)) { xml_child_iter(xml_section, a_child, rc = cib_ok; cib_update_xml_macro(this_section, a_child); ); } else {
int do_find_node_list(xmlNode * xml_node) { int found = 0; xmlNode *node = NULL; xmlNode *nodes = get_object_root(XML_CIB_TAG_NODES, xml_node); for (node = __xml_first_child(nodes); node != NULL; node = __xml_next(node)) { if (crm_str_eq((const char *)node->name, XML_CIB_TAG_NODE, TRUE)) { if (BASH_EXPORT) { printf("export %s=%s\n", crm_element_value(node, XML_ATTR_UNAME), crm_element_value(node, XML_ATTR_ID)); } else { printf("%s node: %s (%s)\n", crm_element_value(node, XML_ATTR_TYPE), crm_element_value(node, XML_ATTR_UNAME), crm_element_value(node, XML_ATTR_ID)); } found++; } } if (found == 0) { printf("NO nodes configured\n"); } return found; }
enum cib_errors cib_process_query( const char *op, int options, const char *section, crm_data_t *input, crm_data_t *existing_cib, crm_data_t **result_cib, crm_data_t **answer) { crm_data_t *obj_root = NULL; enum cib_errors result = cib_ok; crm_debug_2("Processing \"%s\" event for section=%s", op, crm_str(section)); CRM_CHECK(*answer == NULL, free_xml(*answer)); *answer = NULL; if (safe_str_eq(XML_CIB_TAG_SECTION_ALL, section)) { section = NULL; } obj_root = get_object_root(section, existing_cib); if(obj_root == NULL) { result = cib_NOTEXISTS; } else { *answer = obj_root; } if(result == cib_ok && *answer == NULL) { crm_err("Error creating query response"); result = cib_output_data; } return result; }
int do_work(xmlNode * input, int call_options, xmlNode ** output) { /* construct the request */ the_cib->call_timeout = message_timeout_ms; if (strcasecmp(CIB_OP_REPLACE, cib_action) == 0 && safe_str_eq(crm_element_name(input), XML_TAG_CIB)) { xmlNode *status = get_object_root(XML_CIB_TAG_STATUS, input); if (status == NULL) { create_xml_node(input, XML_CIB_TAG_STATUS); } } if (strcasecmp(CIB_OP_SYNC, cib_action) == 0) { crm_trace("Performing %s op...", cib_action); return the_cib->cmds->sync_from(the_cib, host, obj_type, call_options); } else if (strcasecmp(CIB_OP_SLAVE, cib_action) == 0 && (call_options ^ cib_scope_local)) { crm_trace("Performing %s op on all nodes...", cib_action); return the_cib->cmds->set_slave_all(the_cib, call_options); } else if (strcasecmp(CIB_OP_MASTER, cib_action) == 0) { crm_trace("Performing %s op on all nodes...", cib_action); return the_cib->cmds->set_master(the_cib, call_options); } else if (cib_action != NULL) { crm_trace("Passing \"%s\" to variant_op...", cib_action); return cib_internal_op(the_cib, cib_action, host, obj_type, input, output, call_options, NULL); } else { crm_err("You must specify an operation"); } return -EINVAL; }
enum cib_errors cib_process_delete(const char *op, int options, const char *section, xmlNode * req, xmlNode * input, xmlNode * existing_cib, xmlNode ** result_cib, xmlNode ** answer) { xmlNode *obj_root = NULL; crm_debug_2("Processing \"%s\" event", op); if (options & cib_xpath) { return cib_process_xpath(op, options, section, req, input, existing_cib, result_cib, answer); } if (input == NULL) { crm_err("Cannot perform modification with no data"); return cib_NOOBJECT; } obj_root = get_object_root(section, *result_cib); crm_validate_data(input); crm_validate_data(*result_cib); if (replace_xml_child(NULL, obj_root, input, TRUE) == FALSE) { crm_debug_2("No matching object to delete"); } return cib_ok; }
int cib_process_delete(const char *op, int options, const char *section, xmlNode * req, xmlNode * input, xmlNode * existing_cib, xmlNode ** result_cib, xmlNode ** answer) { xmlNode *obj_root = NULL; crm_trace("Processing \"%s\" event", op); if (options & cib_xpath) { return cib_process_xpath(op, options, section, req, input, existing_cib, result_cib, answer); } if (input == NULL) { crm_err("Cannot perform modification with no data"); return -EINVAL; } obj_root = get_object_root(section, *result_cib); if(safe_str_eq(crm_element_name(input), section)) { xmlNode *child = NULL; for(child = __xml_first_child(input); child; child = __xml_next(child)) { if (replace_xml_child(NULL, obj_root, child, TRUE) == FALSE) { crm_trace("No matching object to delete: %s=%s", child->name, ID(child)); } } } else if (replace_xml_child(NULL, obj_root, input, TRUE) == FALSE) { crm_trace("No matching object to delete: %s=%s", input->name, ID(input)); } return pcmk_ok; }
static xmlNode * cib_prepare_common(xmlNode * root, const char *section) { xmlNode *data = NULL; /* extract the CIB from the fragment */ if (root == NULL) { return NULL; } else if (safe_str_eq(crm_element_name(root), XML_TAG_FRAGMENT) || safe_str_eq(crm_element_name(root), F_CRM_DATA) || safe_str_eq(crm_element_name(root), F_CIB_CALLDATA)) { data = first_named_child(root, XML_TAG_CIB); } else { data = root; } /* grab the section specified for the command */ if (section != NULL && data != NULL && crm_str_eq(crm_element_name(data), XML_TAG_CIB, TRUE)) { data = get_object_root(section, data); } /* crm_log_xml_trace(root, "cib:input"); */ return data; }
/* * Unpack everything * At the end you'll have: * - A list of nodes * - A list of resources (each with any dependencies on other resources) * - A list of constraints between resources and nodes * - A list of constraints between start/stop actions * - A list of nodes that need to be stonith'd * - A list of nodes that need to be shutdown * - A list of the possible stop/start actions (without dependencies) */ gboolean cluster_status(pe_working_set_t * data_set) { xmlNode *config = get_object_root(XML_CIB_TAG_CRMCONFIG, data_set->input); xmlNode *cib_nodes = get_object_root(XML_CIB_TAG_NODES, data_set->input); xmlNode *cib_resources = get_object_root(XML_CIB_TAG_RESOURCES, data_set->input); xmlNode *cib_status = get_object_root(XML_CIB_TAG_STATUS, data_set->input); xmlNode *cib_domains = get_object_root(XML_CIB_TAG_DOMAINS, data_set->input); const char *value = crm_element_value(data_set->input, XML_ATTR_HAVE_QUORUM); crm_trace("Beginning unpack"); pe_dataset = data_set; /* reset remaining global variables */ data_set->failed = create_xml_node(NULL, "failed-ops"); if (data_set->input == NULL) { return FALSE; } if (data_set->now == NULL) { data_set->now = crm_time_new(NULL); } if (data_set->input != NULL && crm_element_value(data_set->input, XML_ATTR_DC_UUID) != NULL) { /* this should always be present */ data_set->dc_uuid = crm_element_value_copy(data_set->input, XML_ATTR_DC_UUID); } clear_bit(data_set->flags, pe_flag_have_quorum); if (crm_is_true(value)) { set_bit(data_set->flags, pe_flag_have_quorum); } data_set->op_defaults = get_object_root(XML_CIB_TAG_OPCONFIG, data_set->input); data_set->rsc_defaults = get_object_root(XML_CIB_TAG_RSCCONFIG, data_set->input); unpack_config(config, data_set); if (is_set(data_set->flags, pe_flag_have_quorum) == FALSE && data_set->no_quorum_policy != no_quorum_ignore) { crm_warn("We do not have quorum" " - fencing and resource management disabled"); } unpack_nodes(cib_nodes, data_set); unpack_domains(cib_domains, data_set); unpack_remote_nodes(cib_resources, data_set); unpack_resources(cib_resources, data_set); unpack_status(cib_status, data_set); set_bit(data_set->flags, pe_flag_have_status); return TRUE; }
int cib_process_delete_absolute(const char *op, int options, const char *section, xmlNode * req, xmlNode * input, xmlNode * existing_cib, xmlNode ** result_cib, xmlNode ** answer) { xmlNode *failed = NULL; int result = pcmk_ok; xmlNode *update_section = NULL; crm_trace("Processing \"%s\" event for section=%s", op, crm_str(section)); if (safe_str_eq(XML_CIB_TAG_SECTION_ALL, section)) { section = NULL; } else if (safe_str_eq(XML_TAG_CIB, section)) { section = NULL; } else if (safe_str_eq(crm_element_name(input), XML_TAG_CIB)) { section = NULL; } CRM_CHECK(strcasecmp(CIB_OP_DELETE, op) == 0, return -EINVAL); if (input == NULL) { crm_err("Cannot perform modification with no data"); return -EINVAL; } failed = create_xml_node(NULL, XML_TAG_FAILED); update_section = get_object_root(section, *result_cib); result = delete_cib_object(update_section, input); update_results(failed, input, op, result); if (xml_has_children(failed)) { CRM_CHECK(result != pcmk_ok, result = -EINVAL); } if (result != pcmk_ok) { crm_log_xml_err(failed, "CIB Update failures"); *answer = failed; } else { free_xml(failed); } return result; }
int cib_process_query(const char *op, int options, const char *section, xmlNode * req, xmlNode * input, xmlNode * existing_cib, xmlNode ** result_cib, xmlNode ** answer) { xmlNode *obj_root = NULL; int result = pcmk_ok; crm_trace("Processing \"%s\" event for section=%s", op, crm_str(section)); if (options & cib_xpath) { return cib_process_xpath(op, options, section, req, input, existing_cib, result_cib, answer); } CRM_CHECK(*answer == NULL, free_xml(*answer)); *answer = NULL; if (safe_str_eq(XML_CIB_TAG_SECTION_ALL, section)) { section = NULL; } obj_root = get_object_root(section, existing_cib); if (obj_root == NULL) { result = -ENXIO; } else if (options & cib_no_children) { const char *tag = TYPE(obj_root); xmlNode *shallow = create_xml_node(*answer, tag); copy_in_properties(shallow, obj_root); *answer = shallow; } else { *answer = obj_root; } if (result == pcmk_ok && *answer == NULL) { crm_err("Error creating query response"); result = -ENOMSG; } return result; }
static GListPtr build_constraint_list(xmlNode *root) { GListPtr retval = NULL; xmlNode *cib_constraints = NULL; xmlXPathObjectPtr xpathObj = NULL; int ndx = 0; cib_constraints = get_object_root(XML_CIB_TAG_CONSTRAINTS, root); xpathObj = xpath_search(cib_constraints, "//" XML_CONS_TAG_RSC_LOCATION); for (ndx = 0; ndx < numXpathResults(xpathObj); ndx++) { xmlNode *match = getXpathResult(xpathObj, ndx); retval = g_list_insert_sorted(retval, (gpointer) ID(match), compare_id); } freeXpathObject(xpathObj); return retval; }
int do_work(xmlNode * input, int call_options, xmlNode ** output) { /* construct the request */ the_cib->call_timeout = message_timeout_ms; if (strcasecmp(CIB_OP_REPLACE, cib_action) == 0 && safe_str_eq(crm_element_name(input), XML_TAG_CIB)) { xmlNode *status = get_object_root(XML_CIB_TAG_STATUS, input); if (status == NULL) { create_xml_node(input, XML_CIB_TAG_STATUS); } } if (cib_action != NULL) { crm_trace("Passing \"%s\" to variant_op...", cib_action); return cib_internal_op(the_cib, cib_action, host, obj_type, input, output, call_options, cib_user); } else { crm_err("You must specify an operation"); } return -EINVAL; }
void cli_resource_print_cts_constraints(pe_working_set_t * data_set) { xmlNode *xml_obj = NULL; xmlNode *lifetime = NULL; xmlNode *cib_constraints = get_object_root(XML_CIB_TAG_CONSTRAINTS, data_set->input); for (xml_obj = __xml_first_child(cib_constraints); xml_obj != NULL; xml_obj = __xml_next(xml_obj)) { const char *id = crm_element_value(xml_obj, XML_ATTR_ID); if (id == NULL) { continue; } lifetime = first_named_child(xml_obj, "lifetime"); if (test_ruleset(lifetime, NULL, data_set->now) == FALSE) { continue; } if (safe_str_eq(XML_CONS_TAG_RSC_DEPEND, crm_element_name(xml_obj))) { printf("Constraint %s %s %s %s %s %s %s\n", crm_element_name(xml_obj), cons_string(crm_element_value(xml_obj, XML_ATTR_ID)), cons_string(crm_element_value(xml_obj, XML_COLOC_ATTR_SOURCE)), cons_string(crm_element_value(xml_obj, XML_COLOC_ATTR_TARGET)), cons_string(crm_element_value(xml_obj, XML_RULE_ATTR_SCORE)), cons_string(crm_element_value(xml_obj, XML_COLOC_ATTR_SOURCE_ROLE)), cons_string(crm_element_value(xml_obj, XML_COLOC_ATTR_TARGET_ROLE))); } else if (safe_str_eq(XML_CONS_TAG_RSC_LOCATION, crm_element_name(xml_obj))) { /* unpack_location(xml_obj, data_set); */ } } }
enum cib_errors cib_process_modify( const char *op, int options, const char *section, crm_data_t *input, crm_data_t *existing_cib, crm_data_t **result_cib, crm_data_t **answer) { crm_data_t *obj_root = NULL; crm_debug_2("Processing \"%s\" event", op); if(input == NULL) { crm_err("Cannot perform modification with no data"); return cib_NOOBJECT; } obj_root = get_object_root(section, *result_cib); crm_validate_data(input); crm_validate_data(*result_cib); if(update_xml_child(obj_root, input) == FALSE) { return cib_NOTEXISTS; } return cib_ok; }
int cli_resource_clear_all_expired(xmlNode *root, cib_t *cib_conn, const char *rsc, const char *node, bool scope_master) { xmlXPathObject *xpathObj = NULL; xmlNode *cib_constraints = NULL; crm_time_t *now = crm_time_new(NULL); int i; int rc = pcmk_ok; cib_constraints = get_object_root(XML_CIB_TAG_CONSTRAINTS, root); xpathObj = xpath_search(cib_constraints, "//" XML_CONS_TAG_RSC_LOCATION); for (i = 0; i < numXpathResults(xpathObj); i++) { xmlNode *constraint_node = getXpathResult(xpathObj, i); xmlNode *date_expr_node = NULL; crm_time_t *end = NULL; char *xpath_string = NULL; xpath_string = build_clear_xpath_string(constraint_node, rsc, node, scope_master); if (xpath_string == NULL) { continue; } date_expr_node = get_xpath_object(xpath_string, constraint_node, LOG_DEBUG); if (date_expr_node == NULL) { free(xpath_string); continue; } /* And then finally, see if the date expression is expired. If so, * clear the constraint. */ end = crm_time_new(crm_element_value(date_expr_node, "end")); if (crm_time_compare(now, end) == 1) { xmlNode *fragment = NULL; xmlNode *location = NULL; fragment = create_xml_node(NULL, XML_CIB_TAG_CONSTRAINTS); location = create_xml_node(fragment, XML_CONS_TAG_RSC_LOCATION); crm_xml_set_id(location, "%s", ID(constraint_node)); crm_log_xml_info(fragment, "Delete"); rc = cib_conn->cmds->remove(cib_conn, XML_CIB_TAG_CONSTRAINTS, fragment, cib_options); if (rc != pcmk_ok) { free(xpath_string); goto bail; } free_xml(fragment); } crm_time_free(end); free(xpath_string); } rc = pcmk_ok; bail: freeXpathObject(xpathObj); crm_time_free(now); return rc; }
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 = pcmk_ok; bool verbose = FALSE; gboolean xml_stdin = FALSE; const char *xml_tag = NULL; const char *xml_file = NULL; const char *xml_string = NULL; crm_log_cli_init("crm_verify"); crm_set_options(NULL, "[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) { case 'X': crm_trace("Option %c => %s", flag, optarg); xml_string = optarg; break; case 'x': crm_trace("Option %c => %s", flag, optarg); xml_file = optarg; break; case 'p': xml_stdin = TRUE; break; case 'S': cib_save = optarg; break; case 'V': verbose = TRUE; crm_bump_log_level(argc, argv); break; case 'L': USE_LIVE_CIB = TRUE; break; case '$': case '?': crm_help(flag, EX_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, EX_USAGE); } 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 == pcmk_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 != pcmk_ok) { fprintf(stderr, "Live CIB query failed: %s\n", pcmk_strerror(rc)); goto done; } if (cib_object == NULL) { fprintf(stderr, "Live CIB query failed: empty result\n"); rc = -ENOMSG; goto done; } } 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); rc = -ENODATA; goto done; } } 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); rc = -ENODATA; goto done; } } else if (xml_stdin) { cib_object = stdin2xml(); if (cib_object == NULL) { fprintf(stderr, "Couldn't parse input from STDIN.\n"); rc = -ENODATA; goto done; } } else { fprintf(stderr, "No configuration source specified." " Use --help for usage information.\n"); rc = -ENODATA; goto done; } 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 <cib>).\n"); rc = -EBADMSG; goto done; } 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 (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", xml_latest_schema()); } 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 = crm_time_new(NULL); 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 (verbose == FALSE) { fprintf(stderr, " -V may provide more details\n"); } rc = -pcmk_err_generic; } else if (crm_config_warning) { fprintf(stderr, "Warnings found during check: config may not be valid\n"); if (verbose == FALSE) { fprintf(stderr, " Use -V for more details\n"); } rc = -pcmk_err_generic; } if (USE_LIVE_CIB && cib_conn) { cib_conn->cmds->signoff(cib_conn); cib_delete(cib_conn); } done: return rc; }
int cib_process_modify(const char *op, int options, const char *section, xmlNode * req, xmlNode * input, xmlNode * existing_cib, xmlNode ** result_cib, xmlNode ** answer) { xmlNode *obj_root = NULL; crm_trace("Processing \"%s\" event", op); if (options & cib_xpath) { return cib_process_xpath(op, options, section, req, input, existing_cib, result_cib, answer); } if (input == NULL) { crm_err("Cannot perform modification with no data"); return -EINVAL; } obj_root = get_object_root(section, *result_cib); if (obj_root == NULL) { xmlNode *tmp_section = NULL; const char *path = get_object_parent(section); if (path == NULL) { return -EINVAL; } tmp_section = create_xml_node(NULL, section); cib_process_xpath(CIB_OP_CREATE, 0, path, NULL, tmp_section, NULL, result_cib, answer); free_xml(tmp_section); obj_root = get_object_root(section, *result_cib); } CRM_CHECK(obj_root != NULL, return -EINVAL); if (update_xml_child(obj_root, input) == FALSE) { if (options & cib_can_create) { add_node_copy(obj_root, input); } else { return -ENXIO; } } if(options & cib_mixed_update) { int max = 0, lpc; xmlXPathObjectPtr xpathObj = xpath_search(*result_cib, "//@__delete__"); if (xpathObj) { max = numXpathResults(xpathObj); crm_log_xml_trace(*result_cib, "Mixed result"); } for (lpc = 0; lpc < max; lpc++) { xmlNode *match = getXpathResult(xpathObj, lpc); xmlChar *match_path = xmlGetNodePath(match); crm_debug("Destroying %s", match_path); free(match_path); free_xml(match); } freeXpathObject(xpathObj); } return pcmk_ok; }
int main(int argc, char **argv) { char rsc_cmd = 'L'; const char *v_class = NULL; const char *v_agent = NULL; const char *v_provider = NULL; char *name = NULL; char *value = NULL; GHashTable *validate_options = NULL; const char *rsc_id = NULL; const char *host_uname = NULL; const char *prop_name = NULL; const char *prop_value = NULL; const char *rsc_type = NULL; const char *prop_id = NULL; const char *prop_set = NULL; const char *rsc_long_cmd = NULL; const char *longname = NULL; const char *operation = NULL; const char *interval_spec = NULL; const char *cib_file = getenv("CIB_file"); GHashTable *override_params = NULL; char *xml_file = NULL; crm_ipc_t *crmd_channel = NULL; pe_working_set_t *data_set = NULL; xmlNode *cib_xml_copy = NULL; cib_t *cib_conn = NULL; resource_t *rsc = NULL; bool recursive = FALSE; char *our_pid = NULL; bool validate_cmdline = FALSE; /* whether we are just validating based on command line options */ bool require_resource = TRUE; /* whether command requires that resource be specified */ bool require_dataset = TRUE; /* whether command requires populated dataset instance */ bool require_crmd = FALSE; // whether command requires controller connection bool clear_expired = FALSE; int rc = pcmk_ok; int is_ocf_rc = 0; int option_index = 0; int timeout_ms = 0; int argerr = 0; int flag; int find_flags = 0; // Flags to use when searching for resource crm_exit_t exit_code = CRM_EX_OK; crm_log_cli_init("crm_resource"); crm_set_options(NULL, "(query|command) [options]", long_options, "Perform tasks related to cluster resources.\nAllows resources to be queried (definition and location), modified, and moved around the cluster.\n"); validate_options = crm_str_table_new(); while (1) { flag = crm_get_option_long(argc, argv, &option_index, &longname); if (flag == -1) break; switch (flag) { case 0: /* long options with no short equivalent */ if (safe_str_eq("master", longname)) { scope_master = TRUE; } else if(safe_str_eq(longname, "recursive")) { recursive = TRUE; } else if (safe_str_eq("wait", longname)) { rsc_cmd = flag; rsc_long_cmd = longname; require_resource = FALSE; require_dataset = FALSE; } else if ( safe_str_eq("validate", longname) || safe_str_eq("restart", longname) || safe_str_eq("force-demote", longname) || safe_str_eq("force-stop", longname) || safe_str_eq("force-start", longname) || safe_str_eq("force-promote", longname) || safe_str_eq("force-check", longname)) { rsc_cmd = flag; rsc_long_cmd = longname; find_flags = pe_find_renamed|pe_find_anon; crm_log_args(argc, argv); } else if (safe_str_eq("list-ocf-providers", longname) || safe_str_eq("list-ocf-alternatives", longname) || safe_str_eq("list-standards", longname)) { const char *text = NULL; lrmd_list_t *list = NULL; lrmd_list_t *iter = NULL; lrmd_t *lrmd_conn = lrmd_api_new(); if (safe_str_eq("list-ocf-providers", longname) || safe_str_eq("list-ocf-alternatives", longname)) { rc = lrmd_conn->cmds->list_ocf_providers(lrmd_conn, optarg, &list); text = "OCF providers"; } else if (safe_str_eq("list-standards", longname)) { rc = lrmd_conn->cmds->list_standards(lrmd_conn, &list); text = "standards"; } if (rc > 0) { for (iter = list; iter != NULL; iter = iter->next) { printf("%s\n", iter->val); } lrmd_list_freeall(list); } else if (optarg) { fprintf(stderr, "No %s found for %s\n", text, optarg); exit_code = CRM_EX_NOSUCH; } else { fprintf(stderr, "No %s found\n", text); exit_code = CRM_EX_NOSUCH; } lrmd_api_delete(lrmd_conn); crm_exit(exit_code); } else if (safe_str_eq("show-metadata", longname)) { char *standard = NULL; char *provider = NULL; char *type = NULL; char *metadata = NULL; lrmd_t *lrmd_conn = lrmd_api_new(); rc = crm_parse_agent_spec(optarg, &standard, &provider, &type); if (rc == pcmk_ok) { rc = lrmd_conn->cmds->get_metadata(lrmd_conn, standard, provider, type, &metadata, 0); } else { fprintf(stderr, "'%s' is not a valid agent specification\n", optarg); rc = -ENXIO; } if (metadata) { printf("%s\n", metadata); } else { fprintf(stderr, "Metadata query for %s failed: %s\n", optarg, pcmk_strerror(rc)); exit_code = crm_errno2exit(rc); } lrmd_api_delete(lrmd_conn); crm_exit(exit_code); } else if (safe_str_eq("list-agents", longname)) { lrmd_list_t *list = NULL; lrmd_list_t *iter = NULL; char *provider = strchr (optarg, ':'); lrmd_t *lrmd_conn = lrmd_api_new(); if (provider) { *provider++ = 0; } rc = lrmd_conn->cmds->list_agents(lrmd_conn, &list, optarg, provider); if (rc > 0) { for (iter = list; iter != NULL; iter = iter->next) { printf("%s\n", iter->val); } lrmd_list_freeall(list); } else { fprintf(stderr, "No agents found for standard=%s, provider=%s\n", optarg, (provider? provider : "*")); exit_code = CRM_EX_NOSUCH; } lrmd_api_delete(lrmd_conn); crm_exit(exit_code); } else if (safe_str_eq("class", longname)) { if (!(pcmk_get_ra_caps(optarg) & pcmk_ra_cap_params)) { if (BE_QUIET == FALSE) { fprintf(stdout, "Standard %s does not support parameters\n", optarg); } crm_exit(exit_code); } else { v_class = optarg; } validate_cmdline = TRUE; require_resource = FALSE; } else if (safe_str_eq("agent", longname)) { validate_cmdline = TRUE; require_resource = FALSE; v_agent = optarg; } else if (safe_str_eq("provider", longname)) { validate_cmdline = TRUE; require_resource = FALSE; v_provider = optarg; } else if (safe_str_eq("option", longname)) { crm_info("Scanning: --option %s", optarg); rc = pcmk_scan_nvpair(optarg, &name, &value); if (rc != 2) { fprintf(stderr, "Invalid option: --option %s: %s", optarg, pcmk_strerror(rc)); argerr++; } else { crm_info("Got: '%s'='%s'", name, value); } g_hash_table_replace(validate_options, name, value); } else { crm_err("Unhandled long option: %s", longname); } break; case 'V': resource_verbose++; crm_bump_log_level(argc, argv); break; case '$': case '?': crm_help(flag, CRM_EX_OK); break; case 'x': xml_file = strdup(optarg); break; case 'Q': BE_QUIET = TRUE; break; case 'm': attr_set_type = XML_TAG_META_SETS; break; case 'z': attr_set_type = XML_TAG_UTILIZATION; break; case 'u': move_lifetime = strdup(optarg); break; case 'f': do_force = TRUE; crm_log_args(argc, argv); break; case 'i': prop_id = optarg; break; case 's': prop_set = optarg; break; case 'r': rsc_id = optarg; break; case 'v': prop_value = optarg; break; case 't': rsc_type = optarg; break; case 'T': timeout_ms = crm_get_msec(optarg); break; case 'e': clear_expired = TRUE; require_resource = FALSE; break; case 'C': case 'R': crm_log_args(argc, argv); require_resource = FALSE; if (cib_file == NULL) { require_crmd = TRUE; } rsc_cmd = flag; find_flags = pe_find_renamed|pe_find_anon; break; case 'n': operation = optarg; break; case 'I': interval_spec = optarg; break; case 'D': require_dataset = FALSE; crm_log_args(argc, argv); rsc_cmd = flag; find_flags = pe_find_renamed|pe_find_any; break; case 'F': require_crmd = TRUE; crm_log_args(argc, argv); rsc_cmd = flag; break; case 'U': case 'B': case 'M': crm_log_args(argc, argv); rsc_cmd = flag; find_flags = pe_find_renamed|pe_find_anon; break; case 'c': case 'L': case 'l': case 'O': case 'o': require_resource = FALSE; rsc_cmd = flag; break; case 'Y': require_resource = FALSE; rsc_cmd = flag; find_flags = pe_find_renamed|pe_find_anon; break; case 'q': case 'w': rsc_cmd = flag; find_flags = pe_find_renamed|pe_find_any; break; case 'W': case 'A': case 'a': rsc_cmd = flag; find_flags = pe_find_renamed|pe_find_anon; break; case 'S': require_dataset = FALSE; crm_log_args(argc, argv); prop_name = optarg; rsc_cmd = flag; find_flags = pe_find_renamed|pe_find_any; break; case 'p': case 'd': crm_log_args(argc, argv); prop_name = optarg; rsc_cmd = flag; find_flags = pe_find_renamed|pe_find_any; break; case 'G': case 'g': prop_name = optarg; rsc_cmd = flag; find_flags = pe_find_renamed|pe_find_any; break; case 'H': case 'N': crm_trace("Option %c => %s", flag, optarg); host_uname = optarg; break; default: CMD_ERR("Argument code 0%o (%c) is not (?yet?) supported", flag, flag); ++argerr; break; } } // Catch the case where the user didn't specify a command if (rsc_cmd == 'L') { require_resource = FALSE; } // --expired without --clear/-U doesn't make sense if (clear_expired == TRUE && rsc_cmd != 'U') { CMD_ERR("--expired requires --clear or -U"); argerr++; } if (optind < argc && argv[optind] != NULL && rsc_cmd == 0 && rsc_long_cmd) { override_params = crm_str_table_new(); while (optind < argc && argv[optind] != NULL) { char *name = calloc(1, strlen(argv[optind])); char *value = calloc(1, strlen(argv[optind])); int rc = sscanf(argv[optind], "%[^=]=%s", name, value); if(rc == 2) { g_hash_table_replace(override_params, name, value); } else { CMD_ERR("Error parsing '%s' as a name=value pair for --%s", argv[optind], rsc_long_cmd); free(value); free(name); argerr++; } optind++; } } else if (optind < argc && argv[optind] != NULL && rsc_cmd == 0) { CMD_ERR("non-option ARGV-elements: "); while (optind < argc && argv[optind] != NULL) { CMD_ERR("[%d of %d] %s ", optind, argc, argv[optind]); optind++; argerr++; } } if (optind > argc) { ++argerr; } // Sanity check validating from command line parameters. If everything checks out, // go ahead and run the validation. This way we don't need a CIB connection. if (validate_cmdline == TRUE) { // -r cannot be used with any of --class, --agent, or --provider if (rsc_id != NULL) { CMD_ERR("--resource cannot be used with --class, --agent, and --provider"); argerr++; // If --class, --agent, or --provider are given, --validate must also be given. } else if (!safe_str_eq(rsc_long_cmd, "validate")) { CMD_ERR("--class, --agent, and --provider require --validate"); argerr++; // Not all of --class, --agent, and --provider need to be given. Not all // classes support the concept of a provider. Check that what we were given // is valid. } else if (crm_str_eq(v_class, "stonith", TRUE)) { if (v_provider != NULL) { CMD_ERR("stonith does not support providers"); argerr++; } else if (stonith_agent_exists(v_agent, 0) == FALSE) { CMD_ERR("%s is not a known stonith agent", v_agent ? v_agent : ""); argerr++; } } else if (resources_agent_exists(v_class, v_provider, v_agent) == FALSE) { CMD_ERR("%s:%s:%s is not a known resource", v_class ? v_class : "", v_provider ? v_provider : "", v_agent ? v_agent : ""); argerr++; } if (argerr == 0) { rc = cli_resource_execute_from_params("test", v_class, v_provider, v_agent, "validate-all", validate_options, override_params, timeout_ms); exit_code = crm_errno2exit(rc); return crm_exit(exit_code); } } if (argerr) { CMD_ERR("Invalid option(s) supplied, use --help for valid usage"); crm_exit(CRM_EX_USAGE); } our_pid = crm_getpid_s(); if (do_force) { crm_debug("Forcing..."); cib_options |= cib_quorum_override; } if (require_resource && !rsc_id) { CMD_ERR("Must supply a resource id with -r"); rc = -ENXIO; goto bail; } if (find_flags && rsc_id) { require_dataset = TRUE; } /* Establish a connection to the CIB manager */ cib_conn = cib_new(); rc = cib_conn->cmds->signon(cib_conn, crm_system_name, cib_command); if (rc != pcmk_ok) { CMD_ERR("Error connecting to the CIB manager: %s", pcmk_strerror(rc)); goto bail; } /* Populate working set from XML file if specified or CIB query otherwise */ if (require_dataset) { if (xml_file != NULL) { cib_xml_copy = filename2xml(xml_file); } else { rc = cib_conn->cmds->query(cib_conn, NULL, &cib_xml_copy, cib_scope_local | cib_sync_call); } if(rc != pcmk_ok) { goto bail; } /* Populate the working set instance */ data_set = pe_new_working_set(); if (data_set == NULL) { rc = -ENOMEM; goto bail; } rc = update_working_set_xml(data_set, &cib_xml_copy); if (rc != pcmk_ok) { goto bail; } cluster_status(data_set); } // If command requires that resource exist if specified, find it if (find_flags && rsc_id) { rsc = pe_find_resource_with_flags(data_set->resources, rsc_id, find_flags); if (rsc == NULL) { CMD_ERR("Resource '%s' not found", rsc_id); rc = -ENXIO; goto bail; } } // Establish a connection to the controller if needed if (require_crmd) { xmlNode *xml = NULL; mainloop_io_t *source = mainloop_add_ipc_client(CRM_SYSTEM_CRMD, G_PRIORITY_DEFAULT, 0, NULL, &crm_callbacks); crmd_channel = mainloop_get_ipc_client(source); if (crmd_channel == NULL) { CMD_ERR("Error connecting to the controller"); rc = -ENOTCONN; goto bail; } xml = create_hello_message(our_pid, crm_system_name, "0", "1"); crm_ipc_send(crmd_channel, xml, 0, 0, NULL); free_xml(xml); } /* Handle rsc_cmd appropriately */ if (rsc_cmd == 'L') { rc = pcmk_ok; cli_resource_print_list(data_set, FALSE); } else if (rsc_cmd == 'l') { int found = 0; GListPtr lpc = NULL; rc = pcmk_ok; for (lpc = data_set->resources; lpc != NULL; lpc = lpc->next) { rsc = (resource_t *) lpc->data; found++; cli_resource_print_raw(rsc); } if (found == 0) { printf("NO resources configured\n"); rc = -ENXIO; } } else if (rsc_cmd == 0 && rsc_long_cmd && safe_str_eq(rsc_long_cmd, "restart")) { /* We don't pass data_set because rsc needs to stay valid for the entire * lifetime of cli_resource_restart(), but it will reset and update the * working set multiple times, so it needs to use its own copy. */ rc = cli_resource_restart(rsc, host_uname, timeout_ms, cib_conn); } else if (rsc_cmd == 0 && rsc_long_cmd && safe_str_eq(rsc_long_cmd, "wait")) { rc = wait_till_stable(timeout_ms, cib_conn); } else if (rsc_cmd == 0 && rsc_long_cmd) { // validate, force-(stop|start|demote|promote|check) rc = cli_resource_execute(rsc, rsc_id, rsc_long_cmd, override_params, timeout_ms, cib_conn, data_set); if (rc >= 0) { is_ocf_rc = 1; } } else if (rsc_cmd == 'A' || rsc_cmd == 'a') { GListPtr lpc = NULL; xmlNode *cib_constraints = get_object_root(XML_CIB_TAG_CONSTRAINTS, data_set->input); unpack_constraints(cib_constraints, data_set); // Constraints apply to group/clone, not member/instance rsc = uber_parent(rsc); for (lpc = data_set->resources; lpc != NULL; lpc = lpc->next) { resource_t *r = (resource_t *) lpc->data; clear_bit(r->flags, pe_rsc_allocating); } cli_resource_print_colocation(rsc, TRUE, rsc_cmd == 'A', 1); fprintf(stdout, "* %s\n", rsc->id); cli_resource_print_location(rsc, NULL); for (lpc = data_set->resources; lpc != NULL; lpc = lpc->next) { resource_t *r = (resource_t *) lpc->data; clear_bit(r->flags, pe_rsc_allocating); } cli_resource_print_colocation(rsc, FALSE, rsc_cmd == 'A', 1); } else if (rsc_cmd == 'c') { GListPtr lpc = NULL; rc = pcmk_ok; for (lpc = data_set->resources; lpc != NULL; lpc = lpc->next) { rsc = (resource_t *) lpc->data; cli_resource_print_cts(rsc); } cli_resource_print_cts_constraints(data_set); } else if (rsc_cmd == 'F') { rc = cli_resource_fail(crmd_channel, host_uname, rsc_id, data_set); if (rc == pcmk_ok) { start_mainloop(); } } else if (rsc_cmd == 'O') { rc = cli_resource_print_operations(rsc_id, host_uname, TRUE, data_set); } else if (rsc_cmd == 'o') { rc = cli_resource_print_operations(rsc_id, host_uname, FALSE, data_set); } else if (rsc_cmd == 'W') { rc = cli_resource_search(rsc, rsc_id, data_set); if (rc >= 0) { rc = pcmk_ok; } } else if (rsc_cmd == 'q') { rc = cli_resource_print(rsc, data_set, TRUE); } else if (rsc_cmd == 'w') { rc = cli_resource_print(rsc, data_set, FALSE); } else if (rsc_cmd == 'Y') { node_t *dest = NULL; if (host_uname) { dest = pe_find_node(data_set->nodes, host_uname); if (dest == NULL) { rc = -pcmk_err_node_unknown; goto bail; } } cli_resource_why(cib_conn, data_set->resources, rsc, dest); rc = pcmk_ok; } else if (rsc_cmd == 'U') { GListPtr before = NULL; GListPtr after = NULL; GListPtr remaining = NULL; GListPtr ele = NULL; node_t *dest = NULL; if (BE_QUIET == FALSE) { before = build_constraint_list(data_set->input); } if (clear_expired == TRUE) { rc = cli_resource_clear_all_expired(data_set->input, cib_conn, rsc_id, host_uname, scope_master); } else if (host_uname) { dest = pe_find_node(data_set->nodes, host_uname); if (dest == NULL) { rc = -pcmk_err_node_unknown; if (BE_QUIET == FALSE) { g_list_free(before); } goto bail; } rc = cli_resource_clear(rsc_id, dest->details->uname, NULL, cib_conn, TRUE); } else { rc = cli_resource_clear(rsc_id, NULL, data_set->nodes, cib_conn, TRUE); } if (BE_QUIET == FALSE) { rc = cib_conn->cmds->query(cib_conn, NULL, &cib_xml_copy, cib_scope_local | cib_sync_call); if (rc != pcmk_ok) { CMD_ERR("Could not get modified CIB: %s\n", pcmk_strerror(rc)); g_list_free(before); goto bail; } data_set->input = cib_xml_copy; cluster_status(data_set); after = build_constraint_list(data_set->input); remaining = subtract_lists(before, after, (GCompareFunc) strcmp); for (ele = remaining; ele != NULL; ele = ele->next) { printf("Removing constraint: %s\n", (char *) ele->data); } g_list_free(before); g_list_free(after); g_list_free(remaining); } } else if (rsc_cmd == 'M' && host_uname) { rc = cli_resource_move(rsc, rsc_id, host_uname, cib_conn, data_set); } else if (rsc_cmd == 'B' && host_uname) { node_t *dest = pe_find_node(data_set->nodes, host_uname); if (dest == NULL) { rc = -pcmk_err_node_unknown; goto bail; } rc = cli_resource_ban(rsc_id, dest->details->uname, NULL, cib_conn); } else if (rsc_cmd == 'B' || rsc_cmd == 'M') { pe_node_t *current = NULL; unsigned int nactive = 0; current = pe__find_active_requires(rsc, &nactive); if (nactive == 1) { rc = cli_resource_ban(rsc_id, current->details->uname, NULL, cib_conn); } else if (is_set(rsc->flags, pe_rsc_promotable)) { int count = 0; GListPtr iter = NULL; current = NULL; for(iter = rsc->children; iter; iter = iter->next) { resource_t *child = (resource_t *)iter->data; enum rsc_role_e child_role = child->fns->state(child, TRUE); if(child_role == RSC_ROLE_MASTER) { count++; current = pe__current_node(child); } } if(count == 1 && current) { rc = cli_resource_ban(rsc_id, current->details->uname, NULL, cib_conn); } else { rc = -EINVAL; exit_code = CRM_EX_USAGE; CMD_ERR("Resource '%s' not moved: active in %d locations (promoted in %d).", rsc_id, nactive, count); CMD_ERR("To prevent '%s' from running on a specific location, " "specify a node.", rsc_id); CMD_ERR("To prevent '%s' from being promoted at a specific " "location, specify a node and the master option.", rsc_id); } } else { rc = -EINVAL; exit_code = CRM_EX_USAGE; CMD_ERR("Resource '%s' not moved: active in %d locations.", rsc_id, nactive); CMD_ERR("To prevent '%s' from running on a specific location, " "specify a node.", rsc_id); } } else if (rsc_cmd == 'G') { rc = cli_resource_print_property(rsc, prop_name, data_set); } else if (rsc_cmd == 'S') { xmlNode *msg_data = NULL; if ((rsc_type == NULL) || !strlen(rsc_type)) { CMD_ERR("Must specify -t with resource type"); rc = -ENXIO; goto bail; } else if ((prop_value == NULL) || !strlen(prop_value)) { CMD_ERR("Must supply -v with new value"); rc = -EINVAL; goto bail; } CRM_LOG_ASSERT(prop_name != NULL); msg_data = create_xml_node(NULL, rsc_type); crm_xml_add(msg_data, XML_ATTR_ID, rsc_id); crm_xml_add(msg_data, prop_name, prop_value); rc = cib_conn->cmds->modify(cib_conn, XML_CIB_TAG_RESOURCES, msg_data, cib_options); free_xml(msg_data); } else if (rsc_cmd == 'g') { rc = cli_resource_print_attribute(rsc, prop_name, data_set); } else if (rsc_cmd == 'p') { if (prop_value == NULL || strlen(prop_value) == 0) { CMD_ERR("You need to supply a value with the -v option"); rc = -EINVAL; goto bail; } /* coverity[var_deref_model] False positive */ rc = cli_resource_update_attribute(rsc, rsc_id, prop_set, prop_id, prop_name, prop_value, recursive, cib_conn, data_set); } else if (rsc_cmd == 'd') { /* coverity[var_deref_model] False positive */ rc = cli_resource_delete_attribute(rsc, rsc_id, prop_set, prop_id, prop_name, cib_conn, data_set); } else if ((rsc_cmd == 'C') && rsc) { if (do_force == FALSE) { rsc = uber_parent(rsc); } crmd_replies_needed = 0; crm_debug("Erasing failures of %s (%s requested) on %s", rsc->id, rsc_id, (host_uname? host_uname: "all nodes")); rc = cli_resource_delete(crmd_channel, host_uname, rsc, operation, interval_spec, TRUE, data_set); if ((rc == pcmk_ok) && !BE_QUIET) { // Show any reasons why resource might stay stopped cli_resource_check(cib_conn, rsc); } if (rc == pcmk_ok) { start_mainloop(); } } else if (rsc_cmd == 'C') { rc = cli_cleanup_all(crmd_channel, host_uname, operation, interval_spec, data_set); if (rc == pcmk_ok) { start_mainloop(); } } else if ((rsc_cmd == 'R') && rsc) { if (do_force == FALSE) { rsc = uber_parent(rsc); } crmd_replies_needed = 0; crm_debug("Re-checking the state of %s (%s requested) on %s", rsc->id, rsc_id, (host_uname? host_uname: "all nodes")); rc = cli_resource_delete(crmd_channel, host_uname, rsc, NULL, 0, FALSE, data_set); if ((rc == pcmk_ok) && !BE_QUIET) { // Show any reasons why resource might stay stopped cli_resource_check(cib_conn, rsc); } if (rc == pcmk_ok) { start_mainloop(); } } else if (rsc_cmd == 'R') { const char *router_node = host_uname; xmlNode *msg_data = NULL; xmlNode *cmd = NULL; int attr_options = attrd_opt_none; if (host_uname) { node_t *node = pe_find_node(data_set->nodes, host_uname); if (node && is_remote_node(node)) { node = pe__current_node(node->details->remote_rsc); if (node == NULL) { CMD_ERR("No cluster connection to Pacemaker Remote node %s detected", host_uname); rc = -ENXIO; goto bail; } router_node = node->details->uname; attr_options |= attrd_opt_remote; } } if (crmd_channel == NULL) { printf("Dry run: skipping clean-up of %s due to CIB_file\n", host_uname? host_uname : "all nodes"); rc = pcmk_ok; goto bail; } msg_data = create_xml_node(NULL, "crm-resource-reprobe-op"); crm_xml_add(msg_data, XML_LRM_ATTR_TARGET, host_uname); if (safe_str_neq(router_node, host_uname)) { crm_xml_add(msg_data, XML_LRM_ATTR_ROUTER_NODE, router_node); } cmd = create_request(CRM_OP_REPROBE, msg_data, router_node, CRM_SYSTEM_CRMD, crm_system_name, our_pid); free_xml(msg_data); crm_debug("Re-checking the state of all resources on %s", host_uname?host_uname:"all nodes"); rc = attrd_clear_delegate(NULL, host_uname, NULL, NULL, NULL, NULL, attr_options); if (crm_ipc_send(crmd_channel, cmd, 0, 0, NULL) > 0) { start_mainloop(); } free_xml(cmd); } else if (rsc_cmd == 'D') { xmlNode *msg_data = NULL; if (rsc_type == NULL) { CMD_ERR("You need to specify a resource type with -t"); rc = -ENXIO; goto bail; } msg_data = create_xml_node(NULL, rsc_type); crm_xml_add(msg_data, XML_ATTR_ID, rsc_id); rc = cib_conn->cmds->remove(cib_conn, XML_CIB_TAG_RESOURCES, msg_data, cib_options); free_xml(msg_data); } else { CMD_ERR("Unknown command: %c", rsc_cmd); } bail: free(our_pid); pe_free_working_set(data_set); if (cib_conn != NULL) { cib_conn->cmds->signoff(cib_conn); cib_delete(cib_conn); } if (is_ocf_rc) { exit_code = rc; } else if (rc != pcmk_ok) { CMD_ERR("Error performing operation: %s", pcmk_strerror(rc)); if (rc == -pcmk_err_no_quorum) { CMD_ERR("To ignore quorum, use the force option"); } if (exit_code == CRM_EX_OK) { exit_code = crm_errno2exit(rc); } } return crm_exit(exit_code); }
int cib_process_replace(const char *op, int options, const char *section, xmlNode * req, xmlNode * input, xmlNode * existing_cib, xmlNode ** result_cib, xmlNode ** answer) { const char *tag = NULL; int result = pcmk_ok; crm_trace("Processing \"%s\" event for section=%s", op, crm_str(section)); if (options & cib_xpath) { return cib_process_xpath(op, options, section, req, input, existing_cib, result_cib, answer); } *answer = NULL; if (input == NULL) { return -EINVAL; } tag = crm_element_name(input); if (safe_str_eq(XML_CIB_TAG_SECTION_ALL, section)) { section = NULL; } else if (safe_str_eq(tag, section)) { section = NULL; } if (safe_str_eq(tag, XML_TAG_CIB)) { int updates = 0; int epoch = 0; int admin_epoch = 0; int replace_updates = 0; int replace_epoch = 0; int replace_admin_epoch = 0; const char *reason = NULL; const char *peer = crm_element_value(req, F_ORIG); const char *digest = crm_element_value(req, XML_ATTR_DIGEST); if (digest) { const char *version = crm_element_value(req, XML_ATTR_CRM_VERSION); char *digest_verify = calculate_xml_versioned_digest(input, FALSE, TRUE, version ? version : CRM_FEATURE_SET); if (safe_str_neq(digest_verify, digest)) { crm_err("Digest mis-match on replace from %s: %s vs. %s (expected)", peer, digest_verify, digest); reason = "digest mismatch"; } else { crm_info("Digest matched on replace from %s: %s", peer, digest); } free(digest_verify); } else { crm_trace("No digest to verify"); } cib_version_details(existing_cib, &admin_epoch, &epoch, &updates); cib_version_details(input, &replace_admin_epoch, &replace_epoch, &replace_updates); if (replace_admin_epoch < admin_epoch) { reason = XML_ATTR_GENERATION_ADMIN; } else if (replace_admin_epoch > admin_epoch) { /* no more checks */ } else if (replace_epoch < epoch) { reason = XML_ATTR_GENERATION; } else if (replace_epoch > epoch) { /* no more checks */ } else if (replace_updates < updates) { reason = XML_ATTR_NUMUPDATES; } if (reason != NULL) { crm_info("Replacement %d.%d.%d from %s not applied to %d.%d.%d:" " current %s is greater than the replacement", replace_admin_epoch, replace_epoch, replace_updates, peer, admin_epoch, epoch, updates, reason); result = -pcmk_err_old_data; } else { crm_info("Replaced %d.%d.%d with %d.%d.%d from %s", admin_epoch, epoch, updates, replace_admin_epoch, replace_epoch, replace_updates, peer); } free_xml(*result_cib); *result_cib = copy_xml(input); } else { xmlNode *obj_root = NULL; gboolean ok = TRUE; obj_root = get_object_root(section, *result_cib); ok = replace_xml_child(NULL, obj_root, input, FALSE); if (ok == FALSE) { crm_trace("No matching object to replace"); result = -ENXIO; } } return result; }
enum cib_errors cib_process_create(const char *op, int options, const char *section, xmlNode * req, xmlNode * input, xmlNode * existing_cib, xmlNode ** result_cib, xmlNode ** answer) { xmlNode *failed = NULL; enum cib_errors result = cib_ok; xmlNode *update_section = NULL; crm_debug_2("Processing \"%s\" event for section=%s", op, crm_str(section)); if (safe_str_eq(XML_CIB_TAG_SECTION_ALL, section)) { section = NULL; } else if (safe_str_eq(XML_TAG_CIB, section)) { section = NULL; } else if (safe_str_eq(crm_element_name(input), XML_TAG_CIB)) { section = NULL; } CRM_CHECK(strcasecmp(CIB_OP_CREATE, op) == 0, return cib_operation); if (input == NULL) { crm_err("Cannot perform modification with no data"); return cib_NOOBJECT; } if (section == NULL) { return cib_process_modify(op, options, section, req, input, existing_cib, result_cib, answer); } failed = create_xml_node(NULL, XML_TAG_FAILED); update_section = get_object_root(section, *result_cib); if (safe_str_eq(crm_element_name(input), section)) { xmlNode *a_child = NULL; for (a_child = __xml_first_child(input); a_child != NULL; a_child = __xml_next(a_child)) { result = add_cib_object(update_section, a_child); if (update_results(failed, a_child, op, result)) { break; } } } else { result = add_cib_object(update_section, input); update_results(failed, input, op, result); } if (xml_has_children(failed)) { CRM_CHECK(result != cib_ok, result = cib_unknown); } if (result != cib_ok) { crm_log_xml_err(failed, "CIB Update failures"); *answer = failed; } else { free_xml(failed); } return result; }
enum cib_errors cib_process_change( const char *op, int options, const char *section, crm_data_t *input, crm_data_t *existing_cib, crm_data_t **result_cib, crm_data_t **answer) { gboolean verbose = FALSE; crm_data_t *failed = NULL; enum cib_errors result = cib_ok; int cib_update_op = CIB_UPDATE_OP_NONE; crm_debug_2("Processing \"%s\" event for section=%s", op, crm_str(section)); if (strcasecmp(CIB_OP_CREATE, op) == 0) { cib_update_op = CIB_UPDATE_OP_ADD; } else if (strcasecmp(CIB_OP_UPDATE, op) == 0) { cib_update_op = CIB_UPDATE_OP_MODIFY; } else if (strcasecmp(CIB_OP_DELETE_ALT, op) == 0) { cib_update_op = CIB_UPDATE_OP_DELETE; } else { crm_err("Incorrect request handler invoked for \"%s\" op", crm_str(op)); return cib_operation; } result = cib_ok; if (options & cib_verbose) { verbose = TRUE; } if(safe_str_eq(XML_CIB_TAG_SECTION_ALL, section)) { section = NULL; } if(input == NULL) { crm_err("Cannot perform modification with no data"); return cib_NOOBJECT; } crm_validate_data(input); crm_validate_data(*result_cib); failed = create_xml_node(NULL, XML_TAG_FAILED); /* make changes to a temp copy then activate */ if(section == NULL) { int lpc = 0; const char *type = NULL; crm_data_t *sub_input = NULL; /* order is no longer important here */ const char *type_list[] = { XML_CIB_TAG_NODES, XML_CIB_TAG_CONSTRAINTS, XML_CIB_TAG_RESOURCES, XML_CIB_TAG_STATUS, XML_CIB_TAG_CRMCONFIG }; copy_in_properties(*result_cib, input); for(lpc = 0; lpc < DIMOF(type_list); lpc++) { type = type_list[lpc]; if(result == cib_ok) { crm_debug_2("Processing section=%s", type); sub_input = get_object_root(type, input); result = updateList( *result_cib, sub_input, failed, cib_update_op, type); } } } else { result = updateList( *result_cib, input, failed, cib_update_op, section); } if (result != cib_ok || xml_has_children(failed)) { if(result == cib_ok) { result = cib_unknown; } crm_log_xml_err(failed, "CIB Update failures"); *answer = failed; } else { free_xml(failed); } return result; }
int main(int argc, char **argv) { crm_data_t *cib_object = NULL; crm_data_t *status = NULL; int argerr = 0; int flag; pe_working_set_t data_set; cib_t * cib_conn = NULL; int rc = cib_ok; gboolean xml_stdin = FALSE; const char *xml_file = NULL; const char *xml_string = NULL; crm_system_name = basename(argv[0]); 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*/ cl_log_set_entity(crm_system_name); cl_log_set_facility(HA_LOG_FACILITY); cl_log_enable_stderr(TRUE); set_crm_log_level(LOG_ERR); CL_SIGNAL(DEBUG_INC, alter_debug); CL_SIGNAL(DEBUG_DEC, alter_debug); while (1) { #ifdef HAVE_GETOPT_H int option_index = 0; static struct option long_options[] = { /* Top-level Options */ {F_CRM_DATA, 1, 0, 'X'}, {"dtd-file", 1, 0, 'D'}, {"xml-file", 1, 0, 'x'}, {"xml-pipe", 0, 0, 'p'}, {"save-xml", 1, 0, 'S'}, {"live-check", 0, 0, 'L'}, {"help", 0, 0, '?'}, {0, 0, 0, 0} }; #endif #ifdef HAVE_GETOPT_H flag = getopt_long(argc, argv, OPTARGS, long_options, &option_index); #else flag = getopt(argc, argv, OPTARGS); #endif 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 'D': crm_debug_2("Option %c => %s", flag, optarg); dtd_file = optarg; break; 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 '?': usage(crm_system_name, LSB_EXIT_GENERIC); break; default: printf("?? getopt returned character code 0%o ??\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); usage(crm_system_name, 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_synchronous); } 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) { FILE *xml_strm = fopen(xml_file, "r"); cib_object = file2xml(xml_strm, FALSE); if(cib_object == NULL) { fprintf(stderr, "Couldn't parse input file: %s\n", xml_file); return 1; } fclose(xml_strm); } 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 1; } } else if(xml_stdin) { cib_object = stdin2xml(); if(cib_object == NULL) { fprintf(stderr, "Couldn't parse input from STDIN.\n"); return 1; } } else { fprintf(stderr, "No configuration source specified." " Use --help for usage information.\n"); return 3; } 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 xml_child_iter_filter(status, node_state, XML_CIB_TAG_STATE, xml_remove_prop(node_state, XML_CIB_TAG_LRM); );
enum cib_errors cib_process_replace(const char *op, int options, const char *section, xmlNode * req, xmlNode * input, xmlNode * existing_cib, xmlNode ** result_cib, xmlNode ** answer) { const char *tag = NULL; gboolean verbose = FALSE; enum cib_errors result = cib_ok; crm_debug_2("Processing \"%s\" event for section=%s", op, crm_str(section)); if (options & cib_xpath) { return cib_process_xpath(op, options, section, req, input, existing_cib, result_cib, answer); } *answer = NULL; if (input == NULL) { return cib_NOOBJECT; } tag = crm_element_name(input); if (options & cib_verbose) { verbose = TRUE; } if (safe_str_eq(XML_CIB_TAG_SECTION_ALL, section)) { section = NULL; } else if (safe_str_eq(tag, section)) { section = NULL; } if (safe_str_eq(tag, XML_TAG_CIB)) { int updates = 0; int epoch = 0; int admin_epoch = 0; int replace_updates = 0; int replace_epoch = 0; int replace_admin_epoch = 0; const char *reason = NULL; cib_version_details(existing_cib, &admin_epoch, &epoch, &updates); cib_version_details(input, &replace_admin_epoch, &replace_epoch, &replace_updates); if (replace_admin_epoch < admin_epoch) { reason = XML_ATTR_GENERATION_ADMIN; } else if (replace_admin_epoch > admin_epoch) { /* no more checks */ } else if (replace_epoch < epoch) { reason = XML_ATTR_GENERATION; } else if (replace_epoch > epoch) { /* no more checks */ } else if (replace_updates < updates) { reason = XML_ATTR_NUMUPDATES; } if (reason != NULL) { crm_warn("Replacement %d.%d.%d not applied to %d.%d.%d:" " current %s is greater than the replacement", replace_admin_epoch, replace_epoch, replace_updates, admin_epoch, epoch, updates, reason); result = cib_old_data; } free_xml(*result_cib); *result_cib = copy_xml(input); } else { xmlNode *obj_root = NULL; gboolean ok = TRUE; obj_root = get_object_root(section, *result_cib); ok = replace_xml_child(NULL, obj_root, input, FALSE); if (ok == FALSE) { crm_debug_2("No matching object to replace"); result = cib_NOTEXISTS; } } return result; }
} else if(safe_str_eq(name, XML_ATTR_NUMPEERS)) { goto do_abort; } else if(safe_str_eq(name, XML_ATTR_GENERATION)) { goto do_abort; } else if(safe_str_eq(name, XML_ATTR_GENERATION_ADMIN)) { goto do_abort; } continue; do_abort: crm_debug("Aborting on change to %s", name); crm_log_xml_debug(update, "Abort: CIB Attrs"); return update; ); section = XML_CIB_TAG_NODES; section_xml = get_object_root(section, update); xml_child_iter(section_xml, child, return section_xml; ); section = XML_CIB_TAG_RESOURCES; section_xml = get_object_root(section, update); xml_child_iter(section_xml, child, return section_xml; ); section = XML_CIB_TAG_CONSTRAINTS; section_xml = get_object_root(section, update); xml_child_iter(section_xml, child, return section_xml; );
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(NULL, "[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 <cib>).\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 (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; }
int main(int argc, char **argv) { GListPtr lpc = NULL; gboolean process = TRUE; gboolean all_good = TRUE; enum transition_status graph_rc = -1; crm_graph_t *transition = NULL; ha_time_t *a_date = NULL; cib_t *cib_conn = NULL; xmlNode *cib_object = NULL; int argerr = 0; int flag; char *msg_buffer = NULL; gboolean optional = FALSE; pe_working_set_t data_set; const char *source = NULL; const char *xml_file = NULL; const char *dot_file = NULL; const char *graph_file = NULL; const char *input_file = NULL; const char *input_xml = NULL; /* disable glib's fancy allocators that can't be free'd */ GMemVTable vtable; vtable.malloc = malloc; vtable.realloc = realloc; vtable.free = free; vtable.calloc = calloc; vtable.try_malloc = malloc; vtable.try_realloc = realloc; g_mem_set_vtable(&vtable); crm_log_init_quiet(NULL, LOG_CRIT, FALSE, FALSE, argc, argv); crm_set_options(NULL, "[-?Vv] -[Xxp] {other options}", long_options, "Calculate the cluster's response to the supplied cluster state\n" "\nSuperceeded by crm_simulate and likely to be removed in a future release\n\n"); while (1) { int option_index = 0; flag = crm_get_option(argc, argv, &option_index); if (flag == -1) break; switch (flag) { case 'S': do_simulation = TRUE; break; case 'a': all_actions = TRUE; break; case 'w': inhibit_exit = TRUE; break; case 'X': /*use_stdin = TRUE;*/ input_xml = optarg; break; case 's': show_scores = TRUE; break; case 'U': show_utilization = TRUE; break; case 'x': xml_file = optarg; break; case 'd': use_date = optarg; break; case 'D': dot_file = optarg; break; case 'G': graph_file = optarg; break; case 'I': input_file = optarg; break; case 'V': crm_bump_log_level(); break; case 'L': USE_LIVE_CIB = TRUE; break; case '$': case '?': crm_help(flag, 0); 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('?', 1); } update_all_trace_data(); /* again, so we see which trace points got updated */ if (USE_LIVE_CIB) { int rc = cib_ok; source = "live cib"; cib_conn = cib_new(); rc = cib_conn->cmds->signon(cib_conn, "ptest", cib_command); if (rc == cib_ok) { crm_info("Reading XML from: live cluster"); cib_object = get_cib_copy(cib_conn); } else { 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) { source = xml_file; cib_object = filename2xml(xml_file); } else if (use_stdin) { source = "stdin"; cib_object = filename2xml(NULL); } else if (input_xml) { source = "input string"; cib_object = string2xml(input_xml); } if (cib_object == NULL && source) { fprintf(stderr, "Could not parse configuration input from: %s\n", source); return 4; } else if (cib_object == NULL) { fprintf(stderr, "No configuration specified\n"); crm_help('?', 1); } if (get_object_root(XML_CIB_TAG_STATUS, cib_object) == NULL) { create_xml_node(cib_object, XML_CIB_TAG_STATUS); } if (cli_config_update(&cib_object, NULL, FALSE) == FALSE) { free_xml(cib_object); return cib_STALE; } if (validate_xml(cib_object, NULL, FALSE) != TRUE) { free_xml(cib_object); return cib_dtd_validation; } if (input_file != NULL) { FILE *input_strm = fopen(input_file, "w"); if (input_strm == NULL) { crm_perror(LOG_ERR, "Could not open %s for writing", input_file); } else { msg_buffer = dump_xml_formatted(cib_object); if (fprintf(input_strm, "%s\n", msg_buffer) < 0) { crm_perror(LOG_ERR, "Write to %s failed", input_file); } fflush(input_strm); fclose(input_strm); crm_free(msg_buffer); } } if (use_date != NULL) { a_date = parse_date(&use_date); log_date(LOG_WARNING, "Set fake 'now' to", a_date, ha_log_date | ha_log_time); log_date(LOG_WARNING, "Set fake 'now' to (localtime)", a_date, ha_log_date | ha_log_time | ha_log_local); } set_working_set_defaults(&data_set); if (process) { if (show_scores && show_utilization) { fprintf(stdout, "Allocation scores and utilization information:\n"); } else if (show_scores) { fprintf(stdout, "Allocation scores:\n"); } else if (show_utilization) { fprintf(stdout, "Utilization information:\n"); } do_calculations(&data_set, cib_object, a_date); } msg_buffer = dump_xml_formatted(data_set.graph); if (safe_str_eq(graph_file, "-")) { fprintf(stdout, "%s\n", msg_buffer); fflush(stdout); } else if (graph_file != NULL) { FILE *graph_strm = fopen(graph_file, "w"); if (graph_strm == NULL) { crm_perror(LOG_ERR, "Could not open %s for writing", graph_file); } else { if (fprintf(graph_strm, "%s\n\n", msg_buffer) < 0) { crm_perror(LOG_ERR, "Write to %s failed", graph_file); } fflush(graph_strm); fclose(graph_strm); } } crm_free(msg_buffer); if (dot_file != NULL) { dot_strm = fopen(dot_file, "w"); if (dot_strm == NULL) { crm_perror(LOG_ERR, "Could not open %s for writing", dot_file); } } if (dot_strm == NULL) { goto simulate; } init_dotfile(); for (lpc = data_set.actions; lpc != NULL; lpc = lpc->next) { action_t *action = (action_t *) lpc->data; const char *style = "filled"; const char *font = "black"; const char *color = "black"; const char *fill = NULL; char *action_name = create_action_name(action); crm_trace("Action %d: %p", action->id, action); if (is_set(action->flags, pe_action_pseudo)) { font = "orange"; } style = "dashed"; if (is_set(action->flags, pe_action_dumped)) { style = "bold"; color = "green"; } else if (action->rsc != NULL && is_not_set(action->rsc->flags, pe_rsc_managed)) { color = "purple"; if (all_actions == FALSE) { goto dont_write; } } else if (is_set(action->flags, pe_action_optional)) { color = "blue"; if (all_actions == FALSE) { goto dont_write; } } else { color = "red"; CRM_CHECK(is_set(action->flags, pe_action_runnable) == FALSE,; ); } set_bit_inplace(action->flags, pe_action_dumped); dot_write("\"%s\" [ style=%s color=\"%s\" fontcolor=\"%s\" %s%s]", action_name, style, color, font, fill ? "fillcolor=" : "", fill ? fill : ""); dont_write: crm_free(action_name); }
void te_update_diff(const char *event, HA_Message *msg) { int rc = -1; const char *op = NULL; crm_data_t *diff = NULL; crm_data_t *aborted = NULL; const char *set_name = NULL; int diff_add_updates = 0; int diff_add_epoch = 0; int diff_add_admin_epoch = 0; int diff_del_updates = 0; int diff_del_epoch = 0; int diff_del_admin_epoch = 0; if(msg == NULL) { crm_err("NULL update"); return; } ha_msg_value_int(msg, F_CIB_RC, &rc); op = cl_get_string(msg, F_CIB_OPERATION); if(rc < cib_ok) { crm_debug_2("Ignoring failed %s operation: %s", op, cib_error2string(rc)); return; } diff = get_message_xml(msg, F_CIB_UPDATE_RESULT); cib_diff_version_details( diff, &diff_add_admin_epoch, &diff_add_epoch, &diff_add_updates, &diff_del_admin_epoch, &diff_del_epoch, &diff_del_updates); crm_debug("Processing diff (%s): %d.%d.%d -> %d.%d.%d", op, diff_del_admin_epoch,diff_del_epoch,diff_del_updates, diff_add_admin_epoch,diff_add_epoch,diff_add_updates); log_cib_diff(LOG_DEBUG_2, diff, op); set_name = "diff-added"; if(diff != NULL) { crm_data_t *section = NULL; crm_data_t *change_set = find_xml_node(diff, set_name, FALSE); change_set = find_xml_node(change_set, XML_TAG_CIB, FALSE); if(change_set != NULL) { crm_debug_2("Checking status changes"); section=get_object_root(XML_CIB_TAG_STATUS,change_set); } if(section != NULL) { extract_event(section); } crm_debug_2("Checking change set: %s", set_name); aborted = need_abort(change_set); } set_name = "diff-removed"; if(diff != NULL && aborted == NULL) { crm_data_t *attrs = NULL; crm_data_t *status = NULL; crm_data_t *change_set = find_xml_node(diff, set_name, FALSE); change_set = find_xml_node(change_set, XML_TAG_CIB, FALSE); crm_debug_2("Checking change set: %s", set_name); aborted = need_abort(change_set); if(aborted == NULL && change_set != NULL) { status = get_object_root(XML_CIB_TAG_STATUS, change_set); xml_child_iter_filter( status, node_state, XML_CIB_TAG_STATE, attrs = find_xml_node( node_state, XML_TAG_TRANSIENT_NODEATTRS, FALSE); if(attrs != NULL) { crm_info("Aborting on "XML_TAG_TRANSIENT_NODEATTRS" deletions"); abort_transition(INFINITY, tg_restart, XML_TAG_TRANSIENT_NODEATTRS, attrs); } );