1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.accumulo.core.client;
18
19 import java.io.IOException;
20 import java.nio.ByteBuffer;
21 import java.util.Collections;
22 import java.util.List;
23 import java.util.UUID;
24
25 import org.apache.accumulo.core.Constants;
26 import org.apache.accumulo.core.client.impl.ConnectorImpl;
27 import org.apache.accumulo.core.client.impl.MasterClient;
28 import org.apache.accumulo.core.conf.AccumuloConfiguration;
29 import org.apache.accumulo.core.conf.Property;
30 import org.apache.accumulo.core.file.FileUtil;
31 import org.apache.accumulo.core.master.thrift.MasterClientService.Client;
32 import org.apache.accumulo.core.security.CredentialHelper;
33 import org.apache.accumulo.core.security.thrift.AuthInfo;
34 import org.apache.accumulo.core.security.thrift.Credential;
35 import org.apache.accumulo.core.security.thrift.ThriftSecurityException;
36 import org.apache.accumulo.core.security.tokens.PasswordToken;
37 import org.apache.accumulo.core.security.tokens.SecurityToken;
38 import org.apache.accumulo.core.util.ArgumentChecker;
39 import org.apache.accumulo.core.util.ByteBufferUtil;
40 import org.apache.accumulo.core.util.CachedConfiguration;
41 import org.apache.accumulo.core.util.OpTimer;
42 import org.apache.accumulo.core.util.TextUtil;
43 import org.apache.accumulo.core.util.ThriftUtil;
44 import org.apache.accumulo.core.zookeeper.ZooUtil;
45 import org.apache.accumulo.fate.zookeeper.ZooCache;
46 import org.apache.hadoop.fs.FileStatus;
47 import org.apache.hadoop.fs.FileSystem;
48 import org.apache.hadoop.fs.Path;
49 import org.apache.hadoop.io.Text;
50 import org.apache.log4j.Level;
51 import org.apache.log4j.Logger;
52 import org.apache.thrift.TException;
53 import org.apache.thrift.transport.TTransportException;
54
55 /**
56 * <p>
57 * An implementation of instance that looks in zookeeper to find information needed to connect to an instance of accumulo.
58 *
59 * <p>
60 * The advantage of using zookeeper to obtain information about accumulo is that zookeeper is highly available, very responsive, and supports caching.
61 *
62 * <p>
63 * Because it is possible for multiple instances of accumulo to share a single set of zookeeper servers, all constructors require an accumulo instance name.
64 *
65 * If you do not know the instance names then run accumulo org.apache.accumulo.server.util.ListInstances on an accumulo server.
66 *
67 */
68
69 public class ZooKeeperInstance implements Instance {
70
71 private static final Logger log = Logger.getLogger(ZooKeeperInstance.class);
72
73 private String instanceId = null;
74 private String instanceName = null;
75
76 private ZooCache zooCache;
77
78 private String zooKeepers;
79
80 private int zooKeepersSessionTimeOut;
81
82 /**
83 *
84 * @param instanceName
85 * The name of specific accumulo instance. This is set at initialization time.
86 * @param zooKeepers
87 * A comma separated list of zoo keeper server locations. Each location can contain an optional port, of the format host:port.
88 */
89
90 public ZooKeeperInstance(String instanceName, String zooKeepers) {
91 this(instanceName, zooKeepers, (int) AccumuloConfiguration.getDefaultConfiguration().getTimeInMillis(Property.INSTANCE_ZK_TIMEOUT));
92 }
93
94 /**
95 *
96 * @param instanceName
97 * The name of specific accumulo instance. This is set at initialization time.
98 * @param zooKeepers
99 * A comma separated list of zoo keeper server locations. Each location can contain an optional port, of the format host:port.
100 * @param sessionTimeout
101 * zoo keeper session time out in milliseconds.
102 */
103
104 public ZooKeeperInstance(String instanceName, String zooKeepers, int sessionTimeout) {
105 ArgumentChecker.notNull(instanceName, zooKeepers);
106 this.instanceName = instanceName;
107 this.zooKeepers = zooKeepers;
108 this.zooKeepersSessionTimeOut = sessionTimeout;
109 zooCache = ZooCache.getInstance(zooKeepers, sessionTimeout);
110 getInstanceID();
111 }
112
113 /**
114 *
115 * @param instanceId
116 * The UUID that identifies the accumulo instance you want to connect to.
117 * @param zooKeepers
118 * A comma separated list of zoo keeper server locations. Each location can contain an optional port, of the format host:port.
119 */
120
121 public ZooKeeperInstance(UUID instanceId, String zooKeepers) {
122 this(instanceId, zooKeepers, (int) AccumuloConfiguration.getDefaultConfiguration().getTimeInMillis(Property.INSTANCE_ZK_TIMEOUT));
123 }
124
125 /**
126 *
127 * @param instanceId
128 * The UUID that identifies the accumulo instance you want to connect to.
129 * @param zooKeepers
130 * A comma separated list of zoo keeper server locations. Each location can contain an optional port, of the format host:port.
131 * @param sessionTimeout
132 * zoo keeper session time out in milliseconds.
133 */
134
135 public ZooKeeperInstance(UUID instanceId, String zooKeepers, int sessionTimeout) {
136 ArgumentChecker.notNull(instanceId, zooKeepers);
137 this.instanceId = instanceId.toString();
138 this.zooKeepers = zooKeepers;
139 this.zooKeepersSessionTimeOut = sessionTimeout;
140 zooCache = ZooCache.getInstance(zooKeepers, sessionTimeout);
141 }
142
143 @Override
144 public String getInstanceID() {
145 if (instanceId == null) {
146
147
148 String instanceNamePath = Constants.ZROOT + Constants.ZINSTANCES + "/" + instanceName;
149 byte[] iidb = zooCache.get(instanceNamePath);
150 if (iidb == null) {
151 throw new RuntimeException("Instance name " + instanceName
152 + " does not exist in zookeeper. Run \"accumulo org.apache.accumulo.server.util.ListInstances\" to see a list.");
153 }
154 instanceId = new String(iidb);
155 }
156
157 if (zooCache.get(Constants.ZROOT + "/" + instanceId) == null) {
158 if (instanceName == null)
159 throw new RuntimeException("Instance id " + instanceId + " does not exist in zookeeper");
160 throw new RuntimeException("Instance id " + instanceId + " pointed to by the name " + instanceName + " does not exist in zookeeper");
161 }
162
163 return instanceId;
164 }
165
166 @Override
167 public List<String> getMasterLocations() {
168 String masterLocPath = ZooUtil.getRoot(this) + Constants.ZMASTER_LOCK;
169
170 OpTimer opTimer = new OpTimer(log, Level.TRACE).start("Looking up master location in zoocache.");
171 byte[] loc = ZooUtil.getLockData(zooCache, masterLocPath);
172 opTimer.stop("Found master at " + (loc == null ? null : new String(loc)) + " in %DURATION%");
173
174 if (loc == null) {
175 return Collections.emptyList();
176 }
177
178 return Collections.singletonList(new String(loc));
179 }
180
181 @Override
182 public String getRootTabletLocation() {
183 String zRootLocPath = ZooUtil.getRoot(this) + Constants.ZROOT_TABLET_LOCATION;
184
185 OpTimer opTimer = new OpTimer(log, Level.TRACE).start("Looking up root tablet location in zookeeper.");
186 byte[] loc = zooCache.get(zRootLocPath);
187 opTimer.stop("Found root tablet at " + (loc == null ? null : new String(loc)) + " in %DURATION%");
188
189 if (loc == null) {
190 return null;
191 }
192
193 return new String(loc).split("\\|")[0];
194 }
195
196 @Override
197 public String getInstanceName() {
198 if (instanceName == null)
199 instanceName = lookupInstanceName(zooCache, UUID.fromString(getInstanceID()));
200
201 return instanceName;
202 }
203
204 @Override
205 public String getZooKeepers() {
206 return zooKeepers;
207 }
208
209 @Override
210 public int getZooKeepersSessionTimeOut() {
211 return zooKeepersSessionTimeOut;
212 }
213
214 @Override
215 public Connector getConnector(String user, CharSequence pass) throws AccumuloException, AccumuloSecurityException {
216 return getConnector(user, TextUtil.getBytes(new Text(pass.toString())));
217 }
218
219 @Override
220 public Connector getConnector(String user, ByteBuffer pass) throws AccumuloException, AccumuloSecurityException {
221 return getConnector(user, ByteBufferUtil.toBytes(pass));
222 }
223
224
225 @Override
226 public Connector getConnector(String principal, SecurityToken token) throws AccumuloException, AccumuloSecurityException {
227 return getConnector(CredentialHelper.create(principal, token, getInstanceID()));
228 }
229
230 @SuppressWarnings("deprecation")
231 public Connector getConnector(Credential credential) throws AccumuloException, AccumuloSecurityException {
232 return new ConnectorImpl(this, credential);
233 }
234
235 @Override
236 public Connector getConnector(String principal, byte[] pass) throws AccumuloException, AccumuloSecurityException {
237 return getConnector(principal, new PasswordToken().setPassword(pass));
238 }
239
240 private AccumuloConfiguration conf = null;
241
242 @Override
243 public AccumuloConfiguration getConfiguration() {
244 if (conf == null)
245 conf = AccumuloConfiguration.getDefaultConfiguration();
246 return conf;
247 }
248
249 @Override
250 public void setConfiguration(AccumuloConfiguration conf) {
251 this.conf = conf;
252 }
253
254 /**
255 * @deprecated Use {@link #lookupInstanceName(org.apache.accumulo.fate.zookeeper.ZooCache, UUID)} instead
256 */
257 @Deprecated
258 public static String lookupInstanceName(org.apache.accumulo.core.zookeeper.ZooCache zooCache, UUID instanceId) {
259 return lookupInstanceName((ZooCache) zooCache, instanceId);
260 }
261
262 /**
263 * Given a zooCache and instanceId, look up the instance name.
264 *
265 * @param zooCache
266 * @param instanceId
267 * @return the instance name
268 */
269 public static String lookupInstanceName(ZooCache zooCache, UUID instanceId) {
270 ArgumentChecker.notNull(zooCache, instanceId);
271 for (String name : zooCache.getChildren(Constants.ZROOT + Constants.ZINSTANCES)) {
272 String instanceNamePath = Constants.ZROOT + Constants.ZINSTANCES + "/" + name;
273 UUID iid = UUID.fromString(new String(zooCache.get(instanceNamePath)));
274 if (iid.equals(instanceId)) {
275 return name;
276 }
277 }
278 return null;
279 }
280
281
282 @Deprecated
283 public static String getInstanceIDFromHdfs(Path instanceDirectory) {
284 try {
285 FileSystem fs = FileUtil.getFileSystem(CachedConfiguration.getInstance(), AccumuloConfiguration.getSiteConfiguration());
286 FileStatus[] files = fs.listStatus(instanceDirectory);
287 log.debug("Trying to read instance id from " + instanceDirectory);
288 if (files == null || files.length == 0) {
289 log.error("unable obtain instance id at " + instanceDirectory);
290 throw new RuntimeException("Accumulo not initialized, there is no instance id at " + instanceDirectory);
291 } else if (files.length != 1) {
292 log.error("multiple potential instances in " + instanceDirectory);
293 throw new RuntimeException("Accumulo found multiple possible instance ids in " + instanceDirectory);
294 } else {
295 String result = files[0].getPath().getName();
296 return result;
297 }
298 } catch (IOException e) {
299 throw new RuntimeException("Accumulo not initialized, there is no instance id at " + instanceDirectory, e);
300 }
301 }
302
303 @Override
304 public Connector getConnector(AuthInfo auth) throws AccumuloException, AccumuloSecurityException {
305 return getConnector(auth.user, auth.password);
306 }
307
308 @Override
309 public String getAuthenticatorClassName() throws AccumuloException {
310 Client client = null;
311 try {
312 client = MasterClient.getConnectionWithRetry(this);
313 return client.getAuthenticatorClassName();
314 } catch (TTransportException e) {
315 throw new AccumuloException(e);
316 } catch (ThriftSecurityException e) {
317 throw new AccumuloException(e);
318 } catch (TException e) {
319 throw new AccumuloException(e);
320 } finally {
321 if (client != null) {
322 ThriftUtil.returnClient(client);
323 }
324 }
325 }
326
327 }