You are viewing a plain text version of this content. The canonical link for it is here.
Posted to hdfs-commits@hadoop.apache.org by el...@apache.org on 2012/02/06 09:25:53 UTC

svn commit: r1240917 - in /hadoop/common/branches/HDFS-1623/hadoop-hdfs-project/hadoop-hdfs: ./ src/main/java/org/apache/hadoop/hdfs/ src/main/java/org/apache/hadoop/hdfs/server/namenode/ src/test/java/org/apache/hadoop/hdfs/ src/test/java/org/apache/h...

Author: eli
Date: Mon Feb  6 08:25:52 2012
New Revision: 1240917

URL: http://svn.apache.org/viewvc?rev=1240917&view=rev
Log:
HDFS-2894. HA: automatically determine the nameservice Id if only one nameservice is configured. Contributed by Eli Collins

Modified:
    hadoop/common/branches/HDFS-1623/hadoop-hdfs-project/hadoop-hdfs/CHANGES.HDFS-1623.txt
    hadoop/common/branches/HDFS-1623/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/DFSUtil.java
    hadoop/common/branches/HDFS-1623/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/SecondaryNameNode.java
    hadoop/common/branches/HDFS-1623/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/TestDFSUtil.java
    hadoop/common/branches/HDFS-1623/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/namenode/ha/TestHAConfiguration.java

Modified: hadoop/common/branches/HDFS-1623/hadoop-hdfs-project/hadoop-hdfs/CHANGES.HDFS-1623.txt
URL: http://svn.apache.org/viewvc/hadoop/common/branches/HDFS-1623/hadoop-hdfs-project/hadoop-hdfs/CHANGES.HDFS-1623.txt?rev=1240917&r1=1240916&r2=1240917&view=diff
==============================================================================
--- hadoop/common/branches/HDFS-1623/hadoop-hdfs-project/hadoop-hdfs/CHANGES.HDFS-1623.txt (original)
+++ hadoop/common/branches/HDFS-1623/hadoop-hdfs-project/hadoop-hdfs/CHANGES.HDFS-1623.txt Mon Feb  6 08:25:52 2012
@@ -172,3 +172,5 @@ HDFS-2808. HA: haadmin should use nameno
 HDFS-2819. Document new HA-related configs in hdfs-default.xml. (eli)
 
 HDFS-2752. HA: exit if multiple shared dirs are configured. (eli)
+
+HDFS-2894. HA: automatically determine the nameservice Id if only one nameservice is configured. (eli)

