Skip to content

Commit 80564aa

Browse files
committed
Fix: scheduler: promoted state with promoted state with attribute
Previously attribute based colocation didn't adhere the attribute with promoted state with promoted state.
1 parent e39a875 commit 80564aa

File tree

7 files changed

+61
-30
lines changed

7 files changed

+61
-30
lines changed

cts/cts-scheduler.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -633,6 +633,7 @@ TESTS = [
633633
SchedulerTest("no_quorum_demote", "Promotable demotion and primitive stop with no-quorum-policy=\"demote\""),
634634
SchedulerTest("no-promote-on-unrunnable-guest", "Don't select bundle instance for promotion when container can't run"),
635635
SchedulerTest("leftover-pending-monitor", "Prevent a leftover pending monitor from causing unexpected stop of other instances"),
636+
SchedulerTest("promotable-colocation-with-node-attribute", "Promote dependend clone on nodes belonging to a site that has a primary clone promoted"),
636637
]),
637638
SchedulerTestGroup([
638639
SchedulerTest("history-1", "Correctly parse stateful-1 resource state"),

lib/pacemaker/libpacemaker_private.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -941,13 +941,14 @@ void pcmk__create_instance_actions(pcmk_resource_t *rsc, GList *instances);
941941
G_GNUC_INTERNAL
942942
bool pcmk__instance_matches(const pcmk_resource_t *instance,
943943
const pcmk_node_t *node, enum rsc_role_e role,
944-
bool current);
944+
bool current, const char *node_attribute);
945945

946946
G_GNUC_INTERNAL
947947
pcmk_resource_t *pcmk__find_compatible_instance(const pcmk_resource_t *match_rsc,
948948
const pcmk_resource_t *rsc,
949949
enum rsc_role_e role,
950-
bool current);
950+
bool current,
951+
const char *node_attribute);
951952

952953
G_GNUC_INTERNAL
953954
uint32_t pcmk__instance_update_ordered_actions(pcmk_action_t *first,

lib/pacemaker/pcmk_sched_bundle.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -383,7 +383,7 @@ match_replica_container(const pcmk__bundle_replica_t *replica, void *user_data)
383383
struct match_data *match_data = user_data;
384384

385385
if (pcmk__instance_matches(replica->container, match_data->node,
386-
pcmk_role_unknown, false)) {
386+
pcmk_role_unknown, false, NULL)) {
387387
match_data->container = replica->container;
388388
return false; // Match found, don't bother searching further replicas
389389
}

