This source file includes following definitions.
- evaluate_lifetime
- pcmk__unpack_constraints
- pcmk__find_constraint_resource
- find_constraint_tag
- pcmk__valid_resource_or_tag
- pcmk__expand_tags_in_sets
- pcmk__tag_to_set
- pcmk__create_internal_constraints
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 
   9 
  10 #include <crm_internal.h>
  11 
  12 #include <sys/param.h>
  13 #include <sys/types.h>
  14 #include <stdbool.h>
  15 #include <regex.h>
  16 #include <glib.h>
  17 
  18 #include <crm/crm.h>
  19 #include <crm/cib.h>
  20 #include <crm/msg_xml.h>
  21 #include <crm/common/xml.h>
  22 #include <crm/common/xml_internal.h>
  23 #include <crm/common/iso8601.h>
  24 #include <crm/pengine/status.h>
  25 #include <crm/pengine/internal.h>
  26 #include <crm/pengine/rules.h>
  27 #include <pacemaker-internal.h>
  28 #include "libpacemaker_private.h"
  29 
  30 static bool
  31 evaluate_lifetime(xmlNode *lifetime, pe_working_set_t *data_set)
     
  32 {
  33     bool result = FALSE;
  34     crm_time_t *next_change = crm_time_new_undefined();
  35 
  36     result = pe_evaluate_rules(lifetime, NULL, data_set->now, next_change);
  37     if (crm_time_is_defined(next_change)) {
  38         time_t recheck = (time_t) crm_time_get_seconds_since_epoch(next_change);
  39 
  40         pe__update_recheck_time(recheck, data_set);
  41     }
  42     crm_time_free(next_change);
  43     return result;
  44 }
  45 
  46 
  47 
  48 
  49 
  50 
  51 
  52 
  53 
  54 
  55 void
  56 pcmk__unpack_constraints(pe_working_set_t *data_set)
     
  57 {
  58     xmlNode *xml_constraints = pcmk_find_cib_element(data_set->input,
  59                                                      XML_CIB_TAG_CONSTRAINTS);
  60 
  61     for (xmlNode *xml_obj = pcmk__xe_first_child(xml_constraints);
  62          xml_obj != NULL; xml_obj = pcmk__xe_next(xml_obj)) {
  63 
  64         xmlNode *lifetime = NULL;
  65         const char *id = crm_element_value(xml_obj, XML_ATTR_ID);
  66         const char *tag = crm_element_name(xml_obj);
  67 
  68         if (id == NULL) {
  69             pcmk__config_err("Ignoring <%s> constraint without "
  70                              XML_ATTR_ID, tag);
  71             continue;
  72         }
  73 
  74         crm_trace("Unpacking %s constraint '%s'", tag, id);
  75 
  76         lifetime = first_named_child(xml_obj, "lifetime");
  77         if (lifetime != NULL) {
  78             pcmk__config_warn("Support for 'lifetime' attribute (in %s) is "
  79                               "deprecated (the rules it contains should "
  80                               "instead be direct descendents of the "
  81                               "constraint object)", id);
  82         }
  83 
  84         if ((lifetime != NULL) && !evaluate_lifetime(lifetime, data_set)) {
  85             crm_info("Constraint %s %s is not active", tag, id);
  86 
  87         } else if (pcmk__str_eq(XML_CONS_TAG_RSC_ORDER, tag, pcmk__str_casei)) {
  88             pcmk__unpack_ordering(xml_obj, data_set);
  89 
  90         } else if (pcmk__str_eq(XML_CONS_TAG_RSC_DEPEND, tag, pcmk__str_casei)) {
  91             pcmk__unpack_colocation(xml_obj, data_set);
  92 
  93         } else if (pcmk__str_eq(XML_CONS_TAG_RSC_LOCATION, tag, pcmk__str_casei)) {
  94             pcmk__unpack_location(xml_obj, data_set);
  95 
  96         } else if (pcmk__str_eq(XML_CONS_TAG_RSC_TICKET, tag, pcmk__str_casei)) {
  97             pcmk__unpack_rsc_ticket(xml_obj, data_set);
  98 
  99         } else {
 100             pe_err("Unsupported constraint type: %s", tag);
 101         }
 102     }
 103 }
 104 
 105 pe_resource_t *
 106 pcmk__find_constraint_resource(GList *rsc_list, const char *id)
     
 107 {
 108     GList *rIter = NULL;
 109 
 110     for (rIter = rsc_list; id && rIter; rIter = rIter->next) {
 111         pe_resource_t *parent = rIter->data;
 112         pe_resource_t *match = parent->fns->find_rsc(parent, id, NULL,
 113                                                      pe_find_renamed);
 114 
 115         if (match != NULL) {
 116             if(!pcmk__str_eq(match->id, id, pcmk__str_casei)) {
 117                 
 118                 match = uber_parent(match);
 119                 crm_debug("Found %s for %s", match->id, id);
 120             }
 121             return match;
 122         }
 123     }
 124     crm_trace("No match for %s", id);
 125     return NULL;
 126 }
 127 
 128 
 129 
 130 
 131 
 132 
 133 
 134 
 135 
 136 
 137 
 138 
 139 static bool
 140 find_constraint_tag(pe_working_set_t *data_set, const char *id, pe_tag_t **tag)
     
 141 {
 142     *tag = NULL;
 143 
 144     
 145     if (g_hash_table_lookup_extended(data_set->template_rsc_sets, id,
 146                                      NULL, (gpointer *) tag)) {
 147         if (*tag == NULL) {
 148             crm_warn("No resource is derived from template '%s'", id);
 149             return false;
 150         }
 151         return true;
 152     }
 153 
 154     
 155     if (g_hash_table_lookup_extended(data_set->tags, id,
 156                                      NULL, (gpointer *) tag)) {
 157         if (*tag == NULL) {
 158             crm_warn("No resource is tagged with '%s'", id);
 159             return false;
 160         }
 161         return true;
 162     }
 163 
 164     crm_warn("No template or tag named '%s'", id);
 165     return false;
 166 }
 167 
 168 
 169 
 170 
 171 
 172 
 173 
 174 
 175 
 176 
 177 
 178 
 179 
 180 
 181 bool
 182 pcmk__valid_resource_or_tag(pe_working_set_t *data_set, const char *id,
     
 183                             pe_resource_t **rsc, pe_tag_t **tag)
 184 {
 185     if (rsc != NULL) {
 186         *rsc = pcmk__find_constraint_resource(data_set->resources, id);
 187         if (*rsc != NULL) {
 188             return true;
 189         }
 190     }
 191 
 192     if ((tag != NULL) && find_constraint_tag(data_set, id, tag)) {
 193         return true;
 194     }
 195 
 196     return false;
 197 }
 198 
 199 
 200 
 201 
 202 
 203 
 204 
 205 
 206 
 207 
 208 
 209 
 210 
 211 
 212 
 213 xmlNode *
 214 pcmk__expand_tags_in_sets(xmlNode *xml_obj, pe_working_set_t *data_set)
     
 215 {
 216     xmlNode *new_xml = NULL;
 217     bool any_refs = false;
 218 
 219     
 220     if (first_named_child(xml_obj, XML_CONS_TAG_RSC_SET) == NULL) {
 221         return NULL;
 222     }
 223 
 224     new_xml = copy_xml(xml_obj);
 225 
 226     for (xmlNode *set = first_named_child(new_xml, XML_CONS_TAG_RSC_SET);
 227          set != NULL; set = crm_next_same_xml(set)) {
 228 
 229         GList *tag_refs = NULL;
 230         GList *gIter = NULL;
 231 
 232         for (xmlNode *xml_rsc = first_named_child(set, XML_TAG_RESOURCE_REF);
 233              xml_rsc != NULL; xml_rsc = crm_next_same_xml(xml_rsc)) {
 234 
 235             pe_resource_t *rsc = NULL;
 236             pe_tag_t *tag = NULL;
 237 
 238             if (!pcmk__valid_resource_or_tag(data_set, ID(xml_rsc), &rsc,
 239                                              &tag)) {
 240                 pcmk__config_err("Ignoring resource sets for constraint '%s' "
 241                                  "because '%s' is not a valid resource or tag",
 242                                  ID(xml_obj), ID(xml_rsc));
 243                 free_xml(new_xml);
 244                 return NULL;
 245 
 246             } else if (rsc) {
 247                 continue;
 248 
 249             } else if (tag) {
 250                 
 251                 xmlNode *last_ref = xml_rsc;
 252 
 253                 
 254 
 255 
 256 
 257 
 258 
 259 
 260 
 261 
 262 
 263 
 264 
 265 
 266 
 267 
 268 
 269 
 270 
 271 
 272 
 273 
 274 
 275                 for (gIter = tag->refs; gIter != NULL; gIter = gIter->next) {
 276                     const char *obj_ref = (const char *) gIter->data;
 277                     xmlNode *new_rsc_ref = NULL;
 278 
 279                     new_rsc_ref = xmlNewDocRawNode(getDocPtr(set), NULL,
 280                                                    (pcmkXmlStr) XML_TAG_RESOURCE_REF, NULL);
 281                     crm_xml_add(new_rsc_ref, XML_ATTR_ID, obj_ref);
 282                     xmlAddNextSibling(last_ref, new_rsc_ref);
 283 
 284                     last_ref = new_rsc_ref;
 285                 }
 286 
 287                 any_refs = true;
 288 
 289                 
 290 
 291 
 292                 tag_refs = g_list_append(tag_refs, xml_rsc);
 293             }
 294         }
 295 
 296         
 297 
 298 
 299 
 300 
 301 
 302 
 303 
 304 
 305 
 306         for (gIter = tag_refs; gIter != NULL; gIter = gIter->next) {
 307             xmlNode *tag_ref = gIter->data;
 308 
 309             free_xml(tag_ref);
 310         }
 311         g_list_free(tag_refs);
 312     }
 313 
 314     if (!any_refs) {
 315         free_xml(new_xml);
 316         new_xml = NULL;
 317     }
 318     return new_xml;
 319 }
 320 
 321 
 322 
 323 
 324 
 325 
 326 
 327 
 328 
 329 
 330 
 331 bool
 332 pcmk__tag_to_set(xmlNode *xml_obj, xmlNode **rsc_set, const char *attr,
     
 333                  bool convert_rsc, pe_working_set_t *data_set)
 334 {
 335     const char *cons_id = NULL;
 336     const char *id = NULL;
 337 
 338     pe_resource_t *rsc = NULL;
 339     pe_tag_t *tag = NULL;
 340 
 341     *rsc_set = NULL;
 342 
 343     CRM_CHECK((xml_obj != NULL) && (attr != NULL), return false);
 344 
 345     cons_id = ID(xml_obj);
 346     if (cons_id == NULL) {
 347         pcmk__config_err("Ignoring <%s> constraint without " XML_ATTR_ID,
 348                          crm_element_name(xml_obj));
 349         return false;
 350     }
 351 
 352     id = crm_element_value(xml_obj, attr);
 353     if (id == NULL) {
 354         return true;
 355     }
 356 
 357     if (!pcmk__valid_resource_or_tag(data_set, id, &rsc, &tag)) {
 358         pcmk__config_err("Ignoring constraint '%s' because '%s' is not a "
 359                          "valid resource or tag", cons_id, id);
 360         return false;
 361 
 362     } else if (tag) {
 363         GList *gIter = NULL;
 364 
 365         
 366 
 367 
 368         *rsc_set = create_xml_node(xml_obj, XML_CONS_TAG_RSC_SET);
 369         crm_xml_add(*rsc_set, XML_ATTR_ID, id);
 370 
 371         for (gIter = tag->refs; gIter != NULL; gIter = gIter->next) {
 372             const char *obj_ref = (const char *) gIter->data;
 373             xmlNode *rsc_ref = NULL;
 374 
 375             rsc_ref = create_xml_node(*rsc_set, XML_TAG_RESOURCE_REF);
 376             crm_xml_add(rsc_ref, XML_ATTR_ID, obj_ref);
 377         }
 378 
 379         
 380         pcmk__xe_set_bool_attr(*rsc_set, "sequential", false);
 381 
 382     } else if ((rsc != NULL) && convert_rsc) {
 383         
 384 
 385         xmlNode *rsc_ref = NULL;
 386 
 387         *rsc_set = create_xml_node(xml_obj, XML_CONS_TAG_RSC_SET);
 388         crm_xml_add(*rsc_set, XML_ATTR_ID, id);
 389 
 390         rsc_ref = create_xml_node(*rsc_set, XML_TAG_RESOURCE_REF);
 391         crm_xml_add(rsc_ref, XML_ATTR_ID, id);
 392 
 393     } else {
 394         return true;
 395     }
 396 
 397     
 398     if (*rsc_set != NULL) {
 399         xml_remove_prop(xml_obj, attr);
 400     }
 401 
 402     return true;
 403 }
 404 
 405 
 406 
 407 
 408 
 409 
 410 
 411 void
 412 pcmk__create_internal_constraints(pe_working_set_t *data_set)
     
 413 {
 414     crm_trace("Create internal constraints");
 415     for (GList *iter = data_set->resources; iter != NULL; iter = iter->next) {
 416         pe_resource_t *rsc = (pe_resource_t *) iter->data;
 417 
 418         rsc->cmds->internal_constraints(rsc, data_set);
 419     }
 420 }