Blame SOURCES/020-multiple-active.patch

5ee7c6
From 355461723733acc0f6f9d9cc1318c91ba2a0ae6c Mon Sep 17 00:00:00 2001
5ee7c6
From: Ken Gaillot <kgaillot@redhat.com>
5ee7c6
Date: Tue, 22 May 2018 15:55:14 -0500
5ee7c6
Subject: [PATCH] Fix: all: prefer appropriate node when multiply active
5ee7c6
5ee7c6
---
5ee7c6
 lib/pengine/container.c      |  8 +++----
5ee7c6
 lib/pengine/native.c         |  8 +++----
5ee7c6
 pengine/allocate.c           | 20 ++++++++---------
5ee7c6
 pengine/clone.c              | 51 +++++++++++++++++++-----------------------
5ee7c6
 pengine/graph.c              | 26 +++++++++++++---------
5ee7c6
 pengine/native.c             | 17 +++++++-------
5ee7c6
 pengine/notif.c              |  2 +-
5ee7c6
 tools/crm_mon.c              | 14 ++++--------
5ee7c6
 tools/crm_resource.c         | 21 +++++++++++-------
5ee7c6
 tools/crm_resource_print.c   | 16 ++++++-------
5ee7c6
 tools/crm_resource_runtime.c | 53 ++++++++++++++++++++++----------------------
5ee7c6
 11 files changed, 112 insertions(+), 124 deletions(-)
5ee7c6
5ee7c6
diff --git a/lib/pengine/container.c b/lib/pengine/container.c
5ee7c6
index b5340bf..d82948a 100644
5ee7c6
--- a/lib/pengine/container.c
5ee7c6
+++ b/lib/pengine/container.c
5ee7c6
@@ -807,11 +807,11 @@ container_fix_remote_addr_in(resource_t *rsc, xmlNode *xml, const char *field)
5ee7c6
     }
5ee7c6
 
5ee7c6
     node = tuple->docker->allocated_to;