Modified: hadoop/common/branches/HDFS-1623/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/DFSUtil.java
URL: http://svn.apache.org/viewvc/hadoop/common/branches/HDFS-1623/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/DFSUtil.java?rev=1240917&r1=1240916&r2=1240917&view=diff
==============================================================================
--- hadoop/common/branches/HDFS-1623/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/DFSUtil.java (original)
+++ hadoop/common/branches/HDFS-1623/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/DFSUtil.java Mon Feb  6 08:25:52 2012
@@ -907,9 +907,10 @@ public class DFSUtil {
    * the address of the local node. 
    * 
    * If {@link DFSConfigKeys#DFS_FEDERATION_NAMESERVICE_ID} is not specifically
-   * configured, this method determines the nameservice Id by matching the local
-   * node's address with the configured addresses. When a match is found, it
-   * returns the nameservice Id from the corresponding configuration key.
+   * configured, and more than one nameservice Id is configured, this method 
+   * determines the nameservice Id by matching the local node's address with the
+   * configured addresses. When a match is found, it returns the nameservice Id
+   * from the corresponding configuration key.
    * 
    * @param conf Configuration
    * @param addressKey configuration key to get the address.
@@ -921,6 +922,10 @@ public class DFSUtil {
     if (nameserviceId != null) {
       return nameserviceId;
     }
+    Collection<String> nsIds = getNameServiceIds(conf);
+    if (1 == nsIds.size()) {
+      return nsIds.toArray(new String[1])[0];
+    }
     String nnId = conf.get(DFS_HA_NAMENODE_ID_KEY);
     
     return getSuffixIDs(conf, addressKey, null, nnId, LOCAL_ADDRESS_MATCHER)[0];
@@ -1057,11 +1062,11 @@ public class DFSUtil {
 
     if (nsId == null) {
       Collection<String> nsIds = getNameServiceIds(conf);
-      if (nsIds.size() != 1) {
+      if (1 == nsIds.size()) {
+        nsId = nsIds.toArray(new String[1])[0];
+      } else {
         // No nameservice ID was given and more than one is configured
         return null;
-      } else {
-        nsId = nsIds.toArray(new String[1])[0];
       }
     }
 

Modified: hadoop/common/branches/HDFS-1623/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/SecondaryNameNode.java
URL: http://svn.apache.org/viewvc/hadoop/common/branches/HDFS-1623/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/SecondaryNameNode.java?rev=1240917&r1=1240916&r2=1240917&view=diff
==============================================================================
--- hadoop/common/branches/HDFS-1623/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/SecondaryNameNode.java (original)
+++ hadoop/common/branches/HDFS-1623/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/SecondaryNameNode.java Mon Feb  6 08:25:52 2012
@@ -47,7 +47,6 @@ import static org.apache.hadoop.hdfs.DFS
 import org.apache.hadoop.hdfs.DFSUtil;
 import org.apache.hadoop.hdfs.HAUtil;
 import org.apache.hadoop.hdfs.DFSUtil.ErrorSimulator;
-import org.apache.hadoop.hdfs.HAUtil;
 import org.apache.hadoop.hdfs.HdfsConfiguration;
 import org.apache.hadoop.hdfs.protocol.HdfsConstants;
 import org.apache.hadoop.hdfs.protocolPB.NamenodeProtocolTranslatorPB;
@@ -170,20 +169,17 @@ public class SecondaryNameNode implement
     try {
       String nsId = DFSUtil.getSecondaryNameServiceId(conf);
       if (HAUtil.isHAEnabled(conf, nsId)) {
-        LOG.fatal("Cannot use SecondaryNameNode in an HA cluster." +
+        throw new IOException(
+            "Cannot use SecondaryNameNode in an HA cluster." +
             " The Standby Namenode will perform checkpointing.");
-        shutdown();
-        return;
       }
       NameNode.initializeGenericKeys(conf, nsId, null);
       initialize(conf, commandLineOpts);
-    } catch(IOException e) {
+    } catch (IOException e) {
       shutdown();
-      LOG.fatal("Failed to start secondary namenode. ", e);
       throw e;
-    } catch(HadoopIllegalArgumentException e) {
+    } catch (HadoopIllegalArgumentException e) {
       shutdown();
-      LOG.fatal("Failed to start secondary namenode. ", e);
       throw e;
     }
   }
@@ -335,7 +331,6 @@ public class SecondaryNameNode implement
   // The main work loop
   //
   public void doWork() {
-
     //
     // Poll the Namenode (once every checkpointCheckPeriod seconds) to find the
     // number of transactions in the edit log that haven't yet been checkpointed.
@@ -612,7 +607,13 @@ public class SecondaryNameNode implement
     
     StringUtils.startupShutdownMessage(SecondaryNameNode.class, argv, LOG);
     Configuration tconf = new HdfsConfiguration();
-    SecondaryNameNode secondary = new SecondaryNameNode(tconf, opts);
+    SecondaryNameNode secondary = null;
+    try {
+      secondary = new SecondaryNameNode(tconf, opts);
+    } catch (IOException ioe) {
+      LOG.fatal("Failed to start secondary namenode", ioe);
+      System.exit(-1);
+    }
 
     if (opts.getCommand() != null) {
       int ret = secondary.processStartupCommand(opts);

Modified: hadoop/common/branches/HDFS-1623/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/TestDFSUtil.java
URL: http://svn.apache.org/viewvc/hadoop/common/branches/HDFS-1623/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/TestDFSUtil.java?rev=1240917&r1=1240916&r2=1240917&view=diff
==============================================================================
--- hadoop/common/branches/HDFS-1623/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/TestDFSUtil.java (original)
+++ hadoop/common/branches/HDFS-1623/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/TestDFSUtil.java Mon Feb  6 08:25:52 2012
@@ -214,6 +214,10 @@ public class TestDFSUtil {
     checkNameServiceId(conf, NN1_ADDRESS, "nn1");
     checkNameServiceId(conf, NN2_ADDRESS, "nn2");
     checkNameServiceId(conf, NN3_ADDRESS, null);
+
+    // HA is not enabled in a purely federated config
+    assertFalse(HAUtil.isHAEnabled(conf, "nn1"));
+    assertFalse(HAUtil.isHAEnabled(conf, "nn2"));
   }
 
   public void checkNameServiceId(Configuration conf, String addr,
@@ -399,8 +403,10 @@ public class TestDFSUtil {
     
     Map<String, Map<String, InetSocketAddress>> map =
       DFSUtil.getHaNnRpcAddresses(conf);
-    System.err.println("TestHANameNodesWithFederation:\n" +
-        DFSUtil.addressMapToString(map));
+
+    assertTrue(HAUtil.isHAEnabled(conf, "ns1"));
+    assertTrue(HAUtil.isHAEnabled(conf, "ns2"));
+    assertFalse(HAUtil.isHAEnabled(conf, "ns3"));
     
     assertEquals(NS1_NN1_HOST, map.get("ns1").get("ns1-nn1").toString());
     assertEquals(NS1_NN2_HOST, map.get("ns1").get("ns1-nn2").toString());
@@ -414,9 +420,13 @@ public class TestDFSUtil {
     assertEquals(NS2_NN1_HOST, 
         DFSUtil.getNamenodeServiceAddr(conf, "ns2", "ns2-nn1"));
 
-    // No nameservice was given and we can't determine which to use
-    // as two nameservices could share a namenode ID.
+    // No nameservice was given and we can't determine which service addr
+    // to use as two nameservices could share a namenode ID.
     assertEquals(null, DFSUtil.getNamenodeServiceAddr(conf, null, "ns1-nn1"));
+
+    // Ditto for nameservice IDs, if multiple are defined
+    assertEquals(null, DFSUtil.getNamenodeNameServiceId(conf));
+    assertEquals(null, DFSUtil.getSecondaryNameServiceId(conf));
   }
 
   @Test
@@ -453,6 +463,10 @@ public class TestDFSUtil {
 
     assertEquals(NS1_NN1_HOST_SVC, DFSUtil.getNamenodeServiceAddr(conf, null, "nn1"));
     assertEquals(NS1_NN2_HOST_SVC, DFSUtil.getNamenodeServiceAddr(conf, null, "nn2"));
+
+    // We can determine the nameservice ID, there's only one listed
+    assertEquals("ns1", DFSUtil.getNamenodeNameServiceId(conf));
+    assertEquals("ns1", DFSUtil.getSecondaryNameServiceId(conf));
   }
 
   @Test

Modified: hadoop/common/branches/HDFS-1623/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/namenode/ha/TestHAConfiguration.java
URL: http://svn.apache.org/viewvc/hadoop/common/branches/HDFS-1623/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/namenode/ha/TestHAConfiguration.java?rev=1240917&r1=1240916&r2=1240917&view=diff
==============================================================================
--- hadoop/common/branches/HDFS-1623/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/namenode/ha/TestHAConfiguration.java (original)
+++ hadoop/common/branches/HDFS-1623/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/namenode/ha/TestHAConfiguration.java Mon Feb  6 08:25:52 2012
@@ -29,6 +29,7 @@ import org.apache.hadoop.hdfs.DFSConfigK
 import org.apache.hadoop.hdfs.DFSUtil;
 import org.apache.hadoop.hdfs.server.namenode.FSNamesystem;
 import org.apache.hadoop.hdfs.server.namenode.NameNode;
+import org.apache.hadoop.hdfs.server.namenode.SecondaryNameNode;
 import org.apache.hadoop.test.GenericTestUtils;
 import org.junit.Test;
 import org.mockito.Mockito;
@@ -39,16 +40,13 @@ import org.mockito.Mockito;
  * which don't start daemons.
  */
 public class TestHAConfiguration {
-  private static final String NSID = "ns1";
-  private static String HOST_A = "1.2.3.1";
-  private static String HOST_B = "1.2.3.2";
 
   private FSNamesystem fsn = Mockito.mock(FSNamesystem.class);
-  private Configuration conf = new Configuration();
 
   @Test
   public void testCheckpointerValidityChecks() throws Exception {
     try {
+      Configuration conf = new Configuration();
       new StandbyCheckpointer(conf, fsn);
       fail("Bad config did not throw an error");
     } catch (IllegalArgumentException iae) {
@@ -56,30 +54,37 @@ public class TestHAConfiguration {
           "Invalid URI for NameNode address", iae);
     }
   }
-  
-  @Test
-  public void testGetOtherNNHttpAddress() {
-    conf.set(DFSConfigKeys.DFS_FEDERATION_NAMESERVICES, NSID);    
-    conf.set(DFSConfigKeys.DFS_FEDERATION_NAMESERVICE_ID, NSID);
+
+  private Configuration getHAConf(String nsId, String host1, String host2) {
+    Configuration conf = new Configuration();
+    conf.set(DFSConfigKeys.DFS_FEDERATION_NAMESERVICES, nsId);    
     conf.set(DFSUtil.addKeySuffixes(
-        DFSConfigKeys.DFS_HA_NAMENODES_KEY_PREFIX, NSID),
+        DFSConfigKeys.DFS_HA_NAMENODES_KEY_PREFIX, nsId),
         "nn1,nn2");    
     conf.set(DFSConfigKeys.DFS_HA_NAMENODE_ID_KEY, "nn1");
     conf.set(DFSUtil.addKeySuffixes(
-            DFSConfigKeys.DFS_NAMENODE_RPC_ADDRESS_KEY,
-            NSID, "nn1"),
-        HOST_A + ":12345");
+        DFSConfigKeys.DFS_NAMENODE_RPC_ADDRESS_KEY, nsId, "nn1"),
+        host1 + ":12345");
     conf.set(DFSUtil.addKeySuffixes(
-            DFSConfigKeys.DFS_NAMENODE_RPC_ADDRESS_KEY,
-            NSID, "nn2"),
-        HOST_B + ":12345");
-    NameNode.initializeGenericKeys(conf, NSID, "nn1");
+        DFSConfigKeys.DFS_NAMENODE_RPC_ADDRESS_KEY, nsId, "nn2"),
+        host2 + ":12345");
+    return conf;
+  }
+
+  @Test
+  public void testGetOtherNNHttpAddress() {
+    // Use non-local addresses to avoid host address matching
+    Configuration conf = getHAConf("ns1", "1.2.3.1", "1.2.3.2");
+    conf.set(DFSConfigKeys.DFS_FEDERATION_NAMESERVICE_ID, "ns1");
+
+    // This is done by the NN before the StandbyCheckpointer is created
+    NameNode.initializeGenericKeys(conf, "ns1", "nn1");
 
     // Since we didn't configure the HTTP address, and the default is
-    // 0.0.0.0, it should substitute the address from the RPC configuratoin
+    // 0.0.0.0, it should substitute the address from the RPC configuration
     // above.
     StandbyCheckpointer checkpointer = new StandbyCheckpointer(conf, fsn);
-    assertEquals(HOST_B + ":" + DFSConfigKeys.DFS_NAMENODE_HTTP_PORT_DEFAULT,
+    assertEquals("1.2.3.2:" + DFSConfigKeys.DFS_NAMENODE_HTTP_PORT_DEFAULT,
         checkpointer.getActiveNNAddress());
   }
   
@@ -89,14 +94,33 @@ public class TestHAConfiguration {
    */
   @Test
   public void testHAUniqueEditDirs() throws IOException {
-    Configuration config = new Configuration();
+    Configuration conf = new Configuration();
 
-    config.set(DFS_NAMENODE_EDITS_DIR_KEY, "file://edits/dir, "
+    conf.set(DFS_NAMENODE_EDITS_DIR_KEY, "file://edits/dir, "
         + "file://edits/shared/dir"); // overlapping
-    config.set(DFS_NAMENODE_SHARED_EDITS_DIR_KEY, "file://edits/shared/dir");
+    conf.set(DFS_NAMENODE_SHARED_EDITS_DIR_KEY, "file://edits/shared/dir");
 
     // getNamespaceEditsDirs removes duplicates across edits and shared.edits
-    Collection<URI> editsDirs = FSNamesystem.getNamespaceEditsDirs(config);
+    Collection<URI> editsDirs = FSNamesystem.getNamespaceEditsDirs(conf);
     assertEquals(2, editsDirs.size());
   }
+  
+  /**
+   * Test that the 2NN does not start if given a config with HA NNs.
+   */
+  @Test
+  public void testSecondaryNameNodeDoesNotStart() throws IOException {
+    // Note we're not explicitly setting the nameservice Id in the
+    // config as it is not required to be set and we want to test
+    // that we can determine if HA is enabled when the nameservice Id
+    // is not explicitly defined.
+    Configuration conf = getHAConf("ns1", "1.2.3.1", "1.2.3.2");
+    try {
+      new SecondaryNameNode(conf);
+      fail("Created a 2NN with an HA config");
+    } catch (IOException ioe) {
+      GenericTestUtils.assertExceptionContains(
+          "Cannot use SecondaryNameNode in an HA cluster", ioe);
+    }
+  }
 }