1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.hbase.zookeeper;
20
21 import java.io.IOException;
22 import java.io.InputStream;
23 import java.util.ArrayList;
24 import java.util.List;
25 import java.util.Map.Entry;
26 import java.util.Properties;
27
28 import org.apache.commons.logging.Log;
29 import org.apache.commons.logging.LogFactory;
30 import org.apache.hadoop.conf.Configuration;
31 import org.apache.hadoop.hbase.HConstants;
32 import org.apache.hadoop.hbase.classification.InterfaceAudience;
33
34
35
36
37
38
39
40
41
42 @InterfaceAudience.Private
43 public final class ZKConfig {
44 private static final Log LOG = LogFactory.getLog(ZKConfig.class);
45
46 private static final String VARIABLE_START = "${";
47 private static final int VARIABLE_START_LENGTH = VARIABLE_START.length();
48 private static final String VARIABLE_END = "}";
49 private static final int VARIABLE_END_LENGTH = VARIABLE_END.length();
50
51 private ZKConfig() {
52 }
53
54
55
56
57
58
59
60
61 public static Properties makeZKProps(Configuration conf) {
62 Properties zkProperties = makeZKPropsFromZooCfg(conf);
63
64 if (zkProperties == null) {
65
66 zkProperties = makeZKPropsFromHbaseConfig(conf);
67 }
68 return zkProperties;
69 }
70
71
72
73
74
75
76
77
78
79 private static Properties makeZKPropsFromZooCfg(Configuration conf) {
80 if (conf.getBoolean(HConstants.HBASE_CONFIG_READ_ZOOKEEPER_CONFIG, false)) {
81 LOG.warn(
82 "Parsing ZooKeeper's " + HConstants.ZOOKEEPER_CONFIG_NAME +
83 " file for ZK properties " +
84 "has been deprecated. Please instead place all ZK related HBase " +
85 "configuration under the hbase-site.xml, using prefixes " +
86 "of the form '" + HConstants.ZK_CFG_PROPERTY_PREFIX + "', and " +
87 "set property '" + HConstants.HBASE_CONFIG_READ_ZOOKEEPER_CONFIG +
88 "' to false");
89
90
91 ClassLoader cl = ZKConfig.class.getClassLoader();
92 final InputStream inputStream =
93 cl.getResourceAsStream(HConstants.ZOOKEEPER_CONFIG_NAME);
94 if (inputStream != null) {
95 try {
96 return parseZooCfg(conf, inputStream);
97 } catch (IOException e) {
98 LOG.warn("Cannot read " + HConstants.ZOOKEEPER_CONFIG_NAME +
99 ", loading from XML files", e);
100 }
101 }
102 } else {
103 if (LOG.isTraceEnabled()) {
104 LOG.trace("Skipped reading ZK properties file '" + HConstants.ZOOKEEPER_CONFIG_NAME +
105 "' since '" + HConstants.HBASE_CONFIG_READ_ZOOKEEPER_CONFIG + "' was not set to true");
106 }
107 }
108
109 return null;
110 }
111
112
113
114
115
116
117
118
119
120 private static Properties makeZKPropsFromHbaseConfig(Configuration conf) {
121 Properties zkProperties = new Properties();
122
123
124
125 synchronized (conf) {
126 for (Entry<String, String> entry : conf) {
127 String key = entry.getKey();
128 if (key.startsWith(HConstants.ZK_CFG_PROPERTY_PREFIX)) {
129 String zkKey = key.substring(HConstants.ZK_CFG_PROPERTY_PREFIX_LEN);
130 String value = entry.getValue();
131
132 if (value.contains(VARIABLE_START)) {
133 value = conf.get(key);
134 }
135 zkProperties.put(zkKey, value);
136 }
137 }
138 }
139
140
141 if (zkProperties.getProperty(HConstants.CLIENT_PORT_STR) == null) {
142 zkProperties.put(HConstants.CLIENT_PORT_STR,
143 HConstants.DEFAULT_ZOOKEPER_CLIENT_PORT);
144 }
145
146
147 int peerPort = conf.getInt("hbase.zookeeper.peerport", 2888);
148 int leaderPort = conf.getInt("hbase.zookeeper.leaderport", 3888);
149
150 final String[] serverHosts = conf.getStrings(HConstants.ZOOKEEPER_QUORUM,
151 HConstants.LOCALHOST);
152 String serverHost;
153 String address;
154 String key;
155 for (int i = 0; i < serverHosts.length; ++i) {
156 if (serverHosts[i].contains(":")) {
157 serverHost = serverHosts[i].substring(0, serverHosts[i].indexOf(':'));
158 } else {
159 serverHost = serverHosts[i];
160 }
161 address = serverHost + ":" + peerPort + ":" + leaderPort;
162 key = "server." + i;
163 zkProperties.put(key, address);
164 }
165
166 return zkProperties;
167 }
168
169
170
171
172
173
174
175
176
177
178
179 @Deprecated
180 public static Properties parseZooCfg(Configuration conf,
181 InputStream inputStream) throws IOException {
182 Properties properties = new Properties();
183 try {
184 properties.load(inputStream);
185 } catch (IOException e) {
186 final String msg = "fail to read properties from "
187 + HConstants.ZOOKEEPER_CONFIG_NAME;
188 LOG.fatal(msg);
189 throw new IOException(msg, e);
190 }
191 for (Entry<Object, Object> entry : properties.entrySet()) {
192 String value = entry.getValue().toString().trim();
193 String key = entry.getKey().toString().trim();
194 StringBuilder newValue = new StringBuilder();
195 int varStart = value.indexOf(VARIABLE_START);
196 int varEnd = 0;
197 while (varStart != -1) {
198 varEnd = value.indexOf(VARIABLE_END, varStart);
199 if (varEnd == -1) {
200 String msg = "variable at " + varStart + " has no end marker";
201 LOG.fatal(msg);
202 throw new IOException(msg);
203 }
204 String variable = value.substring(varStart + VARIABLE_START_LENGTH, varEnd);
205
206 String substituteValue = System.getProperty(variable);
207 if (substituteValue == null) {
208 substituteValue = conf.get(variable);
209 }
210 if (substituteValue == null) {
211 String msg = "variable " + variable + " not set in system property "
212 + "or hbase configs";
213 LOG.fatal(msg);
214 throw new IOException(msg);
215 }
216
217 newValue.append(substituteValue);
218
219 varEnd += VARIABLE_END_LENGTH;
220 varStart = value.indexOf(VARIABLE_START, varEnd);
221 }
222
223 if (key.startsWith("server.")) {
224 boolean mode =
225 conf.getBoolean(HConstants.CLUSTER_DISTRIBUTED, HConstants.DEFAULT_CLUSTER_DISTRIBUTED);
226 if (mode == HConstants.CLUSTER_IS_DISTRIBUTED && value.startsWith(HConstants.LOCALHOST)) {
227 String msg = "The server in zoo.cfg cannot be set to localhost " +
228 "in a fully-distributed setup because it won't be reachable. " +
229 "See \"Getting Started\" for more information.";
230 LOG.fatal(msg);
231 throw new IOException(msg);
232 }
233 }
234 newValue.append(value.substring(varEnd));
235 properties.setProperty(key, newValue.toString());
236 }
237 return properties;
238 }
239
240
241
242
243
244
245
246 private static String getZKQuorumServersString(Properties properties) {
247 String clientPort = null;
248 List<String> servers = new ArrayList<String>();
249
250
251
252 boolean anyValid = false;
253 for (Entry<Object,Object> property : properties.entrySet()) {
254 String key = property.getKey().toString().trim();
255 String value = property.getValue().toString().trim();
256 if (key.equals("clientPort")) {
257 clientPort = value;
258 }
259 else if (key.startsWith("server.")) {
260 String host = value.substring(0, value.indexOf(':'));
261 servers.add(host);
262 anyValid = true;
263 }
264 }
265
266 if (!anyValid) {
267 LOG.error("no valid quorum servers found in " + HConstants.ZOOKEEPER_CONFIG_NAME);
268 return null;
269 }
270
271 if (clientPort == null) {
272 LOG.error("no clientPort found in " + HConstants.ZOOKEEPER_CONFIG_NAME);
273 return null;
274 }
275
276 if (servers.isEmpty()) {
277 LOG.fatal("No servers were found in provided ZooKeeper configuration. " +
278 "HBase must have a ZooKeeper cluster configured for its " +
279 "operation. Ensure that you've configured '" +
280 HConstants.ZOOKEEPER_QUORUM + "' properly.");
281 return null;
282 }
283
284 StringBuilder hostPortBuilder = new StringBuilder();
285 for (int i = 0; i < servers.size(); ++i) {
286 String host = servers.get(i);
287 if (i > 0) {
288 hostPortBuilder.append(',');
289 }
290 hostPortBuilder.append(host);
291 hostPortBuilder.append(':');
292 hostPortBuilder.append(clientPort);
293 }
294
295 return hostPortBuilder.toString();
296 }
297
298
299
300
301
302
303
304 private static String getZKQuorumServersStringFromHbaseConfig(Configuration conf) {
305 String defaultClientPort = Integer.toString(
306 conf.getInt(HConstants.ZOOKEEPER_CLIENT_PORT, HConstants.DEFAULT_ZOOKEPER_CLIENT_PORT));
307
308
309 final String[] serverHosts =
310 conf.getStrings(HConstants.ZOOKEEPER_QUORUM, HConstants.LOCALHOST);
311 return buildZKQuorumServerString(serverHosts, defaultClientPort);
312 }
313
314
315
316
317
318
319 public static String getZKQuorumServersString(Configuration conf) {
320
321 Properties zkProperties = makeZKPropsFromZooCfg(conf);
322
323 if (zkProperties != null) {
324 return getZKQuorumServersString(zkProperties);
325 }
326
327 return getZKQuorumServersStringFromHbaseConfig(conf);
328 }
329
330
331
332
333
334
335
336
337 public static String buildZKQuorumServerString(String[] serverHosts, String clientPort) {
338 StringBuilder quorumStringBuilder = new StringBuilder();
339 String serverHost;
340 for (int i = 0; i < serverHosts.length; ++i) {
341 if (serverHosts[i].contains(":")) {
342 serverHost = serverHosts[i];
343 } else {
344 serverHost = serverHosts[i] + ":" + clientPort;
345 }
346 if (i > 0) {
347 quorumStringBuilder.append(',');
348 }
349 quorumStringBuilder.append(serverHost);
350 }
351 return quorumStringBuilder.toString();
352 }
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370 public static void validateClusterKey(String key) throws IOException {
371 transformClusterKey(key);
372 }
373
374
375
376
377
378
379
380
381
382 public static ZKClusterKey transformClusterKey(String key) throws IOException {
383 String[] parts = key.split(":");
384
385 if (parts.length == 3) {
386 if (!parts[2].matches("/.*[^/]")) {
387 throw new IOException("Cluster key passed " + key + " is invalid, the format should be:" +
388 HConstants.ZOOKEEPER_QUORUM + ":" + HConstants.ZOOKEEPER_CLIENT_PORT + ":"
389 + HConstants.ZOOKEEPER_ZNODE_PARENT);
390 }
391 return new ZKClusterKey(parts [0], Integer.parseInt(parts [1]), parts [2]);
392 }
393
394 if (parts.length > 3) {
395
396 String zNodeParent = parts [parts.length - 1];
397 if (!zNodeParent.matches("/.*[^/]")) {
398 throw new IOException("Cluster key passed " + key + " is invalid, the format should be:"
399 + HConstants.ZOOKEEPER_QUORUM + ":" + HConstants.ZOOKEEPER_CLIENT_PORT + ":"
400 + HConstants.ZOOKEEPER_ZNODE_PARENT);
401 }
402
403 String clientPort = parts [parts.length - 2];
404
405
406 int endQuorumIndex = key.length() - zNodeParent.length() - clientPort.length() - 2;
407 String quorumStringInput = key.substring(0, endQuorumIndex);
408 String[] serverHosts = quorumStringInput.split(",");
409
410
411
412
413 if ((parts.length - 2) == (serverHosts.length + 1)) {
414 return new ZKClusterKey(quorumStringInput, Integer.parseInt(clientPort), zNodeParent);
415 }
416
417
418
419 return new ZKClusterKey(
420 buildZKQuorumServerString(serverHosts, clientPort),
421 Integer.parseInt(clientPort),
422 zNodeParent);
423 }
424
425 throw new IOException("Cluster key passed " + key + " is invalid, the format should be:" +
426 HConstants.ZOOKEEPER_QUORUM + ":" + HConstants.ZOOKEEPER_CLIENT_PORT + ":"
427 + HConstants.ZOOKEEPER_ZNODE_PARENT);
428 }
429
430
431
432
433
434
435
436 public static String getZooKeeperClusterKey(Configuration conf) {
437 return getZooKeeperClusterKey(conf, null);
438 }
439
440
441
442
443
444
445
446
447 public static String getZooKeeperClusterKey(Configuration conf, String name) {
448 String ensemble = conf.get(HConstants.ZOOKEEPER_QUORUM).replaceAll(
449 "[\\t\\n\\x0B\\f\\r]", "");
450 StringBuilder builder = new StringBuilder(ensemble);
451 builder.append(":");
452 builder.append(conf.get(HConstants.ZOOKEEPER_CLIENT_PORT));
453 builder.append(":");
454 builder.append(conf.get(HConstants.ZOOKEEPER_ZNODE_PARENT));
455 if (name != null && !name.isEmpty()) {
456 builder.append(",");
457 builder.append(name);
458 }
459 return builder.toString();
460 }
461
462
463
464
465
466
467
468 public static String standardizeZKQuorumServerString(String quorumStringInput,
469 String clientPort) {
470 String[] serverHosts = quorumStringInput.split(",");
471 return buildZKQuorumServerString(serverHosts, clientPort);
472 }
473
474
475
476
477
478
479
480 public static class ZKClusterKey {
481 private String quorumString;
482 private int clientPort;
483 private String znodeParent;
484
485 ZKClusterKey(String quorumString, int clientPort, String znodeParent) {
486 this.quorumString = quorumString;
487 this.clientPort = clientPort;
488 this.znodeParent = znodeParent;
489 }
490
491 public String getQuorumString() {
492 return quorumString;
493 }
494
495 public int getClientPort() {
496 return clientPort;
497 }
498
499 public String getZnodeParent() {
500 return znodeParent;
501 }
502 }
503 }