zookeeper-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From f..@apache.org
Subject [1/2] zookeeper git commit: ZOOKEEPER-2014: Only admin should be allowed to reconfig a cluster.
Date Sun, 13 Nov 2016 20:00:07 GMT
Repository: zookeeper
Updated Branches:
  refs/heads/branch-3.5 6bd38e3d8 -> 65d2572d9


http://git-wip-us.apache.org/repos/asf/zookeeper/blob/65d2572d/src/java/test/org/apache/zookeeper/server/quorum/ReconfigFailureCasesTest.java
----------------------------------------------------------------------
diff --git a/src/java/test/org/apache/zookeeper/server/quorum/ReconfigFailureCasesTest.java b/src/java/test/org/apache/zookeeper/server/quorum/ReconfigFailureCasesTest.java
index e7147b3..e9263bc 100644
--- a/src/java/test/org/apache/zookeeper/server/quorum/ReconfigFailureCasesTest.java
+++ b/src/java/test/org/apache/zookeeper/server/quorum/ReconfigFailureCasesTest.java
@@ -27,20 +27,28 @@ import java.util.List;
 
 import org.apache.zookeeper.KeeperException;
 import org.apache.zookeeper.KeeperException.NewConfigNoQuorum;
-import org.apache.zookeeper.PortAssignment;
 import org.apache.zookeeper.ZooKeeper;
+import org.apache.zookeeper.admin.ZooKeeperAdmin;
 import org.apache.zookeeper.data.Stat;
 import org.apache.zookeeper.test.ClientBase;
 import org.apache.zookeeper.test.QuorumUtil;
 import org.apache.zookeeper.test.ReconfigTest;
 import org.junit.After;
 import org.junit.Assert;
