@@ -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 */
10891092bool
10901093pcmk__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 */
11521176static pcmk_resource_t *
11531177find_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 */
11951222pcmk_resource_t *
11961223pcmk__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 ,
0 commit comments