5ee7c6
-    if(node == NULL && tuple->docker->running_on) {
5ee7c6
+    if (node == NULL) {
5ee7c6
         /* If it won't be running anywhere after the
5ee7c6
          * transition, go with where it's running now.
5ee7c6
          */
5ee7c6
-        node = tuple->docker->running_on->data;
5ee7c6
+        node = pe__current_node(tuple->docker);
5ee7c6
     }
5ee7c6
 
5ee7c6
     if(node == NULL) {
5ee7c6
@@ -1289,9 +1289,7 @@ tuple_print(container_grouping_t * tuple, const char *pre_text, long options, vo
5ee7c6
         offset += snprintf(buffer + offset, LINE_MAX - offset, " (%s)", tuple->ipaddr);
5ee7c6
     }
5ee7c6
 
5ee7c6
-    if (tuple->docker->running_on) {
5ee7c6
-        node = tuple->docker->running_on->data;
5ee7c6
-    }
5ee7c6
+    node = pe__current_node(tuple->docker);
5ee7c6
     common_print(rsc, pre_text, buffer, node, options, print_data);
5ee7c6
 }
5ee7c6
 
5ee7c6
diff --git a/lib/pengine/native.c b/lib/pengine/native.c
5ee7c6
index e01ef17..eda0355 100644
5ee7c6
--- a/lib/pengine/native.c
5ee7c6
+++ b/lib/pengine/native.c
5ee7c6
@@ -457,7 +457,7 @@ native_print_xml(resource_t * rsc, const char *pre_text, long options, void *pri
5ee7c6
     if (options & pe_print_rsconly) {
5ee7c6
         status_print("/>\n");
5ee7c6
         /* do nothing */
5ee7c6
-    } else if (g_list_length(rsc->running_on) > 0) {
5ee7c6
+    } else if (rsc->running_on != NULL) {
5ee7c6
         GListPtr gIter = rsc->running_on;
5ee7c6
 
5ee7c6
         status_print(">\n");
5ee7c6
@@ -529,7 +529,7 @@ common_print(resource_t * rsc, const char *pre_text, const char *name, node_t *n
5ee7c6
         } else if (is_set(rsc->flags, pe_rsc_failed)) {
5ee7c6
             status_print("<font color=\"red\">");
5ee7c6
 
5ee7c6
-        } else if (rsc->variant == pe_native && g_list_length(rsc->running_on) == 0) {
5ee7c6
+        } else if (rsc->variant == pe_native && (rsc->running_on == NULL)) {
5ee7c6
             status_print("<font color=\"red\">");
5ee7c6
 
5ee7c6
         } else if (g_list_length(rsc->running_on) > 1) {
5ee7c6
@@ -742,9 +742,7 @@ native_print(resource_t * rsc, const char *pre_text, long options, void *print_d
5ee7c6
         return;
5ee7c6
     }
5ee7c6
 
5ee7c6
-    if (rsc->running_on != NULL) {
5ee7c6
-        node = rsc->running_on->data;
5ee7c6
-    }
5ee7c6
+    node = pe__current_node(rsc);
5ee7c6
     common_print(rsc, pre_text, rsc_printable_id(rsc), node, options, print_data);
5ee7c6
 }
5ee7c6
 
5ee7c6
diff --git a/pengine/allocate.c b/pengine/allocate.c
5ee7c6
index 724736c..427575b 100644
5ee7c6
--- a/pengine/allocate.c
5ee7c6
+++ b/pengine/allocate.c
5ee7c6
@@ -1101,14 +1101,14 @@ sort_rsc_process_order(gconstpointer a, gconstpointer b, gpointer data)
5ee7c6
     r2_weight = -INFINITY;
5ee7c6
 
5ee7c6
     if (resource1->running_on) {
5ee7c6
-        r1_node = g_list_nth_data(resource1->running_on, 0);
5ee7c6
+        r1_node = pe__current_node(resource1);
5ee7c6
         r1_node = g_hash_table_lookup(r1_nodes, r1_node->details->id);
5ee7c6
         if (r1_node != NULL) {
5ee7c6
             r1_weight = r1_node->weight;
5ee7c6
         }
5ee7c6
     }
5ee7c6
     if (resource2->running_on) {
5ee7c6
-        r2_node = g_list_nth_data(resource2->running_on, 0);
5ee7c6
+        r2_node = pe__current_node(resource2);
5ee7c6
         r2_node = g_hash_table_lookup(r2_nodes, r2_node->details->id);
5ee7c6
         if (r2_node != NULL) {
5ee7c6
             r2_weight = r2_node->weight;
5ee7c6
@@ -1925,10 +1925,7 @@ get_remote_node_state(pe_node_t *node)
5ee7c6
     remote_rsc = node->details->remote_rsc;
5ee7c6
     CRM_ASSERT(remote_rsc);
5ee7c6
 
5ee7c6
-    if(remote_rsc->running_on) {
5ee7c6
-        cluster_node = remote_rsc->running_on->data;
5ee7c6
-    }
5ee7c6
-
5ee7c6
+    cluster_node = pe__current_node(remote_rsc);
5ee7c6
 
5ee7c6
     /* If the cluster node the remote connection resource resides on
5ee7c6
      * is unclean or went offline, we can't process any operations
5ee7c6
@@ -1989,11 +1986,14 @@ get_remote_node_state(pe_node_t *node)
5ee7c6
     return remote_state_alive;
5ee7c6
 }
5ee7c6
 
5ee7c6
+/*!
5ee7c6
+ * \internal
5ee7c6
+ * \brief Order actions on remote node relative to actions for the connection
5ee7c6
+ */
5ee7c6
 static void
5ee7c6
 apply_remote_ordering(action_t *action, pe_working_set_t *data_set)
5ee7c6
 {
5ee7c6
     resource_t *remote_rsc = NULL;
5ee7c6
-    node_t *cluster_node = NULL;
5ee7c6
     enum action_tasks task = text2task(action->task);
5ee7c6
     enum remote_connection_state state = get_remote_node_state(action->node);
5ee7c6
 
5ee7c6
@@ -2009,10 +2009,6 @@ apply_remote_ordering(action_t *action, pe_working_set_t *data_set)
5ee7c6
     remote_rsc = action->node->details->remote_rsc;
5ee7c6
     CRM_ASSERT(remote_rsc);
5ee7c6
 
5ee7c6
-    if(remote_rsc->running_on) {
5ee7c6
-        cluster_node = remote_rsc->running_on->data;
5ee7c6
-    }
5ee7c6
-
5ee7c6
     crm_trace("Order %s action %s relative to %s%s (state: %s)",
5ee7c6
               action->task, action->uuid,
5ee7c6
               is_set(remote_rsc->flags, pe_rsc_failed)? "failed " : "",
5ee7c6
@@ -2093,6 +2089,8 @@ apply_remote_ordering(action_t *action, pe_working_set_t *data_set)
5ee7c6
                                         pe_order_implies_then, data_set);
5ee7c6
 
5ee7c6
             } else {
5ee7c6
+                node_t *cluster_node = pe__current_node(remote_rsc);
5ee7c6
+
5ee7c6
                 if(task == monitor_rsc && state == remote_state_failed) {
5ee7c6
                     /* We would only be here if we do not know the
5ee7c6
                      * state of the resource on the remote node.
5ee7c6
diff --git a/pengine/clone.c b/pengine/clone.c
5ee7c6
index 3192412..1de2661 100644
5ee7c6
--- a/pengine/clone.c
5ee7c6
+++ b/pengine/clone.c
5ee7c6
@@ -69,6 +69,10 @@ sort_clone_instance(gconstpointer a, gconstpointer b, gpointer data_set)
5ee7c6
     int rc = 0;
5ee7c6
     node_t *node1 = NULL;
5ee7c6
     node_t *node2 = NULL;
5ee7c6
+    node_t *current_node1 = NULL;
5ee7c6
+    node_t *current_node2 = NULL;
5ee7c6
+    unsigned int nnodes1 = 0;
5ee7c6
+    unsigned int nnodes2 = 0;
5ee7c6
 
5ee7c6
     gboolean can1 = TRUE;
5ee7c6
     gboolean can2 = TRUE;
5ee7c6
@@ -87,24 +91,22 @@ sort_clone_instance(gconstpointer a, gconstpointer b, gpointer data_set)
5ee7c6
      *  - inactive instances
5ee7c6
      */
5ee7c6
 
5ee7c6
-    if (resource1->running_on && resource2->running_on) {
5ee7c6
-        if (g_list_length(resource1->running_on) < g_list_length(resource2->running_on)) {
5ee7c6
+    current_node1 = pe__find_active_on(resource1, &nnodes1, NULL);
5ee7c6
+    current_node2 = pe__find_active_on(resource2, &nnodes2, NULL);
5ee7c6
+
5ee7c6
+    if (nnodes1 && nnodes2) {
5ee7c6
+        if (nnodes1 < nnodes2) {
5ee7c6
             crm_trace("%s < %s: running_on", resource1->id, resource2->id);
5ee7c6
             return -1;
5ee7c6
 
5ee7c6
-        } else if (g_list_length(resource1->running_on) > g_list_length(resource2->running_on)) {
5ee7c6
+        } else if (nnodes1 > nnodes2) {
5ee7c6
             crm_trace("%s > %s: running_on", resource1->id, resource2->id);
5ee7c6
             return 1;
5ee7c6
         }
5ee7c6
     }
5ee7c6
 
5ee7c6
-    if (resource1->running_on) {
5ee7c6
-        node1 = resource1->running_on->data;
5ee7c6
-    }
5ee7c6
-    if (resource2->running_on) {
5ee7c6
-        node2 = resource2->running_on->data;
5ee7c6
-    }
5ee7c6
-
5ee7c6
+    node1 = current_node1;
5ee7c6
+    node2 = current_node2;
5ee7c6
     if (node1) {
5ee7c6
         node_t *match = pe_hash_table_lookup(resource1->allowed_nodes, node1->details->id);
5ee7c6
 
5ee7c6
@@ -216,10 +218,10 @@ sort_clone_instance(gconstpointer a, gconstpointer b, gpointer data_set)
5ee7c6
         GHashTable *hash2 =
5ee7c6
             g_hash_table_new_full(crm_str_hash, g_str_equal, NULL, g_hash_destroy_str);
5ee7c6
 
5ee7c6
-        n = node_copy(resource1->running_on->data);
5ee7c6
+        n = node_copy(current_node1);
5ee7c6
         g_hash_table_insert(hash1, (gpointer) n->details->id, n);
5ee7c6
 
5ee7c6
-        n = node_copy(resource2->running_on->data);
5ee7c6
+        n = node_copy(current_node2);
5ee7c6
         g_hash_table_insert(hash2, (gpointer) n->details->id, n);
5ee7c6
 
5ee7c6
         if(resource1->parent) {
5ee7c6
@@ -267,11 +269,8 @@ sort_clone_instance(gconstpointer a, gconstpointer b, gpointer data_set)
5ee7c6
         }
5ee7c6
 
5ee7c6
         /* Current location score */
5ee7c6
-        node1 = g_list_nth_data(resource1->running_on, 0);
5ee7c6
-        node1 = g_hash_table_lookup(hash1, node1->details->id);
5ee7c6
-
5ee7c6
-        node2 = g_list_nth_data(resource2->running_on, 0);
5ee7c6
-        node2 = g_hash_table_lookup(hash2, node2->details->id);
5ee7c6
+        node1 = g_hash_table_lookup(hash1, current_node1->details->id);
5ee7c6
+        node2 = g_hash_table_lookup(hash2, current_node2->details->id);
5ee7c6
 
5ee7c6
         if (node1->weight < node2->weight) {
5ee7c6
             if (node1->weight < 0) {
5ee7c6
@@ -295,12 +294,8 @@ sort_clone_instance(gconstpointer a, gconstpointer b, gpointer data_set)
5ee7c6
         list1 = g_hash_table_get_values(hash1);
5ee7c6
         list2 = g_hash_table_get_values(hash2);
5ee7c6
 
5ee7c6
-        list1 =
5ee7c6
-            g_list_sort_with_data(list1, sort_node_weight,
5ee7c6
-                                  g_list_nth_data(resource1->running_on, 0));
5ee7c6
-        list2 =
5ee7c6
-            g_list_sort_with_data(list2, sort_node_weight,
5ee7c6
-                                  g_list_nth_data(resource2->running_on, 0));
5ee7c6
+        list1 = g_list_sort_with_data(list1, sort_node_weight, current_node1);
5ee7c6
+        list2 = g_list_sort_with_data(list2, sort_node_weight, current_node2);
5ee7c6
         max = g_list_length(list1);
5ee7c6
         if (max < g_list_length(list2)) {
5ee7c6
             max = g_list_length(list2);
5ee7c6
@@ -528,8 +523,8 @@ distribute_children(resource_t *rsc, GListPtr children, GListPtr nodes,
5ee7c6
 
5ee7c6
         if (child->running_on && is_set(child->flags, pe_rsc_provisional)
5ee7c6
             && is_not_set(child->flags, pe_rsc_failed)) {
5ee7c6
-            node_t *child_node = child->running_on->data;
5ee7c6
-            node_t *local_node = parent_node_instance(child, child->running_on->data);
5ee7c6
+            node_t *child_node = pe__current_node(child);
5ee7c6
+            node_t *local_node = parent_node_instance(child, child_node);
5ee7c6
 
5ee7c6
             pe_rsc_trace(rsc, "Checking pre-allocation of %s to %s (%d remaining of %d)",
5ee7c6
                          child->id, child_node->details->uname, max - allocated, max);
5ee7c6
@@ -556,9 +551,9 @@ distribute_children(resource_t *rsc, GListPtr children, GListPtr nodes,
5ee7c6
     for (GListPtr gIter = children; gIter != NULL; gIter = gIter->next) {
5ee7c6
         resource_t *child = (resource_t *) gIter->data;
5ee7c6
 
5ee7c6
-        if (g_list_length(child->running_on) > 0) {
5ee7c6
-            node_t *child_node = child->running_on->data;
5ee7c6
-            node_t *local_node = parent_node_instance(child, child->running_on->data);
5ee7c6
+        if (child->running_on != NULL) {
5ee7c6
+            node_t *child_node = pe__current_node(child);
5ee7c6
+            node_t *local_node = parent_node_instance(child, child_node);
5ee7c6
 
5ee7c6
             if (local_node == NULL) {
5ee7c6
                 crm_err("%s is running on %s which isn't allowed",
5ee7c6
diff --git a/pengine/graph.c b/pengine/graph.c
5ee7c6
index 6d4e4c7..236b278 100644
5ee7c6
--- a/pengine/graph.c
5ee7c6
+++ b/pengine/graph.c
5ee7c6
@@ -783,6 +783,7 @@ get_router_node(action_t *action)
5ee7c6
     node_t *began_on = NULL;
5ee7c6
     node_t *ended_on = NULL;
5ee7c6
     node_t *router_node = NULL;
5ee7c6
+    bool partial_migration = FALSE;
5ee7c6
 
5ee7c6
     if (safe_str_eq(action->task, CRM_OP_FENCE) || is_remote_node(action->node) == FALSE) {
5ee7c6
         return NULL;
5ee7c6
@@ -790,10 +791,13 @@ get_router_node(action_t *action)
5ee7c6
 
5ee7c6
     CRM_ASSERT(action->node->details->remote_rsc != NULL);
5ee7c6
 
5ee7c6
-    if (action->node->details->remote_rsc->running_on) {
5ee7c6
-        began_on = action->node->details->remote_rsc->running_on->data;
5ee7c6
-    }
5ee7c6
+    began_on = pe__current_node(action->node->details->remote_rsc);
5ee7c6
     ended_on = action->node->details->remote_rsc->allocated_to;
5ee7c6
+    if (action->node->details->remote_rsc
5ee7c6
+        && (action->node->details->remote_rsc->container == NULL)
5ee7c6
+        && action->node->details->remote_rsc->partial_migration_target) {
5ee7c6
+        partial_migration = TRUE;
5ee7c6
+    }
5ee7c6
 
5ee7c6
     /* if there is only one location to choose from,
5ee7c6
      * this is easy. Check for those conditions first */
5ee7c6
@@ -817,6 +821,10 @@ get_router_node(action_t *action)
5ee7c6
      *    are all required before the remote rsc stop action can occur.) In
5ee7c6
      *    this case, we know these actions have to be routed through the initial
5ee7c6
      *    cluster node the connection resource lived on before the move takes place.
5ee7c6
+     *    The exception is a partial migration of a (non-guest) remote
5ee7c6
+     *    connection resource; in that case, all actions (even these) will be
5ee7c6
+     *    ordered after the connection's pseudo-start on the migration target,
5ee7c6
+     *    so the target is the router node.
5ee7c6
      *
5ee7c6
      * 2. Everything else (start, promote, monitor, probe, refresh, clear failcount
5ee7c6
      *    delete ....) must occur after the resource starts on the node it is
5ee7c6
@@ -824,10 +832,10 @@ get_router_node(action_t *action)
5ee7c6
      */
5ee7c6
 
5ee7c6
     /* 1. before connection rsc moves. */
5ee7c6
-    if (safe_str_eq(action->task, "stop") ||
5ee7c6
+    if ((safe_str_eq(action->task, "stop") ||
5ee7c6
         safe_str_eq(action->task, "demote") ||
5ee7c6
         safe_str_eq(action->task, "migrate_from") ||
5ee7c6
-        safe_str_eq(action->task, "migrate_to")) {
5ee7c6
+        safe_str_eq(action->task, "migrate_to")) && !partial_migration) {
5ee7c6
 
5ee7c6
         router_node = began_on;
5ee7c6
 
5ee7c6
@@ -1234,18 +1242,14 @@ action2xml(action_t * action, gboolean as_input, pe_working_set_t *data_set)
5ee7c6
                 case stopped_rsc:
5ee7c6
                 case action_demote:
5ee7c6
                 case action_demoted:
5ee7c6
-                    if(action->node->details->remote_rsc->container->running_on) {
5ee7c6
-                        host = action->node->details->remote_rsc->container->running_on->data;
5ee7c6
-                    }
5ee7c6
+                    host = pe__current_node(action->node->details->remote_rsc->container);
5ee7c6
                     break;
5ee7c6
                 case start_rsc:
5ee7c6
                 case started_rsc:
5ee7c6
                 case monitor_rsc:
5ee7c6
                 case action_promote:
5ee7c6
                 case action_promoted:
5ee7c6
-                    if(action->node->details->remote_rsc->container->allocated_to) {
5ee7c6
-                        host = action->node->details->remote_rsc->container->allocated_to;
5ee7c6
-                    }
5ee7c6
+                    host = action->node->details->remote_rsc->container->allocated_to;
5ee7c6
                     break;
5ee7c6
                 default:
5ee7c6
                     break;
5ee7c6
diff --git a/pengine/native.c b/pengine/native.c
5ee7c6
index 37ac2e4..1c26642 100644
5ee7c6
--- a/pengine/native.c
5ee7c6
+++ b/pengine/native.c
5ee7c6
@@ -102,7 +102,7 @@ native_choose_node(resource_t * rsc, node_t * prefer, pe_working_set_t * data_se
5ee7c6
     if (length > 0) {
5ee7c6
         nodes = g_hash_table_get_values(rsc->allowed_nodes);
5ee7c6
         nodes = g_list_sort_with_data(nodes, sort_node_weight,
5ee7c6
-                                      g_list_nth_data(rsc->running_on, 0));
5ee7c6
+                                      pe__current_node(rsc));
5ee7c6
 
5ee7c6
         // First node in sorted list has the best score
5ee7c6
         best = g_list_nth_data(nodes, 0);
5ee7c6
@@ -158,7 +158,7 @@ native_choose_node(resource_t * rsc, node_t * prefer, pe_working_set_t * data_se
5ee7c6
              * remaining unallocated instances to prefer a node that's already
5ee7c6
              * running another instance.
5ee7c6
              */
5ee7c6
-            node_t *running = g_list_nth_data(rsc->running_on, 0);
5ee7c6
+            node_t *running = pe__current_node(rsc);
5ee7c6
 
5ee7c6
             if (running && (can_run_resources(running) == FALSE)) {
5ee7c6
                 pe_rsc_trace(rsc, "Current node for %s (%s) can't run resources",
5ee7c6
@@ -534,16 +534,14 @@ native_color(resource_t * rsc, node_t * prefer, pe_working_set_t * data_set)
5ee7c6
         node_t *assign_to = NULL;
5ee7c6
 
5ee7c6
         rsc->next_role = rsc->role;
5ee7c6
-        if (rsc->running_on == NULL) {
5ee7c6
+        assign_to = pe__current_node(rsc);
5ee7c6
+        if (assign_to == NULL) {
5ee7c6
             reason = "inactive";
5ee7c6
         } else if (rsc->role == RSC_ROLE_MASTER) {
5ee7c6
-            assign_to = rsc->running_on->data;
5ee7c6
             reason = "master";
5ee7c6
         } else if (is_set(rsc->flags, pe_rsc_failed)) {
5ee7c6
-            assign_to = rsc->running_on->data;
5ee7c6
             reason = "failed";
5ee7c6
         } else {
5ee7c6
-            assign_to = rsc->running_on->data;
5ee7c6
             reason = "active";
5ee7c6
         }
5ee7c6
         pe_rsc_info(rsc, "Unmanaged resource %s allocated to %s: %s", rsc->id,
5ee7c6
@@ -1834,7 +1832,9 @@ rsc_ticket_constraint(resource_t * rsc_lh, rsc_ticket_t * rsc_ticket, pe_working
5ee7c6
                  rsc_lh->id, rsc_ticket->ticket->id, rsc_ticket->id,
5ee7c6
                  role2text(rsc_ticket->role_lh));
5ee7c6
 
5ee7c6
-    if (rsc_ticket->ticket->granted == FALSE && g_list_length(rsc_lh->running_on) > 0) {
5ee7c6
+    if ((rsc_ticket->ticket->granted == FALSE)
5ee7c6
+        && (rsc_lh->running_on != NULL)) {
5ee7c6
+
5ee7c6
         GListPtr gIter = NULL;
5ee7c6
 
5ee7c6
         switch (rsc_ticket->loss_policy) {
5ee7c6
@@ -1867,7 +1867,7 @@ rsc_ticket_constraint(resource_t * rsc_lh, rsc_ticket_t * rsc_ticket, pe_working
5ee7c6
                 if (filter_rsc_ticket(rsc_lh, rsc_ticket) == FALSE) {
5ee7c6
                     return;
5ee7c6
                 }
5ee7c6
-                if (g_list_length(rsc_lh->running_on) > 0) {
5ee7c6
+                if (rsc_lh->running_on != NULL) {
5ee7c6
                     clear_bit(rsc_lh->flags, pe_rsc_managed);
5ee7c6
                     set_bit(rsc_lh->flags, pe_rsc_block);
5ee7c6
                 }
5ee7c6
@@ -1919,7 +1919,6 @@ native_update_actions(action_t * first, action_t * then, node_t * node, enum pe_
5ee7c6
         } else if ((then_rsc_role >= RSC_ROLE_STARTED)
5ee7c6
                    && safe_str_eq(then->task, RSC_START)
5ee7c6
                    && then->node
5ee7c6
-                   && then_rsc->running_on
5ee7c6
                    && g_list_length(then_rsc->running_on) == 1
5ee7c6
                    && then->node->details == ((node_t *) then_rsc->running_on->data)->details) {
5ee7c6
             /* ignore... if 'then' is supposed to be started after 'first', but
5ee7c6
diff --git a/pengine/notif.c b/pengine/notif.c
5ee7c6
index 3013ee0..4913249 100644
5ee7c6
--- a/pengine/notif.c
5ee7c6
+++ b/pengine/notif.c
5ee7c6
@@ -113,7 +113,7 @@ expand_node_list(GListPtr list, char **uname, char **metal)
5ee7c6
             if(node->details->remote_rsc
5ee7c6
                && node->details->remote_rsc->container
5ee7c6
                && node->details->remote_rsc->container->running_on) {
5ee7c6
-                node = node->details->remote_rsc->container->running_on->data;
5ee7c6
+                node = pe__current_node(node->details->remote_rsc->container);
5ee7c6
             }
5ee7c6
 
5ee7c6
             if (node->details->uname == NULL) {
5ee7c6
diff --git a/tools/crm_mon.c b/tools/crm_mon.c
5ee7c6
index 824b12f..7c63803 100644
5ee7c6
--- a/tools/crm_mon.c
5ee7c6
+++ b/tools/crm_mon.c
5ee7c6
@@ -1953,16 +1953,10 @@ get_node_display_name(node_t *node)
5ee7c6
 
5ee7c6
     /* Host is displayed only if this is a guest node */
5ee7c6
     if (is_container_remote_node(node)) {
5ee7c6
-        if (node->details->remote_rsc->running_on) {
5ee7c6
-            /* running_on is a list, but guest nodes will have exactly one entry
5ee7c6
-             * unless they are in the process of migrating, in which case they
5ee7c6
-             * will have two; either way, we can use the first item in the list
5ee7c6
-             */
5ee7c6
-            node_t *host_node = (node_t *) node->details->remote_rsc->running_on->data;
5ee7c6
-
5ee7c6
-            if (host_node && host_node->details) {
5ee7c6
-                node_host = host_node->details->uname;
5ee7c6
-            }
5ee7c6
+        node_t *host_node = pe__current_node(node->details->remote_rsc);
5ee7c6
+
5ee7c6
+        if (host_node && host_node->details) {
5ee7c6
+            node_host = host_node->details->uname;
5ee7c6
         }
5ee7c6
         if (node_host == NULL) {
5ee7c6
             node_host = ""; /* so we at least get "uname@" to indicate guest */
5ee7c6
diff --git a/tools/crm_resource.c b/tools/crm_resource.c
5ee7c6
index c64432e..0557892 100644
5ee7c6
--- a/tools/crm_resource.c
5ee7c6
+++ b/tools/crm_resource.c
5ee7c6
@@ -1015,23 +1015,27 @@ main(int argc, char **argv)
5ee7c6
         rc = cli_resource_ban(rsc_id, dest->details->uname, NULL, cib_conn);
5ee7c6
 
5ee7c6
     } else if (rsc_cmd == 'B' || rsc_cmd == 'M') {
5ee7c6
+        pe_node_t *current = NULL;
5ee7c6
+        unsigned int nactive = 0;
5ee7c6
+
5ee7c6
         rc = -EINVAL;
5ee7c6
-        if (g_list_length(rsc->running_on) == 1) {
5ee7c6
-            node_t *current = rsc->running_on->data;
5ee7c6
+        current = pe__find_active_requires(rsc, &nactive);
5ee7c6
+
5ee7c6
+        if (nactive == 1) {
5ee7c6
             rc = cli_resource_ban(rsc_id, current->details->uname, NULL, cib_conn);
5ee7c6
 
5ee7c6
         } else if(rsc->variant == pe_master) {
5ee7c6
             int count = 0;
5ee7c6
             GListPtr iter = NULL;
5ee7c6
-            node_t *current = NULL;
5ee7c6
 
5ee7c6
+            current = NULL;
5ee7c6
             for(iter = rsc->children; iter; iter = iter->next) {
5ee7c6
                 resource_t *child = (resource_t *)iter->data;
5ee7c6
                 enum rsc_role_e child_role = child->fns->state(child, TRUE);
5ee7c6
 
5ee7c6
                 if(child_role == RSC_ROLE_MASTER) {
5ee7c6
                     count++;
5ee7c6
-                    current = child->running_on->data;
5ee7c6
+                    current = pe__current_node(child);
5ee7c6
                 }
5ee7c6
             }
5ee7c6
 
5ee7c6
@@ -1039,14 +1043,15 @@ main(int argc, char **argv)
5ee7c6
                 rc = cli_resource_ban(rsc_id, current->details->uname, NULL, cib_conn);
5ee7c6
 
5ee7c6
             } else {
5ee7c6
-                CMD_ERR("Resource '%s' not moved: active in %d locations (promoted in %d).", rsc_id, g_list_length(rsc->running_on), count);
5ee7c6
+                CMD_ERR("Resource '%s' not moved: active in %d locations (promoted in %d).",
5ee7c6
+                        rsc_id, nactive, count);
5ee7c6
                 CMD_ERR("You can prevent '%s' from running on a specific location with: --ban --node <name>", rsc_id);
5ee7c6
                 CMD_ERR("You can prevent '%s' from being promoted at a specific location with:"
5ee7c6
                         " --ban --master --node <name>", rsc_id);
5ee7c6
             }
5ee7c6
 
5ee7c6
         } else {
5ee7c6
-            CMD_ERR("Resource '%s' not moved: active in %d locations.", rsc_id, g_list_length(rsc->running_on));
5ee7c6
+            CMD_ERR("Resource '%s' not moved: active in %d locations.", rsc_id, nactive);
5ee7c6
             CMD_ERR("You can prevent '%s' from running on a specific location with: --ban --node <name>", rsc_id);
5ee7c6
         }
5ee7c6
 
5ee7c6
@@ -1164,12 +1169,12 @@ main(int argc, char **argv)
5ee7c6
             node_t *node = pe_find_node(data_set.nodes, host_uname);
5ee7c6
 
5ee7c6
             if (node && is_remote_node(node)) {
5ee7c6
-                if (node->details->remote_rsc == NULL || node->details->remote_rsc->running_on == NULL) {
5ee7c6
+                node = pe__current_node(node->details->remote_rsc);
5ee7c6
+                if (node == NULL) {
5ee7c6
                     CMD_ERR("No lrmd connection detected to remote node %s", host_uname);
5ee7c6
                     rc = -ENXIO;
5ee7c6
                     goto bail;
5ee7c6
                 }
5ee7c6
-                node = node->details->remote_rsc->running_on->data;
5ee7c6
                 router_node = node->details->uname;
5ee7c6
                 attr_options |= attrd_opt_remote;
5ee7c6
             }
5ee7c6
diff --git a/tools/crm_resource_print.c b/tools/crm_resource_print.c
5ee7c6
index d066c42..2463fb5 100644
5ee7c6
--- a/tools/crm_resource_print.c
5ee7c6
+++ b/tools/crm_resource_print.c
5ee7c6
@@ -68,6 +68,7 @@ cli_resource_print_cts(resource_t * rsc)
5ee7c6
     const char *rtype = crm_element_value(rsc->xml, XML_ATTR_TYPE);
5ee7c6
     const char *rprov = crm_element_value(rsc->xml, XML_AGENT_ATTR_PROVIDER);
5ee7c6
     const char *rclass = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS);
5ee7c6
+    pe_node_t *node = pe__current_node(rsc);
5ee7c6
 
5ee7c6
     if (safe_str_eq(rclass, PCMK_RESOURCE_CLASS_STONITH)) {
5ee7c6
         xmlNode *op = NULL;
5ee7c6
@@ -90,10 +91,8 @@ cli_resource_print_cts(resource_t * rsc)
5ee7c6
         }
5ee7c6
     }
5ee7c6
 
5ee7c6
-    if (rsc->running_on != NULL && g_list_length(rsc->running_on) == 1) {
5ee7c6
-        node_t *tmp = rsc->running_on->data;
5ee7c6
-
5ee7c6
-        host = tmp->details->uname;
5ee7c6
+    if (node != NULL) {
5ee7c6
+        host = node->details->uname;
5ee7c6
     }
5ee7c6
 
5ee7c6
     printf("Resource: %s %s %s %s %s %s %s %s %d %lld 0x%.16llx\n",
5ee7c6
@@ -315,16 +314,15 @@ int
5ee7c6
 cli_resource_print_attribute(resource_t *rsc, const char *attr, pe_working_set_t * data_set)
5ee7c6
 {
5ee7c6
     int rc = -ENXIO;
5ee7c6
-    node_t *current = NULL;
5ee7c6
+    unsigned int count = 0;
5ee7c6
     GHashTable *params = NULL;
5ee7c6
     const char *value = NULL;
5ee7c6
+    node_t *current = pe__find_active_on(rsc, &count, NULL);
5ee7c6
 
5ee7c6
-    if (g_list_length(rsc->running_on) == 1) {
5ee7c6
-        current = rsc->running_on->data;
5ee7c6
-
5ee7c6
-    } else if (g_list_length(rsc->running_on) > 1) {
5ee7c6
+    if (count > 1) {
5ee7c6
         CMD_ERR("%s is active on more than one node,"
5ee7c6
                 " returning the default value for %s", rsc->id, crm_str(attr));
5ee7c6
+        current = NULL;
5ee7c6
     }
5ee7c6
 
5ee7c6
     params = crm_str_table_new();
5ee7c6
diff --git a/tools/crm_resource_runtime.c b/tools/crm_resource_runtime.c
5ee7c6
index 5e54f9e..5004935 100644
5ee7c6
--- a/tools/crm_resource_runtime.c
5ee7c6
+++ b/tools/crm_resource_runtime.c
5ee7c6
@@ -473,11 +473,11 @@ send_lrm_rsc_op(crm_ipc_t * crmd_channel, const char *op,
5ee7c6
         node_t *node = pe_find_node(data_set->nodes, host_uname);
5ee7c6
 
5ee7c6
         if (node && is_remote_node(node)) {
5ee7c6
-            if (node->details->remote_rsc == NULL || node->details->remote_rsc->running_on == NULL) {
5ee7c6
+            node = pe__current_node(node->details->remote_rsc);
5ee7c6
+            if (node == NULL) {
5ee7c6
                 CMD_ERR("No lrmd connection detected to remote node %s", host_uname);
5ee7c6
                 return -ENXIO;
5ee7c6
             }
5ee7c6
-            node = node->details->remote_rsc->running_on->data;
5ee7c6
             router_node = node->details->uname;
5ee7c6
         }
5ee7c6
     }
5ee7c6
@@ -1648,11 +1648,16 @@ cli_resource_move(resource_t *rsc, const char *rsc_id, const char *host_name,
5ee7c6
                   cib_t *cib, pe_working_set_t *data_set)
5ee7c6
 {
5ee7c6
     int rc = -EINVAL;
5ee7c6
-    int count = 0;
5ee7c6
+    unsigned int count = 0;
5ee7c6
     node_t *current = NULL;
5ee7c6
     node_t *dest = pe_find_node(data_set->nodes, host_name);
5ee7c6
     bool cur_is_dest = FALSE;
5ee7c6
 
5ee7c6
+    if (dest == NULL) {
5ee7c6
+        CMD_ERR("Error performing operation: node '%s' is unknown", host_name);
5ee7c6
+        return -ENXIO;
5ee7c6
+    }
5ee7c6
+
5ee7c6
     if (scope_master && rsc->variant != pe_master) {
5ee7c6
         resource_t *p = uber_parent(rsc);
5ee7c6
         if(p->variant == pe_master) {
5ee7c6
@@ -1667,8 +1672,12 @@ cli_resource_move(resource_t *rsc, const char *rsc_id, const char *host_name,
5ee7c6
         }
5ee7c6
     }
5ee7c6
 
5ee7c6
+    current = pe__find_active_requires(rsc, &count);
5ee7c6
+
5ee7c6
     if(rsc->variant == pe_master) {
5ee7c6
         GListPtr iter = NULL;
5ee7c6
+        unsigned int master_count = 0;
5ee7c6
+        pe_node_t *master_node = NULL;
5ee7c6
 
5ee7c6
         for(iter = rsc->children; iter; iter = iter->next) {
5ee7c6
             resource_t *child = (resource_t *)iter->data;
5ee7c6
@@ -1676,37 +1685,27 @@ cli_resource_move(resource_t *rsc, const char *rsc_id, const char *host_name,
5ee7c6
 
5ee7c6
             if(child_role == RSC_ROLE_MASTER) {
5ee7c6
                 rsc = child;
5ee7c6
-                count++;
5ee7c6
+                master_node = pe__current_node(child);
5ee7c6
+                master_count++;
5ee7c6
             }
5ee7c6
         }
5ee7c6
-
5ee7c6
-        if(scope_master == FALSE && count == 0) {
5ee7c6
-            count = g_list_length(rsc->running_on);
5ee7c6
+        if (scope_master || master_count) {
5ee7c6
+            count = master_count;
5ee7c6
+            current = master_node;
5ee7c6
         }
5ee7c6
 
5ee7c6
-    } else if (pe_rsc_is_clone(rsc)) {
5ee7c6
-        count = g_list_length(rsc->running_on);
5ee7c6
-
5ee7c6
-    } else if (g_list_length(rsc->running_on) > 1) {
5ee7c6
-        CMD_ERR("Resource '%s' not moved: active on multiple nodes", rsc_id);
5ee7c6
-        return rc;
5ee7c6
-    }
5ee7c6
-
5ee7c6
-    if(dest == NULL) {
5ee7c6
-        CMD_ERR("Error performing operation: node '%s' is unknown", host_name);
5ee7c6
-        return -ENXIO;
5ee7c6
     }
5ee7c6
 
5ee7c6
-    if(g_list_length(rsc->running_on) == 1) {
5ee7c6
-        current = rsc->running_on->data;
5ee7c6
+    if (count > 1) {
5ee7c6
+        if (pe_rsc_is_clone(rsc)) {
5ee7c6
+            current = NULL;
5ee7c6
+        } else {
5ee7c6
+            CMD_ERR("Resource '%s' not moved: active on multiple nodes", rsc_id);
5ee7c6
+            return rc;
5ee7c6
+        }
5ee7c6
     }
5ee7c6
 
5ee7c6
-    if(current == NULL) {
5ee7c6
-        /* Nothing to check */
5ee7c6
-
5ee7c6
-    } else if(scope_master && rsc->fns->state(rsc, TRUE) != RSC_ROLE_MASTER) {
5ee7c6
-        crm_trace("%s is already active on %s but not in correct state", rsc_id, dest->details->uname);
5ee7c6
-    } else if (safe_str_eq(current->details->uname, dest->details->uname)) {
5ee7c6
+    if (current && (current->details == dest->details)) {
5ee7c6
         cur_is_dest = TRUE;
5ee7c6
         if (do_force) {
5ee7c6
             crm_info("%s is already %s on %s, reinforcing placement with location constraint.",
5ee7c6
@@ -1736,7 +1735,7 @@ cli_resource_move(resource_t *rsc, const char *rsc_id, const char *host_name,
5ee7c6
             (void)cli_resource_ban(rsc_id, current->details->uname, NULL, cib);
5ee7c6
 
5ee7c6
         } else if(count > 1) {
5ee7c6
-            CMD_ERR("Resource '%s' is currently %s in %d locations.  One may now move one to %s",
5ee7c6
+            CMD_ERR("Resource '%s' is currently %s in %d locations. One may now move to %s",
5ee7c6
                     rsc_id, scope_master?"promoted":"active", count, dest->details->uname);
5ee7c6
             CMD_ERR("You can prevent '%s' from being %s at a specific location with:"
5ee7c6
                     " --ban %s--host <name>", rsc_id, scope_master?"promoted":"active", scope_master?"--master ":"");
5ee7c6
-- 
5ee7c6
1.8.3.1
5ee7c6