001/** 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hdfs; 019 020import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_CLIENT_FAILOVER_MAX_ATTEMPTS_DEFAULT; 021import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_CLIENT_FAILOVER_MAX_ATTEMPTS_KEY; 022import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_CLIENT_FAILOVER_PROXY_PROVIDER_KEY_PREFIX; 023import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_CLIENT_FAILOVER_SLEEPTIME_BASE_DEFAULT; 024import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_CLIENT_FAILOVER_SLEEPTIME_BASE_KEY; 025import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_CLIENT_FAILOVER_SLEEPTIME_MAX_DEFAULT; 026import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_CLIENT_FAILOVER_SLEEPTIME_MAX_KEY; 027import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_CLIENT_RETRY_MAX_ATTEMPTS_KEY; 028import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_CLIENT_RETRY_MAX_ATTEMPTS_DEFAULT; 029 030import java.io.IOException; 031import java.lang.reflect.Constructor; 032import java.lang.reflect.InvocationHandler; 033import java.lang.reflect.Proxy; 034import java.net.InetSocketAddress; 035import java.net.URI; 036import java.util.HashMap; 037import java.util.Map; 038import java.util.concurrent.TimeUnit; 039import java.util.concurrent.atomic.AtomicBoolean; 040 041import org.apache.commons.logging.Log; 042import org.apache.commons.logging.LogFactory; 043import org.apache.hadoop.conf.Configuration; 044import org.apache.hadoop.hdfs.DFSClient.Conf; 045import org.apache.hadoop.hdfs.protocol.ClientProtocol; 046import org.apache.hadoop.hdfs.protocol.HdfsConstants; 047import org.apache.hadoop.hdfs.protocolPB.ClientNamenodeProtocolPB; 048import org.apache.hadoop.hdfs.protocolPB.ClientNamenodeProtocolTranslatorPB; 049import org.apache.hadoop.hdfs.protocolPB.JournalProtocolPB; 050import org.apache.hadoop.hdfs.protocolPB.JournalProtocolTranslatorPB; 051import org.apache.hadoop.hdfs.protocolPB.NamenodeProtocolPB; 052import org.apache.hadoop.hdfs.protocolPB.NamenodeProtocolTranslatorPB; 053import org.apache.hadoop.hdfs.server.namenode.ha.AbstractNNFailoverProxyProvider; 054import org.apache.hadoop.hdfs.server.namenode.ha.WrappedFailoverProxyProvider; 055import org.apache.hadoop.hdfs.server.namenode.NameNode; 056import org.apache.hadoop.hdfs.server.namenode.SafeModeException; 057import org.apache.hadoop.hdfs.server.protocol.JournalProtocol; 058import org.apache.hadoop.hdfs.server.protocol.NamenodeProtocol; 059import org.apache.hadoop.hdfs.server.protocol.NamenodeProtocols; 060import org.apache.hadoop.io.Text; 061import org.apache.hadoop.io.retry.DefaultFailoverProxyProvider; 062import org.apache.hadoop.io.retry.FailoverProxyProvider; 063import org.apache.hadoop.io.retry.LossyRetryInvocationHandler; 064import org.apache.hadoop.io.retry.RetryPolicies; 065import org.apache.hadoop.io.retry.RetryPolicy; 066import org.apache.hadoop.io.retry.RetryProxy; 067import org.apache.hadoop.io.retry.RetryUtils; 068import org.apache.hadoop.ipc.ProtobufRpcEngine; 069import org.apache.hadoop.ipc.RPC; 070import org.apache.hadoop.net.NetUtils; 071import org.apache.hadoop.security.RefreshUserMappingsProtocol; 072import org.apache.hadoop.security.SecurityUtil; 073import org.apache.hadoop.security.UserGroupInformation; 074import org.apache.hadoop.security.authorize.RefreshAuthorizationPolicyProtocol; 075import org.apache.hadoop.security.protocolPB.RefreshAuthorizationPolicyProtocolClientSideTranslatorPB; 076import org.apache.hadoop.security.protocolPB.RefreshAuthorizationPolicyProtocolPB; 077import org.apache.hadoop.security.protocolPB.RefreshUserMappingsProtocolClientSideTranslatorPB; 078import org.apache.hadoop.security.protocolPB.RefreshUserMappingsProtocolPB; 079import org.apache.hadoop.ipc.RefreshCallQueueProtocol; 080import org.apache.hadoop.ipc.protocolPB.RefreshCallQueueProtocolPB; 081import org.apache.hadoop.ipc.protocolPB.RefreshCallQueueProtocolClientSideTranslatorPB; 082import org.apache.hadoop.tools.GetUserMappingsProtocol; 083import org.apache.hadoop.tools.protocolPB.GetUserMappingsProtocolClientSideTranslatorPB; 084import org.apache.hadoop.tools.protocolPB.GetUserMappingsProtocolPB; 085 086import com.google.common.annotations.VisibleForTesting; 087import com.google.common.base.Preconditions; 088 089/** 090 * Create proxy objects to communicate with a remote NN. All remote access to an 091 * NN should be funneled through this class. Most of the time you'll want to use 092 * {@link NameNodeProxies#createProxy(Configuration, URI, Class)}, which will 093 * create either an HA- or non-HA-enabled client proxy as appropriate. 094 */ 095public class NameNodeProxies { 096 097 private static final Log LOG = LogFactory.getLog(NameNodeProxies.class); 098 099 /** 100 * Wrapper for a client proxy as well as its associated service ID. 101 * This is simply used as a tuple-like return type for 102 * {@link NameNodeProxies#createProxy} and 103 * {@link NameNodeProxies#createNonHAProxy}. 104 */ 105 public static class ProxyAndInfo<PROXYTYPE> { 106 private final PROXYTYPE proxy; 107 private final Text dtService; 108 private final InetSocketAddress address; 109 110 public ProxyAndInfo(PROXYTYPE proxy, Text dtService, 111 InetSocketAddress address) { 112 this.proxy = proxy; 113 this.dtService = dtService; 114 this.address = address; 115 } 116 117 public PROXYTYPE getProxy() { 118 return proxy; 119 } 120 121 public Text getDelegationTokenService() { 122 return dtService; 123 } 124 125 public InetSocketAddress getAddress() { 126 return address; 127 } 128 } 129 130 /** 131 * Creates the namenode proxy with the passed protocol. This will handle 132 * creation of either HA- or non-HA-enabled proxy objects, depending upon 133 * if the provided URI is a configured logical URI. 134 * 135 * @param conf the configuration containing the required IPC 136 * properties, client failover configurations, etc. 137 * @param nameNodeUri the URI pointing either to a specific NameNode 138 * or to a logical nameservice. 139 * @param xface the IPC interface which should be created 140 * @return an object containing both the proxy and the associated 141 * delegation token service it corresponds to 142 * @throws IOException if there is an error creating the proxy 143 **/ 144 @SuppressWarnings("unchecked") 145 public static <T> ProxyAndInfo<T> createProxy(Configuration conf, 146 URI nameNodeUri, Class<T> xface) throws IOException { 147 return createProxy(conf, nameNodeUri, xface, null); 148 } 149 150 /** 151 * Creates the namenode proxy with the passed protocol. This will handle 152 * creation of either HA- or non-HA-enabled proxy objects, depending upon 153 * if the provided URI is a configured logical URI. 154 * 155 * @param conf the configuration containing the required IPC 156 * properties, client failover configurations, etc. 157 * @param nameNodeUri the URI pointing either to a specific NameNode 158 * or to a logical nameservice. 159 * @param xface the IPC interface which should be created 160 * @param fallbackToSimpleAuth set to true or false during calls to indicate if 161 * a secure client falls back to simple auth 162 * @return an object containing both the proxy and the associated 163 * delegation token service it corresponds to 164 * @throws IOException if there is an error creating the proxy 165 **/ 166 @SuppressWarnings("unchecked") 167 public static <T> ProxyAndInfo<T> createProxy(Configuration conf, 168 URI nameNodeUri, Class<T> xface, AtomicBoolean fallbackToSimpleAuth) 169 throws IOException { 170 AbstractNNFailoverProxyProvider<T> failoverProxyProvider = 171 createFailoverProxyProvider(conf, nameNodeUri, xface, true, 172 fallbackToSimpleAuth); 173 174 if (failoverProxyProvider == null) { 175 // Non-HA case 176 return createNonHAProxy(conf, NameNode.getAddress(nameNodeUri), xface, 177 UserGroupInformation.getCurrentUser(), true, fallbackToSimpleAuth); 178 } else { 179 // HA case 180 Conf config = new Conf(conf); 181 T proxy = (T) RetryProxy.create(xface, failoverProxyProvider, 182 RetryPolicies.failoverOnNetworkException( 183 RetryPolicies.TRY_ONCE_THEN_FAIL, config.maxFailoverAttempts, 184 config.maxRetryAttempts, config.failoverSleepBaseMillis, 185 config.failoverSleepMaxMillis)); 186 187 Text dtService; 188 if (failoverProxyProvider.useLogicalURI()) { 189 dtService = HAUtil.buildTokenServiceForLogicalUri(nameNodeUri, 190 HdfsConstants.HDFS_URI_SCHEME); 191 } else { 192 dtService = SecurityUtil.buildTokenService( 193 NameNode.getAddress(nameNodeUri)); 194 } 195 return new ProxyAndInfo<T>(proxy, dtService, 196 NameNode.getAddress(nameNodeUri)); 197 } 198 } 199 200 /** 201 * Generate a dummy namenode proxy instance that utilizes our hacked 202 * {@link LossyRetryInvocationHandler}. Proxy instance generated using this 203 * method will proactively drop RPC responses. Currently this method only 204 * support HA setup. null will be returned if the given configuration is not 205 * for HA. 206 * 207 * @param config the configuration containing the required IPC 208 * properties, client failover configurations, etc. 209 * @param nameNodeUri the URI pointing either to a specific NameNode 210 * or to a logical nameservice. 211 * @param xface the IPC interface which should be created 212 * @param numResponseToDrop The number of responses to drop for each RPC call 213 * @param fallbackToSimpleAuth set to true or false during calls to indicate if 214 * a secure client falls back to simple auth 215 * @return an object containing both the proxy and the associated 216 * delegation token service it corresponds to. Will return null of the 217 * given configuration does not support HA. 218 * @throws IOException if there is an error creating the proxy 219 */ 220 @SuppressWarnings("unchecked") 221 public static <T> ProxyAndInfo<T> createProxyWithLossyRetryHandler( 222 Configuration config, URI nameNodeUri, Class<T> xface, 223 int numResponseToDrop, AtomicBoolean fallbackToSimpleAuth) 224 throws IOException { 225 Preconditions.checkArgument(numResponseToDrop > 0); 226 AbstractNNFailoverProxyProvider<T> failoverProxyProvider = 227 createFailoverProxyProvider(config, nameNodeUri, xface, true, 228 fallbackToSimpleAuth); 229 230 if (failoverProxyProvider != null) { // HA case 231 int delay = config.getInt( 232 DFS_CLIENT_FAILOVER_SLEEPTIME_BASE_KEY, 233 DFS_CLIENT_FAILOVER_SLEEPTIME_BASE_DEFAULT); 234 int maxCap = config.getInt( 235 DFS_CLIENT_FAILOVER_SLEEPTIME_MAX_KEY, 236 DFS_CLIENT_FAILOVER_SLEEPTIME_MAX_DEFAULT); 237 int maxFailoverAttempts = config.getInt( 238 DFS_CLIENT_FAILOVER_MAX_ATTEMPTS_KEY, 239 DFS_CLIENT_FAILOVER_MAX_ATTEMPTS_DEFAULT); 240 int maxRetryAttempts = config.getInt( 241 DFS_CLIENT_RETRY_MAX_ATTEMPTS_KEY, 242 DFS_CLIENT_RETRY_MAX_ATTEMPTS_DEFAULT); 243 InvocationHandler dummyHandler = new LossyRetryInvocationHandler<T>( 244 numResponseToDrop, failoverProxyProvider, 245 RetryPolicies.failoverOnNetworkException( 246 RetryPolicies.TRY_ONCE_THEN_FAIL, maxFailoverAttempts, 247 Math.max(numResponseToDrop + 1, maxRetryAttempts), delay, 248 maxCap)); 249 250 T proxy = (T) Proxy.newProxyInstance( 251 failoverProxyProvider.getInterface().getClassLoader(), 252 new Class[] { xface }, dummyHandler); 253 Text dtService; 254 if (failoverProxyProvider.useLogicalURI()) { 255 dtService = HAUtil.buildTokenServiceForLogicalUri(nameNodeUri, 256 HdfsConstants.HDFS_URI_SCHEME); 257 } else { 258 dtService = SecurityUtil.buildTokenService( 259 NameNode.getAddress(nameNodeUri)); 260 } 261 return new ProxyAndInfo<T>(proxy, dtService, 262 NameNode.getAddress(nameNodeUri)); 263 } else { 264 LOG.warn("Currently creating proxy using " + 265 "LossyRetryInvocationHandler requires NN HA setup"); 266 return null; 267 } 268 } 269 270 /** 271 * Creates an explicitly non-HA-enabled proxy object. Most of the time you 272 * don't want to use this, and should instead use {@link NameNodeProxies#createProxy}. 273 * 274 * @param conf the configuration object 275 * @param nnAddr address of the remote NN to connect to 276 * @param xface the IPC interface which should be created 277 * @param ugi the user who is making the calls on the proxy object 278 * @param withRetries certain interfaces have a non-standard retry policy 279 * @return an object containing both the proxy and the associated 280 * delegation token service it corresponds to 281 * @throws IOException 282 */ 283 @SuppressWarnings("unchecked") 284 public static <T> ProxyAndInfo<T> createNonHAProxy( 285 Configuration conf, InetSocketAddress nnAddr, Class<T> xface, 286 UserGroupInformation ugi, boolean withRetries) throws IOException { 287 return createNonHAProxy(conf, nnAddr, xface, ugi, withRetries, null); 288 } 289 290 /** 291 * Creates an explicitly non-HA-enabled proxy object. Most of the time you 292 * don't want to use this, and should instead use {@link NameNodeProxies#createProxy}. 293 * 294 * @param conf the configuration object 295 * @param nnAddr address of the remote NN to connect to 296 * @param xface the IPC interface which should be created 297 * @param ugi the user who is making the calls on the proxy object 298 * @param withRetries certain interfaces have a non-standard retry policy 299 * @param fallbackToSimpleAuth - set to true or false during this method to 300 * indicate if a secure client falls back to simple auth 301 * @return an object containing both the proxy and the associated 302 * delegation token service it corresponds to 303 * @throws IOException 304 */ 305 @SuppressWarnings("unchecked") 306 public static <T> ProxyAndInfo<T> createNonHAProxy( 307 Configuration conf, InetSocketAddress nnAddr, Class<T> xface, 308 UserGroupInformation ugi, boolean withRetries, 309 AtomicBoolean fallbackToSimpleAuth) throws IOException { 310 Text dtService = SecurityUtil.buildTokenService(nnAddr); 311 312 T proxy; 313 if (xface == ClientProtocol.class) { 314 proxy = (T) createNNProxyWithClientProtocol(nnAddr, conf, ugi, 315 withRetries, fallbackToSimpleAuth); 316 } else if (xface == JournalProtocol.class) { 317 proxy = (T) createNNProxyWithJournalProtocol(nnAddr, conf, ugi); 318 } else if (xface == NamenodeProtocol.class) { 319 proxy = (T) createNNProxyWithNamenodeProtocol(nnAddr, conf, ugi, 320 withRetries); 321 } else if (xface == GetUserMappingsProtocol.class) { 322 proxy = (T) createNNProxyWithGetUserMappingsProtocol(nnAddr, conf, ugi); 323 } else if (xface == RefreshUserMappingsProtocol.class) { 324 proxy = (T) createNNProxyWithRefreshUserMappingsProtocol(nnAddr, conf, ugi); 325 } else if (xface == RefreshAuthorizationPolicyProtocol.class) { 326 proxy = (T) createNNProxyWithRefreshAuthorizationPolicyProtocol(nnAddr, 327 conf, ugi); 328 } else if (xface == RefreshCallQueueProtocol.class) { 329 proxy = (T) createNNProxyWithRefreshCallQueueProtocol(nnAddr, conf, ugi); 330 } else { 331 String message = "Unsupported protocol found when creating the proxy " + 332 "connection to NameNode: " + 333 ((xface != null) ? xface.getClass().getName() : "null"); 334 LOG.error(message); 335 throw new IllegalStateException(message); 336 } 337 338 return new ProxyAndInfo<T>(proxy, dtService, nnAddr); 339 } 340 341 private static JournalProtocol createNNProxyWithJournalProtocol( 342 InetSocketAddress address, Configuration conf, UserGroupInformation ugi) 343 throws IOException { 344 JournalProtocolPB proxy = (JournalProtocolPB) createNameNodeProxy(address, 345 conf, ugi, JournalProtocolPB.class); 346 return new JournalProtocolTranslatorPB(proxy); 347 } 348 349 private static RefreshAuthorizationPolicyProtocol 350 createNNProxyWithRefreshAuthorizationPolicyProtocol(InetSocketAddress address, 351 Configuration conf, UserGroupInformation ugi) throws IOException { 352 RefreshAuthorizationPolicyProtocolPB proxy = (RefreshAuthorizationPolicyProtocolPB) 353 createNameNodeProxy(address, conf, ugi, RefreshAuthorizationPolicyProtocolPB.class); 354 return new RefreshAuthorizationPolicyProtocolClientSideTranslatorPB(proxy); 355 } 356 357 private static RefreshUserMappingsProtocol 358 createNNProxyWithRefreshUserMappingsProtocol(InetSocketAddress address, 359 Configuration conf, UserGroupInformation ugi) throws IOException { 360 RefreshUserMappingsProtocolPB proxy = (RefreshUserMappingsProtocolPB) 361 createNameNodeProxy(address, conf, ugi, RefreshUserMappingsProtocolPB.class); 362 return new RefreshUserMappingsProtocolClientSideTranslatorPB(proxy); 363 } 364 365 private static RefreshCallQueueProtocol 366 createNNProxyWithRefreshCallQueueProtocol(InetSocketAddress address, 367 Configuration conf, UserGroupInformation ugi) throws IOException { 368 RefreshCallQueueProtocolPB proxy = (RefreshCallQueueProtocolPB) 369 createNameNodeProxy(address, conf, ugi, RefreshCallQueueProtocolPB.class); 370 return new RefreshCallQueueProtocolClientSideTranslatorPB(proxy); 371 } 372 373 private static GetUserMappingsProtocol createNNProxyWithGetUserMappingsProtocol( 374 InetSocketAddress address, Configuration conf, UserGroupInformation ugi) 375 throws IOException { 376 GetUserMappingsProtocolPB proxy = (GetUserMappingsProtocolPB) 377 createNameNodeProxy(address, conf, ugi, GetUserMappingsProtocolPB.class); 378 return new GetUserMappingsProtocolClientSideTranslatorPB(proxy); 379 } 380 381 private static NamenodeProtocol createNNProxyWithNamenodeProtocol( 382 InetSocketAddress address, Configuration conf, UserGroupInformation ugi, 383 boolean withRetries) throws IOException { 384 NamenodeProtocolPB proxy = (NamenodeProtocolPB) createNameNodeProxy( 385 address, conf, ugi, NamenodeProtocolPB.class); 386 if (withRetries) { // create the proxy with retries 387 RetryPolicy timeoutPolicy = RetryPolicies.exponentialBackoffRetry(5, 200, 388 TimeUnit.MILLISECONDS); 389 Map<String, RetryPolicy> methodNameToPolicyMap 390 = new HashMap<String, RetryPolicy>(); 391 methodNameToPolicyMap.put("getBlocks", timeoutPolicy); 392 methodNameToPolicyMap.put("getAccessKeys", timeoutPolicy); 393 NamenodeProtocol translatorProxy = 394 new NamenodeProtocolTranslatorPB(proxy); 395 return (NamenodeProtocol) RetryProxy.create( 396 NamenodeProtocol.class, translatorProxy, methodNameToPolicyMap); 397 } else { 398 return new NamenodeProtocolTranslatorPB(proxy); 399 } 400 } 401 402 private static ClientProtocol createNNProxyWithClientProtocol( 403 InetSocketAddress address, Configuration conf, UserGroupInformation ugi, 404 boolean withRetries, AtomicBoolean fallbackToSimpleAuth) 405 throws IOException { 406 RPC.setProtocolEngine(conf, ClientNamenodeProtocolPB.class, ProtobufRpcEngine.class); 407 408 final RetryPolicy defaultPolicy = 409 RetryUtils.getDefaultRetryPolicy( 410 conf, 411 DFSConfigKeys.DFS_CLIENT_RETRY_POLICY_ENABLED_KEY, 412 DFSConfigKeys.DFS_CLIENT_RETRY_POLICY_ENABLED_DEFAULT, 413 DFSConfigKeys.DFS_CLIENT_RETRY_POLICY_SPEC_KEY, 414 DFSConfigKeys.DFS_CLIENT_RETRY_POLICY_SPEC_DEFAULT, 415 SafeModeException.class); 416 417 final long version = RPC.getProtocolVersion(ClientNamenodeProtocolPB.class); 418 ClientNamenodeProtocolPB proxy = RPC.getProtocolProxy( 419 ClientNamenodeProtocolPB.class, version, address, ugi, conf, 420 NetUtils.getDefaultSocketFactory(conf), 421 org.apache.hadoop.ipc.Client.getTimeout(conf), defaultPolicy, 422 fallbackToSimpleAuth).getProxy(); 423 424 if (withRetries) { // create the proxy with retries 425 426 Map<String, RetryPolicy> methodNameToPolicyMap 427 = new HashMap<String, RetryPolicy>(); 428 429 ClientProtocol translatorProxy = 430 new ClientNamenodeProtocolTranslatorPB(proxy); 431 return (ClientProtocol) RetryProxy.create( 432 ClientProtocol.class, 433 new DefaultFailoverProxyProvider<ClientProtocol>( 434 ClientProtocol.class, translatorProxy), 435 methodNameToPolicyMap, 436 defaultPolicy); 437 } else { 438 return new ClientNamenodeProtocolTranslatorPB(proxy); 439 } 440 } 441 442 private static Object createNameNodeProxy(InetSocketAddress address, 443 Configuration conf, UserGroupInformation ugi, Class<?> xface) 444 throws IOException { 445 RPC.setProtocolEngine(conf, xface, ProtobufRpcEngine.class); 446 Object proxy = RPC.getProxy(xface, RPC.getProtocolVersion(xface), address, 447 ugi, conf, NetUtils.getDefaultSocketFactory(conf)); 448 return proxy; 449 } 450 451 /** Gets the configured Failover proxy provider's class */ 452 @VisibleForTesting 453 public static <T> Class<FailoverProxyProvider<T>> getFailoverProxyProviderClass( 454 Configuration conf, URI nameNodeUri) throws IOException { 455 if (nameNodeUri == null) { 456 return null; 457 } 458 String host = nameNodeUri.getHost(); 459 460 String configKey = DFS_CLIENT_FAILOVER_PROXY_PROVIDER_KEY_PREFIX + "." 461 + host; 462 try { 463 @SuppressWarnings("unchecked") 464 Class<FailoverProxyProvider<T>> ret = (Class<FailoverProxyProvider<T>>) conf 465 .getClass(configKey, null, FailoverProxyProvider.class); 466 return ret; 467 } catch (RuntimeException e) { 468 if (e.getCause() instanceof ClassNotFoundException) { 469 throw new IOException("Could not load failover proxy provider class " 470 + conf.get(configKey) + " which is configured for authority " 471 + nameNodeUri, e); 472 } else { 473 throw e; 474 } 475 } 476 } 477 478 /** Creates the Failover proxy provider instance*/ 479 @VisibleForTesting 480 public static <T> AbstractNNFailoverProxyProvider<T> createFailoverProxyProvider( 481 Configuration conf, URI nameNodeUri, Class<T> xface, boolean checkPort, 482 AtomicBoolean fallbackToSimpleAuth) throws IOException { 483 Class<FailoverProxyProvider<T>> failoverProxyProviderClass = null; 484 AbstractNNFailoverProxyProvider<T> providerNN; 485 Preconditions.checkArgument( 486 xface.isAssignableFrom(NamenodeProtocols.class), 487 "Interface %s is not a NameNode protocol", xface); 488 try { 489 // Obtain the class of the proxy provider 490 failoverProxyProviderClass = getFailoverProxyProviderClass(conf, 491 nameNodeUri); 492 if (failoverProxyProviderClass == null) { 493 return null; 494 } 495 // Create a proxy provider instance. 496 Constructor<FailoverProxyProvider<T>> ctor = failoverProxyProviderClass 497 .getConstructor(Configuration.class, URI.class, Class.class); 498 FailoverProxyProvider<T> provider = ctor.newInstance(conf, nameNodeUri, 499 xface); 500 501 // If the proxy provider is of an old implementation, wrap it. 502 if (!(provider instanceof AbstractNNFailoverProxyProvider)) { 503 providerNN = new WrappedFailoverProxyProvider<T>(provider); 504 } else { 505 providerNN = (AbstractNNFailoverProxyProvider<T>)provider; 506 } 507 } catch (Exception e) { 508 String message = "Couldn't create proxy provider " + failoverProxyProviderClass; 509 if (LOG.isDebugEnabled()) { 510 LOG.debug(message, e); 511 } 512 if (e.getCause() instanceof IOException) { 513 throw (IOException) e.getCause(); 514 } else { 515 throw new IOException(message, e); 516 } 517 } 518 519 // Check the port in the URI, if it is logical. 520 if (checkPort && providerNN.useLogicalURI()) { 521 int port = nameNodeUri.getPort(); 522 if (port > 0 && port != NameNode.DEFAULT_PORT) { 523 // Throwing here without any cleanup is fine since we have not 524 // actually created the underlying proxies yet. 525 throw new IOException("Port " + port + " specified in URI " 526 + nameNodeUri + " but host '" + nameNodeUri.getHost() 527 + "' is a logical (HA) namenode" 528 + " and does not use port information."); 529 } 530 } 531 providerNN.setFallbackToSimpleAuth(fallbackToSimpleAuth); 532 return providerNN; 533 } 534 535}