+import org.junit.Before;
 import org.junit.Test;
 
 public class ReconfigFailureCasesTest extends QuorumPeerTestBase {
 
     private QuorumUtil qu;
 
+    @Before
+    public void setup() {
+        QuorumPeerConfig.setReconfigEnabled(true);
+        System.setProperty("zookeeper.DigestAuthenticationProvider.superDigest",
+                "super:D/InIHSb7yEEbrWz8b9l71RjZJU="/* password is 'test'*/);
+    }
+
     @After
     public void tearDown() throws Exception {
         if (qu != null) {
@@ -57,6 +65,7 @@ public class ReconfigFailureCasesTest extends QuorumPeerTestBase {
         qu.disableJMXTest = true;
         qu.startAll();
         ZooKeeper[] zkArr = ReconfigTest.createHandles(qu);
+        ZooKeeperAdmin[] zkAdminArr = ReconfigTest.createAdminHandles(qu);
 
         ArrayList<String> members = new ArrayList<String>();
         members.add("group.1=3:4:5");
@@ -75,14 +84,14 @@ public class ReconfigFailureCasesTest extends QuorumPeerTestBase {
         }
 
         // Change the quorum system from majority to hierarchical.
-        ReconfigTest.reconfig(zkArr[1], null, null, members, -1);
+        ReconfigTest.reconfig(zkAdminArr[1], null, null, members, -1);
         ReconfigTest.testNormalOperation(zkArr[1], zkArr[2]);
 
         // Attempt an incremental reconfig.
         List<String> leavingServers = new ArrayList<String>();
         leavingServers.add("3");
         try {
-             zkArr[1].reconfig(null, leavingServers, null, -1, null);
+             zkAdminArr[1].reconfig(null, leavingServers, null, -1, null);
             Assert.fail("Reconfig should have failed since the current config isn't Majority QS");
         } catch (KeeperException.BadArgumentsException e) {
             // We expect this to happen.
@@ -90,7 +99,7 @@ public class ReconfigFailureCasesTest extends QuorumPeerTestBase {
             Assert.fail("Should have been BadArgumentsException!");
         }
 
-        ReconfigTest.closeAllHandles(zkArr);
+        ReconfigTest.closeAllHandles(zkArr, zkAdminArr);
     }
 
     /*
@@ -106,12 +115,13 @@ public class ReconfigFailureCasesTest extends QuorumPeerTestBase {
         qu.disableJMXTest = true;
         qu.startAll();
         ZooKeeper[] zkArr = ReconfigTest.createHandles(qu);
+        ZooKeeperAdmin[] zkAdminArr = ReconfigTest.createAdminHandles(qu);
 
         List<String> leavingServers = new ArrayList<String>();
         leavingServers.add("2");
         leavingServers.add("3");
         try {
-             zkArr[1].reconfig(null, leavingServers, null, -1, null);
+             zkAdminArr[1].reconfig(null, leavingServers, null, -1, null);
             Assert.fail("Reconfig should have failed since the current config version is not 8");
         } catch (KeeperException.BadArgumentsException e) {
             // We expect this to happen.
@@ -119,7 +129,7 @@ public class ReconfigFailureCasesTest extends QuorumPeerTestBase {
             Assert.fail("Should have been BadArgumentsException!");
         }
 
-        ReconfigTest.closeAllHandles(zkArr);
+        ReconfigTest.closeAllHandles(zkArr, zkAdminArr);
     }
 
     /*
@@ -132,11 +142,12 @@ public class ReconfigFailureCasesTest extends QuorumPeerTestBase {
         qu.disableJMXTest = true;
         qu.startAll();
         ZooKeeper[] zkArr = ReconfigTest.createHandles(qu);
+        ZooKeeperAdmin[] zkAdminArr = ReconfigTest.createAdminHandles(qu);
 
         List<String> leavingServers = new ArrayList<String>();
         leavingServers.add("3");
         try {
-             zkArr[1].reconfig(null, leavingServers, null, 8, null);
+             zkAdminArr[1].reconfig(null, leavingServers, null, 8, null);
             Assert.fail("Reconfig should have failed since the current config version is not 8");
         } catch (KeeperException.BadVersionException e) {
             // We expect this to happen.
@@ -144,7 +155,7 @@ public class ReconfigFailureCasesTest extends QuorumPeerTestBase {
             Assert.fail("Should have been BadVersionException!");
         }
 
-        ReconfigTest.closeAllHandles(zkArr);
+        ReconfigTest.closeAllHandles(zkArr, zkAdminArr);
     }
 
     /*
@@ -158,6 +169,7 @@ public class ReconfigFailureCasesTest extends QuorumPeerTestBase {
         qu.disableJMXTest = true;
         qu.startAll();
         ZooKeeper[] zkArr = ReconfigTest.createHandles(qu);
+        ZooKeeperAdmin[] zkAdminArr = ReconfigTest.createAdminHandles(qu);
 
         List<String> leavingServers = new ArrayList<String>();
         leavingServers.add("3");
@@ -170,7 +182,7 @@ public class ReconfigFailureCasesTest extends QuorumPeerTestBase {
             // We try to remove server 3, which requires a quorum of {1,2,3}
             // (we have that) and of {1,2}, but 2 is down so we won't get a
             // quorum of new config ACKs.
-            zkArr[1].reconfig(null, leavingServers, null, -1, null);
+            zkAdminArr[1].reconfig(null, leavingServers, null, -1, null);
             Assert.fail("Reconfig should have failed since we don't have quorum of new config");
         } catch (KeeperException.ConnectionLossException e) {
             // We expect leader to lose quorum of proposed config and time out
@@ -186,7 +198,7 @@ public class ReconfigFailureCasesTest extends QuorumPeerTestBase {
                 qu.getPeer(1).peer.getServerState());
         Assert.assertEquals(QuorumStats.Provider.LOOKING_STATE,
                 qu.getPeer(3).peer.getServerState());
-        ReconfigTest.closeAllHandles(zkArr);
+        ReconfigTest.closeAllHandles(zkArr, zkAdminArr);
     }
 
     /*
@@ -222,6 +234,7 @@ public class ReconfigFailureCasesTest extends QuorumPeerTestBase {
 
         MainThread mt[] = new MainThread[SERVER_COUNT];
         ZooKeeper zk[] = new ZooKeeper[SERVER_COUNT];
+        ZooKeeperAdmin zkAdmin[] = new ZooKeeperAdmin[SERVER_COUNT];
 
         // Server 0 stays down
         for (int i = 1; i < SERVER_COUNT; i++) {
@@ -230,6 +243,9 @@ public class ReconfigFailureCasesTest extends QuorumPeerTestBase {
             mt[i].start();
             zk[i] = new ZooKeeper("127.0.0.1:" + ports[i][2],
                     ClientBase.CONNECTION_TIMEOUT, this);
+            zkAdmin[i] = new ZooKeeperAdmin("127.0.0.1:" + ports[i][2],
+                    ClientBase.CONNECTION_TIMEOUT, this);
+            zkAdmin[i].addAuthInfo("digest", "super:test".getBytes());
         }
 
         for (int i = 1; i < SERVER_COUNT; i++) {
@@ -239,7 +255,7 @@ public class ReconfigFailureCasesTest extends QuorumPeerTestBase {
         }
 
         try {
-            zk[1].reconfig("", "", nextQuorumCfgSection, -1, new Stat());
+            zkAdmin[1].reconfig("", "", nextQuorumCfgSection, -1, new Stat());
             Assert.fail("Reconfig should have failed with NewConfigNoQuorum");
         } catch (NewConfigNoQuorum e) {
             // This is expected case since server 0 is down and 3 can't vote
@@ -250,19 +266,20 @@ public class ReconfigFailureCasesTest extends QuorumPeerTestBase {
         // In this scenario to change 3's role to participant we need to remove it first
         ArrayList<String> leavingServers = new ArrayList<String>();
         leavingServers.add("3");
-        ReconfigTest.reconfig(zk[1], null, leavingServers, null, -1);
+        ReconfigTest.reconfig(zkAdmin[1], null, leavingServers, null, -1);
         ReconfigTest.testNormalOperation(zk[2], zk[3]);
         ReconfigTest.testServerHasConfig(zk[3], null, leavingServers);
 
         // Now we're adding it back as a participant and everything should work.
         List<String> newMembers = Arrays.asList(nextQuorumCfgSection.split("\n"));
-        ReconfigTest.reconfig(zk[1], null, null, newMembers, -1);
+        ReconfigTest.reconfig(zkAdmin[1], null, null, newMembers, -1);
         ReconfigTest.testNormalOperation(zk[2], zk[3]);
         for (int i = 1; i < SERVER_COUNT; i++) {
             ReconfigTest.testServerHasConfig(zk[i], newMembers, null);
         }
         for (int i = 1; i < SERVER_COUNT; i++) {
             zk[i].close();
+            zkAdmin[i].close();
             mt[i].shutdown();
         }
     }

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/65d2572d/src/java/test/org/apache/zookeeper/server/quorum/ReconfigLegacyTest.java
----------------------------------------------------------------------
diff --git a/src/java/test/org/apache/zookeeper/server/quorum/ReconfigLegacyTest.java b/src/java/test/org/apache/zookeeper/server/quorum/ReconfigLegacyTest.java
index ee9f2e2..80a8bfe 100644
--- a/src/java/test/org/apache/zookeeper/server/quorum/ReconfigLegacyTest.java
+++ b/src/java/test/org/apache/zookeeper/server/quorum/ReconfigLegacyTest.java
@@ -31,6 +31,7 @@ import org.apache.zookeeper.CreateMode;
 import org.apache.zookeeper.PortAssignment;
 import org.apache.zookeeper.ZooDefs.Ids;
 import org.apache.zookeeper.ZooKeeper;
+import org.apache.zookeeper.admin.ZooKeeperAdmin;
 import org.apache.zookeeper.test.ClientBase;
 import org.apache.zookeeper.test.ReconfigTest;
 import org.junit.Assert;
@@ -44,6 +45,9 @@ public class ReconfigLegacyTest extends QuorumPeerTestBase {
     @Before
     public void setup() {
         ClientBase.setupTestEnv();
+        QuorumPeerConfig.setReconfigEnabled(true);
+        System.setProperty("zookeeper.DigestAuthenticationProvider.superDigest",
+                "super:D/InIHSb7yEEbrWz8b9l71RjZJU="/* password is 'test'*/);
     }
 
     /**
@@ -174,6 +178,7 @@ public class ReconfigLegacyTest extends QuorumPeerTestBase {
 
         MainThread mt[] = new MainThread[SERVER_COUNT];
         ZooKeeper zk[] = new ZooKeeper[SERVER_COUNT];
+        ZooKeeperAdmin zkAdmin[] = new ZooKeeperAdmin[SERVER_COUNT];
 
         // Start the servers with a static config file, without a dynamic config file.
         for (int i = 0; i < SERVER_COUNT; i++) {
@@ -188,6 +193,9 @@ public class ReconfigLegacyTest extends QuorumPeerTestBase {
                     ClientBase.waitForServerUp("127.0.0.1:" + clientPorts[i],
                             CONNECTION_TIMEOUT));
             zk[i] = ClientBase.createZKClient("127.0.0.1:" + clientPorts[i]);
+            zkAdmin[i] = new ZooKeeperAdmin("127.0.0.1:" + clientPorts[i],
+                    ClientBase.CONNECTION_TIMEOUT, this);
+            zkAdmin[i].addAuthInfo("digest", "super:test".getBytes());
 
             ReconfigTest.testServerHasConfig(zk[i], allServers, null);
             Properties cfg = readPropertiesFromFile(mt[i].confFile);
@@ -197,7 +205,7 @@ public class ReconfigLegacyTest extends QuorumPeerTestBase {
         }
         ReconfigTest.testNormalOperation(zk[0], zk[1]);
 
-        ReconfigTest.reconfig(zk[1], null, null, newServers, -1);
+        ReconfigTest.reconfig(zkAdmin[1], null, null, newServers, -1);
         ReconfigTest.testNormalOperation(zk[0], zk[1]);
 
         // Sleep since writing the config files may take time.
@@ -220,6 +228,7 @@ public class ReconfigLegacyTest extends QuorumPeerTestBase {
         for (int i = 0; i < SERVER_COUNT; i++) {
             mt[i].shutdown();
             zk[i].close();
+            zkAdmin[i].close();
         }
     }
 

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/65d2572d/src/java/test/org/apache/zookeeper/server/quorum/StandaloneDisabledTest.java
----------------------------------------------------------------------
diff --git a/src/java/test/org/apache/zookeeper/server/quorum/StandaloneDisabledTest.java b/src/java/test/org/apache/zookeeper/server/quorum/StandaloneDisabledTest.java
index 1f6ce1f..9a85d77 100644
--- a/src/java/test/org/apache/zookeeper/server/quorum/StandaloneDisabledTest.java
+++ b/src/java/test/org/apache/zookeeper/server/quorum/StandaloneDisabledTest.java
@@ -27,6 +27,7 @@ import org.apache.zookeeper.KeeperException;
 import org.apache.zookeeper.data.Stat;
 import org.apache.zookeeper.PortAssignment;
 import org.apache.zookeeper.ZooKeeper;
+import org.apache.zookeeper.admin.ZooKeeperAdmin;
 import org.apache.zookeeper.test.ClientBase;
 import org.apache.zookeeper.test.ReconfigTest;
 import org.junit.Assert;
@@ -37,6 +38,7 @@ public class StandaloneDisabledTest extends QuorumPeerTestBase {
     private final int NUM_SERVERS = 5;
     private MainThread peers[];
     private ZooKeeper zkHandles[];
+    private ZooKeeperAdmin zkAdminHandles[];
     private int clientPorts[];
     private final int leaderId = 0;
     private final int follower1 = 1;
@@ -75,7 +77,7 @@ public class StandaloneDisabledTest extends QuorumPeerTestBase {
         reconfigServers.clear();
         reconfigServers.add(Integer.toString(follower2));
         try {
-            ReconfigTest.reconfig(zkHandles[follower1], null, reconfigServers, null, -1);
+            ReconfigTest.reconfig(zkAdminHandles[follower1], null, reconfigServers, null, -1);
             Assert.fail("reconfig completed successfully even though there is no quorum up in new config!");
         } catch (KeeperException.NewConfigNoQuorum e) { }
 
@@ -92,7 +94,7 @@ public class StandaloneDisabledTest extends QuorumPeerTestBase {
         reconfigServers.clear();
         reconfigServers.add(Integer.toString(follower2));
         try {
-            zkHandles[follower2].reconfig(null, reconfigServers, null, -1, new Stat());
+            zkAdminHandles[follower2].reconfig(null, reconfigServers, null, -1, new Stat());
             Assert.fail("reconfig completed successfully even though there is no quorum up in new config!");
         } catch (KeeperException.BadArgumentsException e) {
             // This is expected.
@@ -118,11 +120,15 @@ public class StandaloneDisabledTest extends QuorumPeerTestBase {
     private void setUpData() throws Exception {
         ClientBase.setupTestEnv();
         QuorumPeerConfig.setStandaloneEnabled(false);
+        QuorumPeerConfig.setReconfigEnabled(true);
         peers = new MainThread[NUM_SERVERS];
         zkHandles = new ZooKeeper[NUM_SERVERS];
+        zkAdminHandles = new ZooKeeperAdmin[NUM_SERVERS];
         clientPorts = new int[NUM_SERVERS];
         serverStrings = buildServerStrings();
         reconfigServers = new ArrayList<String>();
+        System.setProperty("zookeeper.DigestAuthenticationProvider.superDigest",
+                "super:D/InIHSb7yEEbrWz8b9l71RjZJU="/* password is 'test'*/);
     }
 
     /**
@@ -131,6 +137,7 @@ public class StandaloneDisabledTest extends QuorumPeerTestBase {
     private void shutDownData() throws Exception {
         for (int i = 0; i < NUM_SERVERS; i++) {
             zkHandles[i].close();
+            zkAdminHandles[i].close();
         }
         for (int i = 1; i < NUM_SERVERS; i++) {
             peers[i].shutdown();
@@ -167,6 +174,8 @@ public class StandaloneDisabledTest extends QuorumPeerTestBase {
         Assert.assertTrue("Error- Server started in Standalone Mode!",
                 peers[id].isQuorumPeerRunning());
         zkHandles[id] = ClientBase.createZKClient("127.0.0.1:" + clientPorts[id]);
+        zkAdminHandles[id] = new ZooKeeperAdmin("127.0.0.1:" + clientPorts[id], CONNECTION_TIMEOUT, this);
+        zkAdminHandles[id].addAuthInfo("digest", "super:test".getBytes());
     }
 
     /**
@@ -221,14 +230,14 @@ public class StandaloneDisabledTest extends QuorumPeerTestBase {
     private void testReconfig(int id, boolean adding,
                               ArrayList<String> servers) throws Exception {
         if (adding) {
-            ReconfigTest.reconfig(zkHandles[id], servers, null, null, -1);
+            ReconfigTest.reconfig(zkAdminHandles[id], servers, null, null, -1);
             for (String server : servers) {
                 int id2 = Integer.parseInt(server.substring(7, 8)); //server.#
                 ReconfigTest.testNormalOperation(zkHandles[id], zkHandles[id2]);
             }
             ReconfigTest.testServerHasConfig(zkHandles[id], servers, null);
         } else {
-            ReconfigTest.reconfig(zkHandles[id], null, servers, null, -1);
+            ReconfigTest.reconfig(zkAdminHandles[id], null, servers, null, -1);
             ReconfigTest.testServerHasConfig(zkHandles[id], null, servers);
         }
 

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/65d2572d/src/java/test/org/apache/zookeeper/server/quorum/Zab1_0Test.java
----------------------------------------------------------------------
diff --git a/src/java/test/org/apache/zookeeper/server/quorum/Zab1_0Test.java b/src/java/test/org/apache/zookeeper/server/quorum/Zab1_0Test.java
index 6a01447..22827bd 100644
--- a/src/java/test/org/apache/zookeeper/server/quorum/Zab1_0Test.java
+++ b/src/java/test/org/apache/zookeeper/server/quorum/Zab1_0Test.java
@@ -1216,13 +1216,13 @@ public class Zab1_0Test extends ZKTestCase {
     }
     
     private Leader createLeader(File tmpDir, QuorumPeer peer)
-    throws IOException, NoSuchFieldException, IllegalAccessException{
+    throws IOException, NoSuchFieldException, IllegalAccessException {
         LeaderZooKeeperServer zk = prepareLeader(tmpDir, peer);
         return new Leader(peer, zk);
     }
     
     private Leader createMockLeader(File tmpDir, QuorumPeer peer)
-    throws IOException, NoSuchFieldException, IllegalAccessException{
+    throws IOException, NoSuchFieldException, IllegalAccessException {
         LeaderZooKeeperServer zk = prepareLeader(tmpDir, peer);
         return new MockLeader(peer, zk);
     }

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/65d2572d/src/java/test/org/apache/zookeeper/test/ACLTest.java
----------------------------------------------------------------------
diff --git a/src/java/test/org/apache/zookeeper/test/ACLTest.java b/src/java/test/org/apache/zookeeper/test/ACLTest.java
index 9920fc4..e88f7f4 100644
--- a/src/java/test/org/apache/zookeeper/test/ACLTest.java
+++ b/src/java/test/org/apache/zookeeper/test/ACLTest.java
@@ -115,7 +115,8 @@ public class ACLTest extends ZKTestCase implements Watcher {
                 zk.create(path, path.getBytes(), Ids.OPEN_ACL_UNSAFE,
                         CreateMode.PERSISTENT);
             }
-            Assert.assertTrue("size of the acl map ", (1 == zks.getZKDatabase().getAclSize()));
+            int size = zks.getZKDatabase().getAclSize();
+            Assert.assertTrue("size of the acl map ", (2 == zks.getZKDatabase().getAclSize()));
             for (int j = 100; j < 200; j++) {
                 path = "/" + j;
                 ACL acl = new ACL();
@@ -128,7 +129,7 @@ public class ACLTest extends ZKTestCase implements Watcher {
                 list.add(acl);
                 zk.create(path, path.getBytes(), list, CreateMode.PERSISTENT);
             }
-            Assert.assertTrue("size of the acl map ", (101 == zks.getZKDatabase().getAclSize()));
+            Assert.assertTrue("size of the acl map ", (102 == zks.getZKDatabase().getAclSize()));
         } finally {
             // now shutdown the server and restart it
             f.shutdown();
@@ -145,7 +146,7 @@ public class ACLTest extends ZKTestCase implements Watcher {
             Assert.assertTrue("waiting for server up",
                        ClientBase.waitForServerUp(HOSTPORT, CONNECTION_TIMEOUT));
             zk = ClientBase.createZKClient(HOSTPORT);
-            Assert.assertTrue("acl map ", (101 == zks.getZKDatabase().getAclSize()));
+            Assert.assertTrue("acl map ", (102 == zks.getZKDatabase().getAclSize()));
             for (int j = 200; j < 205; j++) {
                 path = "/" + j;
                 ACL acl = new ACL();
@@ -158,7 +159,7 @@ public class ACLTest extends ZKTestCase implements Watcher {
                 list.add(acl);
                 zk.create(path, path.getBytes(), list, CreateMode.PERSISTENT);
             }
-            Assert.assertTrue("acl map ", (106 == zks.getZKDatabase().getAclSize()));
+            Assert.assertTrue("acl map ", (107 == zks.getZKDatabase().getAclSize()));
     
             zk.close();
         } finally {

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/65d2572d/src/java/test/org/apache/zookeeper/test/ReconfigExceptionTest.java
----------------------------------------------------------------------
diff --git a/src/java/test/org/apache/zookeeper/test/ReconfigExceptionTest.java b/src/java/test/org/apache/zookeeper/test/ReconfigExceptionTest.java
new file mode 100644
index 0000000..e56ae6f
--- /dev/null
+++ b/src/java/test/org/apache/zookeeper/test/ReconfigExceptionTest.java
@@ -0,0 +1,220 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.zookeeper.test;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.TimeoutException;
+
+import org.apache.zookeeper.ZKTestCase;
+import org.apache.zookeeper.KeeperException;
+import org.apache.zookeeper.ZooDefs;
+import org.apache.zookeeper.PortAssignment;
+import org.apache.zookeeper.admin.ZooKeeperAdmin;
+import org.apache.zookeeper.data.ACL;
+import org.apache.zookeeper.data.Id;
+import org.apache.zookeeper.data.Stat;
+import org.apache.zookeeper.server.quorum.QuorumPeerConfig;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ReconfigExceptionTest extends ZKTestCase {
+    private static final Logger LOG = LoggerFactory
+            .getLogger(ReconfigExceptionTest.class);
+    private static String authProvider = "zookeeper.DigestAuthenticationProvider.superDigest";
+    // Use DigestAuthenticationProvider.base64Encode or
+    // run ZooKeeper jar with org.apache.zookeeper.server.auth.DigestAuthenticationProvider to generate password.
+    // An example:
+    // java -cp zookeeper-3.6.0-SNAPSHOT.jar:lib/log4j-1.2.17.jar:lib/slf4j-log4j12-1.7.5.jar:
+    // lib/slf4j-api-1.7.5.jar org.apache.zookeeper.server.auth.DigestAuthenticationProvider super:test
+    // The password here is 'test'.
+    private static String superDigest = "super:D/InIHSb7yEEbrWz8b9l71RjZJU=";
+    private QuorumUtil qu;
+    private ZooKeeperAdmin zkAdmin;
+
+    @Before
+    public void setup() throws InterruptedException {
+        System.setProperty(authProvider, superDigest);
+        QuorumPeerConfig.setReconfigEnabled(false);
+
+        // Get a three server quorum.
+        qu = new QuorumUtil(1);
+        qu.disableJMXTest = true;
+
+        try {
+            qu.startAll();
+        } catch (IOException e) {
+            Assert.fail("Fail to start quorum servers.");
+        }
+
+        resetZKAdmin();
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        System.clearProperty(authProvider);
+        try {
+            if (qu != null) {
+                qu.tearDown();
+            }
+            if (zkAdmin != null) {
+                zkAdmin.close();
+            }
+        } catch (Exception e) {
+            // Ignore.
+        }
+    }
+
+    @Test(timeout = 10000)
+    public void testReconfigDisabledByDefault() throws InterruptedException {
+        try {
+            reconfigPort();
+            Assert.fail("Reconfig should be disabled by default.");
+        } catch (KeeperException e) {
+            Assert.assertTrue(e.code() == KeeperException.Code.RECONFIGDISABLED);
+        }
+    }
+
+    @Test(timeout = 10000)
+    public void testReconfigFailWithoutAuth() throws InterruptedException {
+        // Now enable reconfig feature by turning on the switch.
+        QuorumPeerConfig.setReconfigEnabled(true);
+
+        try {
+            reconfigPort();
+            Assert.fail("Reconfig should fail without auth.");
+        } catch (KeeperException e) {
+            // However a failure is still expected as user is not authenticated, so ACL check will fail.
+            Assert.assertTrue(e.code() == KeeperException.Code.NOAUTH);
+        }
+    }
+
+    @Test(timeout = 10000)
+    public void testReconfigEnabledWithSuperUser() throws InterruptedException {
+        QuorumPeerConfig.setReconfigEnabled(true);
+
+        try {
+            zkAdmin.addAuthInfo("digest", "super:test".getBytes());
+            Assert.assertTrue(reconfigPort());
+        } catch (KeeperException e) {
+            Assert.fail("Reconfig should not fail, but failed with exception : " + e.getMessage());
+        }
+    }
+
+    @Test(timeout = 10000)
+    public void testReconfigFailWithAuthWithNoACL() throws InterruptedException {
+        resetZKAdmin();
+        QuorumPeerConfig.setReconfigEnabled(true);
+
+        try {
+            zkAdmin.addAuthInfo("digest", "user:test".getBytes());
+            reconfigPort();
+            Assert.fail("Reconfig should fail without a valid ACL associated with user.");
+        } catch (KeeperException e) {
+            // Again failure is expected because no ACL is associated with this user.
+            Assert.assertTrue(e.code() == KeeperException.Code.NOAUTH);
+        }
+    }
+
+    @Test(timeout = 10000)
+    public void testReconfigEnabledWithAuthAndWrongACL() throws InterruptedException {
+        resetZKAdmin();
+        QuorumPeerConfig.setReconfigEnabled(true);
+
+        try {
+            zkAdmin.addAuthInfo("digest", "super:test".getBytes());
+            // There is ACL however the permission is wrong - need WRITE permission at leaste.
+            ArrayList<ACL> acls = new ArrayList<ACL>(
+                    Collections.singletonList(
+                            new ACL(ZooDefs.Perms.READ,
+                                    new Id("digest", "user:tl+z3z0vO6PfPfEENfLF96E6pM0="/* password is test */))));
+            zkAdmin.setACL(ZooDefs.CONFIG_NODE, acls, -1);
+            resetZKAdmin();
+            zkAdmin.addAuthInfo("digest", "user:test".getBytes());
+            reconfigPort();
+            Assert.fail("Reconfig should fail with an ACL that is read only!");
+        } catch (KeeperException e) {
+            Assert.assertTrue(e.code() == KeeperException.Code.NOAUTH);
+        }
+    }
+
+    @Test(timeout = 10000)
+    public void testReconfigEnabledWithAuthAndACL() throws InterruptedException {
+        resetZKAdmin();
+        QuorumPeerConfig.setReconfigEnabled(true);
+
+        try {
+            zkAdmin.addAuthInfo("digest", "super:test".getBytes());
+            ArrayList<ACL> acls = new ArrayList<ACL>(
+                    Collections.singletonList(
+                            new ACL(ZooDefs.Perms.WRITE,
+                            new Id("digest", "user:tl+z3z0vO6PfPfEENfLF96E6pM0="/* password is test */))));
+            zkAdmin.setACL(ZooDefs.CONFIG_NODE, acls, -1);
+            resetZKAdmin();
+            zkAdmin.addAuthInfo("digest", "user:test".getBytes());
+            Assert.assertTrue(reconfigPort());
+        } catch (KeeperException e) {
+            Assert.fail("Reconfig should not fail, but failed with exception : " + e.getMessage());
+        }
+    }
+
+    // Utility method that recreates a new ZooKeeperAdmin handle, and wait for the handle to connect to
+    // quorum servers.
+    private void resetZKAdmin() throws InterruptedException {
+        String cnxString;
+        ClientBase.CountdownWatcher watcher = new ClientBase.CountdownWatcher();
+        try {
+            cnxString = "127.0.0.1:" + qu.getPeer(1).peer.getClientPort();
+            if (zkAdmin != null) {
+                zkAdmin.close();
+            }
+            zkAdmin = new ZooKeeperAdmin(cnxString,
+                    ClientBase.CONNECTION_TIMEOUT, watcher);
+        } catch (IOException e) {
+            Assert.fail("Fail to create ZooKeeperAdmin handle.");
+            return;
+        }
+
+        try {
+            watcher.waitForConnected(ClientBase.CONNECTION_TIMEOUT);
+        } catch (InterruptedException | TimeoutException e) {
+            Assert.fail("ZooKeeper admin client can not connect to " + cnxString);
+        }
+    }
+
+    private boolean reconfigPort() throws KeeperException, InterruptedException {
+        List<String> joiningServers = new ArrayList<String>();
+        int leaderId = 1;
+        while (qu.getPeer(leaderId).peer.leader == null)
+            leaderId++;
+        int followerId = leaderId == 1 ? 2 : 1;
+        joiningServers.add("server." + followerId + "=localhost:"
+                + qu.getPeer(followerId).peer.getQuorumAddress().getPort() /*quorum port*/
+                + ":" + qu.getPeer(followerId).peer.getElectionAddress().getPort() /*election port*/
+                + ":participant;localhost:" + PortAssignment.unique()/* new client port */);
+        zkAdmin.reconfig(joiningServers, null, null, -1, new Stat());
+        return true;
+    }
+}

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/65d2572d/src/java/test/org/apache/zookeeper/test/ReconfigMisconfigTest.java
----------------------------------------------------------------------
diff --git a/src/java/test/org/apache/zookeeper/test/ReconfigMisconfigTest.java b/src/java/test/org/apache/zookeeper/test/ReconfigMisconfigTest.java
new file mode 100644
index 0000000..7aaa419
--- /dev/null
+++ b/src/java/test/org/apache/zookeeper/test/ReconfigMisconfigTest.java
@@ -0,0 +1,130 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.zookeeper.test;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.TimeoutException;
+
+import org.apache.zookeeper.ZKTestCase;
+import org.apache.zookeeper.KeeperException;
+import org.apache.zookeeper.PortAssignment;
+import org.apache.zookeeper.admin.ZooKeeperAdmin;
+import org.apache.zookeeper.data.Stat;
+import org.apache.zookeeper.server.quorum.QuorumPeerConfig;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ReconfigMisconfigTest extends ZKTestCase {
+    private static final Logger LOG = LoggerFactory.getLogger(ReconfigMisconfigTest.class);
+    private QuorumUtil qu;
+    private ZooKeeperAdmin zkAdmin;
+    private static String errorMsg = "Reconfig should fail without configuring the super " +
+            "user's password on server side first.";
+
+    @Before
+    public void setup() throws InterruptedException {
+        QuorumPeerConfig.setReconfigEnabled(false);
+        // Get a three server quorum.
+        qu = new QuorumUtil(1);
+        qu.disableJMXTest = true;
+        try {
+            qu.startAll();
+        } catch (IOException e) {
+            Assert.fail("Fail to start quorum servers.");
+        }
+
+        instantiateZKAdmin();
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        try {
+            if (qu != null) {
+                qu.tearDown();
+            }
+            if (zkAdmin != null) {
+                zkAdmin.close();
+            }
+        } catch (Exception e) {
+            // Ignore.
+        }
+    }
+
+    @Test(timeout = 10000)
+    public void testReconfigFailWithoutSuperuserPasswordConfiguredOnServer() throws InterruptedException {
+        // This tests the case where ZK ensemble does not have the super user's password configured.
+        // Reconfig should fail as the super user has to be explicitly configured via
+        // zookeeper.DigestAuthenticationProvider.superDigest.
+        QuorumPeerConfig.setReconfigEnabled(true);
+        try {
+            reconfigPort();
+            Assert.fail(errorMsg);
+        } catch (KeeperException e) {
+            Assert.assertTrue(e.getCode() == KeeperException.Code.NoAuth);
+        }
+
+        try {
+            zkAdmin.addAuthInfo("digest", "super:".getBytes());
+            reconfigPort();
+            Assert.fail(errorMsg);
+        } catch (KeeperException e) {
+            Assert.assertTrue(e.getCode() == KeeperException.Code.NoAuth);
+        }
+    }
+
+    private void instantiateZKAdmin() throws InterruptedException {
+        String cnxString;
+        ClientBase.CountdownWatcher watcher = new ClientBase.CountdownWatcher();
+        try {
+            cnxString = "127.0.0.1:" + qu.getPeer(1).peer.getClientPort();
+            zkAdmin = new ZooKeeperAdmin(cnxString,
+                    ClientBase.CONNECTION_TIMEOUT, watcher);
+        } catch (IOException e) {
+            Assert.fail("Fail to create ZooKeeperAdmin handle.");
+            return;
+        }
+
+        try {
+            watcher.waitForConnected(ClientBase.CONNECTION_TIMEOUT);
+        } catch (InterruptedException | TimeoutException e) {
+            Assert.fail("ZooKeeper admin client can not connect to " + cnxString);
+        }
+    }
+
+    private boolean reconfigPort() throws KeeperException, InterruptedException {
+        List<String> joiningServers = new ArrayList<String>();
+        int leaderId = 1;
+        while (qu.getPeer(leaderId).peer.leader == null)
+            leaderId++;
+        int followerId = leaderId == 1 ? 2 : 1;
+        joiningServers.add("server." + followerId + "=localhost:"
+                + qu.getPeer(followerId).peer.getQuorumAddress().getPort() /*quorum port*/
+                + ":" + qu.getPeer(followerId).peer.getElectionAddress().getPort() /*election port*/
+                + ":participant;localhost:" + PortAssignment.unique()/* new client port */);
+        zkAdmin.reconfig(joiningServers, null, null, -1, new Stat());
+        return true;
+    }
+}
+

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/65d2572d/src/java/test/org/apache/zookeeper/test/ReconfigTest.java
----------------------------------------------------------------------
diff --git a/src/java/test/org/apache/zookeeper/test/ReconfigTest.java b/src/java/test/org/apache/zookeeper/test/ReconfigTest.java
index 248a754..6ca415c 100644
--- a/src/java/test/org/apache/zookeeper/test/ReconfigTest.java
+++ b/src/java/test/org/apache/zookeeper/test/ReconfigTest.java
@@ -29,25 +29,28 @@ import java.util.ArrayList;
 import java.util.LinkedList;
 import java.util.List;
 
