31#define RSC_ROLE_MAX (pcmk_role_promoted + 1)
174 if (prefer == NULL) {
175 prefer = most_free_node;
184 nodes = sorted_allowed_nodes(rsc);
189 if ((prefer != NULL) && (nodes != NULL)) {
194 if (chosen == NULL) {
196 pcmk__node_name(prefer), rsc->
id);
206 pcmk__node_name(chosen), rsc->
id);
211 pcmk__node_name(chosen), rsc->
id);
216 "Chose preferred node %s for %s "
217 "(ignoring %d candidates)",
218 pcmk__node_name(chosen), rsc->
id,
219 g_list_length(nodes));
223 if ((chosen == NULL) && (best != NULL)) {
244 if (running == NULL) {
249 "Current node for %s (%s) can't run resources",
250 rsc->
id, pcmk__node_name(running));
253 int nodes_with_best_score = 1;
255 for (GList *iter = nodes->next; iter; iter = iter->next) {
258 if (allowed->assign->score != chosen->
assign->
score) {
262 if (pcmk__same_node(allowed, running)) {
266 nodes_with_best_score++;
269 if (nodes_with_best_score > 1) {
270 uint8_t log_level = LOG_INFO;
273 log_level = LOG_WARNING;
276 "Chose %s for %s from %d nodes with score %s",
277 pcmk__node_name(chosen), rsc->
id,
278 nodes_with_best_score,
285 pcmk__node_name(chosen), rsc->
id, g_list_length(nodes));
303 GHashTable *archive = NULL;
308 || ((colocation->
score < 0)
315 "%s: Assigning colocation %s primary %s first"
316 "(score=%d role=%s)",
317 rsc->
id, colocation->
id, other->
id,
325 if ((archive != NULL)
328 "%s: Reverting scores from colocation with %s "
329 "because no nodes allowed",
335 if (archive != NULL) {
336 g_hash_table_destroy(archive);
357 crm_trace(
"Pacemaker Remote node %s will be online",
366 crm_trace(
"Pacemaker Remote node %s will be shut down "
367 "(%sassigned connection's next role is %s)",
397 GList *this_with_colocations = NULL;
398 GList *with_this_colocations = NULL;
412 parent->priv->cmds->assign(
parent, prefer, stop_if_fail);
417 const char *node_name =
"no node";
440 for (iter = this_with_colocations; iter != NULL; iter = iter->next) {
441 colocation = iter->data;
445 apply_this_with(colocation, rsc);
448 for (iter = with_this_colocations; iter != NULL; iter = iter->next) {
449 colocation = iter->data;
461 for (iter = this_with_colocations; iter != NULL; iter = iter->next) {
462 colocation = iter->data;
466 apply_this_with(colocation, rsc);
469 for (iter = with_this_colocations; iter != NULL; iter = iter->next) {
470 colocation = iter->data;
478 g_list_free(this_with_colocations);
479 g_list_free(with_this_colocations);
483 "Banning %s from all nodes because it will be stopped",
491 crm_notice(
"Resource %s cannot be elevated from %s to %s due to "
511 const char *reason = NULL;
515 assign_to = pcmk__current_node(rsc);
516 if (assign_to == NULL) {
526 (assign_to? assign_to->
priv->
name :
"no node"),
539 }
else if (!assign_best_node(rsc, prefer, stop_if_fail)) {
551 remote_connection_assigned(rsc);
570 bool need_stop,
bool need_promote)
581 pcmk__rsc_trace(rsc,
"Creating %s action to take %s down from %s to %s",
582 (need_stop?
"required" :
"optional"), rsc->
id,
584 fn = rsc_action_matrix[role][next_role];
588 fn(rsc, current, !need_stop);
596 bool required = need_stop;
603 (required?
"required" :
"optional"), rsc->
id,
605 fn = rsc_action_matrix[role][next_role];
651 "Creating action for %s to represent already pending start",
674 "Creating action to take %s from %s to %s "
679 fn = rsc_action_matrix[role][next_role];
697 bool need_stop =
false;
698 bool need_promote =
false;
699 bool is_moving =
false;
700 bool allow_migrate =
false;
701 bool multiply_active =
false;
705 unsigned int num_all_active = 0;
706 unsigned int num_clean_active = 0;
707 const char *next_role_source = NULL;
711 next_role_source = set_default_next_role(rsc);
713 "Creating all actions for %s transition from %s to %s "
730 rsc->
id, pcmk__node_name(current),
742 && (migration_target != NULL) && allow_migrate && (num_all_active == 2)
749 "Partial migration of %s from %s to %s will continue",
752 pcmk__node_name(migration_target));
755 || (migration_target != NULL)) {
758 if (num_all_active > 2) {
760 crm_notice(
"Forcing recovery of %s because it is migrating "
761 "from %s to %s and possibly active elsewhere",
764 pcmk__node_name(migration_target));
767 crm_notice(
"Forcing recovery of %s because it can no longer "
768 "migrate from %s to %s",
771 pcmk__node_name(migration_target));
776 allow_migrate =
false;
779 multiply_active = (num_all_active > 1);
788 multiply_active = (num_clean_active > 1);
791 if (multiply_active) {
796 "%s resource %s might be active on %u nodes (%s)",
797 pcmk__s(
class,
"Untyped"), rsc->id, num_all_active,
799 crm_notice(
"For more information, see \"What are multiply active "
801 "https://projects.clusterlabs.org/w/clusterlabs/faq/");
803 switch (rsc->priv->multiply_active_policy) {
820 create_pending_start(rsc);
857 schedule_restart_actions(rsc, current, need_stop, need_promote);
860 schedule_role_transition_actions(rsc);
882 while (g_hash_table_iter_next(&iter, NULL, (
void **) &node)) {
883 if (node->priv->remote != NULL) {
905 GList *allowed_nodes = NULL;
915 return allowed_nodes;
927 GList *allowed_nodes = NULL;
928 bool check_unfencing =
false;
929 bool check_utilization =
false;
937 "Skipping implicit constraints for unmanaged resource "
987 if (check_unfencing || check_utilization
990 allowed_nodes = allowed_nodes_as_list(rsc);
993 if (check_unfencing) {
997 if (check_utilization) {
1041 if (remote_rsc != NULL) {
1045 for (GList *item = allowed_nodes; item; item = item->next) {
1060 crm_trace(
"Order and colocate %s relative to its launcher %s",
1097 rsc_avoids_remote_nodes(rsc);
1099 g_list_free(allowed_nodes);
1126 && (colocation != NULL));
1128 if (for_dependent) {
1137 ((colocation->
score > 0)?
"Colocating" :
"Anti-colocating"),
1138 dependent->
id, primary->
id, colocation->
id,
1142 switch (filter_results) {
1165 pcmk__assert(pcmk__is_primitive(rsc) && (list != NULL));
1168 if (rsc == orig_rsc) {
1175 parent->priv->cmds->with_this_colocations(
parent, orig_rsc, list);
1180 iter != NULL; iter = iter->next) {
1199 pcmk__assert(pcmk__is_primitive(rsc) && (list != NULL));
1202 if (rsc == orig_rsc) {
1209 parent->priv->cmds->this_with_colocations(
parent, orig_rsc, list);
1214 iter != NULL; iter = iter->next) {
1237 return (uint32_t)
action->flags;
1257 return pcmk_all_flags_set(rsc->
flags,
1275 iter != NULL; iter = iter->next) {
1280 if (is_expected_node(rsc, current)) {
1286 "Skipping stop of multiply active resource %s "
1287 "on expected node %s",
1288 rsc->
id, pcmk__node_name(current));
1297 "Skipping stop of %s on %s "
1298 "because partial migration there will continue",
1299 rsc->
id, pcmk__node_name(current));
1303 "Forcing stop of %s on %s "
1304 "because migration target changed",
1305 rsc->
id, pcmk__node_name(current));
1311 rsc->
id, pcmk__node_name(current));
1337 "Stopping %s until %s can be unfenced",
1338 rsc->
id, pcmk__node_name(current));
1360 (optional?
"optional" :
"required"), rsc->
id,
1370 if (is_expected_node(rsc, node)) {
1375 "Start of multiply active resouce %s "
1376 "on expected node %s will be a pseudo-action",
1377 rsc->
id, pcmk__node_name(node));
1394 GList *action_list = NULL;
1395 bool runnable =
true;
1401 for (iter = action_list; iter != NULL; iter = iter->next) {
1408 g_list_free(action_list);
1414 (optional?
"optional" :
"required"), rsc->
id,
1415 pcmk__node_name(node));
1417 if (is_expected_node(rsc, node)) {
1422 "Promotion of multiply active resouce %s "
1423 "on expected node %s will be a pseudo-action",
1424 rsc->
id, pcmk__node_name(node));
1429 rsc->
id, pcmk__node_name(node));
1432 for (iter = action_list; iter != NULL; iter = iter->next) {
1437 g_list_free(action_list);
1458 iter != NULL; iter = iter->next) {
1462 if (is_expected_node(rsc, current)) {
1464 "Skipping demote of multiply active resource %s "
1465 "on expected node %s",
1466 rsc->
id, pcmk__node_name(current));
1469 (optional?
"optional" :
"required"), rsc->
id,
1470 pcmk__node_name(current));
1501 CRM_CHECK((rsc != NULL) && (node != NULL),
return);
1504 pcmk__rsc_trace(rsc,
"Skipping clean-up of %s on %s: resource failed",
1505 rsc->
id, pcmk__node_name(node));
1510 pcmk__rsc_trace(rsc,
"Skipping clean-up of %s on %s: node unavailable",
1511 rsc->
id, pcmk__node_name(node));
1515 crm_notice(
"Scheduling clean-up of %s on %s",
1516 rsc->
id, pcmk__node_name(node));
1540 pcmk__assert(pcmk__is_primitive(rsc) && (xml != NULL));
1547 if (value != NULL) {
1555 if (value != NULL) {
1565 if (
parent->priv->launcher != NULL) {
1567 parent->priv->launcher->id);
1575 value = g_hash_table_lookup(rsc->
priv->
meta,
"external-ip");
1576 if (value != NULL) {
1585 GList *all_rscs, GHashTable *utilization)
1587 pcmk__assert(pcmk__is_primitive(rsc) && (orig_rsc != NULL)
1588 && (utilization != NULL));
1595 "%s: Adding primitive %s as colocated utilization",
1596 orig_rsc->
id, rsc->
id);
1615 if (shutdown != NULL) {
1616 long long result_ll;
1620 result = (time_t) result_ll;
1622 crm_warn(
"Ignoring invalid value '%s' for %s "
1624 shutdown, pcmk__node_name(node),
pcmk_rc_str(rc));
1641ban_if_not_locked(gpointer
data, gpointer user_data)
1676 "Cancelling shutdown lock "
1677 "because %s is already active", rsc->
id);
1690 "Not locking %s to unclean %s for shutdown",
1691 rsc->
id, pcmk__node_name(node));
1708 pcmk__rsc_info(rsc,
"Locking %s to %s due to shutdown (expires @%lld)",
1710 (
long long) lock_expiration);
1712 "shutdown lock expiration");
@ pcmk__ar_if_on_same_node
Relation applies only if actions are on same node.
@ pcmk__ar_first_implies_then
@ pcmk__ar_then_implies_first
@ pcmk__ar_intermediate_stop
@ pcmk__ar_promoted_then_implies_first
@ pcmk__ar_unrunnable_first_blocks
'then' is runnable (and migratable) only if 'first' is runnable
@ pcmk__ar_ordered
Actions are ordered (optionally, if no other flags are set)
@ pcmk__ar_then_cancels_first
If 'then' action becomes required, 'first' becomes optional.
#define PCMK_ACTION_PROMOTE
#define PCMK_ACTION_LRM_DELETE
#define PCMK_ACTION_START
#define PCMK_ACTION_DELETE
#define PCMK_ACTION_MONITOR
#define PCMK_ACTION_DEMOTE
@ pcmk__action_always_in_graph
#define pcmk__set_action_flags(action, flags_to_set)
char * pcmk__op_key(const char *rsc_id, const char *op_type, guint interval_ms)
Generate an operation key (RESOURCE_ACTION_INTERVAL)
#define pcmk__clear_action_flags(action, flags_to_clear)
const char * pcmk__node_attr(const pcmk_node_t *node, const char *name, const char *target, enum pcmk__rsc_node node_type)
guint pcmk__timeout_ms2s(guint timeout_ms)
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
G_GNUC_INTERNAL enum pcmk__coloc_affects pcmk__colocation_affects(const pcmk_resource_t *dependent, const pcmk_resource_t *primary, const pcmk__colocation_t *colocation, bool preview)
G_GNUC_INTERNAL void pcmk__add_this_with_list(GList **list, GList *addition, const pcmk_resource_t *rsc)
void pcmk__abort_dangling_migration(void *data, void *user_data)
void pcmk__create_migration_actions(pcmk_resource_t *rsc, const pcmk_node_t *current)
G_GNUC_INTERNAL void pcmk__create_recurring_actions(pcmk_resource_t *rsc)
G_GNUC_INTERNAL void pcmk__new_ordering(pcmk_resource_t *first_rsc, char *first_task, pcmk_action_t *first_action, pcmk_resource_t *then_rsc, char *then_task, pcmk_action_t *then_action, uint32_t flags, pcmk_scheduler_t *sched)
G_GNUC_INTERNAL bool pcmk__any_node_available(GHashTable *nodes)
#define pcmk__order_resource_actions(first_rsc, first_task, then_rsc, then_task, flags)
G_GNUC_INTERNAL void pcmk__apply_coloc_to_scores(pcmk_resource_t *dependent, const pcmk_resource_t *primary, const pcmk__colocation_t *colocation)
@ pcmk__coloc_affects_location
@ pcmk__coloc_affects_role
G_GNUC_INTERNAL bool pcmk__assign_resource(pcmk_resource_t *rsc, pcmk_node_t *node, bool force, bool stop_if_fail)
G_GNUC_INTERNAL void pcmk__order_vs_unfence(const pcmk_resource_t *rsc, pcmk_node_t *node, pcmk_action_t *action, enum pcmk__action_relation_flags order)
G_GNUC_INTERNAL GList * pcmk__with_this_colocations(const pcmk_resource_t *rsc)
G_GNUC_INTERNAL void pcmk__add_this_with(GList **list, const pcmk__colocation_t *colocation, const pcmk_resource_t *rsc)
G_GNUC_INTERNAL int pcmk__apply_coloc_to_priority(pcmk_resource_t *dependent, const pcmk_resource_t *primary, const pcmk__colocation_t *colocation)
G_GNUC_INTERNAL GList * pcmk__sort_nodes(GList *nodes, pcmk_node_t *active_node)
G_GNUC_INTERNAL void pcmk__add_with_this_list(GList **list, GList *addition, const pcmk_resource_t *rsc)
G_GNUC_INTERNAL void pcmk__new_colocation(const char *id, const char *node_attr, int score, pcmk_resource_t *dependent, pcmk_resource_t *primary, const char *dependent_role_spec, const char *primary_role_spec, uint32_t flags)
G_GNUC_INTERNAL void pcmk__order_restart_vs_unfence(gpointer data, gpointer user_data)
G_GNUC_INTERNAL void pcmk__add_with_this(GList **list, const pcmk__colocation_t *colocation, const pcmk_resource_t *rsc)
G_GNUC_INTERNAL void pcmk__create_utilization_constraints(pcmk_resource_t *rsc, const GList *allowed_nodes)
G_GNUC_INTERNAL const pcmk_node_t * pcmk__ban_insufficient_capacity(pcmk_resource_t *rsc)
G_GNUC_INTERNAL void pcmk__add_dependent_scores(gpointer data, gpointer user_data)
G_GNUC_INTERNAL GList * pcmk__this_with_colocations(const pcmk_resource_t *rsc)
bool pcmk__rsc_can_migrate(const pcmk_resource_t *rsc, const pcmk_node_t *current)
G_GNUC_INTERNAL bool pcmk__node_unfenced(const pcmk_node_t *node)
G_GNUC_INTERNAL void pcmk__release_node_capacity(GHashTable *current_utilization, const pcmk_resource_t *rsc)
G_GNUC_INTERNAL bool pcmk__node_available(const pcmk_node_t *node, bool consider_score, bool consider_guest)
G_GNUC_INTERNAL GHashTable * pcmk__copy_node_table(GHashTable *nodes)
#define do_crm_log(level, fmt, args...)
Log a message.
#define crm_warn(fmt, args...)
#define crm_notice(fmt, args...)
#define CRM_CHECK(expr, failure_action)
#define crm_trace(fmt, args...)
pcmk_scheduler_t * scheduler
#define PCMK__NODE_ATTR_SHUTDOWN
char * crm_meta_name(const char *field)
Get the environment variable equivalent of a meta-attribute name.
#define PCMK_OPT_STOP_ALL_RESOURCES
#define PCMK_OPT_NO_QUORUM_POLICY
#define PCMK_META_REMOTE_NODE
#define PCMK_VALUE_FREEZE
#define PCMK_META_TARGET_ROLE
#define PCMK_VALUE_DEFAULT
#define PCMK_OPT_SHUTDOWN_LOCK
#define PCMK__META_CONTAINER
pcmk__action_result_t result
pcmk_node_t * pcmk__primitive_assign(pcmk_resource_t *rsc, const pcmk_node_t *prefer, bool stop_if_fail)
void pcmk__primitive_internal_constraints(pcmk_resource_t *rsc)
void pcmk__primitive_add_utilization(const pcmk_resource_t *rsc, const pcmk_resource_t *orig_rsc, GList *all_rscs, GHashTable *utilization)
void pcmk__primitive_add_graph_meta(const pcmk_resource_t *rsc, xmlNode *xml)
void(* rsc_transition_fn)(pcmk_resource_t *rsc, pcmk_node_t *node, bool optional)
void pcmk__with_primitive_colocations(const pcmk_resource_t *rsc, const pcmk_resource_t *orig_rsc, GList **list)
uint32_t pcmk__primitive_action_flags(pcmk_action_t *action, const pcmk_node_t *node)
int pcmk__primitive_apply_coloc_score(pcmk_resource_t *dependent, const pcmk_resource_t *primary, const pcmk__colocation_t *colocation, bool for_dependent)
void pcmk__primitive_create_actions(pcmk_resource_t *rsc)
void pcmk__schedule_cleanup(pcmk_resource_t *rsc, const pcmk_node_t *node, bool optional)
void pcmk__primitive_with_colocations(const pcmk_resource_t *rsc, const pcmk_resource_t *orig_rsc, GList **list)
void pcmk__primitive_shutdown_lock(pcmk_resource_t *rsc)
#define delete_action(rsc, node, optional)
GList * pe__resource_actions(const pcmk_resource_t *rsc, const pcmk_node_t *node, const char *task, bool require_node)
Find all actions of given type for a resource.
#define demote_action(rsc, node, optional)
const pcmk_resource_t * pe__const_top_resource(const pcmk_resource_t *rsc, bool include_bundle)
#define pe__show_node_scores(level, rsc, text, nodes, scheduler)
#define start_action(rsc, node, optional)
void resource_location(pcmk_resource_t *rsc, const pcmk_node_t *node, int score, const char *tag, pcmk_scheduler_t *scheduler)
gboolean order_actions(pcmk_action_t *first, pcmk_action_t *then, uint32_t flags)
gint pe__cmp_node_name(gconstpointer a, gconstpointer b)
void pe_action_set_reason(pcmk_action_t *action, const char *reason, bool overwrite)
pcmk_action_t * pe_fence_op(pcmk_node_t *node, const char *op, bool optional, const char *reason, bool priority_delay, pcmk_scheduler_t *scheduler)
void pe__set_next_role(pcmk_resource_t *rsc, enum rsc_role_e role, const char *why)
#define stop_action(rsc, node, optional)
void pe__clear_resource_history(pcmk_resource_t *rsc, const pcmk_node_t *node)
#define promote_action(rsc, node, optional)
pcmk_resource_t * pe__resource_contains_guest_node(const pcmk_scheduler_t *scheduler, const pcmk_resource_t *rsc)
@ pcmk__rsc_stop_if_failed
@ pcmk__rsc_needs_unfencing
@ pcmk__rsc_stop_unexpected
@ pcmk__rsc_needs_fencing
@ pcmk__rsc_is_remote_connection
@ pcmk__rsc_remote_nesting_allowed
@ pcmk__rsc_start_pending
#define pcmk__set_rsc_flags(resource, flags_to_set)
const char * pcmk__multiply_active_text(const pcmk_resource_t *rsc)
Get readable description of a multiply-active recovery type.
@ pcmk__multiply_active_restart
Stop on all, start on desired.
@ pcmk__multiply_active_unexpected
Stop unexpected instances.
#define pcmk__clear_rsc_flags(resource, flags_to_clear)
const char * pcmk_rc_str(int rc)
Get a user-friendly description of a return code.
#define pcmk__assert(expr)
const char * pcmk_role_text(enum rsc_role_e role)
Get readable description of a resource role.
@ pcmk_role_started
Started.
@ pcmk_role_unknown
Resource role is unknown.
@ pcmk_role_unpromoted
Unpromoted.
@ pcmk_role_promoted
Promoted.
@ pcmk_role_stopped
Stopped.
@ pcmk_no_quorum_freeze
Do not recover resources from outside partition.
pcmk_node_t * pcmk_find_node(const pcmk_scheduler_t *scheduler, const char *node_name)
Find a node by name in scheduler data.
#define pcmk__sched_err(scheduler, fmt...)
#define pcmk__rsc_info(rsc, fmt, args...)
#define pcmk__rsc_trace(rsc, fmt, args...)
time_t pcmk__scheduler_epoch_time(pcmk_scheduler_t *scheduler)
#define pcmk__rsc_debug(rsc, fmt, args...)
void pcmk__update_recheck_time(time_t recheck, pcmk_scheduler_t *scheduler, const char *reason)
@ pcmk__sched_enable_unfencing
@ pcmk__sched_fencing_enabled
@ pcmk__sched_output_scores
@ pcmk__sched_have_fencing
const char * pcmk_readable_score(int score)
Return a displayable static string for a score value.
#define PCMK_SCORE_INFINITY
Integer score to use to represent "infinity".
int pcmk__scan_ll(const char *text, long long *result, long long default_value)
pcmk_node_t *(* assign)(pcmk_resource_t *rsc, const pcmk_node_t *prefer, bool stop_if_fail)
int(* apply_coloc_score)(pcmk_resource_t *dependent, const pcmk_resource_t *primary, const pcmk__colocation_t *colocation, bool for_dependent)
pcmk_resource_t * primary
pcmk_scheduler_t * scheduler
pcmk_node_t * assigned_node
GList * this_with_colocations
GList * with_this_colocations
pcmk_node_t * partial_migration_target
const pcmk_node_t * lock_node
pcmk_scheduler_t * scheduler
pcmk_node_t * partial_migration_source
GList * dangling_migration_sources
enum rsc_role_e orig_role
pcmk_resource_t * launcher
enum rsc_role_e next_role
const pcmk__assignment_methods_t * cmds
const pcmk__rsc_methods_t * fns
GHashTable * allowed_nodes
pcmk__resource_private_t * priv
pcmk_node_t *(* active_node)(const pcmk_resource_t *rsc, unsigned int *count_all, unsigned int *count_clean)
const char * placement_strategy
pcmk__scheduler_private_t * priv
enum pe_quorum_policy no_quorum_policy
pcmk__node_private_t * priv
struct pcmk__node_details * details
struct pcmk__node_assignment * assign
Wrappers for and extensions to libxml2.
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
const char * crm_xml_add(xmlNode *node, const char *name, const char *value)
Create an XML attribute with specified name and value.