13 #define VARIANT_CLONE 1
20 sort_rsc_id(gconstpointer a, gconstpointer b)
33 num1 = strtol(strrchr(resource1->
id,
':') + 1, NULL, 10);
34 num2 = strtol(strrchr(resource2->
id,
':') + 1, NULL, 10);
37 }
else if (num1 > num2) {
48 if (node != NULL && rsc->
parent) {
50 }
else if(node != NULL) {
65 for (; gIter != NULL; gIter = gIter->next) {
68 if (did_fail(child_rsc)) {
81 node_t *current_node1 = NULL;
82 node_t *current_node2 = NULL;
83 unsigned int nnodes1 = 0;
84 unsigned int nnodes2 = 0;
106 if (nnodes1 && nnodes2) {
107 if (nnodes1 < nnodes2) {
108 crm_trace(
"%s < %s: running_on", resource1->
id, resource2->
id);
111 }
else if (nnodes1 > nnodes2) {
112 crm_trace(
"%s > %s: running_on", resource1->
id, resource2->
id);
117 node1 = current_node1;
118 node2 = current_node2;
122 if (match == NULL || match->
weight < 0) {
123 crm_trace(
"%s: current location is unavailable", resource1->
id);
132 if (match == NULL || match->
weight < 0) {
133 crm_trace(
"%s: current location is unavailable", resource2->
id);
141 crm_trace(
"%s < %s: availability of current location", resource1->
id, resource2->
id);
144 crm_trace(
"%s > %s: availability of current location", resource1->
id, resource2->
id);
149 crm_trace(
"%s < %s: priority", resource1->
id, resource2->
id);
153 crm_trace(
"%s > %s: priority", resource1->
id, resource2->
id);
157 if (node1 == NULL && node2 == NULL) {
158 crm_trace(
"%s == %s: not active", resource1->
id, resource2->
id);
162 if (node1 != node2) {
166 }
else if (node2 == NULL) {
183 node1 = parent_node_instance(resource1, node1);
184 node2 = parent_node_instance(resource2, node2);
185 if (node1 != NULL && node2 == NULL) {
186 crm_trace(
"%s < %s: not allowed", resource1->
id, resource2->
id);
188 }
else if (node1 == NULL && node2 != NULL) {
189 crm_trace(
"%s > %s: not allowed", resource1->
id, resource2->
id);
193 if (node1 == NULL || node2 == NULL) {
194 crm_trace(
"%s == %s: not allowed", resource1->
id, resource2->
id);
207 can1 = did_fail(resource1);
208 can2 = did_fail(resource2);
218 if (node1 && node2) {
226 g_hash_table_new_full(
crm_str_hash, g_str_equal, NULL, free);
228 g_hash_table_new_full(
crm_str_hash, g_str_equal, NULL, free);
231 g_hash_table_insert(hash1, (gpointer) n->
details->
id, n);
234 g_hash_table_insert(hash2, (gpointer) n->
details->
id, n);
237 for (gIter = resource1->
parent->
rsc_cons; gIter; gIter = gIter->next) {
240 crm_trace(
"Applying %s to %s", constraint->
id, resource1->
id);
250 crm_trace(
"Applying %s to %s", constraint->
id, resource1->
id);
259 for (gIter = resource2->
parent->
rsc_cons; gIter; gIter = gIter->next) {
262 crm_trace(
"Applying %s to %s", constraint->
id, resource2->
id);
272 crm_trace(
"Applying %s to %s", constraint->
id, resource2->
id);
281 node1 = g_hash_table_lookup(hash1, current_node1->
details->
id);
282 node2 = g_hash_table_lookup(hash2, current_node2->
details->
id);
303 list1 = g_hash_table_get_values(hash1);
304 list2 = g_hash_table_get_values(hash2);
308 max = g_list_length(list1);
309 if (max < g_list_length(list2)) {
310 max = g_list_length(list2);
313 for (; lpc < max; lpc++) {
314 node1 = g_list_nth_data(list1, lpc);
315 node2 = g_list_nth_data(list2, lpc);
317 crm_trace(
"%s < %s: colocated score NULL", resource1->
id, resource2->
id);
321 }
else if (node2 == NULL) {
322 crm_trace(
"%s > %s: colocated score NULL", resource1->
id, resource2->
id);
328 crm_trace(
"%s < %s: colocated score", resource1->
id, resource2->
id);
333 crm_trace(
"%s > %s: colocated score", resource1->
id, resource2->
id);
341 g_hash_table_destroy(hash1);
342 g_hash_table_destroy(hash2);
351 rc = strcmp(resource1->
id, resource2->
id);
352 crm_trace(
"%s %c %s: default", resource1->
id, rc < 0 ?
'<' :
'>', resource2->
id);
359 node_t *local_node = NULL;
364 while (g_hash_table_iter_next(&iter, NULL, (
void **)&local_node)) {
365 can_run_instance(rsc, local_node, limit);
377 local_node = parent_node_instance(rsc, node);
379 if (local_node == NULL) {
383 }
else if (local_node->
weight < 0) {
385 pe_rsc_trace(rsc,
"%s cannot run on %s: Parent node weight doesn't allow it.",
388 }
else if (local_node->
count < limit) {
389 pe_rsc_trace(rsc,
"%s can run on %s (already running %d)",
394 pe_rsc_trace(rsc,
"%s cannot run on %s: node full (%d >= %d)",
409 GHashTable *backup = NULL;
412 pe_rsc_trace(rsc,
"Checking allocation of %s (preferring %s, using %s parent colocations)",
414 (all_coloc?
"all" :
"some"));
420 pe_rsc_debug(rsc,
"Dependency loop detected involving %s", rsc->
id);
427 append_parent_colocation(rsc->
parent, rsc, all_coloc);
432 if (local_prefer == NULL || local_prefer->
weight < 0) {
433 pe_rsc_trace(rsc,
"Not pre-allocating %s to %s - unavailable", rsc->
id,
439 can_run_instance(rsc, NULL, limit);
444 crm_info(
"Not pre-allocating %s to %s because %s is better",
453 pe_node_t *local_node = parent_node_instance(rsc, chosen);
467 g_hash_table_destroy(backup);
479 for (; gIter != NULL; gIter = gIter->next) {
488 for (; gIter != NULL; gIter = gIter->next) {
491 if (all || cons->
score < 0) {
508 int available_nodes = 0;
511 for(
GListPtr nIter = nodes; nIter != NULL; nIter = nIter->next) {
520 if(available_nodes) {
521 loop_max = max / available_nodes;
527 pe_rsc_debug(rsc,
"Allocating up to %d %s instances to a possible %d nodes (at most %d per host, %d optimal)",
528 max, rsc->
id, available_nodes, per_host_max, loop_max);
531 for (
GListPtr gIter = children; gIter != NULL && allocated < max; gIter = gIter->next) {
536 node_t *child_node = pe__current_node(child);
537 node_t *local_node = parent_node_instance(child, child_node);
539 pe_rsc_trace(rsc,
"Checking pre-allocation of %s to %s (%d remaining of %d)",
543 pe_rsc_trace(rsc,
"Not pre-allocating because %s can not run %s",
546 }
else if(local_node && local_node->
count >= loop_max) {
548 "Not pre-allocating because %s already allocated optimal instances",
551 }
else if (color_instance(child, child_node, max < available_nodes, per_host_max, data_set)) {
559 pe_rsc_trace(rsc,
"Done pre-allocating (%d of %d)", allocated, max);
561 for (
GListPtr gIter = children; gIter != NULL; gIter = gIter->next) {
565 node_t *child_node = pe__current_node(child);
566 node_t *local_node = parent_node_instance(child, child_node);
568 if (local_node == NULL) {
569 crm_err(
"%s is running on %s which isn't allowed",
575 }
else if (allocated >= max) {
576 pe_rsc_debug(rsc,
"Child %s not allocated - limit reached %d %d", child->
id, allocated, max);
579 if (color_instance(child, NULL, max < available_nodes, per_host_max, data_set)) {
585 pe_rsc_debug(rsc,
"Allocated %d %s instances of a possible %d",
586 allocated, rsc->
id, max);
594 clone_variant_data_t *clone_data = NULL;
596 get_clone_variant_data(clone_data, rsc);
602 pe_rsc_debug(rsc,
"Dependency loop detected involving %s", rsc->
id);
652 clone_update_pseudo_status(
resource_t * rsc, gboolean * stopping, gboolean * starting,
660 for (; gIter != NULL; gIter = gIter->next) {
663 clone_update_pseudo_status(child, stopping, starting, active);
678 for (; gIter != NULL; gIter = gIter->next) {
681 if (*starting && *stopping) {
699 pe_rsc_trace(rsc,
"Skipping pseudo-op: %s run=%d, pseudo=%d",
714 find_rsc_action(
pe_resource_t *rsc,
const char *task, gboolean active_only,
726 for (; gIter != NULL; gIter = gIter->next) {
730 active = g_list_prepend(active, op);
734 if (active && g_list_length(active) == 1) {
735 match = g_list_nth_data(active, 0);
743 }
else if (possible && g_list_length(possible) == 1) {
744 match = g_list_nth_data(possible, 0);
753 g_list_free(possible);
770 gboolean active_only = TRUE;
771 clone_variant_data_t *clone_data = NULL;
773 get_clone_variant_data(clone_data, rsc);
775 if (clone_data->ordered == FALSE) {
781 for (gIter = rsc->
children; gIter != NULL; gIter = gIter->next) {
784 stop = find_rsc_action(child,
RSC_STOP, active_only, NULL);
793 start = find_rsc_action(child,
RSC_START, active_only, NULL);
807 clone_variant_data_t *clone_data = NULL;
809 get_clone_variant_data(clone_data, rsc);
811 child_ordering_constraints(rsc, data_set);
821 gboolean child_active = FALSE;
822 gboolean child_starting = FALSE;
823 gboolean child_stopping = FALSE;
824 gboolean allow_dependent_migrations = TRUE;
834 for (
GListPtr gIter = children; gIter != NULL; gIter = gIter->next) {
836 gboolean starting = FALSE;
837 gboolean stopping = FALSE;
840 clone_update_pseudo_status(child_rsc, &stopping, &starting, &child_active);
841 if (stopping && starting) {
842 allow_dependent_migrations = FALSE;
845 child_stopping |= stopping;
846 child_starting |= starting;
854 if (child_active || child_starting) {
858 if (start_notify != NULL && *start_notify == NULL) {
866 if (allow_dependent_migrations) {
870 if (stop_notify != NULL && *stop_notify == NULL) {
873 if (start_notify && *start_notify && *stop_notify) {
884 clone_variant_data_t *clone_data = NULL;
886 get_clone_variant_data(clone_data, rsc);
898 if (clone_data->ordered) {
902 for (gIter = rsc->
children; gIter != NULL; gIter = gIter->next) {
910 if (clone_data->ordered && last_rsc) {
917 if (clone_data->ordered && last_rsc) {
921 last_rsc = child_rsc;
931 bool changed = FALSE;
958 CRM_CHECK(child_rsc && local_node,
return FALSE);
961 node = child_rsc->
fns->
location(child_rsc, NULL, current);
977 crm_trace(
"%s - not allocated %d", child_rsc->
id, current);
990 node_t *local_node = NULL;
992 local_node = local_child->
fns->
location(local_child, NULL, current);
997 scratch = g_hash_table_get_values(local_child->
allowed_nodes);
1001 for (; gIter != NULL; gIter = gIter->next) {
1012 g_list_free(scratch);
1034 gboolean do_interleave = FALSE;
1035 const char *interleave_s = NULL;
1038 CRM_CHECK(rsc_lh != NULL,
pe_err(
"rsc_lh was NULL for %s", constraint->
id);
return);
1039 CRM_CHECK(rsc_rh != NULL,
pe_err(
"rsc_rh was NULL for %s", constraint->
id);
return);
1042 pe_rsc_trace(rsc_rh,
"Processing constraint %s: %s -> %s %d",
1043 constraint->
id, rsc_lh->
id, rsc_rh->
id, constraint->
score);
1050 pe_rsc_trace(rsc_rh,
"Handling %s as a clone colocation", constraint->
id);
1063 " they do not support the same number of copies per node",
1067 do_interleave = TRUE;
1075 }
else if (do_interleave) {
1087 crm_notice(
"Cannot pair %s with instance of %s", rsc_lh->
id, rsc_rh->
id);
1091 pe_rsc_debug(rsc_rh,
"Cannot pair %s with instance of %s", rsc_lh->
id, rsc_rh->
id);
1100 for (; gIter != NULL; gIter = gIter->next) {
1106 rhs = g_list_prepend(rhs, chosen);
1116 for (; gIter != NULL; gIter = gIter->next) {
1136 char *key = action->
uuid;
1137 int lpc = strlen(key);
1139 for (; lpc > 0; lpc--) {
1140 if (key[lpc] ==
'_' && stop == 0) {
1143 }
else if (key[lpc] ==
'_') {
1144 char *task_mutable = NULL;
1147 task_mutable = strdup(key + lpc);
1148 task_mutable[stop - lpc] = 0;
1150 crm_trace(
"Extracted action '%s' from '%s'", task_mutable, key);
1167 gboolean any_runnable = FALSE;
1168 gboolean check_runnable = TRUE;
1173 for (gIter = children; gIter != NULL; gIter = gIter->next) {
1178 pe_rsc_trace(action->
rsc,
"Checking for %s in %s on %s (%s)", task_s, child->
id,
1179 node ? node->details->uname :
"none", child_action?child_action->
uuid:
"NA");
1186 child_action->
uuid);
1191 any_runnable = TRUE;
1196 if (check_runnable && any_runnable == FALSE) {
1218 pe_rsc_trace(rsc,
"Processing location constraint %s for %s", constraint->
id, rsc->
id);
1222 for (; gIter != NULL; gIter = gIter->next) {
1233 clone_variant_data_t *clone_data = NULL;
1235 get_clone_variant_data(clone_data, rsc);
1238 for (; gIter != NULL; gIter = gIter->next) {
1244 if (clone_data->start_notify) {
1250 if (clone_data->stop_notify) {
1256 if (clone_data->promote_notify) {
1262 if (clone_data->demote_notify) {
1271 for (; gIter != NULL; gIter = gIter->next) {
1274 child_rsc->
cmds->
expand(child_rsc, data_set);
1281 clone_data->demote_notify = NULL;
1283 clone_data->stop_notify = NULL;
1285 clone_data->start_notify = NULL;
1287 clone_data->promote_notify = NULL;
1295 for (GList *child_iter = rsc->
children; child_iter != NULL;
1296 child_iter = child_iter->next) {
1300 if (rsc_known_on(child, node)) {
1306 GHashTableIter iter;
1307 node_t *known_node = NULL;
1309 g_hash_table_iter_init(&iter, rsc->
known_on);
1310 while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &known_node)) {
1323 for (GList *gIter = clone->
children; gIter != NULL; gIter = gIter->next) {
1326 if (rsc_known_on(child, node)) {
1338 gboolean any_created = FALSE;
1340 for (GList *child_iter = rsc->
children; child_iter != NULL;
1341 child_iter = child_iter->next) {
1361 if (child == NULL) {
1362 for (GList *child_iter = rsc->
children; child_iter && !child;
1363 child_iter = child_iter->next) {
1365 node_t *local_node = NULL;
1368 local_node = child_rsc->
fns->
location(child_rsc, NULL, FALSE);
1376 if (child == NULL) {
1386 gboolean any_created = FALSE;
1392 pe_warn(
"Clone %s has no children", rsc->
id);
1414 any_created = probe_unique_clone(rsc, node, complete, force, data_set);
1416 any_created = probe_anonymous_clone(rsc, node, complete, force,
1426 clone_variant_data_t *clone_data = NULL;
1428 get_clone_variant_data(clone_data, rsc);
#define CRM_CHECK(expr, failure_action)
const char * task2text(enum action_tasks task)
enum pe_action_flags(* action_flags)(action_t *, node_t *)
#define crm_notice(fmt, args...)
gboolean is_child_compatible(resource_t *child_rsc, node_t *local_node, enum rsc_role_e filter, gboolean current)
bool assign_node(resource_t *rsc, node_t *node, gboolean force)
void native_expand(resource_t *rsc, pe_working_set_t *data_set)
#define pe_rsc_debug(rsc, fmt, args...)
void native_deallocate(resource_t *rsc)
void create_promotable_actions(resource_t *rsc, pe_working_set_t *data_set)
enum rsc_role_e(* state)(const pe_resource_t *, gboolean)
node_t * clone_color(resource_t *rsc, node_t *preferred, pe_working_set_t *data_set)
GList * sort_nodes_by_weight(GList *nodes, pe_node_t *active_node, pe_working_set_t *data_set)
node_t * node_copy(const node_t *this_node)
void promotable_colocation_rh(resource_t *lh_rsc, resource_t *rh_rsc, rsc_colocation_t *constraint, pe_working_set_t *data_set)
pe_node_t * pe__find_active_on(const pe_resource_t *rsc, unsigned int *count_all, unsigned int *count_clean)
void distribute_children(resource_t *rsc, GListPtr children, GListPtr nodes, int max, int per_host_max, pe_working_set_t *data_set)
int copies_per_node(resource_t *rsc)
void(* expand)(resource_t *, pe_working_set_t *)
enum action_tasks clone_child_action(action_t *action)
GHashTable * clone_merge_weights(resource_t *rsc, const char *rhs, GHashTable *nodes, const char *attr, float factor, enum pe_weights flags)
resource_alloc_functions_t * cmds
#define crm_config_err(fmt...)
enum action_tasks get_complex_task(resource_t *rsc, const char *name, gboolean allow_non_atomic)
void clone_rsc_colocation_lh(pe_resource_t *lh_rsc, pe_resource_t *rh_rsc, rsc_colocation_t *constraint, pe_working_set_t *data_set)
gint sort_clone_instance(gconstpointer a, gconstpointer b, gpointer data_set)
const char * crm_xml_add_int(xmlNode *node, const char *name, int value)
Create an XML attribute with specified name and integer value.
gboolean exclusive_discover
void common_update_score(resource_t *rsc, const char *id, int score)
void(* rsc_colocation_lh)(pe_resource_t *, pe_resource_t *, rsc_colocation_t *, pe_working_set_t *)
resource_object_functions_t * fns
const char * crm_xml_add(xmlNode *node, const char *name, const char *value)
Create an XML attribute with specified name and value.
gboolean clone_create_probe(resource_t *rsc, node_t *node, action_t *complete, gboolean force, pe_working_set_t *data_set)
void(* create_actions)(resource_t *, pe_working_set_t *)
enum pe_action_flags clone_action_flags(action_t *action, node_t *node)
#define clear_bit(word, bit)
void native_rsc_location(pe_resource_t *rsc, pe__location_t *constraint)
#define XML_RSC_ATTR_MASTER_NODEMAX
notify_data_t * create_notification_boundaries(resource_t *rsc, const char *action, action_t *start, action_t *end, pe_working_set_t *data_set)
#define XML_RSC_ATTR_INCARNATION_MAX
void collect_notification_data(resource_t *rsc, gboolean state, gboolean activity, notify_data_t *n_data)
gboolean native_assign_node(resource_t *rsc, GListPtr candidates, node_t *chosen, gboolean force)
char * crm_meta_name(const char *field)
void(* rsc_colocation_rh)(pe_resource_t *, pe_resource_t *, rsc_colocation_t *, pe_working_set_t *)
node_t * color_promotable(resource_t *rsc, pe_working_set_t *data_set)
void free_notification_data(notify_data_t *n_data)
#define pe_rsc_provisional
#define crm_warn(fmt, args...)
#define set_bit(word, bit)
#define order_stop_stop(rsc1, rsc2, type)
void clone_create_pseudo_actions(resource_t *rsc, GListPtr children, notify_data_t **start_notify, notify_data_t **stop_notify, pe_working_set_t *data_set)
void clone_expand(resource_t *rsc, pe_working_set_t *data_set)
const char * node_attribute
void promotable_constraints(resource_t *rsc, pe_working_set_t *data_set)
gboolean expand_notification_data(resource_t *rsc, notify_data_t *n_data, pe_working_set_t *data_set)
#define crm_trace(fmt, args...)
action_t * find_first_action(GListPtr input, const char *uuid, const char *task, node_t *on_node)
struct pe_node_shared_s * details
resource_t * find_compatible_child_by_node(resource_t *local_child, node_t *local_node, resource_t *rsc, enum rsc_role_e filter, gboolean current)
GHashTable * rsc_merge_weights(resource_t *rsc, const char *rhs, GHashTable *nodes, const char *attr, float factor, enum pe_weights flags)
#define pe_rsc_promotable
#define XML_RSC_ATTR_INCARNATION_NODEMAX
void clone_internal_constraints(resource_t *rsc, pe_working_set_t *data_set)
GHashTable * node_hash_dup(GHashTable *hash)
#define pe_rsc_allocating
enum pe_obj_types variant
enum pe_action_flags summary_action_flags(action_t *action, GListPtr children, node_t *node)
gboolean can_run_resources(const node_t *node)
#define XML_RSC_ATTR_NOTIFY
void(* rsc_location)(pe_resource_t *, pe__location_t *)
#define XML_RSC_ATTR_UNIQUE
pe_resource_t * find_compatible_child(pe_resource_t *local_child, pe_resource_t *rsc, enum rsc_role_e filter, gboolean current, pe_working_set_t *data_set)
#define XML_RSC_ATTR_MASTER_MAX
pe_action_t * create_pseudo_resource_op(resource_t *rsc, const char *task, bool optional, bool runnable, pe_working_set_t *data_set)
#define XML_RSC_ATTR_PROMOTED_MAX
void(* internal_constraints)(resource_t *, pe_working_set_t *)
gboolean update_action_flags(action_t *action, enum pe_action_flags flags, const char *source, int line)
void clone_rsc_location(pe_resource_t *rsc, pe__location_t *constraint)
void clone_rsc_colocation_rh(pe_resource_t *lh_rsc, pe_resource_t *rh_rsc, rsc_colocation_t *constraint, pe_working_set_t *data_set)
#define crm_err(fmt, args...)
void resource_location(resource_t *rsc, node_t *node, int score, const char *tag, pe_working_set_t *data_set)
void node_list_exclude(GHashTable *list, GListPtr list2, gboolean merge_scores)
#define pe_clear_action_bit(action, bit)
GHashTable * native_merge_weights(resource_t *rsc, const char *rhs, GHashTable *nodes, const char *attr, float factor, enum pe_weights flags)
gboolean(* create_probe)(resource_t *, node_t *, action_t *, gboolean, pe_working_set_t *)
#define XML_RSC_ATTR_PROMOTED_NODEMAX
void clone_append_meta(resource_t *rsc, xmlNode *xml)
enum pe_action_flags flags
pe_node_t *(* location)(const pe_resource_t *, GList **, int)
#define order_start_start(rsc1, rsc2, type)
void apply_master_prefs(resource_t *rsc)
void clone_create_actions(resource_t *rsc, pe_working_set_t *data_set)
void create_notifications(resource_t *rsc, notify_data_t *n_data, pe_working_set_t *data_set)
gboolean crm_is_true(const char *s)
#define pe_rsc_trace(rsc, fmt, args...)
#define dump_node_scores(level, rsc, text, nodes)
#define safe_str_eq(a, b)
#define XML_RSC_ATTR_INTERLEAVE
node_t *(* allocate)(resource_t *, node_t *, pe_working_set_t *)
gboolean order_actions(action_t *lh_action, action_t *rh_action, enum pe_ordering order)
GList * pe__resource_actions(const pe_resource_t *rsc, const pe_node_t *node, const char *task, bool require_node)
Find all actions of given type for a resource.
bool is_set_recursive(resource_t *rsc, long long flag, bool any)
#define crm_info(fmt, args...)
GHashTable *(* merge_weights)(resource_t *, const char *, GHashTable *, const char *, float, enum pe_weights)
GHashTable * allowed_nodes
int new_rsc_order(resource_t *lh_rsc, const char *lh_task, resource_t *rh_rsc, const char *rh_task, enum pe_ordering type, pe_working_set_t *data_set)