-import org.apache.zookeeper.AsyncCallback.DataCallback;
-import org.apache.zookeeper.CreateMode;
 import org.apache.zookeeper.KeeperException;
-import org.apache.zookeeper.PortAssignment;
-import org.apache.zookeeper.WatchedEvent;
-import org.apache.zookeeper.Watcher;
 import org.apache.zookeeper.ZKTestCase;
-import org.apache.zookeeper.ZooDefs;
-import org.apache.zookeeper.ZooKeeper;
+import org.apache.zookeeper.AsyncCallback.DataCallback;
 import org.apache.zookeeper.data.Stat;
 import org.apache.zookeeper.jmx.CommonNames;
 import org.apache.zookeeper.server.quorum.QuorumPeer;
 import org.apache.zookeeper.server.quorum.QuorumPeer.QuorumServer;
 import org.apache.zookeeper.server.quorum.QuorumPeer.ServerState;
+import org.apache.zookeeper.server.quorum.QuorumPeerConfig;
 import org.apache.zookeeper.server.quorum.flexible.QuorumHierarchical;
 import org.apache.zookeeper.server.quorum.flexible.QuorumMaj;
 import org.apache.zookeeper.server.quorum.flexible.QuorumVerifier;
+import org.apache.zookeeper.ZooKeeper;
+import org.apache.zookeeper.admin.ZooKeeperAdmin;
+import org.apache.zookeeper.Watcher;
+import org.apache.zookeeper.WatchedEvent;
+import org.apache.zookeeper.ZooDefs;
+import org.apache.zookeeper.CreateMode;
+import org.apache.zookeeper.PortAssignment;
 import org.junit.After;
 import org.junit.Assert;
