private void stopAppendConfigRestartAll(Map<Integer, MainThread> members, String config) throws Exception { for (Map.Entry<Integer, MainThread> entry : members.entrySet()) { int clientPort = entry.getKey(); MainThread member = entry.getValue(); member.shutdown(); Assert.assertTrue(ClientBase.waitForServerDown("127.0.0.1:" + clientPort, CONNECTION_TIMEOUT)); FileWriter fileWriter = new FileWriter(member.getConfFile(), true); fileWriter.write(config); fileWriter.flush(); fileWriter.close(); member.start(); Assert.assertTrue(ClientBase.waitForServerUp("127.0.0.1:" + clientPort, CONNECTION_TIMEOUT)); } }
protected int[] startQuorum(final int serverCount, StringBuilder connectStr, Map<String, String> authConfigs, int authServerCount) throws IOException { final int clientPorts[] = new int[serverCount]; StringBuilder sb = new StringBuilder(); for (int i = 0; i < serverCount; i++) { clientPorts[i] = PortAssignment.unique(); String server = String.format( "server.%d=localhost:%d:%d:participant", i, PortAssignment.unique(), PortAssignment.unique()); sb.append(server + "\n"); connectStr.append("127.0.0.1:" + clientPorts[i]); if (i < serverCount - 1) { connectStr.append(","); } } String quorumCfg = sb.toString(); // servers with authentication interfaces configured int i = 0; for (; i < authServerCount; i++) { startServer(authConfigs, clientPorts, quorumCfg, i); } // servers without any authentication configured for (int j = 0; j < serverCount - authServerCount; j++, i++) { MainThread mthread = new MainThread(i, clientPorts[i], quorumCfg); mt.add(mthread); mthread.start(); } return clientPorts; }
private void startServer(Map<String, String> authConfigs, final int[] clientPorts, String quorumCfg, int i) throws IOException { MainThread mthread = new MainThread(i, clientPorts[i], quorumCfg, authConfigs); mt.add(mthread); mthread.start(); }
@Test public void testRevalidation() throws Exception { setUp(-1); q3.start(); Assert.assertTrue("waiting for server 3 being up", ClientBase.waitForServerUp("127.0.0.1:" + CLIENT_PORT_OBS, CONNECTION_TIMEOUT)); final int leaderProxyPort = PortAssignment.unique(); final int obsProxyPort = PortAssignment.unique(); int leaderPort = q1.getQuorumPeer().leader == null ? CLIENT_PORT_QP2 : CLIENT_PORT_QP1; PortForwarder leaderPF = new PortForwarder(leaderProxyPort, leaderPort); latch = new CountDownLatch(1); zk = new ZooKeeper(String.format("127.0.0.1:%d,127.0.0.1:%d", leaderProxyPort, obsProxyPort), ClientBase.CONNECTION_TIMEOUT, this); latch.await(); zk.create("/revalidtest", "test".getBytes(),Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL); Assert.assertNotNull("Read-after write failed", zk.exists("/revalidtest", null)); latch = new CountDownLatch(2); PortForwarder obsPF = new PortForwarder(obsProxyPort, CLIENT_PORT_OBS); try { leaderPF.shutdown(); } catch (Exception e) { // ignore? } latch.await(); Assert.assertEquals(new String(zk.getData("/revalidtest", null, null)), "test"); obsPF.shutdown(); shutdown(); }
@Test(timeout = 60000) // Verify no zoo.cfg.dynamic and zoo.cfg.bak files existing locally // when reconfig feature flag is off by default. public void testNoLocalDynamicConfigAndBackupFiles() throws InterruptedException, IOException { int serverCount = 3; String config = generateNewQuorumConfig(serverCount); QuorumPeerTestBase.MainThread mt[] = new QuorumPeerTestBase.MainThread[serverCount]; String[] staticFileContent = new String[serverCount]; for (int i = 0; i < serverCount; i++) { mt[i] = new QuorumPeerTestBase.MainThread(i, clientPorts.get(i), config, false); mt[i].start(); } for (int i = 0; i < serverCount; i++) { Assert.assertTrue("waiting for server " + i + " being up", ClientBase.waitForServerUp("127.0.0.1:" + clientPorts.get(i), CONNECTION_TIMEOUT)); Assert.assertNull("static file backup (zoo.cfg.bak) shouldn't exist!", mt[i].getFileByName(ZOO_CFG_BAK_FILE)); Assert.assertNull("dynamic configuration file (zoo.cfg.dynamic.*) shouldn't exist!", mt[i].getFileByName(mt[i].getQuorumPeer().getNextDynamicConfigFilename())); staticFileContent[i] = Files.readAllLines(mt[i].confFile.toPath(), StandardCharsets.UTF_8).toString(); Assert.assertTrue("static config file should contain server entry " + serverAddress.get(i), staticFileContent[i].contains(serverAddress.get(i))); } for (int i = 0; i < serverCount; i++) { mt[i].shutdown(); } }
/** * Verifies that QuorumPeer exits immediately */ @Test public void testQuorumPeerExitTime() throws Exception { long maxwait = 3000; final int CLIENT_PORT_QP1 = PortAssignment.unique(); String quorumCfgSection = "server.1=127.0.0.1:" + PortAssignment.unique() + ":" + PortAssignment.unique() + ";" + CLIENT_PORT_QP1 + "\nserver.2=127.0.0.1:" + PortAssignment.unique() + ":" + PortAssignment.unique() + ";" + PortAssignment.unique(); MainThread q1 = new MainThread(1, CLIENT_PORT_QP1, quorumCfgSection); q1.start(); // Let the notifications timeout Thread.sleep(30000); long start = Time.currentElapsedTime(); q1.shutdown(); long end = Time.currentElapsedTime(); if ((end - start) > maxwait) { Assert.fail("QuorumPeer took " + (end - start) + " to shutdown, expected " + maxwait); } }
/** * It's possible during taking fuzzy snapshot, the parent is serialized * before the child get deleted in the fuzzy range. * * In which case, we need to make sure the pzxid get correctly updated * when replaying the txns. */ @Test public void testPZxidUpdatedWhenLoadingSnapshot() throws Exception { final String parent = "/testPZxidUpdatedDuringTakingSnapshot"; final String child = parent + "/child"; createEmptyNode(zk[followerA], parent); createEmptyNode(zk[followerA], child); LOG.info("Set up ZKDatabase to catch the node serializing in DataTree"); addSerializeListener(followerA, parent, child); LOG.info("Take snapshot on follower A"); ZooKeeperServer zkServer = mt[followerA].main.quorumPeer.getActiveServer(); zkServer.takeSnapshot(true); LOG.info("Restarting follower A to load snapshot"); mt[followerA].shutdown(); QuorumPeerMainTest.waitForOne(zk[followerA], States.CONNECTING); mt[followerA].start(); QuorumPeerMainTest.waitForOne(zk[followerA], States.CONNECTED); LOG.info("Check and make sure the pzxid of the parent is the same " + "on leader and follower A"); compareStat(parent, leaderId, followerA); }
@Test public void testRollingUpgrade() throws Exception { // Form a quorum without ssl q1 = new MainThread(1, clientPortQp1, quorumConfiguration); q2 = new MainThread(2, clientPortQp2, quorumConfiguration); q3 = new MainThread(3, clientPortQp3, quorumConfiguration); Map<Integer, MainThread> members = new HashMap<>(); members.put(clientPortQp1, q1); members.put(clientPortQp2, q2); members.put(clientPortQp3, q3); for (MainThread member : members.values()) { member.start(); } for (int clientPort : members.keySet()) { Assert.assertTrue(ClientBase.waitForServerUp("127.0.0.1:" + clientPort, CONNECTION_TIMEOUT)); } // Set SSL system properties and port unification, begin restarting servers setSSLSystemProperties(); stopAppendConfigRestartAll(members, PORT_UNIFICATION_ENABLED); stopAppendConfigRestartAll(members, SSL_QUORUM_ENABLED); stopAppendConfigRestartAll(members, PORT_UNIFICATION_DISABLED); }
/** * Developers might use standalone mode (which is the default for one server). * This test checks SSL works in standalone mode of ZK server. * <p/> * Note that in this test the Zk server has only secureClientPort */ @Test public void testSecureStandaloneServer() throws Exception { Integer secureClientPort = PortAssignment.unique(); MainThread mt = new MainThread(MainThread.UNSET_MYID, "", secureClientPort, false); mt.start(); ZooKeeper zk = ClientBase.createZKClient("127.0.0.1:" + secureClientPort, TIMEOUT); zk.create("/test", "".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); zk.delete("/test", -1); zk.close(); mt.shutdown(); } }
/** * Ensure that observer only comes up when a proper ensemble is configured. * (and will not come up with standalone server). */ @Test public void testObserverWithStandlone() throws Exception { ClientBase.setupTestEnv(); final int CLIENT_PORT_QP1 = PortAssignment.unique(); String quorumCfgSection = "server.1=127.0.0.1:" + (PortAssignment.unique()) + ":" + (PortAssignment.unique()) + ":observer\n" + "server.2=127.0.0.1:" + (PortAssignment.unique()) + ":" + (PortAssignment.unique()) + "\npeerType=observer\n"; MainThread q1 = new MainThread(1, CLIENT_PORT_QP1, quorumCfgSection); q1.start(); q1.join(ClientBase.CONNECTION_TIMEOUT); Assert.assertFalse(q1.isAlive()); }
/** * Starts a single server in replicated mode, * initializes its client, and waits for it * to be connected. */ private void startServer(int id, String config) throws Exception { peers[id] = new MainThread(id, clientPorts[id], config); peers[id].start(); Assert.assertTrue("Server " + id + " is not up", ClientBase.waitForServerUp("127.0.0.1:" + clientPorts[id], CONNECTION_TIMEOUT)); 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()); String statCommandOut = FourLetterWordMain.send4LetterWord("127.0.0.1", clientPorts[id], "stat"); LOG.info(String.format("Started server id %d with config:\n%s\nStat output:\n%s", id, config, statCommandOut)); }
/** * This test ensures that an Observer does not elect itself as a leader, or * indeed come up properly, if it is the lone member of an ensemble. * @throws Exception */ @Test public void testObserverOnly() throws Exception { ClientBase.setupTestEnv(); final int CLIENT_PORT_QP1 = PortAssignment.unique(); String quorumCfgSection = "server.1=127.0.0.1:" + (PortAssignment.unique()) + ":" + (PortAssignment.unique()) + ":observer;" + CLIENT_PORT_QP1 + "\n"; MainThread q1 = new MainThread(1, CLIENT_PORT_QP1, quorumCfgSection); q1.start(); q1.join(ClientBase.CONNECTION_TIMEOUT); Assert.assertFalse(q1.isAlive()); }
@Test public void testProtocolVersion() throws Exception { System.setProperty(quorumX509Util.getSslProtocolProperty(), "TLSv1.2"); q1 = new MainThread(1, clientPortQp1, quorumConfiguration, SSL_QUORUM_ENABLED); q2 = new MainThread(2, clientPortQp2, quorumConfiguration, SSL_QUORUM_ENABLED); q1.start(); q2.start(); Assert.assertTrue(ClientBase.waitForServerUp("127.0.0.1:" + clientPortQp1, CONNECTION_TIMEOUT)); Assert.assertTrue(ClientBase.waitForServerUp("127.0.0.1:" + clientPortQp2, CONNECTION_TIMEOUT)); System.setProperty(quorumX509Util.getSslProtocolProperty(), "TLSv1.1"); // This server should fail to join the quorum as it is not using TLSv1.2 q3 = new MainThread(3, clientPortQp3, quorumConfiguration, SSL_QUORUM_ENABLED); q3.start(); Assert.assertFalse(ClientBase.waitForServerUp("127.0.0.1:" + clientPortQp3, CONNECTION_TIMEOUT)); } }
/** * Ensure observer cannot start by itself **/ @Test public void startObserver() throws Exception { int clientPort = PortAssignment.unique(); String config = "server." + observer1 + "=localhost:"+ PortAssignment.unique() + ":" + clientPort + ":observer;" + "localhost:" + PortAssignment.unique(); MainThread observer = new MainThread(observer1, clientPort, config); observer.start(); Assert.assertFalse("Observer was able to start by itself!", ClientBase.waitForServerUp("127.0.0.1:" + clientPort, CONNECTION_TIMEOUT)); } }
@Test public void testQuorumSSL() throws Exception { q1 = new MainThread(1, clientPortQp1, quorumConfiguration, SSL_QUORUM_ENABLED); q2 = new MainThread(2, clientPortQp2, quorumConfiguration, SSL_QUORUM_ENABLED); q1.start(); q2.start(); Assert.assertTrue(ClientBase.waitForServerUp("127.0.0.1:" + clientPortQp1, CONNECTION_TIMEOUT)); Assert.assertTrue(ClientBase.waitForServerUp("127.0.0.1:" + clientPortQp2, CONNECTION_TIMEOUT)); clearSSLSystemProperties(); // This server should fail to join the quorum as it is not using ssl. q3 = new MainThread(3, clientPortQp3, quorumConfiguration); q3.start(); Assert.assertFalse(ClientBase.waitForServerUp("127.0.0.1:" + clientPortQp3, CONNECTION_TIMEOUT)); }
public void restartAllServersAndClients(Watcher watcher) throws IOException, InterruptedException { for (MainThread t : mt) { if (!t.isAlive()) { t.start(); } } for (int i = 0; i < zk.length; i++) { restartClient(i, watcher); } }
protected void startServer(MainThread restartPeer, Map<String, String> authConfigs) throws IOException { MainThread mthread = new MainThread(restartPeer.getMyid(), restartPeer.getClientPort(), restartPeer.getQuorumCfgSection(), authConfigs); mt.add(mthread); mthread.start(); }
void verifyStandalone(MainThread mt, int clientPort) throws InterruptedException { mt.start(); try { Assert.assertTrue("waiting for server 1 being up", ClientBase.waitForServerUp("127.0.0.1:" + clientPort, CONNECTION_TIMEOUT)); } finally { Assert.assertFalse("Error- MainThread started in Quorum Mode!", mt.isQuorumPeerRunning()); mt.shutdown(); } }