SOLR-8561: Add fallback to ZkController.getLeaderProps for a mixed 5.4-pre-5.4 deployments

git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/branches/lucene_solr_5_4@1725212 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index 5e983498..452be4a 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -34,6 +34,11 @@
 
 * SOLR-8418: Adapt to changes in LUCENE-6590 for use of boosts with MLTHandler and
   Simple/CloudMLTQParser (Jens Wille, Ramkumar Aiyengar)
+  
+* SOLR-8561: Doing a rolling upgrade to 5.4.0 fails because the new nodes cannot find the 
+  shard leader properties where they expect. This bug was first introduced in 5.4.0 and a
+  fallback was added so that the leader properties are searched in both the old location
+  and the new one. (Shai Erera)
 
 New Features
 ----------------------
diff --git a/solr/core/src/java/org/apache/solr/cloud/ZkController.java b/solr/core/src/java/org/apache/solr/cloud/ZkController.java
index d83cf81..1315279 100644
--- a/solr/core/src/java/org/apache/solr/cloud/ZkController.java
+++ b/solr/core/src/java/org/apache/solr/cloud/ZkController.java
@@ -1056,11 +1056,8 @@
     Exception exp = null;
     while (iterCount-- > 0) {
       try {
-        byte[] data = zkClient.getData(
-            ZkStateReader.getShardLeadersPath(collection, slice), null, null,
-            true);
-        ZkCoreNodeProps leaderProps = new ZkCoreNodeProps(
-            ZkNodeProps.load(data));
+        byte[] data = getLeaderPropsWithFallback(collection, slice);
+        ZkCoreNodeProps leaderProps = new ZkCoreNodeProps(ZkNodeProps.load(data));
         return leaderProps;
       } catch (InterruptedException e) {
         throw e;
@@ -1081,6 +1078,17 @@
     throw new SolrException(ErrorCode.SERVICE_UNAVAILABLE, "Could not get leader props", exp);
   }
 
+  private byte[] getLeaderPropsWithFallback(String collection, String slice) throws KeeperException, InterruptedException {
+    final String leaderPath = ZkStateReader.getShardLeadersPath(collection, slice);
+    try {
+      return zkClient.getData(leaderPath, null, null, true);
+    } catch (final KeeperException.NoNodeException e) {
+      // If the original leader node isn't found, fallback to a pre-5.4 format, where the leader props were set
+      // on the parent node (in case the current leader is a pre-5.4 Solr instance).
+      final String parentLeaderPath = new org.apache.hadoop.fs.Path(leaderPath).getParent().toString();
+      return zkClient.getData(parentLeaderPath, null, null, true);
+    }
+  }
 
   private void joinElection(CoreDescriptor cd, boolean afterExpiration, boolean joinAtHead)
       throws InterruptedException, KeeperException, IOException {