From c0bacb578b7c85373efe2ad64646bfe55a95a1a1 Mon Sep 17 00:00:00 2001 From: Aaron Myers Date: Mon, 14 May 2012 16:28:23 +0000 Subject: [PATCH] HDFS-3414. Balancer does not find NameNode if rpc-address or servicerpc-address are not set in client configs. Contributed by Aaron T. Myers. git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/branches/branch-2@1338277 13f79535-47bb-0310-9956-ffa450edef68 --- hadoop-hdfs-project/hadoop-hdfs/CHANGES.txt | 3 + .../java/org/apache/hadoop/hdfs/DFSUtil.java | 41 +++++++++-- .../apache/hadoop/hdfs/MiniDFSCluster.java | 7 ++ .../org/apache/hadoop/hdfs/TestDFSUtil.java | 68 +++++++++++++++---- 4 files changed, 102 insertions(+), 17 deletions(-) diff --git a/hadoop-hdfs-project/hadoop-hdfs/CHANGES.txt b/hadoop-hdfs-project/hadoop-hdfs/CHANGES.txt index 407cb9035d5..766d6ea9b17 100644 --- a/hadoop-hdfs-project/hadoop-hdfs/CHANGES.txt +++ b/hadoop-hdfs-project/hadoop-hdfs/CHANGES.txt @@ -542,6 +542,9 @@ Release 2.0.0 - UNRELEASED HDFS-3026. HA: Handle failure during HA state transition. (atm) + HDFS-3414. Balancer does not find NameNode if rpc-address or + servicerpc-address are not set in client configs. (atm) + BREAKDOWN OF HDFS-1623 SUBTASKS HDFS-2179. Add fencing framework and mechanisms for NameNode HA. (todd) diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/DFSUtil.java b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/DFSUtil.java index fd4ad3eabb7..003eefc4581 100644 --- a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/DFSUtil.java +++ b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/DFSUtil.java @@ -43,6 +43,7 @@ import org.apache.hadoop.HadoopIllegalArgumentException; import org.apache.hadoop.classification.InterfaceAudience; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.BlockLocation; +import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.fs.Path; import org.apache.hadoop.hdfs.protocol.AlreadyBeingCreatedException; import org.apache.hadoop.hdfs.protocol.ClientDatanodeProtocol; @@ -614,6 +615,14 @@ public class DFSUtil { public static Collection getNameServiceUris(Configuration conf, String... keys) { Set ret = new HashSet(); + + // We're passed multiple possible configuration keys for any given NN or HA + // nameservice, and search the config in order of these keys. In order to + // make sure that a later config lookup (e.g. fs.defaultFS) doesn't add a + // URI for a config key for which we've already found a preferred entry, we + // keep track of non-preferred keys here. + Set nonPreferredUris = new HashSet(); + for (String nsId : getNameServiceIds(conf)) { if (HAUtil.isHAEnabled(conf, nsId)) { // Add the logical URI of the nameservice. @@ -624,24 +633,46 @@ public class DFSUtil { } } else { // Add the URI corresponding to the address of the NN. + boolean uriFound = false; for (String key : keys) { String addr = conf.get(concatSuffixes(key, nsId)); if (addr != null) { - ret.add(createUri(HdfsConstants.HDFS_URI_SCHEME, - NetUtils.createSocketAddr(addr))); - break; + URI uri = createUri(HdfsConstants.HDFS_URI_SCHEME, + NetUtils.createSocketAddr(addr)); + if (!uriFound) { + uriFound = true; + ret.add(uri); + } else { + nonPreferredUris.add(uri); + } } } } } + // Add the generic configuration keys. + boolean uriFound = false; for (String key : keys) { String addr = conf.get(key); if (addr != null) { - ret.add(createUri("hdfs", NetUtils.createSocketAddr(addr))); - break; + URI uri = createUri("hdfs", NetUtils.createSocketAddr(addr)); + if (!uriFound) { + uriFound = true; + ret.add(uri); + } else { + nonPreferredUris.add(uri); + } } } + + // Add the default URI if it is an HDFS URI. + URI defaultUri = FileSystem.getDefaultUri(conf); + if (defaultUri != null && + HdfsConstants.HDFS_URI_SCHEME.equals(defaultUri.getScheme()) && + !nonPreferredUris.contains(defaultUri)) { + ret.add(defaultUri); + } + return ret; } diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/MiniDFSCluster.java b/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/MiniDFSCluster.java index 38106144cfd..11526a230c3 100644 --- a/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/MiniDFSCluster.java +++ b/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/MiniDFSCluster.java @@ -1251,6 +1251,13 @@ public class MiniDFSCluster { public int getNameNodePort(int nnIndex) { return nameNodes[nnIndex].nameNode.getNameNodeAddress().getPort(); } + + /** + * @return the service rpc port used by the NameNode at the given index. + */ + public int getNameNodeServicePort(int nnIndex) { + return nameNodes[nnIndex].nameNode.getServiceRpcAddress().getPort(); + } /** * Shutdown all the nodes in the cluster. diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/TestDFSUtil.java b/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/TestDFSUtil.java index a991d37c8a3..a0948e6cbf6 100644 --- a/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/TestDFSUtil.java +++ b/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/TestDFSUtil.java @@ -533,29 +533,73 @@ public class TestDFSUtil { public void testGetNNUris() throws Exception { HdfsConfiguration conf = new HdfsConfiguration(); - final String NS1_NN1_HOST = "ns1-nn1.example.com:8020"; - final String NS1_NN2_HOST = "ns1-nn1.example.com:8020"; - final String NS2_NN_HOST = "ns2-nn.example.com:8020"; - final String NN_HOST = "nn.example.com:8020"; + final String NS1_NN1_ADDR = "ns1-nn1.example.com:8020"; + final String NS1_NN2_ADDR = "ns1-nn2.example.com:8020"; + final String NS2_NN_ADDR = "ns2-nn.example.com:8020"; + final String NN1_ADDR = "nn.example.com:8020"; + final String NN1_SRVC_ADDR = "nn.example.com:8021"; + final String NN2_ADDR = "nn2.example.com:8020"; conf.set(DFS_FEDERATION_NAMESERVICES, "ns1,ns2"); conf.set(DFSUtil.addKeySuffixes(DFS_HA_NAMENODES_KEY_PREFIX, "ns1"),"nn1,nn2"); conf.set(DFSUtil.addKeySuffixes( - DFS_NAMENODE_RPC_ADDRESS_KEY, "ns1", "nn1"), NS1_NN1_HOST); + DFS_NAMENODE_RPC_ADDRESS_KEY, "ns1", "nn1"), NS1_NN1_ADDR); conf.set(DFSUtil.addKeySuffixes( - DFS_NAMENODE_RPC_ADDRESS_KEY, "ns1", "nn2"), NS1_NN2_HOST); + DFS_NAMENODE_RPC_ADDRESS_KEY, "ns1", "nn2"), NS1_NN2_ADDR); conf.set(DFSUtil.addKeySuffixes(DFS_NAMENODE_SERVICE_RPC_ADDRESS_KEY, "ns2"), - NS2_NN_HOST); + NS2_NN_ADDR); - conf.set(DFS_NAMENODE_RPC_ADDRESS_KEY, "hdfs://" + NN_HOST); + conf.set(DFS_NAMENODE_RPC_ADDRESS_KEY, "hdfs://" + NN1_ADDR); - Collection uris = DFSUtil.getNameServiceUris(conf, DFS_NAMENODE_RPC_ADDRESS_KEY, - DFS_NAMENODE_SERVICE_RPC_ADDRESS_KEY); + conf.set(CommonConfigurationKeys.FS_DEFAULT_NAME_KEY, "hdfs://" + NN2_ADDR); + + Collection uris = DFSUtil.getNameServiceUris(conf, + DFS_NAMENODE_SERVICE_RPC_ADDRESS_KEY, DFS_NAMENODE_RPC_ADDRESS_KEY); + + assertEquals(4, uris.size()); + assertTrue(uris.contains(new URI("hdfs://ns1"))); + assertTrue(uris.contains(new URI("hdfs://" + NS2_NN_ADDR))); + assertTrue(uris.contains(new URI("hdfs://" + NN1_ADDR))); + assertTrue(uris.contains(new URI("hdfs://" + NN2_ADDR))); + + // Make sure that non-HDFS URIs in fs.defaultFS don't get included. + conf.set(CommonConfigurationKeys.FS_DEFAULT_NAME_KEY, + "viewfs://vfs-name.example.com"); + + uris = DFSUtil.getNameServiceUris(conf, DFS_NAMENODE_SERVICE_RPC_ADDRESS_KEY, + DFS_NAMENODE_RPC_ADDRESS_KEY); assertEquals(3, uris.size()); assertTrue(uris.contains(new URI("hdfs://ns1"))); - assertTrue(uris.contains(new URI("hdfs://" + NS2_NN_HOST))); - assertTrue(uris.contains(new URI("hdfs://" + NN_HOST))); + assertTrue(uris.contains(new URI("hdfs://" + NS2_NN_ADDR))); + assertTrue(uris.contains(new URI("hdfs://" + NN1_ADDR))); + + // Make sure that an HA URI being the default URI doesn't result in multiple + // entries being returned. + conf.set(CommonConfigurationKeys.FS_DEFAULT_NAME_KEY, "hdfs://ns1"); + + uris = DFSUtil.getNameServiceUris(conf, DFS_NAMENODE_SERVICE_RPC_ADDRESS_KEY, + DFS_NAMENODE_RPC_ADDRESS_KEY); + + assertEquals(3, uris.size()); + assertTrue(uris.contains(new URI("hdfs://ns1"))); + assertTrue(uris.contains(new URI("hdfs://" + NS2_NN_ADDR))); + assertTrue(uris.contains(new URI("hdfs://" + NN1_ADDR))); + + // Make sure that when a service RPC address is used that is distinct from + // the client RPC address, and that client RPC address is also used as the + // default URI, that the client URI does not end up in the set of URIs + // returned. + conf = new HdfsConfiguration(); + conf.set(CommonConfigurationKeys.FS_DEFAULT_NAME_KEY, "hdfs://" + NN1_ADDR); + conf.set(DFS_NAMENODE_RPC_ADDRESS_KEY, NN1_ADDR); + conf.set(DFS_NAMENODE_SERVICE_RPC_ADDRESS_KEY, NN1_SRVC_ADDR); + + uris = DFSUtil.getNameServiceUris(conf, DFS_NAMENODE_SERVICE_RPC_ADDRESS_KEY, + DFS_NAMENODE_RPC_ADDRESS_KEY); + + assertEquals(1, uris.size()); + assertTrue(uris.contains(new URI("hdfs://" + NN1_SRVC_ADDR))); } }