root/tools/fake_transition.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. inject_transient_attr
  2. update_failcounts
  3. create_node_entry
  4. create_op
  5. inject_op
  6. inject_node_state
  7. modify_node
  8. find_resource_xml
  9. inject_resource
  10. find_ticket_state
  11. set_ticket_state_attr
  12. modify_configuration
  13. exec_pseudo_action
  14. exec_rsc_action
  15. exec_crmd_action
  16. exec_stonith_action
  17. run_simulation

   1 /*
   2  * Copyright (C) 2009 Andrew Beekhof <andrew@beekhof.net>
   3  *
   4  * This program is free software; you can redistribute it and/or
   5  * modify it under the terms of the GNU General Public
   6  * License as published by the Free Software Foundation; either
   7  * version 2 of the License, or (at your option) any later version.
   8  *
   9  * This software is distributed in the hope that it will be useful,
  10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  12  * General Public License for more details.
  13  *
  14  * You should have received a copy of the GNU General Public
  15  * License along with this library; if not, write to the Free Software
  16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  17  */
  18 
  19 #include <crm_internal.h>
  20 
  21 #include <stdio.h>
  22 #include <unistd.h>
  23 #include <stdlib.h>
  24 
  25 #include <sys/stat.h>
  26 #include <sys/param.h>
  27 #include <sys/types.h>
  28 #include <dirent.h>
  29 
  30 #include <crm/crm.h>
  31 #include <crm/cib.h>
  32 #include <crm/common/util.h>
  33 #include <crm/transition.h>
  34 #include <crm/common/iso8601.h>
  35 #include <crm/pengine/status.h>
  36 #include <allocate.h>
  37 #include "fake_transition.h"
  38 
  39 static bool fake_quiet = FALSE;
  40 static cib_t *fake_cib = NULL;
  41 static GListPtr fake_resource_list = NULL;
  42 static GListPtr fake_op_fail_list = NULL;
  43 gboolean bringing_nodes_online = FALSE;
  44 
  45 #define STATUS_PATH_MAX 512
  46 
  47 #define quiet_log(fmt, args...) do {              \
  48               if(fake_quiet) {                         \
  49                   crm_trace(fmt, ##args);         \
  50               } else {                            \
  51                   printf(fmt , ##args);           \
  52               }                                   \
  53     } while(0)
  54 
  55 #define new_node_template "//"XML_CIB_TAG_NODE"[@uname='%s']"
  56 #define node_template "//"XML_CIB_TAG_STATE"[@uname='%s']"
  57 #define rsc_template "//"XML_CIB_TAG_STATE"[@uname='%s']//"XML_LRM_TAG_RESOURCE"[@id='%s']"
  58 #define op_template  "//"XML_CIB_TAG_STATE"[@uname='%s']//"XML_LRM_TAG_RESOURCE"[@id='%s']/"XML_LRM_TAG_RSC_OP"[@id='%s']"
  59 /* #define op_template  "//"XML_CIB_TAG_STATE"[@uname='%s']//"XML_LRM_TAG_RESOURCE"[@id='%s']/"XML_LRM_TAG_RSC_OP"[@id='%s' and @"XML_LRM_ATTR_CALLID"='%d']" */
  60 
  61 
  62 static void
  63 inject_transient_attr(xmlNode * cib_node, const char *name, const char *value)
     /* [previous][next][first][last][top][bottom][index][help] */
  64 {
  65     xmlNode *attrs = NULL;
  66     xmlNode *instance_attrs = NULL;
  67     xmlChar *node_path;
  68     const char *node_uuid = ID(cib_node);
  69 
  70     node_path = xmlGetNodePath(cib_node);
  71     quiet_log(" + Injecting attribute %s=%s into %s '%s'\n",
  72               name, value, node_path, ID(cib_node));
  73     free(node_path);
  74 
  75     attrs = first_named_child(cib_node, XML_TAG_TRANSIENT_NODEATTRS);
  76     if (attrs == NULL) {
  77         attrs = create_xml_node(cib_node, XML_TAG_TRANSIENT_NODEATTRS);
  78         crm_xml_add(attrs, XML_ATTR_ID, node_uuid);
  79     }
  80 
  81     instance_attrs = first_named_child(attrs, XML_TAG_ATTR_SETS);
  82     if (instance_attrs == NULL) {
  83         instance_attrs = create_xml_node(attrs, XML_TAG_ATTR_SETS);
  84         crm_xml_add(instance_attrs, XML_ATTR_ID, node_uuid);
  85     }
  86 
  87     crm_create_nvpair_xml(instance_attrs, NULL, name, value);
  88 }
  89 
  90 static void
  91 update_failcounts(xmlNode * cib_node, const char *resource, const char *task,
     /* [previous][next][first][last][top][bottom][index][help] */
  92                   int interval, int rc)
  93 {
  94     if (rc == 0) {
  95         return;
  96 
  97     } else if (rc == 7 && interval == 0) {
  98         return;
  99 
 100     } else {
 101         char *name = NULL;
 102         char *now = crm_itoa(time(NULL));
 103 
 104         name = crm_failcount_name(resource, task, interval);
 105         inject_transient_attr(cib_node, name, "value++");
 106         free(name);
 107 
 108         name = crm_lastfailure_name(resource, task, interval);
 109         inject_transient_attr(cib_node, name, now);
 110         free(name);
 111         free(now);
 112     }
 113 }
 114 
 115 static void
 116 create_node_entry(cib_t * cib_conn, const char *node)
     /* [previous][next][first][last][top][bottom][index][help] */
 117 {
 118     int rc = pcmk_ok;
 119     int max = strlen(new_node_template) + strlen(node) + 1;
 120     char *xpath = NULL;
 121 
 122     xpath = calloc(1, max);
 123 
 124     snprintf(xpath, max, new_node_template, node);
 125     rc = cib_conn->cmds->query(cib_conn, xpath, NULL, cib_xpath | cib_sync_call | cib_scope_local);
 126 
 127     if (rc == -ENXIO) {
 128         xmlNode *cib_object = create_xml_node(NULL, XML_CIB_TAG_NODE);
 129 
 130         /* Using node uname as uuid ala corosync/openais */
 131         crm_xml_add(cib_object, XML_ATTR_ID, node);
 132         crm_xml_add(cib_object, XML_ATTR_UNAME, node);
 133         cib_conn->cmds->create(cib_conn, XML_CIB_TAG_NODES, cib_object,
 134                                cib_sync_call | cib_scope_local);
 135         /* Not bothering with subsequent query to see if it exists,
 136            we'll bomb out later in the call to query_node_uuid()... */
 137 
 138         free_xml(cib_object);
 139     }
 140 
 141     free(xpath);
 142 }
 143 
 144 static lrmd_event_data_t *
 145 create_op(xmlNode * cib_resource, const char *task, int interval, int outcome)
     /* [previous][next][first][last][top][bottom][index][help] */
 146 {
 147     lrmd_event_data_t *op = NULL;
 148     xmlNode *xop = NULL;
 149 
 150     op = calloc(1, sizeof(lrmd_event_data_t));
 151 
 152     op->rsc_id = strdup(ID(cib_resource));
 153     op->interval = interval;
 154     op->op_type = strdup(task);
 155 
 156     op->rc = outcome;
 157     op->op_status = 0;
 158     op->params = NULL;          /* TODO: Fill me in */
 159     op->t_run = time(NULL);
 160     op->t_rcchange = op->t_run;
 161 
 162     op->call_id = 0;
 163     for (xop = __xml_first_child(cib_resource); xop != NULL; xop = __xml_next(xop)) {
 164         int tmp = 0;
 165 
 166         crm_element_value_int(xop, XML_LRM_ATTR_CALLID, &tmp);
 167         if (tmp > op->call_id) {
 168             op->call_id = tmp;
 169         }
 170     }
 171     op->call_id++;
 172 
 173     return op;
 174 }
 175 
 176 static xmlNode *
 177 inject_op(xmlNode * cib_resource, lrmd_event_data_t * op, int target_rc)
     /* [previous][next][first][last][top][bottom][index][help] */
 178 {
 179     return create_operation_update(cib_resource, op, CRM_FEATURE_SET, target_rc, NULL, crm_system_name,
 180                                    LOG_DEBUG_2);
 181 }
 182 
 183 static xmlNode *
 184 inject_node_state(cib_t * cib_conn, const char *node, const char *uuid)
     /* [previous][next][first][last][top][bottom][index][help] */
 185 {
 186     int rc = pcmk_ok;
 187     xmlNode *cib_object = NULL;
 188     char *xpath = crm_strdup_printf(node_template, node);
 189 
 190     if (bringing_nodes_online) {
 191         create_node_entry(cib_conn, node);
 192     }
 193 
 194     rc = cib_conn->cmds->query(cib_conn, xpath, &cib_object,
 195                                cib_xpath | cib_sync_call | cib_scope_local);
 196 
 197     if (cib_object && ID(cib_object) == NULL) {
 198         crm_err("Detected multiple node_state entries for xpath=%s, bailing", xpath);
 199         crm_log_xml_warn(cib_object, "Duplicates");
 200         free(xpath);
 201         crm_exit(ENOTUNIQ);
 202         return NULL; // not reached, but makes static analysis happy
 203     }
 204 
 205     if (rc == -ENXIO) {
 206         char *found_uuid = NULL;
 207 
 208         if (uuid == NULL) {
 209             query_node_uuid(cib_conn, node, &found_uuid, NULL);
 210         } else {
 211             found_uuid = strdup(uuid);
 212         }
 213 
 214         cib_object = create_xml_node(NULL, XML_CIB_TAG_STATE);
 215         crm_xml_add(cib_object, XML_ATTR_UUID, found_uuid);
 216         crm_xml_add(cib_object, XML_ATTR_UNAME, node);
 217         cib_conn->cmds->create(cib_conn, XML_CIB_TAG_STATUS, cib_object,
 218                                cib_sync_call | cib_scope_local);
 219         free_xml(cib_object);
 220         free(found_uuid);
 221 
 222         rc = cib_conn->cmds->query(cib_conn, xpath, &cib_object,
 223                                    cib_xpath | cib_sync_call | cib_scope_local);
 224         crm_trace("injecting node state for %s. rc is %d", node, rc);
 225     }
 226 
 227     free(xpath);
 228     CRM_ASSERT(rc == pcmk_ok);
 229     return cib_object;
 230 }
 231 
 232 static xmlNode *
 233 modify_node(cib_t * cib_conn, char *node, gboolean up)
     /* [previous][next][first][last][top][bottom][index][help] */
 234 {
 235     xmlNode *cib_node = inject_node_state(cib_conn, node, NULL);
 236 
 237     if (up) {
 238         crm_xml_add(cib_node, XML_NODE_IN_CLUSTER, XML_BOOLEAN_YES);
 239         crm_xml_add(cib_node, XML_NODE_IS_PEER, ONLINESTATUS);
 240         crm_xml_add(cib_node, XML_NODE_JOIN_STATE, CRMD_JOINSTATE_MEMBER);
 241         crm_xml_add(cib_node, XML_NODE_EXPECTED, CRMD_JOINSTATE_MEMBER);
 242 
 243     } else {
 244         crm_xml_add(cib_node, XML_NODE_IN_CLUSTER, XML_BOOLEAN_NO);
 245         crm_xml_add(cib_node, XML_NODE_IS_PEER, OFFLINESTATUS);
 246         crm_xml_add(cib_node, XML_NODE_JOIN_STATE, CRMD_JOINSTATE_DOWN);
 247         crm_xml_add(cib_node, XML_NODE_EXPECTED, CRMD_JOINSTATE_DOWN);
 248     }
 249 
 250     crm_xml_add(cib_node, XML_ATTR_ORIGIN, crm_system_name);
 251     return cib_node;
 252 }
 253 
 254 static xmlNode *
 255 find_resource_xml(xmlNode * cib_node, const char *resource)
     /* [previous][next][first][last][top][bottom][index][help] */
 256 {
 257     char *xpath = NULL;
 258     xmlNode *match = NULL;
 259     const char *node = crm_element_value(cib_node, XML_ATTR_UNAME);
 260     int max = strlen(rsc_template) + strlen(node) + strlen(resource) + 1;
 261 
 262     xpath = calloc(1, max);
 263 
 264     snprintf(xpath, max, rsc_template, node, resource);
 265     match = get_xpath_object(xpath, cib_node, LOG_DEBUG_2);
 266 
 267     free(xpath);
 268     return match;
 269 }
 270 
 271 
 272 static xmlNode *
 273 inject_resource(xmlNode * cib_node, const char *resource, const char *rclass, const char *rtype,
     /* [previous][next][first][last][top][bottom][index][help] */
 274                 const char *rprovider)
 275 {
 276     xmlNode *lrm = NULL;
 277     xmlNode *container = NULL;
 278     xmlNode *cib_resource = NULL;
 279     char *xpath = NULL;
 280 
 281     cib_resource = find_resource_xml(cib_node, resource);
 282     if (cib_resource != NULL) {
 283         return cib_resource;
 284     }
 285 
 286     /* One day, add query for class, provider, type */
 287 
 288     if (rclass == NULL || rtype == NULL) {
 289         fprintf(stderr, "Resource %s not found in the status section of %s."
 290                 "  Please supply the class and type to continue\n", resource, ID(cib_node));
 291         return NULL;
 292 
 293     } else if (safe_str_neq(rclass, PCMK_RESOURCE_CLASS_OCF)
 294                && safe_str_neq(rclass, PCMK_RESOURCE_CLASS_STONITH)
 295                && safe_str_neq(rclass, PCMK_RESOURCE_CLASS_HB)
 296                && safe_str_neq(rclass, PCMK_RESOURCE_CLASS_SERVICE)
 297                && safe_str_neq(rclass, PCMK_RESOURCE_CLASS_UPSTART)
 298                && safe_str_neq(rclass, PCMK_RESOURCE_CLASS_SYSTEMD)
 299                && safe_str_neq(rclass, PCMK_RESOURCE_CLASS_LSB)) {
 300         fprintf(stderr, "Invalid class for %s: %s\n", resource, rclass);
 301         return NULL;
 302 
 303     } else if (crm_provider_required(rclass) && (rprovider == NULL)) {
 304         fprintf(stderr, "Please specify the provider for resource %s\n", resource);
 305         return NULL;
 306     }
 307 
 308     xpath = (char *)xmlGetNodePath(cib_node);
 309     crm_info("Injecting new resource %s into %s '%s'", resource, xpath, ID(cib_node));
 310     free(xpath);
 311 
 312     lrm = first_named_child(cib_node, XML_CIB_TAG_LRM);
 313     if (lrm == NULL) {
 314         const char *node_uuid = ID(cib_node);
 315 
 316         lrm = create_xml_node(cib_node, XML_CIB_TAG_LRM);
 317         crm_xml_add(lrm, XML_ATTR_ID, node_uuid);
 318     }
 319 
 320     container = first_named_child(lrm, XML_LRM_TAG_RESOURCES);
 321     if (container == NULL) {
 322         container = create_xml_node(lrm, XML_LRM_TAG_RESOURCES);
 323     }
 324 
 325     cib_resource = create_xml_node(container, XML_LRM_TAG_RESOURCE);
 326     crm_xml_add(cib_resource, XML_ATTR_ID, resource);
 327 
 328     crm_xml_add(cib_resource, XML_AGENT_ATTR_CLASS, rclass);
 329     crm_xml_add(cib_resource, XML_AGENT_ATTR_PROVIDER, rprovider);
 330     crm_xml_add(cib_resource, XML_ATTR_TYPE, rtype);
 331 
 332     return cib_resource;
 333 }
 334 
 335 #define XPATH_MAX 1024
 336 
 337 static int
 338 find_ticket_state(cib_t * the_cib, const char *ticket_id, xmlNode ** ticket_state_xml)
     /* [previous][next][first][last][top][bottom][index][help] */
 339 {
 340     int offset = 0;
 341     int rc = pcmk_ok;
 342     xmlNode *xml_search = NULL;
 343 
 344     char *xpath_string = NULL;
 345 
 346     CRM_ASSERT(ticket_state_xml != NULL);
 347     *ticket_state_xml = NULL;
 348 
 349     xpath_string = calloc(1, XPATH_MAX);
 350     offset += snprintf(xpath_string + offset, XPATH_MAX - offset, "%s", "/cib/status/tickets");
 351 
 352     if (ticket_id) {
 353         offset += snprintf(xpath_string + offset, XPATH_MAX - offset, "/%s[@id=\"%s\"]",
 354                            XML_CIB_TAG_TICKET_STATE, ticket_id);
 355     }
 356     CRM_LOG_ASSERT(offset > 0);
 357     rc = the_cib->cmds->query(the_cib, xpath_string, &xml_search,
 358                               cib_sync_call | cib_scope_local | cib_xpath);
 359 
 360     if (rc != pcmk_ok) {
 361         goto bail;
 362     }
 363 
 364     crm_log_xml_debug(xml_search, "Match");
 365     if (xml_has_children(xml_search)) {
 366         if (ticket_id) {
 367             fprintf(stdout, "Multiple ticket_states match ticket_id=%s\n", ticket_id);
 368         }
 369         *ticket_state_xml = xml_search;
 370     } else {
 371         *ticket_state_xml = xml_search;
 372     }
 373 
 374   bail:
 375     free(xpath_string);
 376     return rc;
 377 }
 378 
 379 static int
 380 set_ticket_state_attr(const char *ticket_id, const char *attr_name,
     /* [previous][next][first][last][top][bottom][index][help] */
 381                       const char *attr_value, cib_t * cib, int cib_options)
 382 {
 383     int rc = pcmk_ok;
 384     xmlNode *xml_top = NULL;
 385     xmlNode *ticket_state_xml = NULL;
 386 
 387     rc = find_ticket_state(cib, ticket_id, &ticket_state_xml);
 388     if (rc == pcmk_ok) {
 389         crm_debug("Found a match state for ticket: id=%s", ticket_id);
 390         xml_top = ticket_state_xml;
 391 
 392     } else if (rc != -ENXIO) {
 393         return rc;
 394 
 395     } else {
 396         xmlNode *xml_obj = NULL;
 397 
 398         xml_top = create_xml_node(NULL, XML_CIB_TAG_STATUS);
 399         xml_obj = create_xml_node(xml_top, XML_CIB_TAG_TICKETS);
 400         ticket_state_xml = create_xml_node(xml_obj, XML_CIB_TAG_TICKET_STATE);
 401         crm_xml_add(ticket_state_xml, XML_ATTR_ID, ticket_id);
 402     }
 403 
 404     crm_xml_add(ticket_state_xml, attr_name, attr_value);
 405 
 406     crm_log_xml_debug(xml_top, "Update");
 407 
 408     rc = cib->cmds->modify(cib, XML_CIB_TAG_STATUS, xml_top, cib_options);
 409 
 410     free_xml(xml_top);
 411 
 412     return rc;
 413 }
 414 
 415 void
 416 modify_configuration(pe_working_set_t * data_set, cib_t *cib,
     /* [previous][next][first][last][top][bottom][index][help] */
 417                      const char *quorum, const char *watchdog, GListPtr node_up, GListPtr node_down, GListPtr node_fail,
 418                      GListPtr op_inject, GListPtr ticket_grant, GListPtr ticket_revoke,
 419                      GListPtr ticket_standby, GListPtr ticket_activate)
 420 {
 421     int rc = pcmk_ok;
 422     GListPtr gIter = NULL;
 423 
 424     xmlNode *cib_op = NULL;
 425     xmlNode *cib_node = NULL;
 426     xmlNode *cib_resource = NULL;
 427 
 428     lrmd_event_data_t *op = NULL;
 429 
 430     if (quorum) {
 431         xmlNode *top = create_xml_node(NULL, XML_TAG_CIB);
 432 
 433         quiet_log(" + Setting quorum: %s\n", quorum);
 434         /* crm_xml_add(top, XML_ATTR_DC_UUID, dc_uuid);      */
 435         crm_xml_add(top, XML_ATTR_HAVE_QUORUM, quorum);
 436 
 437         rc = cib->cmds->modify(cib, NULL, top, cib_sync_call | cib_scope_local);
 438         CRM_ASSERT(rc == pcmk_ok);
 439     }
 440 
 441     if (watchdog) {
 442         quiet_log(" + Setting watchdog: %s\n", watchdog);
 443 
 444         rc = update_attr_delegate(cib, cib_sync_call | cib_scope_local,
 445                              XML_CIB_TAG_CRMCONFIG, NULL, NULL, NULL, NULL,
 446                              XML_ATTR_HAVE_WATCHDOG, watchdog, FALSE, NULL, NULL);
 447 
 448         CRM_ASSERT(rc == pcmk_ok);
 449     }
 450 
 451     for (gIter = node_up; gIter != NULL; gIter = gIter->next) {
 452         char *node = (char *)gIter->data;
 453 
 454         quiet_log(" + Bringing node %s online\n", node);
 455         cib_node = modify_node(cib, node, TRUE);
 456         CRM_ASSERT(cib_node != NULL);
 457 
 458         rc = cib->cmds->modify(cib, XML_CIB_TAG_STATUS, cib_node,
 459                                       cib_sync_call | cib_scope_local);
 460         CRM_ASSERT(rc == pcmk_ok);
 461         free_xml(cib_node);
 462     }
 463 
 464     for (gIter = node_down; gIter != NULL; gIter = gIter->next) {
 465         char xpath[STATUS_PATH_MAX];
 466         char *node = (char *)gIter->data;
 467 
 468         quiet_log(" + Taking node %s offline\n", node);
 469         cib_node = modify_node(cib, node, FALSE);
 470         CRM_ASSERT(cib_node != NULL);
 471 
 472         rc = cib->cmds->modify(cib, XML_CIB_TAG_STATUS, cib_node,
 473                                       cib_sync_call | cib_scope_local);
 474         CRM_ASSERT(rc == pcmk_ok);
 475         free_xml(cib_node);
 476 
 477         snprintf(xpath, STATUS_PATH_MAX, "//node_state[@uname='%s']/%s", node, XML_CIB_TAG_LRM);
 478         cib->cmds->delete(cib, xpath, NULL,
 479                                       cib_xpath | cib_sync_call | cib_scope_local);
 480 
 481         snprintf(xpath, STATUS_PATH_MAX, "//node_state[@uname='%s']/%s", node,
 482                  XML_TAG_TRANSIENT_NODEATTRS);
 483         cib->cmds->delete(cib, xpath, NULL,
 484                                       cib_xpath | cib_sync_call | cib_scope_local);
 485 
 486     }
 487 
 488     for (gIter = node_fail; gIter != NULL; gIter = gIter->next) {
 489         char *node = (char *)gIter->data;
 490 
 491         quiet_log(" + Failing node %s\n", node);
 492         cib_node = modify_node(cib, node, TRUE);
 493         crm_xml_add(cib_node, XML_NODE_IN_CLUSTER, XML_BOOLEAN_NO);
 494         CRM_ASSERT(cib_node != NULL);
 495 
 496         rc = cib->cmds->modify(cib, XML_CIB_TAG_STATUS, cib_node,
 497                                       cib_sync_call | cib_scope_local);
 498         CRM_ASSERT(rc == pcmk_ok);
 499         free_xml(cib_node);
 500     }
 501 
 502     for (gIter = ticket_grant; gIter != NULL; gIter = gIter->next) {
 503         char *ticket_id = (char *)gIter->data;
 504 
 505         quiet_log(" + Granting ticket %s\n", ticket_id);
 506         rc = set_ticket_state_attr(ticket_id, "granted", "true",
 507                                    cib, cib_sync_call | cib_scope_local);
 508 
 509         CRM_ASSERT(rc == pcmk_ok);
 510     }
 511 
 512     for (gIter = ticket_revoke; gIter != NULL; gIter = gIter->next) {
 513         char *ticket_id = (char *)gIter->data;
 514 
 515         quiet_log(" + Revoking ticket %s\n", ticket_id);
 516         rc = set_ticket_state_attr(ticket_id, "granted", "false",
 517                                    cib, cib_sync_call | cib_scope_local);
 518 
 519         CRM_ASSERT(rc == pcmk_ok);
 520     }
 521 
 522     for (gIter = ticket_standby; gIter != NULL; gIter = gIter->next) {
 523         char *ticket_id = (char *)gIter->data;
 524 
 525         quiet_log(" + Making ticket %s standby\n", ticket_id);
 526         rc = set_ticket_state_attr(ticket_id, "standby", "true",
 527                                    cib, cib_sync_call | cib_scope_local);
 528 
 529         CRM_ASSERT(rc == pcmk_ok);
 530     }
 531 
 532     for (gIter = ticket_activate; gIter != NULL; gIter = gIter->next) {
 533         char *ticket_id = (char *)gIter->data;
 534 
 535         quiet_log(" + Activating ticket %s\n", ticket_id);
 536         rc = set_ticket_state_attr(ticket_id, "standby", "false",
 537                                    cib, cib_sync_call | cib_scope_local);
 538 
 539         CRM_ASSERT(rc == pcmk_ok);
 540     }
 541 
 542     for (gIter = op_inject; gIter != NULL; gIter = gIter->next) {
 543         char *spec = (char *)gIter->data;
 544 
 545         int rc = 0;
 546         int outcome = 0;
 547         int interval = 0;
 548 
 549         char *key = NULL;
 550         char *node = NULL;
 551         char *task = NULL;
 552         char *resource = NULL;
 553 
 554         const char *rtype = NULL;
 555         const char *rclass = NULL;
 556         const char *rprovider = NULL;
 557 
 558         resource_t *rsc = NULL;
 559 
 560         quiet_log(" + Injecting %s into the configuration\n", spec);
 561 
 562         key = calloc(1, strlen(spec) + 1);
 563         node = calloc(1, strlen(spec) + 1);
 564         rc = sscanf(spec, "%[^@]@%[^=]=%d", key, node, &outcome);
 565         if (rc != 3) {
 566             fprintf(stderr, "Invalid operation spec: %s.  Only found %d fields\n", spec, rc);
 567             free(key);
 568             free(node);
 569             continue;
 570         }
 571 
 572         parse_op_key(key, &resource, &task, &interval);
 573 
 574         rsc = pe_find_resource(data_set->resources, resource);
 575         if (rsc == NULL) {
 576             fprintf(stderr, " - Invalid resource name: %s\n", resource);
 577         } else {
 578             rclass = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS);
 579             rtype = crm_element_value(rsc->xml, XML_ATTR_TYPE);
 580             rprovider = crm_element_value(rsc->xml, XML_AGENT_ATTR_PROVIDER);
 581 
 582             cib_node = inject_node_state(cib, node, NULL);
 583             CRM_ASSERT(cib_node != NULL);
 584 
 585             update_failcounts(cib_node, resource, task, interval, outcome);
 586 
 587             cib_resource = inject_resource(cib_node, resource, rclass, rtype, rprovider);
 588             CRM_ASSERT(cib_resource != NULL);
 589 
 590             op = create_op(cib_resource, task, interval, outcome);
 591             CRM_ASSERT(op != NULL);
 592 
 593             cib_op = inject_op(cib_resource, op, 0);
 594             CRM_ASSERT(cib_op != NULL);
 595             lrmd_free_event(op);
 596 
 597             rc = cib->cmds->modify(cib, XML_CIB_TAG_STATUS, cib_node,
 598                                           cib_sync_call | cib_scope_local);
 599             CRM_ASSERT(rc == pcmk_ok);
 600         }
 601         free(task);
 602         free(node);
 603         free(key);
 604     }
 605 }
 606 
 607 static gboolean
 608 exec_pseudo_action(crm_graph_t * graph, crm_action_t * action)
     /* [previous][next][first][last][top][bottom][index][help] */
 609 {
 610     const char *node = crm_element_value(action->xml, XML_LRM_ATTR_TARGET);
 611     const char *task = crm_element_value(action->xml, XML_LRM_ATTR_TASK_KEY);
 612 
 613     action->confirmed = TRUE;
 614 
 615     quiet_log(" * Pseudo action:   %s%s%s\n", task, node ? " on " : "", node ? node : "");
 616     update_graph(graph, action);
 617     return TRUE;
 618 }
 619 
 620 static gboolean
 621 exec_rsc_action(crm_graph_t * graph, crm_action_t * action)
     /* [previous][next][first][last][top][bottom][index][help] */
 622 {
 623     int rc = 0;
 624     GListPtr gIter = NULL;
 625     lrmd_event_data_t *op = NULL;
 626     int target_outcome = 0;
 627     gboolean uname_is_uuid = FALSE;
 628 
 629     const char *rtype = NULL;
 630     const char *rclass = NULL;
 631     const char *resource = NULL;
 632     const char *rprovider = NULL;
 633     const char *operation = crm_element_value(action->xml, "operation");
 634     const char *target_rc_s = crm_meta_value(action->params, XML_ATTR_TE_TARGET_RC);
 635 
 636     xmlNode *cib_node = NULL;
 637     xmlNode *cib_resource = NULL;
 638     xmlNode *action_rsc = first_named_child(action->xml, XML_CIB_TAG_RESOURCE);
 639 
 640     char *node = crm_element_value_copy(action->xml, XML_LRM_ATTR_TARGET);
 641     char *uuid = crm_element_value_copy(action->xml, XML_LRM_ATTR_TARGET_UUID);
 642     const char *router_node = crm_element_value(action->xml, XML_LRM_ATTR_ROUTER_NODE);
 643 
 644     if (safe_str_eq(operation, CRM_OP_PROBED)
 645         || safe_str_eq(operation, CRM_OP_REPROBE)) {
 646         crm_info("Skipping %s op for %s", operation, node);
 647         goto done;
 648     }
 649 
 650     if (action_rsc == NULL) {
 651         crm_log_xml_err(action->xml, "Bad");
 652         free(node); free(uuid);
 653         return FALSE;
 654     }
 655 
 656     /* Look for the preferred name
 657      * If not found, try the expected 'local' name
 658      * If not found use the preferred name anyway
 659      */
 660     resource = crm_element_value(action_rsc, XML_ATTR_ID);
 661     if (pe_find_resource(fake_resource_list, resource) == NULL) {
 662         const char *longname = crm_element_value(action_rsc, XML_ATTR_ID_LONG);
 663 
 664         if (pe_find_resource(fake_resource_list, longname)) {
 665             resource = longname;
 666         }
 667     }
 668 
 669     if (safe_str_eq(operation, "delete") || safe_str_eq(operation, RSC_METADATA)) {
 670         quiet_log(" * Resource action: %-15s %s on %s\n", resource, operation, node);
 671         goto done;
 672     }
 673 
 674     rclass = crm_element_value(action_rsc, XML_AGENT_ATTR_CLASS);
 675     rtype = crm_element_value(action_rsc, XML_ATTR_TYPE);
 676     rprovider = crm_element_value(action_rsc, XML_AGENT_ATTR_PROVIDER);
 677 
 678     if (target_rc_s != NULL) {
 679         target_outcome = crm_parse_int(target_rc_s, "0");
 680     }
 681 
 682     CRM_ASSERT(fake_cib->cmds->query(fake_cib, NULL, NULL, cib_sync_call | cib_scope_local) ==
 683                pcmk_ok);
 684 
 685     if (router_node) {
 686         uname_is_uuid = TRUE;
 687     }
 688 
 689     cib_node = inject_node_state(fake_cib, node, uname_is_uuid ? node : uuid);
 690     CRM_ASSERT(cib_node != NULL);
 691 
 692     cib_resource = inject_resource(cib_node, resource, rclass, rtype, rprovider);
 693     CRM_ASSERT(cib_resource != NULL);
 694 
 695     op = convert_graph_action(cib_resource, action, 0, target_outcome);
 696     if (op->interval) {
 697         quiet_log(" * Resource action: %-15s %s=%d on %s\n", resource, op->op_type, op->interval,
 698                   node);
 699     } else {
 700         quiet_log(" * Resource action: %-15s %s on %s\n", resource, op->op_type, node);
 701     }
 702 
 703     for (gIter = fake_op_fail_list; gIter != NULL; gIter = gIter->next) {
 704         char *spec = (char *)gIter->data;
 705         char *key = NULL;
 706 
 707         key = calloc(1, 1 + strlen(spec));
 708         snprintf(key, strlen(spec), "%s_%s_%d@%s=", resource, op->op_type, op->interval, node);
 709 
 710         if (strncasecmp(key, spec, strlen(key)) == 0) {
 711             rc = sscanf(spec, "%*[^=]=%d", (int *) &op->rc);
 712             // ${resource}_${task}_${interval}@${node}=${rc}
 713 
 714             if (rc != 1) {
 715                 fprintf(stderr,
 716                         "Invalid failed operation spec: %s. Result code must be integer\n",
 717                         spec);
 718                 free(key);
 719                 continue;
 720             }
 721             action->failed = TRUE;
 722             graph->abort_priority = INFINITY;
 723             printf("\tPretending action %d failed with rc=%d\n", action->id, op->rc);
 724             update_failcounts(cib_node, resource, op->op_type, op->interval, op->rc);
 725             free(key);
 726             break;
 727         }
 728         free(key);
 729     }
 730 
 731     inject_op(cib_resource, op, target_outcome);
 732     lrmd_free_event(op);
 733 
 734     rc = fake_cib->cmds->modify(fake_cib, XML_CIB_TAG_STATUS, cib_node,
 735                                   cib_sync_call | cib_scope_local);
 736     CRM_ASSERT(rc == pcmk_ok);
 737 
 738   done:
 739     free(node); free(uuid);
 740     free_xml(cib_node);
 741     action->confirmed = TRUE;
 742     update_graph(graph, action);
 743     return TRUE;
 744 }
 745 
 746 static gboolean
 747 exec_crmd_action(crm_graph_t * graph, crm_action_t * action)
     /* [previous][next][first][last][top][bottom][index][help] */
 748 {
 749     const char *node = crm_element_value(action->xml, XML_LRM_ATTR_TARGET);
 750     const char *task = crm_element_value(action->xml, XML_LRM_ATTR_TASK);
 751     xmlNode *rsc = first_named_child(action->xml, XML_CIB_TAG_RESOURCE);
 752 
 753     action->confirmed = TRUE;
 754 
 755     if(rsc) {
 756         quiet_log(" * Cluster action:  %s for %s on %s\n", task, ID(rsc), node);
 757     } else {
 758         quiet_log(" * Cluster action:  %s on %s\n", task, node);
 759     }
 760     update_graph(graph, action);
 761     return TRUE;
 762 }
 763 
 764 static gboolean
 765 exec_stonith_action(crm_graph_t * graph, crm_action_t * action)
     /* [previous][next][first][last][top][bottom][index][help] */
 766 {
 767     const char *op = crm_meta_value(action->params, "stonith_action");
 768     char *target = crm_element_value_copy(action->xml, XML_LRM_ATTR_TARGET);
 769 
 770     quiet_log(" * Fencing %s (%s)\n", target, op);
 771     if(safe_str_neq(op, "on")) {
 772         int rc = 0;
 773         char xpath[STATUS_PATH_MAX];
 774         xmlNode *cib_node = modify_node(fake_cib, target, FALSE);
 775 
 776         crm_xml_add(cib_node, XML_ATTR_ORIGIN, __FUNCTION__);
 777         CRM_ASSERT(cib_node != NULL);
 778 
 779         rc = fake_cib->cmds->replace(fake_cib, XML_CIB_TAG_STATUS, cib_node,
 780                                    cib_sync_call | cib_scope_local);
 781         CRM_ASSERT(rc == pcmk_ok);
 782 
 783         snprintf(xpath, STATUS_PATH_MAX, "//node_state[@uname='%s']/%s", target, XML_CIB_TAG_LRM);
 784         fake_cib->cmds->delete(fake_cib, xpath, NULL,
 785                                       cib_xpath | cib_sync_call | cib_scope_local);
 786 
 787         snprintf(xpath, STATUS_PATH_MAX, "//node_state[@uname='%s']/%s", target,
 788                  XML_TAG_TRANSIENT_NODEATTRS);
 789         fake_cib->cmds->delete(fake_cib, xpath, NULL,
 790                                       cib_xpath | cib_sync_call | cib_scope_local);
 791 
 792         free_xml(cib_node);
 793     }
 794 
 795     action->confirmed = TRUE;
 796     update_graph(graph, action);
 797     free(target);
 798     return TRUE;
 799 }
 800 
 801 int
 802 run_simulation(pe_working_set_t * data_set, cib_t *cib, GListPtr op_fail_list, bool quiet)
     /* [previous][next][first][last][top][bottom][index][help] */
 803 {
 804     crm_graph_t *transition = NULL;
 805     enum transition_status graph_rc = -1;
 806 
 807     crm_graph_functions_t exec_fns = {
 808         exec_pseudo_action,
 809         exec_rsc_action,
 810         exec_crmd_action,
 811         exec_stonith_action,
 812     };
 813 
 814     fake_cib = cib;
 815     fake_quiet = quiet;
 816     fake_op_fail_list = op_fail_list;
 817 
 818     quiet_log("\nExecuting cluster transition:\n");
 819 
 820     set_graph_functions(&exec_fns);
 821     transition = unpack_graph(data_set->graph, crm_system_name);
 822     print_graph(LOG_DEBUG, transition);
 823 
 824     fake_resource_list = data_set->resources;
 825     do {
 826         graph_rc = run_graph(transition);
 827 
 828     } while (graph_rc == transition_active);
 829     fake_resource_list = NULL;
 830 
 831     if (graph_rc != transition_complete) {
 832         fprintf(stdout, "Transition failed: %s\n", transition_status(graph_rc));
 833         print_graph(LOG_ERR, transition);
 834     }
 835     destroy_graph(transition);
 836     if (graph_rc != transition_complete) {
 837         fprintf(stdout, "An invalid transition was produced\n");
 838     }
 839 
 840     if (quiet == FALSE) {
 841         xmlNode *cib_object = NULL;
 842         int rc = fake_cib->cmds->query(fake_cib, NULL, &cib_object, cib_sync_call | cib_scope_local);
 843 
 844         CRM_ASSERT(rc == pcmk_ok);
 845         cleanup_alloc_calculations(data_set);
 846         data_set->input = cib_object;
 847     }
 848 
 849     if (graph_rc != transition_complete) {
 850         return graph_rc;
 851     }
 852     return 0;
 853 }

/* [previous][next][first][last][top][bottom][index][help] */