root/lib/pacemaker/pcmk_trans_unpack.c

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

DEFINITIONS

This source file includes following definitions.
  1. unpack_action
  2. unpack_synapse
  3. unpack_graph
  4. destroy_action
  5. destroy_synapse
  6. destroy_graph
  7. convert_graph_action

   1 /*
   2  * Copyright 2004-2021 the Pacemaker project contributors
   3  *
   4  * The version control history for this file may have further details.
   5  *
   6  * This source code is licensed under the GNU Lesser General Public License
   7  * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
   8  */
   9 
  10 #include <crm_internal.h>
  11 
  12 #include <sys/param.h>
  13 #include <sys/stat.h>
  14 
  15 #include <crm/crm.h>
  16 #include <crm/msg_xml.h>
  17 #include <crm/common/xml.h>
  18 #include <crm/common/xml_internal.h>
  19 #include <pacemaker-internal.h>
  20 
  21 static crm_action_t *
  22 unpack_action(synapse_t * parent, xmlNode * xml_action)
     /* [previous][next][first][last][top][bottom][index][help] */
  23 {
  24     crm_action_t *action = NULL;
  25     const char *value = crm_element_value(xml_action, XML_ATTR_ID);
  26 
  27     if (value == NULL) {
  28         crm_err("Actions must have an id!");
  29         crm_log_xml_trace(xml_action, "Action with missing id");
  30         return NULL;
  31     }
  32 
  33     action = calloc(1, sizeof(crm_action_t));
  34     if (action == NULL) {
  35         crm_perror(LOG_CRIT, "Cannot unpack action");
  36         crm_log_xml_trace(xml_action, "Lost action");
  37         return NULL;
  38     }
  39 
  40     pcmk__scan_min_int(value, &(action->id), -1);
  41     action->type = action_type_rsc;
  42     action->xml = copy_xml(xml_action);
  43     action->synapse = parent;
  44 
  45     if (pcmk__str_eq(crm_element_name(action->xml), XML_GRAPH_TAG_RSC_OP, pcmk__str_casei)) {
  46         action->type = action_type_rsc;
  47 
  48     } else if (pcmk__str_eq(crm_element_name(action->xml), XML_GRAPH_TAG_PSEUDO_EVENT, pcmk__str_casei)) {
  49         action->type = action_type_pseudo;
  50 
  51     } else if (pcmk__str_eq(crm_element_name(action->xml), XML_GRAPH_TAG_CRM_EVENT, pcmk__str_casei)) {
  52         action->type = action_type_crm;
  53     }
  54 
  55     action->params = xml2list(action->xml);
  56 
  57     value = g_hash_table_lookup(action->params, "CRM_meta_timeout");
  58     pcmk__scan_min_int(value, &(action->timeout), 0);
  59 
  60     /* Take start-delay into account for the timeout of the action timer */
  61     value = g_hash_table_lookup(action->params, "CRM_meta_start_delay");
  62     {
  63         int start_delay;
  64 
  65         pcmk__scan_min_int(value, &start_delay, 0);
  66         action->timeout += start_delay;
  67     }
  68 
  69     if (pcmk__guint_from_hash(action->params,
  70                               CRM_META "_" XML_LRM_ATTR_INTERVAL, 0,
  71                               &(action->interval_ms)) != pcmk_rc_ok) {
  72         action->interval_ms = 0;
  73     }
  74 
  75     value = g_hash_table_lookup(action->params, "CRM_meta_can_fail");
  76     if (value != NULL) {
  77         crm_str_to_boolean(value, &(action->can_fail));
  78 #ifndef PCMK__COMPAT_2_0
  79         if (action->can_fail) {
  80             crm_warn("Support for the can_fail meta-attribute is deprecated"
  81                      " and will be removed in a future release");
  82         }
  83 #endif
  84     }
  85 
  86     crm_trace("Action %d has timer set to %dms", action->id, action->timeout);
  87 
  88     return action;
  89 }
  90 
  91 static synapse_t *
  92 unpack_synapse(crm_graph_t * new_graph, xmlNode * xml_synapse)
     /* [previous][next][first][last][top][bottom][index][help] */
  93 {
  94     const char *value = NULL;
  95     xmlNode *inputs = NULL;
  96     xmlNode *action_set = NULL;
  97     synapse_t *new_synapse = NULL;
  98 
  99     CRM_CHECK(xml_synapse != NULL, return NULL);
 100     crm_trace("looking in synapse %s", ID(xml_synapse));
 101 
 102     new_synapse = calloc(1, sizeof(synapse_t));
 103     pcmk__scan_min_int(ID(xml_synapse), &(new_synapse->id), 0);
 104 
 105     value = crm_element_value(xml_synapse, XML_CIB_ATTR_PRIORITY);
 106     pcmk__scan_min_int(value, &(new_synapse->priority), 0);
 107 
 108     CRM_CHECK(new_synapse->id >= 0, free(new_synapse);
 109               return NULL);
 110 
 111     new_graph->num_synapses++;
 112 
 113     crm_trace("look for actions in synapse %s", crm_element_value(xml_synapse, XML_ATTR_ID));
 114 
 115     for (action_set = pcmk__xml_first_child(xml_synapse); action_set != NULL;
 116          action_set = pcmk__xml_next(action_set)) {
 117 
 118         if (pcmk__str_eq((const char *)action_set->name, "action_set",
 119                          pcmk__str_none)) {
 120             xmlNode *action = NULL;
 121 
 122             for (action = pcmk__xml_first_child(action_set); action != NULL;
 123                  action = pcmk__xml_next(action)) {
 124                 crm_action_t *new_action = unpack_action(new_synapse, action);
 125 
 126                 if (new_action == NULL) {
 127                     continue;
 128                 }
 129 
 130                 new_graph->num_actions++;
 131 
 132                 crm_trace("Adding action %d to synapse %d", new_action->id, new_synapse->id);
 133 
 134                 new_synapse->actions = g_list_append(new_synapse->actions, new_action);
 135             }
 136         }
 137     }
 138 
 139     crm_trace("look for inputs in synapse %s", ID(xml_synapse));
 140 
 141     for (inputs = pcmk__xml_first_child(xml_synapse); inputs != NULL;
 142          inputs = pcmk__xml_next(inputs)) {
 143 
 144         if (pcmk__str_eq((const char *)inputs->name, "inputs", pcmk__str_none)) {
 145             xmlNode *trigger = NULL;
 146 
 147             for (trigger = pcmk__xml_first_child(inputs); trigger != NULL;
 148                  trigger = pcmk__xml_next(trigger)) {
 149                 xmlNode *input = NULL;
 150 
 151                 for (input = pcmk__xml_first_child(trigger); input != NULL;
 152                      input = pcmk__xml_next(input)) {
 153                     crm_action_t *new_input = unpack_action(new_synapse, input);
 154 
 155                     if (new_input == NULL) {
 156                         continue;
 157                     }
 158 
 159                     crm_trace("Adding input %d to synapse %d", new_input->id, new_synapse->id);
 160 
 161                     new_synapse->inputs = g_list_append(new_synapse->inputs, new_input);
 162                 }
 163             }
 164         }
 165     }
 166 
 167     return new_synapse;
 168 }
 169 
 170 static void destroy_action(crm_action_t * action);
 171 
 172 crm_graph_t *
 173 unpack_graph(xmlNode * xml_graph, const char *reference)
     /* [previous][next][first][last][top][bottom][index][help] */
 174 {
 175 /*
 176   <transition_graph>
 177   <synapse>
 178   <action_set>
 179   <rsc_op id="2"
 180   ...
 181   <inputs>
 182   <rsc_op id="2"
 183   ...
 184 */
 185     crm_graph_t *new_graph = NULL;
 186     const char *t_id = NULL;
 187     const char *time = NULL;
 188     xmlNode *synapse = NULL;
 189 
 190     new_graph = calloc(1, sizeof(crm_graph_t));
 191 
 192     new_graph->id = -1;
 193     new_graph->abort_priority = 0;
 194     new_graph->network_delay = 0;
 195     new_graph->stonith_timeout = 0;
 196     new_graph->completion_action = tg_done;
 197 
 198     if (reference) {
 199         new_graph->source = strdup(reference);
 200     } else {
 201         new_graph->source = strdup("unknown");
 202     }
 203 
 204     if (xml_graph != NULL) {
 205         t_id = crm_element_value(xml_graph, "transition_id");
 206         CRM_CHECK(t_id != NULL, free(new_graph);
 207                   return NULL);
 208         pcmk__scan_min_int(t_id, &(new_graph->id), -1);
 209 
 210         time = crm_element_value(xml_graph, "cluster-delay");
 211         CRM_CHECK(time != NULL, free(new_graph);
 212                   return NULL);
 213         new_graph->network_delay = crm_parse_interval_spec(time);
 214 
 215         time = crm_element_value(xml_graph, "stonith-timeout");
 216         if (time == NULL) {
 217             new_graph->stonith_timeout = new_graph->network_delay;
 218         } else {
 219             new_graph->stonith_timeout = crm_parse_interval_spec(time);
 220         }
 221 
 222         // Use 0 (dynamic limit) as default/invalid, -1 (no limit) as minimum
 223         t_id = crm_element_value(xml_graph, "batch-limit");
 224         if ((t_id == NULL)
 225             || (pcmk__scan_min_int(t_id, &(new_graph->batch_limit),
 226                                    -1) != pcmk_rc_ok)) {
 227             new_graph->batch_limit = 0;
 228         }
 229 
 230         t_id = crm_element_value(xml_graph, "migration-limit");
 231         pcmk__scan_min_int(t_id, &(new_graph->migration_limit), -1);
 232     }
 233 
 234     for (synapse = pcmk__xml_first_child(xml_graph); synapse != NULL;
 235          synapse = pcmk__xml_next(synapse)) {
 236 
 237         if (pcmk__str_eq((const char *)synapse->name, "synapse", pcmk__str_none)) {
 238             synapse_t *new_synapse = unpack_synapse(new_graph, synapse);
 239 
 240             if (new_synapse != NULL) {
 241                 new_graph->synapses = g_list_append(new_graph->synapses, new_synapse);
 242             }
 243         }
 244     }
 245 
 246     crm_debug("Unpacked transition %d: %d actions in %d synapses",
 247               new_graph->id, new_graph->num_actions, new_graph->num_synapses);
 248 
 249     return new_graph;
 250 }
 251 
 252 static void
 253 destroy_action(crm_action_t * action)
     /* [previous][next][first][last][top][bottom][index][help] */
 254 {
 255     if (action->timer && action->timer->source_id != 0) {
 256         crm_warn("Cancelling timer for action %d (src=%d)", action->id, action->timer->source_id);
 257         g_source_remove(action->timer->source_id);
 258     }
 259     if (action->params) {
 260         g_hash_table_destroy(action->params);
 261     }
 262     free_xml(action->xml);
 263     free(action->timer);
 264     free(action);
 265 }
 266 
 267 static void
 268 destroy_synapse(synapse_t * synapse)
     /* [previous][next][first][last][top][bottom][index][help] */
 269 {
 270     while (synapse->actions != NULL) {
 271         crm_action_t *action = g_list_nth_data(synapse->actions, 0);
 272 
 273         synapse->actions = g_list_remove(synapse->actions, action);
 274         destroy_action(action);
 275     }
 276 
 277     while (synapse->inputs != NULL) {
 278         crm_action_t *action = g_list_nth_data(synapse->inputs, 0);
 279 
 280         synapse->inputs = g_list_remove(synapse->inputs, action);
 281         destroy_action(action);
 282     }
 283     free(synapse);
 284 }
 285 
 286 void
 287 destroy_graph(crm_graph_t * graph)
     /* [previous][next][first][last][top][bottom][index][help] */
 288 {
 289     if (graph == NULL) {
 290         return;
 291     }
 292     while (graph->synapses != NULL) {
 293         synapse_t *synapse = g_list_nth_data(graph->synapses, 0);
 294 
 295         graph->synapses = g_list_remove(graph->synapses, synapse);
 296         destroy_synapse(synapse);
 297     }
 298 
 299     free(graph->source);
 300     free(graph);
 301 }
 302 
 303 lrmd_event_data_t *
 304 convert_graph_action(xmlNode * resource, crm_action_t * action, int status, int rc)
     /* [previous][next][first][last][top][bottom][index][help] */
 305 {
 306     xmlNode *xop = NULL;
 307     lrmd_event_data_t *op = NULL;
 308     GHashTableIter iter;
 309     const char *name = NULL;
 310     const char *value = NULL;
 311     xmlNode *action_resource = NULL;
 312 
 313     CRM_CHECK(action != NULL, return NULL);
 314     CRM_CHECK(action->type == action_type_rsc, return NULL);
 315 
 316     action_resource = first_named_child(action->xml, XML_CIB_TAG_RESOURCE);
 317     CRM_CHECK(action_resource != NULL, crm_log_xml_warn(action->xml, "Bad");
 318               return NULL);
 319 
 320     op = lrmd_new_event(ID(action_resource),
 321                         crm_element_value(action->xml, XML_LRM_ATTR_TASK),
 322                         action->interval_ms);
 323     op->rc = rc;
 324     op->op_status = status;
 325     op->t_run = time(NULL);
 326     op->t_rcchange = op->t_run;
 327     op->params = pcmk__strkey_table(free, free);
 328 
 329     g_hash_table_iter_init(&iter, action->params);
 330     while (g_hash_table_iter_next(&iter, (void **)&name, (void **)&value)) {
 331         g_hash_table_insert(op->params, strdup(name), strdup(value));
 332     }
 333 
 334     for (xop = pcmk__xml_first_child(resource); xop != NULL;
 335          xop = pcmk__xml_next(xop)) {
 336         int tmp = 0;
 337 
 338         crm_element_value_int(xop, XML_LRM_ATTR_CALLID, &tmp);
 339         crm_debug("Got call_id=%d for %s", tmp, ID(resource));
 340         if (tmp > op->call_id) {
 341             op->call_id = tmp;
 342         }
 343     }
 344 
 345     op->call_id++;
 346     return op;
 347 }

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