17 #include <sys/param.h>
18 #include <sys/types.h>
29 static bool fake_quiet = FALSE;
30 static cib_t *fake_cib = NULL;
31 static GListPtr fake_resource_list = NULL;
32 static GListPtr fake_op_fail_list = NULL;
35 #define STATUS_PATH_MAX 512
37 #define quiet_log(fmt, args...) do { \
39 crm_trace(fmt, ##args); \
41 printf(fmt , ##args); \
45 #define NEW_NODE_TEMPLATE "//"XML_CIB_TAG_NODE"[@uname='%s']"
46 #define NODE_TEMPLATE "//"XML_CIB_TAG_STATE"[@uname='%s']"
47 #define RSC_TEMPLATE "//"XML_CIB_TAG_STATE"[@uname='%s']//"XML_LRM_TAG_RESOURCE"[@id='%s']"
51 inject_transient_attr(xmlNode * cib_node,
const char *name,
const char *value)
53 xmlNode *attrs = NULL;
54 xmlNode *instance_attrs = NULL;
56 const char *node_uuid =
ID(cib_node);
58 node_path = xmlGetNodePath(cib_node);
59 quiet_log(
" + Injecting attribute %s=%s into %s '%s'\n",
60 name, value, node_path,
ID(cib_node));
70 if (instance_attrs == NULL) {
79 update_failcounts(xmlNode * cib_node,
const char *resource,
const char *task,
80 guint interval_ms,
int rc)
85 }
else if ((rc == 7) && (interval_ms == 0)) {
90 char *now = crm_ttoa(time(NULL));
92 name = crm_failcount_name(resource, task, interval_ms);
93 inject_transient_attr(cib_node, name,
"value++");
96 name = crm_lastfailure_name(resource, task, interval_ms);
97 inject_transient_attr(cib_node, name, now);
104 create_node_entry(
cib_t * cib_conn,
const char *node)
128 create_op(xmlNode *cib_resource,
const char *task, guint interval_ms,
136 op->
rsc_id = strdup(
ID(cib_resource));
143 op->
t_run = (
unsigned int) time(NULL);
147 for (xop = __xml_first_child_element(cib_resource); xop != NULL;
148 xop = __xml_next_element(xop)) {
171 inject_node_state(
cib_t * cib_conn,
const char *node,
const char *uuid)
174 xmlNode *cib_object = NULL;
178 create_node_entry(cib_conn, node);
181 rc = cib_conn->
cmds->
query(cib_conn, xpath, &cib_object,
184 if (cib_object &&
ID(cib_object) == NULL) {
185 crm_err(
"Detected multiple node_state entries for xpath=%s, bailing", xpath);
193 char *found_uuid = NULL;
198 found_uuid = strdup(uuid);
209 rc = cib_conn->
cmds->
query(cib_conn, xpath, &cib_object,
211 crm_trace(
"injecting node state for %s. rc is %d", node, rc);
220 modify_node(
cib_t * cib_conn,
char *node, gboolean up)
222 xmlNode *cib_node = inject_node_state(cib_conn, node, NULL);
242 find_resource_xml(xmlNode * cib_node,
const char *resource)
244 xmlNode *match = NULL;
255 inject_resource(xmlNode * cib_node,
const char *resource,
const char *lrm_name,
256 const char *rclass,
const char *rtype,
const char *rprovider)
259 xmlNode *container = NULL;
260 xmlNode *cib_resource = NULL;
263 cib_resource = find_resource_xml(cib_node, resource);
264 if (cib_resource != NULL) {
272 if (strcmp(resource, lrm_name)) {
273 cib_resource = find_resource_xml(cib_node, lrm_name);
274 if (cib_resource != NULL) {
281 if (rclass == NULL || rtype == NULL) {
282 fprintf(stderr,
"Resource %s not found in the status section of %s."
283 " Please supply the class and type to continue\n", resource,
ID(cib_node));
292 fprintf(stderr,
"Invalid class for %s: %s\n", resource, rclass);
296 && (rprovider == NULL)) {
297 fprintf(stderr,
"Please specify the provider for resource %s\n", resource);
301 xpath = (
char *)xmlGetNodePath(cib_node);
302 crm_info(
"Injecting new resource %s into %s '%s'", lrm_name, xpath,
ID(cib_node));
307 const char *node_uuid =
ID(cib_node);
314 if (container == NULL) {
330 #define XPATH_MAX 1024
333 find_ticket_state(
cib_t * the_cib,
const char *ticket_id, xmlNode ** ticket_state_xml)
337 xmlNode *xml_search = NULL;
339 char *xpath_string = NULL;
342 *ticket_state_xml = NULL;
345 offset += snprintf(xpath_string + offset,
XPATH_MAX - offset,
"%s",
"/cib/status/tickets");
348 offset += snprintf(xpath_string + offset,
XPATH_MAX - offset,
"/%s[@id=\"%s\"]",
352 rc = the_cib->
cmds->
query(the_cib, xpath_string, &xml_search,
362 fprintf(stdout,
"Multiple ticket_states match ticket_id=%s\n", ticket_id);
364 *ticket_state_xml = xml_search;
366 *ticket_state_xml = xml_search;
375 set_ticket_state_attr(
const char *ticket_id,
const char *attr_name,
376 const char *attr_value,
cib_t * cib,
int cib_options)
379 xmlNode *xml_top = NULL;
380 xmlNode *ticket_state_xml = NULL;
382 rc = find_ticket_state(cib, ticket_id, &ticket_state_xml);
384 crm_debug(
"Found a match state for ticket: id=%s", ticket_id);
385 xml_top = ticket_state_xml;
387 }
else if (rc != -ENXIO) {
391 xmlNode *xml_obj = NULL;
399 crm_xml_add(ticket_state_xml, attr_name, attr_value);
419 xmlNode *cib_op = NULL;
420 xmlNode *cib_node = NULL;
421 xmlNode *cib_resource = NULL;
428 quiet_log(
" + Setting quorum: %s\n", quorum);
437 quiet_log(
" + Setting watchdog: %s\n", watchdog);
446 for (gIter = node_up; gIter != NULL; gIter = gIter->next) {
447 char *node = (
char *)gIter->data;
449 quiet_log(
" + Bringing node %s online\n", node);
450 cib_node = modify_node(cib, node, TRUE);
459 for (gIter = node_down; gIter != NULL; gIter = gIter->next) {
461 char *node = (
char *)gIter->data;
463 quiet_log(
" + Taking node %s offline\n", node);
464 cib_node = modify_node(cib, node, FALSE);
483 for (gIter = node_fail; gIter != NULL; gIter = gIter->next) {
484 char *node = (
char *)gIter->data;
487 cib_node = modify_node(cib, node, TRUE);
497 for (gIter = ticket_grant; gIter != NULL; gIter = gIter->next) {
498 char *ticket_id = (
char *)gIter->data;
500 quiet_log(
" + Granting ticket %s\n", ticket_id);
501 rc = set_ticket_state_attr(ticket_id,
"granted",
"true",
507 for (gIter = ticket_revoke; gIter != NULL; gIter = gIter->next) {
508 char *ticket_id = (
char *)gIter->data;
510 quiet_log(
" + Revoking ticket %s\n", ticket_id);
511 rc = set_ticket_state_attr(ticket_id,
"granted",
"false",
517 for (gIter = ticket_standby; gIter != NULL; gIter = gIter->next) {
518 char *ticket_id = (
char *)gIter->data;
520 quiet_log(
" + Making ticket %s standby\n", ticket_id);
521 rc = set_ticket_state_attr(ticket_id,
"standby",
"true",
527 for (gIter = ticket_activate; gIter != NULL; gIter = gIter->next) {
528 char *ticket_id = (
char *)gIter->data;
530 quiet_log(
" + Activating ticket %s\n", ticket_id);
531 rc = set_ticket_state_attr(ticket_id,
"standby",
"false",
537 for (gIter = op_inject; gIter != NULL; gIter = gIter->next) {
538 char *spec = (
char *)gIter->data;
542 guint interval_ms = 0;
547 char *resource = NULL;
549 const char *rtype = NULL;
550 const char *rclass = NULL;
551 const char *rprovider = NULL;
555 quiet_log(
" + Injecting %s into the configuration\n", spec);
557 key = calloc(1, strlen(spec) + 1);
558 node = calloc(1, strlen(spec) + 1);
559 rc = sscanf(spec,
"%[^@]@%[^=]=%d", key, node, &outcome);
561 fprintf(stderr,
"Invalid operation spec: %s. Only found %d fields\n", spec, rc);
571 fprintf(stderr,
" - Invalid resource name: %s\n", resource);
577 cib_node = inject_node_state(cib, node, NULL);
580 update_failcounts(cib_node, resource, task, interval_ms, outcome);
582 cib_resource = inject_resource(cib_node, resource, resource,
583 rclass, rtype, rprovider);
586 op = create_op(cib_resource, task, interval_ms, outcome);
589 cib_op = inject_op(cib_resource, op, 0);
611 quiet_log(
" * Pseudo action: %s%s%s\n", task, node ?
" on " :
"", node ? node :
"");
622 int target_outcome = 0;
624 const char *rtype = NULL;
625 const char *rclass = NULL;
626 const char *resource = NULL;
627 const char *rprovider = NULL;
628 const char *lrm_name = NULL;
632 xmlNode *cib_node = NULL;
633 xmlNode *cib_resource = NULL;
642 crm_info(
"Skipping %s op for %s", operation, node);
646 if (action_rsc == NULL) {
648 free(node); free(uuid);
668 quiet_log(
" * Resource action: %-15s %s on %s\n", resource, operation, node);
676 if (target_rc_s != NULL) {
683 cib_node = inject_node_state(fake_cib, node, (router_node? node : uuid));
686 cib_resource = inject_resource(cib_node, resource, lrm_name,
687 rclass, rtype, rprovider);
688 if (cib_resource == NULL) {
689 crm_err(
"invalid resource in transition");
690 free(node); free(uuid);
697 quiet_log(
" * Resource action: %-15s %s=%u on %s\n",
700 quiet_log(
" * Resource action: %-15s %s on %s\n", resource, op->
op_type, node);
703 for (gIter = fake_op_fail_list; gIter != NULL; gIter = gIter->next) {
704 char *spec = (
char *)gIter->data;
706 const char *match_name = NULL;
711 if (strncasecmp(key, spec, strlen(key)) == 0) {
712 match_name = resource;
716 if ((match_name == NULL) && strcmp(resource, lrm_name)) {
719 if (strncasecmp(key, spec, strlen(key)) == 0) {
720 match_name = lrm_name;
725 if (match_name != NULL) {
727 rc = sscanf(spec,
"%*[^=]=%d", (
int *) &op->
rc);
732 "Invalid failed operation spec: %s. Result code must be integer\n",
738 printf(
"\tPretending action %d failed with rc=%d\n", action->
id, op->
rc);
739 update_failcounts(cib_node, match_name, op->
op_type,
745 inject_op(cib_resource, op, target_outcome);
753 free(node); free(uuid);
770 quiet_log(
" * Cluster action: %s for %s on %s\n", task,
ID(rsc), node);
772 quiet_log(
" * Cluster action: %s on %s\n", task, node);
784 quiet_log(
" * Fencing %s (%s)\n", target, op);
788 xmlNode *cib_node = modify_node(fake_cib, target, FALSE);
801 snprintf(xpath,
STATUS_PATH_MAX,
"//node_state[@uname='%s']/%s", target,
830 fake_op_fail_list = op_fail_list;
832 quiet_log(
"\nExecuting cluster transition:\n");
838 fake_resource_list = data_set->
resources;
843 fake_resource_list = NULL;
851 fprintf(stdout,
"An invalid transition was produced\n");
854 if (quiet == FALSE) {
855 xmlNode *cib_object = NULL;
860 data_set->
input = cib_object;