+import org.junit.Before;
 import org.junit.Test;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -58,6 +61,13 @@ public class ReconfigTest extends ZKTestCase implements DataCallback{
 
     private QuorumUtil qu;
 
+    @Before
+    public void setup() {
+        System.setProperty("zookeeper.DigestAuthenticationProvider.superDigest",
+                "super:D/InIHSb7yEEbrWz8b9l71RjZJU="/* password is 'test'*/);
+        QuorumPeerConfig.setReconfigEnabled(true);
+    }
+
     @After
     public void tearDown() throws Exception {
         if (qu != null) {
@@ -65,13 +75,13 @@ public class ReconfigTest extends ZKTestCase implements DataCallback{
         }
     }
 
-    public static String reconfig(ZooKeeper zk, List<String> joiningServers,
-            List<String> leavingServers, List<String> newMembers, long fromConfig)
+    public static String reconfig(ZooKeeperAdmin zkAdmin, List<String> joiningServers,
+                                  List<String> leavingServers, List<String> newMembers, long fromConfig)
             throws KeeperException, InterruptedException {
         byte[] config = null;
         for (int j = 0; j < 30; j++) {
             try {
-                config = zk.reconfig(joiningServers, leavingServers,
+                config = zkAdmin.reconfig(joiningServers, leavingServers,
                         newMembers, fromConfig, new Stat());
                 break;
             } catch (KeeperException.ConnectionLossException e) {
@@ -208,19 +218,40 @@ public class ReconfigTest extends ZKTestCase implements DataCallback{
         return zkArr;
     }
 
-    public static void closeAllHandles(ZooKeeper[] zkArr) throws InterruptedException {
+    public static ZooKeeperAdmin[] createAdminHandles(QuorumUtil qu) throws IOException {
+        // create an extra handle, so we can index the handles from 1 to qu.ALL
+        // using the server id.
+        ZooKeeperAdmin[] zkAdminArr = new ZooKeeperAdmin[qu.ALL + 1];
+        zkAdminArr[0] = null; // not used.
+        for (int i = 1; i <= qu.ALL; i++) {
+            // server ids are 1, 2 and 3
+            zkAdminArr[i] = new ZooKeeperAdmin("127.0.0.1:"
+                    + qu.getPeer(i).peer.getClientPort(),
+                    ClientBase.CONNECTION_TIMEOUT, new Watcher() {
+                public void process(WatchedEvent event) {
+                }});
+            zkAdminArr[i].addAuthInfo("digest", "super:test".getBytes());
+        }
+
+        return zkAdminArr;
+    }
+
+    public static void closeAllHandles(ZooKeeper[] zkArr, ZooKeeperAdmin[] zkAdminArr) throws InterruptedException {
         for (ZooKeeper zk : zkArr)
             if (zk != null)
                 zk.close();
+        for (ZooKeeperAdmin zkAdmin : zkAdminArr)
+            if (zkAdmin != null)
+                zkAdmin.close();
     }
 
- 
     @Test
     public void testRemoveAddOne() throws Exception {
         qu = new QuorumUtil(1); // create 3 servers
         qu.disableJMXTest = true;
         qu.startAll();
         ZooKeeper[] zkArr = createHandles(qu);
+        ZooKeeperAdmin[] zkAdminArr = createAdminHandles(qu);
 
         List<String> leavingServers = new ArrayList<String>();
         List<String> joiningServers = new ArrayList<String>();
@@ -242,6 +273,10 @@ public class ReconfigTest extends ZKTestCase implements DataCallback{
                     : zkArr[(leaderIndex % qu.ALL) + 1];
             ZooKeeper zk2 = (leavingIndex == leaderIndex) ? zkArr[(leaderIndex % qu.ALL) + 1]
                     : zkArr[leaderIndex];
+            ZooKeeperAdmin zkAdmin1 = (leavingIndex == leaderIndex) ? zkAdminArr[leaderIndex]
+                    : zkAdminArr[(leaderIndex % qu.ALL) + 1];
+            ZooKeeperAdmin zkAdmin2 = (leavingIndex == leaderIndex) ? zkAdminArr[(leaderIndex % qu.ALL) + 1]
+                    : zkAdminArr[leaderIndex];
 
             leavingServers.add(Integer.toString(leavingIndex));
 
@@ -256,7 +291,7 @@ public class ReconfigTest extends ZKTestCase implements DataCallback{
                             .getPort() + ":participant;localhost:"
                     + qu.getPeer(leavingIndex).peer.getClientPort());
 
-            String configStr = reconfig(zk1, null, leavingServers, null, -1);
+            String configStr = reconfig(zkAdmin1, null, leavingServers, null, -1);
             testServerHasConfig(zk2, null, leavingServers);
             testNormalOperation(zk2, zk1);
 
@@ -265,13 +300,13 @@ public class ReconfigTest extends ZKTestCase implements DataCallback{
 
             // checks that conditioning on version works properly
             try {
-                reconfig(zk2, joiningServers, null, null, version + 1);
+                reconfig(zkAdmin2, joiningServers, null, null, version + 1);
                 Assert.fail("reconfig succeeded even though version condition was incorrect!");
             } catch (KeeperException.BadVersionException e) {
 
             }
 
-            reconfig(zk2, joiningServers, null, null, version);
+            reconfig(zkAdmin2, joiningServers, null, null, version);
 
             testNormalOperation(zk1, zk2);
             testServerHasConfig(zk1, joiningServers, null);
@@ -283,7 +318,7 @@ public class ReconfigTest extends ZKTestCase implements DataCallback{
             joiningServers.clear();
         }
 
-        closeAllHandles(zkArr);
+        closeAllHandles(zkArr, zkAdminArr);
     }
 
     /**
@@ -298,6 +333,7 @@ public class ReconfigTest extends ZKTestCase implements DataCallback{
         qu.disableJMXTest = true;
         qu.startAll();
         ZooKeeper[] zkArr = createHandles(qu);
+        ZooKeeperAdmin[] zkAdminArr = createAdminHandles(qu);
 
         List<String> leavingServers = new ArrayList<String>();
         List<String> joiningServers = new ArrayList<String>();
@@ -345,7 +381,7 @@ public class ReconfigTest extends ZKTestCase implements DataCallback{
         qu.shutdown(leavingIndex2);
 
         // 3 servers still up so this should work
-        reconfig(zkArr[stayingIndex2], null, leavingServers, null, -1);
+        reconfig(zkAdminArr[stayingIndex2], null, leavingServers, null, -1);
         
         qu.shutdown(stayingIndex2);
 
@@ -366,7 +402,7 @@ public class ReconfigTest extends ZKTestCase implements DataCallback{
         Thread.sleep(10000);
 
         try {
-            reconfig(zkArr[stayingIndex1], joiningServers, null, null, -1);
+            reconfig(zkAdminArr[stayingIndex1], joiningServers, null, null, -1);
             Assert.fail("reconfig completed successfully even though there is no quorum up in new config!");
         } catch (KeeperException.NewConfigNoQuorum e) {
 
@@ -375,7 +411,7 @@ public class ReconfigTest extends ZKTestCase implements DataCallback{
         // now start the third server so that new config has quorum
         qu.restart(stayingIndex2);
 
-        reconfig(zkArr[stayingIndex1], joiningServers, null, null, -1);
+        reconfig(zkAdminArr[stayingIndex1], joiningServers, null, null, -1);
         testNormalOperation(zkArr[stayingIndex2], zkArr[stayingIndex3]);
         testServerHasConfig(zkArr[stayingIndex2], joiningServers, null);
 
@@ -388,7 +424,7 @@ public class ReconfigTest extends ZKTestCase implements DataCallback{
         testNormalOperation(zkArr[stayingIndex2], zkArr[leavingIndex2]);
         testServerHasConfig(zkArr[leavingIndex2], joiningServers, null);
 
-        closeAllHandles(zkArr);
+        closeAllHandles(zkArr, zkAdminArr);
     }
 
     @Test
@@ -397,6 +433,7 @@ public class ReconfigTest extends ZKTestCase implements DataCallback{
         qu.disableJMXTest = true;
         qu.startAll();
         ZooKeeper[] zkArr = createHandles(qu);
+        ZooKeeperAdmin[] zkAdminArr = createAdminHandles(qu);
 
         // new config will have three of the servers as followers
         // two of the servers as observers, and all ports different
@@ -413,7 +450,7 @@ public class ReconfigTest extends ZKTestCase implements DataCallback{
         qu.shutdown(6);
         qu.shutdown(7);
         
-        reconfig(zkArr[1], null, null, newServers, -1);
+        reconfig(zkAdminArr[1], null, null, newServers, -1);
         testNormalOperation(zkArr[1], zkArr[2]);
        
         testServerHasConfig(zkArr[1], newServers, null);
@@ -426,7 +463,7 @@ public class ReconfigTest extends ZKTestCase implements DataCallback{
         
         testNormalOperation(zkArr[1], zkArr[2]);
 
-        closeAllHandles(zkArr);
+        closeAllHandles(zkArr, zkAdminArr);
     }
 
     @Test
@@ -435,6 +472,7 @@ public class ReconfigTest extends ZKTestCase implements DataCallback{
         qu.disableJMXTest = true;
         qu.startAll();
         ZooKeeper[] zkArr = createHandles(qu);
+        ZooKeeperAdmin[] zkAdminArr = createAdminHandles(qu);
 
         List<String> leavingServers = new ArrayList<String>();
        
@@ -443,7 +481,7 @@ public class ReconfigTest extends ZKTestCase implements DataCallback{
  
         LinkedList<Integer> results = new LinkedList<Integer>();
         
-        zkArr[1].reconfig(null, leavingServers, null, -1, this, results);   
+        zkAdminArr[1].reconfig(null, leavingServers, null, -1, this, results);
         
         synchronized (results) {
             while (results.size() < 1) {
@@ -456,7 +494,7 @@ public class ReconfigTest extends ZKTestCase implements DataCallback{
         for (int i=1; i<=5; i++)
             testServerHasConfig(zkArr[i], null, leavingServers);
 
-        closeAllHandles(zkArr);
+        closeAllHandles(zkArr, zkAdminArr);
     }
 
     @SuppressWarnings("unchecked")
@@ -475,6 +513,7 @@ public class ReconfigTest extends ZKTestCase implements DataCallback{
         qu.disableJMXTest = true;
         qu.startAll();
         ZooKeeper[] zkArr = createHandles(qu);
+        ZooKeeperAdmin[] zkAdminArr = createAdminHandles(qu);
 
         // changing a server's role / port is done by "adding" it with the same
         // id but different role / port
@@ -501,6 +540,8 @@ public class ReconfigTest extends ZKTestCase implements DataCallback{
             // to removed server
             ZooKeeper zk1 = (changingIndex == leaderIndex) ? zkArr[leaderIndex]
                     : zkArr[(leaderIndex % qu.ALL) + 1];
+            ZooKeeperAdmin zkAdmin1 = (changingIndex == leaderIndex) ? zkAdminArr[leaderIndex]
+                    : zkAdminArr[(leaderIndex % qu.ALL) + 1];
 
             // exactly as it is now, except for role change
             joiningServers.add("server."
@@ -513,7 +554,7 @@ public class ReconfigTest extends ZKTestCase implements DataCallback{
                             .getPort() + ":" + newRole + ";localhost:"
                     + qu.getPeer(changingIndex).peer.getClientPort());
 
-            reconfig(zk1, joiningServers, null, null, -1);
+            reconfig(zkAdmin1, joiningServers, null, null, -1);
             testNormalOperation(zkArr[changingIndex], zk1);
 
             if (newRole.equals("observer")) {
@@ -540,7 +581,7 @@ public class ReconfigTest extends ZKTestCase implements DataCallback{
                 changingIndex = leaderIndex;
             }
         }
-        closeAllHandles(zkArr);
+        closeAllHandles(zkArr, zkAdminArr);
     }
 
     @Test
@@ -549,6 +590,7 @@ public class ReconfigTest extends ZKTestCase implements DataCallback{
         qu.disableJMXTest = true;
         qu.startAll();
         ZooKeeper[] zkArr = createHandles(qu);
+        ZooKeeperAdmin[] zkAdminArr = createAdminHandles(qu);
 
         List<String> joiningServers = new ArrayList<String>();
 
@@ -568,7 +610,7 @@ public class ReconfigTest extends ZKTestCase implements DataCallback{
         // any reconfig is invoked
         testNormalOperation(zkArr[followerIndex], zkArr[leaderIndex]);
 
-        reconfig(zkArr[followerIndex], joiningServers, null, null, -1);
+        reconfig(zkAdminArr[followerIndex], joiningServers, null, null, -1);
 
         try {
           for (int i=0; i < 20; i++) {
@@ -584,6 +626,14 @@ public class ReconfigTest extends ZKTestCase implements DataCallback{
                 + oldClientPort,
                 ClientBase.CONNECTION_TIMEOUT, new Watcher() {
                     public void process(WatchedEvent event) {}});
+
+        zkAdminArr[followerIndex].close();
+        zkAdminArr[followerIndex] = new ZooKeeperAdmin("127.0.0.1:"
+                + oldClientPort,
+                ClientBase.CONNECTION_TIMEOUT, new Watcher() {
+            public void process(WatchedEvent event) {}});
+        zkAdminArr[followerIndex].addAuthInfo("digest", "super:test".getBytes());
+
         for (int i = 0; i < 10; i++) {
             try {
                 Thread.sleep(1000);
@@ -599,6 +649,13 @@ public class ReconfigTest extends ZKTestCase implements DataCallback{
                 ClientBase.CONNECTION_TIMEOUT, new Watcher() {
                     public void process(WatchedEvent event) {}});
 
+        zkAdminArr[followerIndex].close();
+        zkAdminArr[followerIndex] = new ZooKeeperAdmin("127.0.0.1:"
+                + newClientPort,
+                ClientBase.CONNECTION_TIMEOUT, new Watcher() {
+            public void process(WatchedEvent event) {}});
+        zkAdminArr[followerIndex].addAuthInfo("digest", "super:test".getBytes());
+
         testNormalOperation(zkArr[followerIndex], zkArr[leaderIndex]);
         testServerHasConfig(zkArr[followerIndex], joiningServers, null);
         Assert.assertEquals(newClientPort, qu.getPeer(followerIndex).peer.getClientPort());
@@ -615,7 +672,7 @@ public class ReconfigTest extends ZKTestCase implements DataCallback{
                 + ":participant;localhost:"
                 + qu.getPeer(leaderIndex).peer.getClientPort());
 
-        reconfig(zkArr[leaderIndex], joiningServers, null, null, -1);
+        reconfig(zkAdminArr[leaderIndex], joiningServers, null, null, -1);
 
         testNormalOperation(zkArr[followerIndex], zkArr[leaderIndex]);
 
@@ -634,7 +691,7 @@ public class ReconfigTest extends ZKTestCase implements DataCallback{
                     + qu.getPeer(i).peer.getClientPort());
         }
 
-        reconfig(zkArr[1], joiningServers, null, null, -1);
+        reconfig(zkAdminArr[1], joiningServers, null, null, -1);
 
         leaderIndex = getLeaderId(qu);
         int follower1 = leaderIndex == 1 ? 2 : 1;
@@ -650,7 +707,7 @@ public class ReconfigTest extends ZKTestCase implements DataCallback{
         testServerHasConfig(zkArr[follower1], joiningServers, null);
         testServerHasConfig(zkArr[follower2], joiningServers, null);
 
-        closeAllHandles(zkArr);
+        closeAllHandles(zkArr, zkAdminArr);
     }
 
     @Test
@@ -667,6 +724,7 @@ public class ReconfigTest extends ZKTestCase implements DataCallback{
         qu.disableJMXTest = true;
         qu.startAll();
         ZooKeeper[] zkArr = createHandles(qu);
+        ZooKeeperAdmin[] zkAdminArr = createAdminHandles(qu);
 
         List<String> joiningServers = new ArrayList<String>();
 
@@ -692,7 +750,7 @@ public class ReconfigTest extends ZKTestCase implements DataCallback{
             testNormalOperation(zkArr[followerIndex], zkArr[leaderIndex]);
 
             // Reconfigure
-            reconfig(zkArr[reconfigIndex], joiningServers, null, null, -1);
+            reconfig(zkAdminArr[reconfigIndex], joiningServers, null, null, -1);
             Thread.sleep(1000);
 
             // The follower reconfiguration will have failed
@@ -702,6 +760,12 @@ public class ReconfigTest extends ZKTestCase implements DataCallback{
                     ClientBase.CONNECTION_TIMEOUT, new Watcher() {
                         public void process(WatchedEvent event) {}});
 
+            zkAdminArr[serverIndex].close();
+            zkAdminArr[serverIndex] = new ZooKeeperAdmin("127.0.0.1:"
+                    + newClientPort,
+                    ClientBase.CONNECTION_TIMEOUT, new Watcher() {
+                public void process(WatchedEvent event) {}});
+
             try {
                 Thread.sleep(1000);
                 zkArr[serverIndex].setData("/test", "teststr".getBytes(), -1);
@@ -721,7 +785,7 @@ public class ReconfigTest extends ZKTestCase implements DataCallback{
             joiningServers.add("server." + serverIndex + "=localhost:" + quorumPort
                     + ":" + electionPort + ":participant;localhost:" + oldClientPort);
 
-            reconfig(zkArr[reconfigIndex], joiningServers, null, null, -1);
+            reconfig(zkAdminArr[reconfigIndex], joiningServers, null, null, -1);
 
             zkArr[serverIndex].close();
             zkArr[serverIndex] = new ZooKeeper("127.0.0.1:"
@@ -733,7 +797,7 @@ public class ReconfigTest extends ZKTestCase implements DataCallback{
             testServerHasConfig(zkArr[serverIndex], joiningServers, null);
             Assert.assertEquals(oldClientPort, qu.getPeer(serverIndex).peer.getClientPort());
         }
-        closeAllHandles(zkArr);
+        closeAllHandles(zkArr, zkAdminArr);
     }
 
     @Test
@@ -754,6 +818,7 @@ public class ReconfigTest extends ZKTestCase implements DataCallback{
         qu.disableJMXTest = true;
         qu.startAll();
         ZooKeeper[] zkArr = createHandles(qu);
+        ZooKeeperAdmin[] zkAdminArr = createAdminHandles(qu);
 
         ArrayList<String> members = new ArrayList<String>();
         members.add("group.1=3:4:5");
@@ -771,7 +836,7 @@ public class ReconfigTest extends ZKTestCase implements DataCallback{
                     + "127.0.0.1:" + qu.getPeer(i).peer.getClientPort());
         }
 
-        reconfig(zkArr[1], null, null, members, -1);
+        reconfig(zkAdminArr[1], null, null, members, -1);
 
         // this should flush the config to servers 2, 3, 4 and 5
         testNormalOperation(zkArr[2], zkArr[3]);
@@ -803,7 +868,7 @@ public class ReconfigTest extends ZKTestCase implements DataCallback{
                     + "127.0.0.1:" + qu.getPeer(i).peer.getClientPort());
         }
 
-        reconfig(zkArr[1], null, null, members, -1);
+        reconfig(zkAdminArr[1], null, null, members, -1);
 
         // flush the config to server 2
         testNormalOperation(zkArr[1], zkArr[2]);
@@ -821,7 +886,7 @@ public class ReconfigTest extends ZKTestCase implements DataCallback{
                         + " doesn't think the quorum system is a majority quorum system!");
         }
 
-        closeAllHandles(zkArr);
+        closeAllHandles(zkArr, zkAdminArr);
     }
     
     @Test
@@ -849,6 +914,7 @@ public class ReconfigTest extends ZKTestCase implements DataCallback{
         qu.disableJMXTest = true;
         qu.startAll();
         ZooKeeper[] zkArr = createHandles(qu);
+        ZooKeeperAdmin[] zkAdminArr = createAdminHandles(qu);
 
         List<String> leavingServers = new ArrayList<String>();
         List<String> joiningServers = new ArrayList<String>();
@@ -873,6 +939,7 @@ public class ReconfigTest extends ZKTestCase implements DataCallback{
         assertRemotePeerMXBeanAttributes(leavingQS3, remotePeerBean3);
 
         ZooKeeper zk = zkArr[leavingIndex];
+        ZooKeeperAdmin zkAdmin = zkAdminArr[leavingIndex];
 
         leavingServers.add(Integer.toString(leavingIndex));
 
@@ -885,7 +952,7 @@ public class ReconfigTest extends ZKTestCase implements DataCallback{
                 + qu.getPeer(leavingIndex).peer.getClientPort());
 
         // Remove ReplicatedServer_1 from the ensemble
-        reconfig(zk, null, leavingServers, null, -1);
+        reconfig(zkAdmin, null, leavingServers, null, -1);
 
         // localPeerBean.1 of ReplicatedServer_1
         QuorumPeer removedPeer = qu.getPeer(leavingIndex).peer;
@@ -900,7 +967,7 @@ public class ReconfigTest extends ZKTestCase implements DataCallback{
         JMXEnv.ensureNone(remotePeerBean3);
 
         // Add ReplicatedServer_1 back to the ensemble
-        reconfig(zk, joiningServers, null, null, -1);
+        reconfig(zkAdmin, joiningServers, null, null, -1);
 
         // localPeerBean.1 of ReplicatedServer_1
         assertLocalPeerMXBeanAttributes(removedPeer, localPeerBean, true);
@@ -913,7 +980,7 @@ public class ReconfigTest extends ZKTestCase implements DataCallback{
         leavingQS3 = peer3.getView().get(new Long(leavingIndex));
         assertRemotePeerMXBeanAttributes(leavingQS3, remotePeerBean3);
 
-        closeAllHandles(zkArr);
+        closeAllHandles(zkArr, zkAdminArr);
     }
 
     /**
@@ -926,6 +993,7 @@ public class ReconfigTest extends ZKTestCase implements DataCallback{
         qu.disableJMXTest = true;
         qu.startAll();
         ZooKeeper[] zkArr = createHandles(qu);
+        ZooKeeperAdmin[] zkAdminArr = createAdminHandles(qu);
 
         // changing a server's role / port is done by "adding" it with the same
         // id but different role / port
@@ -953,6 +1021,7 @@ public class ReconfigTest extends ZKTestCase implements DataCallback{
         String newRole = "observer";
 
         ZooKeeper zk = zkArr[changingIndex];
+        ZooKeeperAdmin zkAdmin = zkAdminArr[changingIndex];
 
         // exactly as it is now, except for role change
         joiningServers.add("server." + changingIndex + "=127.0.0.1:"
@@ -962,7 +1031,7 @@ public class ReconfigTest extends ZKTestCase implements DataCallback{
                 + ":" + newRole + ";127.0.0.1:"
                 + qu.getPeer(changingIndex).peer.getClientPort());
 
-        reconfig(zk, joiningServers, null, null, -1);
+        reconfig(zkAdmin, joiningServers, null, null, -1);
         testNormalOperation(zkArr[changingIndex], zk);
 
         Assert.assertTrue(qu.getPeer(changingIndex).peer.observer != null
@@ -986,7 +1055,7 @@ public class ReconfigTest extends ZKTestCase implements DataCallback{
         changingQS3 = peer3.getView().get(new Long(changingIndex));
         assertRemotePeerMXBeanAttributes(changingQS3, remotePeerBean3);
 
-        closeAllHandles(zkArr);
+        closeAllHandles(zkArr, zkAdminArr);
     }
 
     private void assertLocalPeerMXBeanAttributes(QuorumPeer qp,

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/65d2572d/src/java/test/org/apache/zookeeper/test/StandaloneTest.java
----------------------------------------------------------------------
diff --git a/src/java/test/org/apache/zookeeper/test/StandaloneTest.java b/src/java/test/org/apache/zookeeper/test/StandaloneTest.java
index 5c95280..db1a362 100644
--- a/src/java/test/org/apache/zookeeper/test/StandaloneTest.java
+++ b/src/java/test/org/apache/zookeeper/test/StandaloneTest.java
@@ -24,17 +24,20 @@ import java.io.File;
 import java.util.ArrayList;
 import java.util.List;
 
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.apache.zookeeper.KeeperException;
-import org.apache.zookeeper.PortAssignment;
 import org.apache.zookeeper.Watcher;
-import org.apache.zookeeper.ZooKeeper;
+import org.apache.zookeeper.PortAssignment;
+import org.apache.zookeeper.KeeperException;
+import org.apache.zookeeper.server.quorum.QuorumPeerConfig;
 import org.apache.zookeeper.data.Stat;
 import org.apache.zookeeper.server.ServerCnxnFactory;
 import org.apache.zookeeper.server.ZooKeeperServer;
 import org.apache.zookeeper.server.quorum.QuorumPeerTestBase;
 import org.apache.zookeeper.test.ClientBase.CountdownWatcher;
+import org.apache.zookeeper.ZooKeeper;
+import org.apache.zookeeper.admin.ZooKeeperAdmin;
+import org.junit.Before;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.junit.Assert;
 import org.junit.Test;
 
@@ -45,6 +48,13 @@ public class StandaloneTest extends QuorumPeerTestBase implements Watcher{
     protected static final Logger LOG =
         LoggerFactory.getLogger(StandaloneTest.class);
 
+    @Before
+    public void setup() {
+        System.setProperty("zookeeper.DigestAuthenticationProvider.superDigest",
+                "super:D/InIHSb7yEEbrWz8b9l71RjZJU="/* password is 'test'*/);
+        QuorumPeerConfig.setReconfigEnabled(true);
+    }
+
     /**
      * This test wouldn't create any dynamic config.
      * However, it adds a "clientPort=XXX" in static config file.
@@ -133,13 +143,15 @@ public class StandaloneTest extends QuorumPeerTestBase implements Watcher{
 
         CountdownWatcher watcher = new CountdownWatcher();
         ZooKeeper zk = new ZooKeeper(HOSTPORT, CONNECTION_TIMEOUT, watcher);
+        ZooKeeperAdmin zkAdmin = new ZooKeeperAdmin(HOSTPORT, CONNECTION_TIMEOUT, watcher);
         watcher.waitForConnected(CONNECTION_TIMEOUT);
 
         List<String> joiners = new ArrayList<String>();
         joiners.add("server.2=localhost:1234:1235;1236");
         // generate some transactions that will get logged
         try {
-            zk.reconfig(joiners, null, null, -1, new Stat());
+            zkAdmin.addAuthInfo("digest", "super:test".getBytes());
+            zkAdmin.reconfig(joiners, null, null, -1, new Stat());
             Assert.fail("Reconfiguration in standalone should trigger " +
                         "UnimplementedException");
         } catch (KeeperException.UnimplementedException ex) {


Mime
View raw message