15 #include <sys/param.h>
16 #include <sys/types.h>
27 static bool fake_quiet = FALSE;
28 static cib_t *fake_cib = NULL;
29 static GListPtr fake_resource_list = NULL;
30 static GListPtr fake_op_fail_list = NULL;
33 #define STATUS_PATH_MAX 512
35 #define quiet_log(fmt, args...) do { \
37 crm_trace(fmt, ##args); \
39 printf(fmt , ##args); \
43 #define NEW_NODE_TEMPLATE "//"XML_CIB_TAG_NODE"[@uname='%s']"
44 #define NODE_TEMPLATE "//"XML_CIB_TAG_STATE"[@uname='%s']"
45 #define RSC_TEMPLATE "//"XML_CIB_TAG_STATE"[@uname='%s']//"XML_LRM_TAG_RESOURCE"[@id='%s']"
49 inject_transient_attr(xmlNode * cib_node,
const char *name,
const char *value)
51 xmlNode *attrs = NULL;
52 xmlNode *instance_attrs = NULL;
54 const char *node_uuid =
ID(cib_node);
56 node_path = xmlGetNodePath(cib_node);
57 quiet_log(
" + Injecting attribute %s=%s into %s '%s'\n",
58 name, value, node_path,
ID(cib_node));
68 if (instance_attrs == NULL) {
77 update_failcounts(xmlNode * cib_node,
const char *resource,
const char *task,
78 guint interval_ms,
int rc)
83 }
else if ((rc == 7) && (interval_ms == 0)) {
88 char *now = crm_itoa(time(NULL));
90 name = crm_failcount_name(resource, task, interval_ms);
91 inject_transient_attr(cib_node, name,
"value++");
94 name = crm_lastfailure_name(resource, task, interval_ms);
95 inject_transient_attr(cib_node, name, now);
102 create_node_entry(
cib_t * cib_conn,
const char *node)
126 create_op(xmlNode *cib_resource,
const char *task, guint interval_ms,
134 op->
rsc_id = strdup(
ID(cib_resource));
141 op->
t_run = time(NULL);
145 for (xop = __xml_first_child(cib_resource); xop != NULL; xop = __xml_next(xop)) {
166 inject_node_state(
cib_t * cib_conn,
const char *node,
const char *uuid)
169 xmlNode *cib_object = NULL;
173 create_node_entry(cib_conn, node);
176 rc = cib_conn->
cmds->
query(cib_conn, xpath, &cib_object,
179 if (cib_object &&
ID(cib_object) == NULL) {
180 crm_err(
"Detected multiple node_state entries for xpath=%s, bailing", xpath);
188 char *found_uuid = NULL;
193 found_uuid = strdup(uuid);
204 rc = cib_conn->
cmds->
query(cib_conn, xpath, &cib_object,
206 crm_trace(
"injecting node state for %s. rc is %d", node, rc);
215 modify_node(
cib_t * cib_conn,
char *node, gboolean up)
217 xmlNode *cib_node = inject_node_state(cib_conn, node, NULL);
237 find_resource_xml(xmlNode * cib_node,
const char *resource)
239 xmlNode *match = NULL;
250 inject_resource(xmlNode * cib_node,
const char *resource,
const char *lrm_name,
251 const char *rclass,
const char *rtype,
const char *rprovider)
254 xmlNode *container = NULL;
255 xmlNode *cib_resource = NULL;
258 cib_resource = find_resource_xml(cib_node, resource);
259 if (cib_resource != NULL) {
267 if (strcmp(resource, lrm_name)) {
268 cib_resource = find_resource_xml(cib_node, lrm_name);
269 if (cib_resource != NULL) {
276 if (rclass == NULL || rtype == NULL) {
277 fprintf(stderr,
"Resource %s not found in the status section of %s."
278 " Please supply the class and type to continue\n", resource,
ID(cib_node));
287 fprintf(stderr,
"Invalid class for %s: %s\n", resource, rclass);
291 && (rprovider == NULL)) {
292 fprintf(stderr,
"Please specify the provider for resource %s\n", resource);
296 xpath = (
char *)xmlGetNodePath(cib_node);
297 crm_info(
"Injecting new resource %s into %s '%s'", lrm_name, xpath,
ID(cib_node));
302 const char *node_uuid =
ID(cib_node);
309 if (container == NULL) {
325 #define XPATH_MAX 1024
328 find_ticket_state(
cib_t * the_cib,
const char *ticket_id, xmlNode ** ticket_state_xml)
332 xmlNode *xml_search = NULL;
334 char *xpath_string = NULL;
337 *ticket_state_xml = NULL;
340 offset += snprintf(xpath_string + offset,
XPATH_MAX - offset,
"%s",
"/cib/status/tickets");
343 offset += snprintf(xpath_string + offset,
XPATH_MAX - offset,
"/%s[@id=\"%s\"]",
347 rc = the_cib->
cmds->
query(the_cib, xpath_string, &xml_search,
357 fprintf(stdout,
"Multiple ticket_states match ticket_id=%s\n", ticket_id);
359 *ticket_state_xml = xml_search;
361 *ticket_state_xml = xml_search;
370 set_ticket_state_attr(
const char *ticket_id,
const char *attr_name,
371 const char *attr_value,
cib_t * cib,
int cib_options)
374 xmlNode *xml_top = NULL;
375 xmlNode *ticket_state_xml = NULL;
377 rc = find_ticket_state(cib, ticket_id, &ticket_state_xml);
379 crm_debug(
"Found a match state for ticket: id=%s", ticket_id);
380 xml_top = ticket_state_xml;
382 }
else if (rc != -ENXIO) {
386 xmlNode *xml_obj = NULL;
394 crm_xml_add(ticket_state_xml, attr_name, attr_value);
414 xmlNode *cib_op = NULL;
415 xmlNode *cib_node = NULL;
416 xmlNode *cib_resource = NULL;
423 quiet_log(
" + Setting quorum: %s\n", quorum);
432 quiet_log(
" + Setting watchdog: %s\n", watchdog);
441 for (gIter = node_up; gIter != NULL; gIter = gIter->next) {
442 char *node = (
char *)gIter->data;
444 quiet_log(
" + Bringing node %s online\n", node);
445 cib_node = modify_node(cib, node, TRUE);
454 for (gIter = node_down; gIter != NULL; gIter = gIter->next) {
456 char *node = (
char *)gIter->data;
458 quiet_log(
" + Taking node %s offline\n", node);
459 cib_node = modify_node(cib, node, FALSE);
478 for (gIter = node_fail; gIter != NULL; gIter = gIter->next) {
479 char *node = (
char *)gIter->data;
482 cib_node = modify_node(cib, node, TRUE);
492 for (gIter = ticket_grant; gIter != NULL; gIter = gIter->next) {
493 char *ticket_id = (
char *)gIter->data;
495 quiet_log(
" + Granting ticket %s\n", ticket_id);
496 rc = set_ticket_state_attr(ticket_id,
"granted",
"true",
502 for (gIter = ticket_revoke; gIter != NULL; gIter = gIter->next) {
503 char *ticket_id = (
char *)gIter->data;
505 quiet_log(
" + Revoking ticket %s\n", ticket_id);
506 rc = set_ticket_state_attr(ticket_id,
"granted",
"false",
512 for (gIter = ticket_standby; gIter != NULL; gIter = gIter->next) {
513 char *ticket_id = (
char *)gIter->data;
515 quiet_log(
" + Making ticket %s standby\n", ticket_id);
516 rc = set_ticket_state_attr(ticket_id,
"standby",
"true",
522 for (gIter = ticket_activate; gIter != NULL; gIter = gIter->next) {
523 char *ticket_id = (
char *)gIter->data;
525 quiet_log(
" + Activating ticket %s\n", ticket_id);
526 rc = set_ticket_state_attr(ticket_id,
"standby",
"false",
532 for (gIter = op_inject; gIter != NULL; gIter = gIter->next) {
533 char *spec = (
char *)gIter->data;
537 guint interval_ms = 0;
542 char *resource = NULL;
544 const char *rtype = NULL;
545 const char *rclass = NULL;
546 const char *rprovider = NULL;
550 quiet_log(
" + Injecting %s into the configuration\n", spec);
552 key = calloc(1, strlen(spec) + 1);
553 node = calloc(1, strlen(spec) + 1);
554 rc = sscanf(spec,
"%[^@]@%[^=]=%d", key, node, &outcome);
556 fprintf(stderr,
"Invalid operation spec: %s. Only found %d fields\n", spec, rc);
566 fprintf(stderr,
" - Invalid resource name: %s\n", resource);
572 cib_node = inject_node_state(cib, node, NULL);
575 update_failcounts(cib_node, resource, task, interval_ms, outcome);
577 cib_resource = inject_resource(cib_node, resource, resource,
578 rclass, rtype, rprovider);
581 op = create_op(cib_resource, task, interval_ms, outcome);
584 cib_op = inject_op(cib_resource, op, 0);
606 quiet_log(
" * Pseudo action: %s%s%s\n", task, node ?
" on " :
"", node ? node :
"");
617 int target_outcome = 0;
619 const char *rtype = NULL;
620 const char *rclass = NULL;
621 const char *resource = NULL;
622 const char *rprovider = NULL;
623 const char *lrm_name = NULL;
627 xmlNode *cib_node = NULL;
628 xmlNode *cib_resource = NULL;
637 crm_info(
"Skipping %s op for %s", operation, node);
641 if (action_rsc == NULL) {
643 free(node); free(uuid);
663 quiet_log(
" * Resource action: %-15s %s on %s\n", resource, operation, node);
671 if (target_rc_s != NULL) {
678 cib_node = inject_node_state(fake_cib, node, (router_node? node : uuid));
681 cib_resource = inject_resource(cib_node, resource, lrm_name,
682 rclass, rtype, rprovider);
683 if (cib_resource == NULL) {
684 crm_err(
"invalid resource in transition");
685 free(node); free(uuid);
692 quiet_log(
" * Resource action: %-15s %s=%u on %s\n",
695 quiet_log(
" * Resource action: %-15s %s on %s\n", resource, op->
op_type, node);
698 for (gIter = fake_op_fail_list; gIter != NULL; gIter = gIter->next) {
699 char *spec = (
char *)gIter->data;
701 const char *match_name = NULL;
706 if (strncasecmp(key, spec, strlen(key)) == 0) {
707 match_name = resource;
711 if ((match_name == NULL) && strcmp(resource, lrm_name)) {
714 if (strncasecmp(key, spec, strlen(key)) == 0) {
715 match_name = lrm_name;
720 if (match_name != NULL) {
722 rc = sscanf(spec,
"%*[^=]=%d", (
int *) &op->
rc);
727 "Invalid failed operation spec: %s. Result code must be integer\n",
733 printf(
"\tPretending action %d failed with rc=%d\n", action->
id, op->
rc);
734 update_failcounts(cib_node, match_name, op->
op_type,
740 inject_op(cib_resource, op, target_outcome);
748 free(node); free(uuid);
765 quiet_log(
" * Cluster action: %s for %s on %s\n", task,
ID(rsc), node);
767 quiet_log(
" * Cluster action: %s on %s\n", task, node);
779 quiet_log(
" * Fencing %s (%s)\n", target, op);
783 xmlNode *cib_node = modify_node(fake_cib, target, FALSE);
796 snprintf(xpath,
STATUS_PATH_MAX,
"//node_state[@uname='%s']/%s", target,
825 fake_op_fail_list = op_fail_list;
827 quiet_log(
"\nExecuting cluster transition:\n");
833 fake_resource_list = data_set->
resources;
838 fake_resource_list = NULL;
846 fprintf(stdout,
"An invalid transition was produced\n");
849 if (quiet == FALSE) {
850 xmlNode *cib_object = NULL;
855 data_set->
input = cib_object;
int(* query)(cib_t *cib, const char *section, xmlNode **output_data, int call_options)
gboolean parse_op_key(const char *key, char **rsc_id, char **op_type, guint *interval_ms)
gboolean safe_str_neq(const char *a, const char *b)
_Noreturn crm_exit_t crm_exit(crm_exit_t rc)
void destroy_graph(crm_graph_t *graph)
xmlNode * first_named_child(const xmlNode *parent, const char *name)
#define PCMK_RESOURCE_CLASS_SYSTEMD
void modify_configuration(pe_working_set_t *data_set, cib_t *cib, const char *quorum, const char *watchdog, GListPtr node_up, GListPtr node_down, GListPtr node_fail, GListPtr op_inject, GListPtr ticket_grant, GListPtr ticket_revoke, GListPtr ticket_standby, GListPtr ticket_activate)
lrmd_event_data_t * convert_graph_action(xmlNode *resource, crm_action_t *action, int status, int rc)
#define XML_TAG_TRANSIENT_NODEATTRS
const char * crm_meta_value(GHashTable *hash, const char *field)
void set_graph_functions(crm_graph_functions_t *fns)
#define XML_LRM_TAG_RESOURCE
const char * crm_xml_add(xmlNode *node, const char *name, const char *value)
Create an XML attribute with specified name and value.
void lrmd_free_event(lrmd_event_data_t *event)
int crm_parse_int(const char *text, const char *default_text)
Parse an integer value from a string.
#define XML_NODE_EXPECTED
int query_node_uuid(cib_t *the_cib, const char *uname, char **uuid, int *is_remote_node)
#define CRM_LOG_ASSERT(expr)
int(* replace)(cib_t *cib, const char *section, xmlNode *data, int call_options)
int crm_element_value_int(const xmlNode *data, const char *name, int *dest)
Retrieve the integer value of an XML attribute.
#define XML_CIB_TAG_NODES
xmlNode * get_xpath_object(const char *xpath, xmlNode *xml_obj, int error_level)
int(* modify)(cib_t *cib, const char *section, xmlNode *data, int call_options)
#define XML_LRM_ATTR_TASK_KEY
#define XML_TAG_ATTR_SETS
#define XML_LRM_ATTR_TASK
void pe_reset_working_set(pe_working_set_t *data_set)
Reset a working set to default state without freeing it.
#define CRMD_JOINSTATE_DOWN
#define PCMK_RESOURCE_CLASS_OCF
cib_api_operations_t * cmds
#define crm_debug(fmt, args...)
char * crm_element_value_copy(const xmlNode *data, const char *name)
Retrieve a copy of the value of an XML attribute.
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
#define XML_CIB_TAG_RESOURCE
#define XML_CIB_TAG_STATE
gboolean bringing_nodes_online
void print_graph(unsigned int log_level, crm_graph_t *graph)
#define PCMK_RESOURCE_CLASS_SERVICE
#define crm_trace(fmt, args...)
#define CRMD_JOINSTATE_MEMBER
xmlNode * create_operation_update(xmlNode *parent, lrmd_event_data_t *event, const char *caller_version, int target_rc, const char *node, const char *origin, int level)
#define crm_log_xml_debug(xml, text)
#define XML_AGENT_ATTR_PROVIDER
#define XML_ATTR_HAVE_QUORUM
xmlNode * create_xml_node(xmlNode *parent, const char *name)
#define crm_log_xml_warn(xml, text)
uint32_t pcmk_get_ra_caps(const char *standard)
Get capabilities of a resource agent standard.
gboolean update_graph(crm_graph_t *graph, crm_action_t *action)
#define XML_LRM_ATTR_ROUTER_NODE
#define NEW_NODE_TEMPLATE
void free_xml(xmlNode *child)
gboolean xml_has_children(const xmlNode *root)
int(* remove)(cib_t *cib, const char *section, xmlNode *data, int call_options)
pe_resource_t * pe_find_resource(GListPtr rsc_list, const char *id_rh)
#define XML_LRM_ATTR_TARGET_UUID
crm_graph_t * unpack_graph(xmlNode *xml_graph, const char *reference)
#define PCMK_RESOURCE_CLASS_STONITH
#define quiet_log(fmt, args...)
int run_simulation(pe_working_set_t *data_set, cib_t *cib, GListPtr op_fail_list, bool quiet)
#define crm_log_xml_err(xml, text)
Cluster status and scheduling.
#define PCMK_RESOURCE_CLASS_LSB
#define XML_LRM_TAG_RESOURCES
#define crm_err(fmt, args...)
#define XML_CIB_TAG_TICKET_STATE
int run_graph(crm_graph_t *graph)
#define XML_CIB_TAG_CRMCONFIG
#define PCMK_RESOURCE_CLASS_UPSTART
#define XML_ATTR_HAVE_WATCHDOG
int update_attr_delegate(cib_t *the_cib, int call_options, const char *section, const char *node_uuid, const char *set_type, const char *set_name, const char *attr_id, const char *attr_name, const char *attr_value, gboolean to_console, const char *user_name, const char *node_type)
#define XML_LRM_ATTR_CALLID
#define XML_NODE_JOIN_STATE
#define XML_CIB_TAG_STATUS
int(* create)(cib_t *cib, const char *section, xmlNode *data, int call_options)
#define XML_NODE_IN_CLUSTER
#define XML_LRM_ATTR_TARGET
xmlNode * crm_create_nvpair_xml(xmlNode *parent, const char *id, const char *name, const char *value)
Create an XML name/value pair.
#define safe_str_eq(a, b)
char * crm_strdup_printf(char const *format,...) __attribute__((__format__(__printf__
#define XML_CIB_TAG_TICKETS
#define crm_info(fmt, args...)
#define XML_ATTR_TE_TARGET_RC
#define XML_AGENT_ATTR_CLASS