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