Skip to content

Commit 0e68d1c

Browse files
author
甘梓辰
committed
fix:small observer can't join quorum, so need use getView()
1 parent 9d52264 commit 0e68d1c

File tree

3 files changed

+122
-8
lines changed

3 files changed

+122
-8
lines changed

zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/QuorumCnxManager.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -502,8 +502,9 @@ private boolean startConnection(Socket sock, Long sid) throws IOException {
502502
return false;
503503
}
504504

505+
// fix: small observer can't join quorum, so need use getView()
505506
// authenticate learner
506-
QuorumPeer.QuorumServer qps = self.getVotingView().get(sid);
507+
QuorumPeer.QuorumServer qps = self.getView().get(sid);
507508
if (qps != null) {
508509
// TODO - investigate why reconfig makes qps null.
509510
authLearner.authenticate(sock, qps.hostname);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
package org.apache.zookeeper.server.quorum.auth;
20+
21+
import org.apache.zookeeper.CreateMode;
22+
import org.apache.zookeeper.ZooDefs.Ids;
23+
import org.apache.zookeeper.ZooKeeper;
24+
import org.apache.zookeeper.test.ClientBase;
25+
import org.apache.zookeeper.test.ClientBase.CountdownWatcher;
26+
import org.junit.jupiter.api.AfterAll;
27+
import org.junit.jupiter.api.AfterEach;
28+
import org.junit.jupiter.api.Test;
29+
import org.junit.jupiter.api.Timeout;
30+
31+
import java.util.HashMap;
32+
import java.util.Map;
33+
34+
public class QuorumAuthObserverTest extends QuorumAuthTestBase {
35+
36+
static {
37+
String jaasEntries = "QuorumServer {\n"
38+
+ " org.apache.zookeeper.server.auth.DigestLoginModule required\n"
39+
+ " user_test=\"mypassword\";\n"
40+
+ "};\n"
41+
+ "QuorumLearner {\n"
42+
+ " org.apache.zookeeper.server.auth.DigestLoginModule required\n"
43+
+ " username=\"test\"\n"
44+
+ " password=\"mypassword\";\n"
45+
+ "};\n";
46+
setupJaasConfig(jaasEntries);
47+
}
48+
49+
@AfterEach
50+
@Override
51+
public void tearDown() throws Exception {
52+
shutdownAll();
53+
super.tearDown();
54+
}
55+
56+
@AfterAll
57+
public static void cleanup() {
58+
cleanupJaasConfig();
59+
}
60+
61+
/**
62+
* Test to myid small observer join quorum.
63+
* peer0 myid:11 participant
64+
* peer1 myid:21 participant
65+
* peer2 myid:1 observer
66+
*/
67+
@Test
68+
@Timeout(value = 30)
69+
public void testSmallObserverJoinSASLQuorum() throws Exception {
70+
Map<String, String> authConfigs = new HashMap<>();
71+
authConfigs.put(QuorumAuth.QUORUM_SASL_AUTH_ENABLED, "true");
72+
authConfigs.put(QuorumAuth.QUORUM_SERVER_SASL_AUTH_REQUIRED, "true");
73+
authConfigs.put(QuorumAuth.QUORUM_LEARNER_SASL_AUTH_REQUIRED, "true");
74+
75+
// create quorum
76+
StringBuilder connectStringBuilder = new StringBuilder();
77+
int[] myidList = {11, 21, 1};
78+
String[] roleList = {"participant", "participant", "observer"};
79+
int[] clientPorts = startQuorum(3, connectStringBuilder, authConfigs, 3, false, myidList, roleList);
80+
81+
// small observer can't join quorum
82+
String connectStr = "127.0.0.1:" + clientPorts[2];
83+
CountdownWatcher watcher = new CountdownWatcher();
84+
ZooKeeper zk = new ZooKeeper(connectStr, ClientBase.CONNECTION_TIMEOUT, watcher);
85+
watcher.waitForConnected(ClientBase.CONNECTION_TIMEOUT);
86+
87+
zk.create("/foo", new byte[0], Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
88+
zk.close();
89+
}
90+
}

zookeeper-server/src/test/java/org/apache/zookeeper/server/quorum/auth/QuorumAuthTestBase.java

+30-7
Original file line numberDiff line numberDiff line change
@@ -103,16 +103,28 @@ protected String startQuorum(
103103
}
104104

105105
protected int[] startQuorum(final int serverCount, StringBuilder connectStr, Map<String, String> authConfigs,
106-
int authServerCount, boolean multiAddress) throws IOException {
106+
int authServerCount, boolean multiAddress) throws IOException {
107+
int[] defalutMyidList = new int[serverCount];
108+
String[] defalutRoleList = new String[serverCount];
109+
for (int i = 0; i < serverCount; i++) {
110+
defalutMyidList[i] = i;
111+
defalutRoleList[i] = "participant";
112+
}
113+
return startQuorum(serverCount, connectStr, authConfigs, authServerCount, multiAddress, defalutMyidList, defalutRoleList);
114+
}
115+
116+
protected int[] startQuorum(final int serverCount, StringBuilder connectStr, Map<String, String> authConfigs,
117+
int authServerCount, boolean multiAddress, int[] myidList, String[] roleList) throws IOException {
107118
final int[] clientPorts = new int[serverCount];
108119
StringBuilder sb = new StringBuilder();
109120
for (int i = 0; i < serverCount; i++) {
110121
clientPorts[i] = PortAssignment.unique();
111-
String server = String.format("server.%d=localhost:%d:%d", i, PortAssignment.unique(), PortAssignment.unique());
122+
String server = String.format("server.%d=localhost:%d:%d", myidList[i], PortAssignment.unique(), PortAssignment.unique());
112123
if (multiAddress) {
113124
server = server + String.format("|localhost:%d:%d", PortAssignment.unique(), PortAssignment.unique());
114125
}
115-
sb.append(server + ":participant\n");
126+
127+
sb.append(server + ":" + roleList[i] + "\n");
116128
connectStr.append("127.0.0.1:" + clientPorts[i]);
117129
if (i < serverCount - 1) {
118130
connectStr.append(",");
@@ -122,11 +134,11 @@ protected int[] startQuorum(final int serverCount, StringBuilder connectStr, Map
122134
// servers with authentication interfaces configured
123135
int i = 0;
124136
for (; i < authServerCount; i++) {
125-
startServer(authConfigs, clientPorts, quorumCfg, i);
137+
startServer(authConfigs, clientPorts, quorumCfg, i, myidList);
126138
}
127139
// servers without any authentication configured
128140
for (int j = 0; j < serverCount - authServerCount; j++, i++) {
129-
MainThread mthread = new MainThread(i, clientPorts[i], quorumCfg);
141+
MainThread mthread = new MainThread(myidList[i], clientPorts[i], quorumCfg);
130142
mt.add(mthread);
131143
mthread.start();
132144
}
@@ -137,8 +149,9 @@ private void startServer(
137149
Map<String, String> authConfigs,
138150
final int[] clientPorts,
139151
String quorumCfg,
140-
int i) throws IOException {
141-
MainThread mthread = new MainThread(i, clientPorts[i], quorumCfg, authConfigs);
152+
int i,
153+
int[] myidList) throws IOException {
154+
MainThread mthread = new MainThread(myidList[i], clientPorts[i], quorumCfg, authConfigs);
142155
mt.add(mthread);
143156
mthread.start();
144157
}
@@ -149,6 +162,16 @@ protected void startServer(MainThread restartPeer, Map<String, String> authConfi
149162
mthread.start();
150163
}
151164

165+
protected void startServer(
166+
Map<String, String> authConfigs,
167+
final int clientPort,
168+
String quorumCfg,
169+
int myid) throws IOException {
170+
MainThread mthread = new MainThread(myid, clientPort, quorumCfg, authConfigs);
171+
mt.add(mthread);
172+
mthread.start();
173+
}
174+
152175
void shutdownAll() {
153176
for (int i = 0; i < mt.size(); i++) {
154177
shutdown(i);

0 commit comments

Comments
 (0)