lib/pacemaker/pcmk_sched_clone.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,7 @@ pcmk__clone_apply_coloc_score(pcmk_resource_t *dependent,
301301

302302
primary_instance = pcmk__find_compatible_instance(dependent, primary,
303303
pcmk_role_unknown,
304-
false);
304+
false, NULL);
305305
if (primary_instance != NULL) {
306306
pcmk__rsc_debug(primary, "Interleaving %s with %s",
307307
dependent->id, primary_instance->id);

lib/pacemaker/pcmk_sched_instances.c

Lines changed: 52 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1077,18 +1077,22 @@ free_instance_list(const pcmk_resource_t *rsc, GList *list)
10771077
* \internal
10781078
* \brief Check whether an instance is compatible with a role and node
10791079
*
1080-
* \param[in] instance Clone instance or bundle replica container
1081-
* \param[in] node Instance must match this node
1082-
* \param[in] role If not pcmk_role_unknown, instance must match this role
1083-
* \param[in] current If true, compare instance's original node and role,
1084-
* otherwise compare assigned next node and role
1080+
* \param[in] instance Clone instance or bundle replica container
1081+
* \param[in] node Instance must match this node
1082+
* \param[in] role If not pcmk_role_unknown, instance must match this role
1083+
* \param[in] current If true, compare instance's original node and role,
1084+
* otherwise compare assigned next node and role
1085+
* \param[in] node_attribute If not NULL, instance's node must have the same value
1086+
* for this attribute as \p node (instead of requiring
1087+
* the exact same node)
10851088
*
10861089
* \return true if \p instance is compatible with \p node and \p role,
10871090
* otherwise false
10881091
*/
10891092
bool
10901093
pcmk__instance_matches(const pcmk_resource_t *instance, const pcmk_node_t *node,
1091-
enum rsc_role_e role, bool current)
1094+
enum rsc_role_e role, bool current,
1095+
const char *node_attribute)
10921096
{
10931097
pcmk_node_t *instance_node = NULL;
10941098

@@ -1121,7 +1125,25 @@ pcmk__instance_matches(const pcmk_resource_t *instance, const pcmk_node_t *node,
11211125
return false;
11221126
}
11231127

1124-
if (!pcmk__same_node(instance_node, node)) {
1128+
if (node_attribute != NULL) {
1129+
// Compare by node attribute value instead of node identity
1130+
const char *instance_value = pcmk__colocation_node_attr(instance_node,
1131+
node_attribute,
1132+
instance);
1133+
const char *target_value = pcmk__colocation_node_attr(node,
1134+
node_attribute,
1135+
instance);
1136+
1137+
if (!pcmk__str_eq(instance_value, target_value, pcmk__str_casei)) {
1138+
pcmk__rsc_trace(instance,
1139+
"%s is not a compatible instance "
1140+
"(instance has %s=%s, target node has %s=%s)",
1141+
instance->id, node_attribute,
1142+
pcmk__s(instance_value, "<none>"),
1143+
node_attribute, pcmk__s(target_value, "<none>"));
1144+
return false;
1145+
}
1146+
} else if (!pcmk__same_node(instance_node, node)) {
11251147
pcmk__rsc_trace(instance,
11261148
"%s is not a compatible instance "
11271149
"(assigned to %s not %s)",
@@ -1140,28 +1162,31 @@ pcmk__instance_matches(const pcmk_resource_t *instance, const pcmk_node_t *node,
11401162
* \internal
11411163
* \brief Find an instance that matches a given resource by node and role
11421164
*
1143-
* \param[in] match_rsc Resource that instance must match (for logging only)
1144-
* \param[in] rsc Clone or bundle resource to check for matching instance
1145-
* \param[in] node Instance must match this node
1146-
* \param[in] role If not pcmk_role_unknown, instance must match this role
1147-
* \param[in] current If true, compare instance's original node and role,
1148-
* otherwise compare assigned next node and role
1165+
* \param[in] match_rsc Resource that instance must match (for logging only)
1166+
* \param[in] rsc Clone or bundle resource to check for matching instance
1167+
* \param[in] node Instance must match this node
1168+
* \param[in] role If not pcmk_role_unknown, instance must match this role
1169+
* \param[in] current If true, compare instance's original node and role,
1170+
* otherwise compare assigned next node and role
1171+
* \param[in] node_attribute If not NULL, match instances by this node attribute
1172+
* instead of by node identity
11491173
*
11501174
* \return \p rsc instance matching \p node and \p role if any, otherwise NULL
11511175
*/
11521176
static pcmk_resource_t *
11531177
find_compatible_instance_on_node(const pcmk_resource_t *match_rsc,
11541178
const pcmk_resource_t *rsc,
11551179
const pcmk_node_t *node, enum rsc_role_e role,
1156-
bool current)
1180+
bool current, const char *node_attribute)
11571181
{
11581182
GList *instances = NULL;
11591183

11601184
instances = get_instance_list(rsc);
11611185
for (GList *iter = instances; iter != NULL; iter = iter->next) {
11621186
pcmk_resource_t *instance = (pcmk_resource_t *) iter->data;
11631187

1164-
if (pcmk__instance_matches(instance, node, role, current)) {
1188+
if (pcmk__instance_matches(instance, node, role, current,
1189+
node_attribute)) {
11651190
pcmk__rsc_trace(match_rsc,
11661191
"Found %s %s instance %s compatible with %s on %s",
11671192
display_role(role), rsc->id, instance->id,
@@ -1183,19 +1208,21 @@ find_compatible_instance_on_node(const pcmk_resource_t *match_rsc,
11831208
* \internal
11841209
* \brief Find a clone instance or bundle container compatible with a resource
11851210
*
1186-
* \param[in] match_rsc Resource that instance must match
1187-
* \param[in] rsc Clone or bundle resource to check for matching instance
1188-
* \param[in] role If not pcmk_role_unknown, instance must match this role
1189-
* \param[in] current If true, compare instance's original node and role,
1190-
* otherwise compare assigned next node and role
1211+
* \param[in] match_rsc Resource that instance must match
1212+
* \param[in] rsc Clone or bundle resource to check for matching instance
1213+
* \param[in] role If not pcmk_role_unknown, instance must match this role
1214+
* \param[in] current If true, compare instance's original node and role,
1215+
* otherwise compare assigned next node and role
1216+
* \param[in] node_attribute If not NULL, match instances by this node attribute
1217+
* instead of by node identity
11911218
*
11921219
* \return Compatible (by \p role and \p match_rsc location) instance of \p rsc
11931220
* if any, otherwise NULL
11941221
*/
11951222
pcmk_resource_t *
11961223
pcmk__find_compatible_instance(const pcmk_resource_t *match_rsc,
11971224
const pcmk_resource_t *rsc, enum rsc_role_e role,
1198-
bool current)
1225+
bool current, const char *node_attribute)
11991226
{
12001227
pcmk_resource_t *instance = NULL;
12011228
GList *nodes = NULL;
@@ -1211,7 +1238,7 @@ pcmk__find_compatible_instance(const pcmk_resource_t *match_rsc,
12111238
node = match_rsc->priv->fns->location(match_rsc, NULL, target);
12121239
if (node != NULL) {
12131240
return find_compatible_instance_on_node(match_rsc, rsc, node, role,
1214-
current);
1241+
current, node_attribute);
12151242
}
12161243

12171244
// Otherwise check for an instance matching any of match_rsc's allowed nodes
@@ -1220,7 +1247,8 @@ pcmk__find_compatible_instance(const pcmk_resource_t *match_rsc,
12201247
iter = iter->next) {
12211248
instance = find_compatible_instance_on_node(match_rsc, rsc,
12221249
(pcmk_node_t *) iter->data,
1223-
role, current);
1250+
role, current,
1251+
node_attribute);
12241252
}
12251253

12261254
if (instance == NULL) {
@@ -1434,7 +1462,7 @@ update_interleaved_actions(pcmk_action_t *first, pcmk_action_t *then,
14341462
first_instance = pcmk__find_compatible_instance(then_instance,
14351463
first->rsc,
14361464
pcmk_role_unknown,
1437-
current);
1465+
current, NULL);
14381466

14391467
if (first_instance == NULL) { // No instance can be interleaved
14401468
if (unassign_if_mandatory(first, then, then_instance, type,

lib/pacemaker/pcmk_sched_probes.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -614,7 +614,7 @@ add_restart_orderings_for_probe(pcmk_action_t *probe, pcmk_action_t *after)
614614
compatible_rsc = pcmk__find_compatible_instance(probe->rsc,
615615
after->rsc,
616616
pcmk_role_unknown,
617-
false);
617+
false, NULL);
618618
}
619619
}
620620

lib/pacemaker/pcmk_sched_promotable.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1333,7 +1333,8 @@ pcmk__update_promotable_dependent_priority(const pcmk_resource_t *primary,
13331333
// Look for a primary instance where dependent will be
13341334
primary_instance = pcmk__find_compatible_instance(dependent, primary,
13351335
colocation->primary_role,
1336-
false);
1336+
false,
1337+
colocation->node_attribute);
13371338

13381339
if (primary_instance != NULL) {
13391340
// Add primary instance's priority to dependent's

0 commit comments

Comments
 (0)