Return-Path: X-Original-To: apmail-hadoop-hdfs-commits-archive@minotaur.apache.org Delivered-To: apmail-hadoop-hdfs-commits-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 6CC3510A69 for ; Mon, 24 Mar 2014 22:23:01 +0000 (UTC) Received: (qmail 89210 invoked by uid 500); 24 Mar 2014 22:23:00 -0000 Delivered-To: apmail-hadoop-hdfs-commits-archive@hadoop.apache.org Received: (qmail 89169 invoked by uid 500); 24 Mar 2014 22:22:59 -0000 Mailing-List: contact hdfs-commits-help@hadoop.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: hdfs-dev@hadoop.apache.org Delivered-To: mailing list hdfs-commits@hadoop.apache.org Received: (qmail 89161 invoked by uid 99); 24 Mar 2014 22:22:59 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 24 Mar 2014 22:22:59 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 24 Mar 2014 22:22:56 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id CA4B923889E2; Mon, 24 Mar 2014 22:22:33 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1581092 - in /hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs: ./ src/main/java/org/apache/hadoop/hdfs/ src/main/java/org/apache/hadoop/hdfs/server/blockmanagement/ src/main/resources/ src/test/java/org/apache/hadoop/hdfs/s... Date: Mon, 24 Mar 2014 22:22:33 -0000 To: hdfs-commits@hadoop.apache.org From: cnauroth@apache.org X-Mailer: svnmailer-1.0.9 Message-Id: <20140324222233.CA4B923889E2@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: cnauroth Date: Mon Mar 24 22:22:33 2014 New Revision: 1581092 URL: http://svn.apache.org/r1581092 Log: HDFS-5846. Merging change r1581091 from trunk to branch-2. Added: hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/blockmanagement/UnresolvedTopologyException.java - copied unchanged from r1581091, hadoop/common/trunk/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/blockmanagement/UnresolvedTopologyException.java Modified: hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/CHANGES.txt hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/DFSConfigKeys.java hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/blockmanagement/DatanodeManager.java hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/main/resources/hdfs-default.xml hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/blockmanagement/TestDatanodeManager.java Modified: hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/CHANGES.txt URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/CHANGES.txt?rev=1581092&r1=1581091&r2=1581092&view=diff ============================================================================== --- hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/CHANGES.txt (original) +++ hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/CHANGES.txt Mon Mar 24 22:22:33 2014 @@ -441,6 +441,9 @@ Release 2.4.0 - UNRELEASED HDFS-6135. In HDFS upgrade with HA setup, JournalNode cannot handle layout version bump when rolling back. (jing9) + HDFS-5846. Assigning DEFAULT_RACK in resolveNetworkLocation method can break + data resiliency. (Nikola Vujic via cnauroth) + BREAKDOWN OF HDFS-5698 SUBTASKS AND RELATED JIRAS HDFS-5717. Save FSImage header in protobuf. (Haohui Mai via jing9) Modified: hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/DFSConfigKeys.java URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/DFSConfigKeys.java?rev=1581092&r1=1581091&r2=1581092&view=diff ============================================================================== --- hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/DFSConfigKeys.java (original) +++ hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/DFSConfigKeys.java Mon Mar 24 22:22:33 2014 @@ -612,7 +612,13 @@ public class DFSConfigKeys extends Commo public static final int DFS_HTTP_CLIENT_FAILOVER_SLEEPTIME_BASE_DEFAULT = 500; public static final String DFS_HTTP_CLIENT_FAILOVER_SLEEPTIME_MAX_KEY = "dfs.http.client.failover.sleep.max.millis"; public static final int DFS_HTTP_CLIENT_FAILOVER_SLEEPTIME_MAX_DEFAULT = 15000; - + + // Handling unresolved DN topology mapping + public static final String DFS_REJECT_UNRESOLVED_DN_TOPOLOGY_MAPPING_KEY = + "dfs.namenode.reject-unresolved-dn-topology-mapping"; + public static final boolean DFS_REJECT_UNRESOLVED_DN_TOPOLOGY_MAPPING_DEFAULT = + false; + // hedged read properties public static final String DFS_DFSCLIENT_HEDGED_READ_THRESHOLD_MILLIS = "dfs.client.hedged.read.threshold.millis"; Modified: hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/blockmanagement/DatanodeManager.java URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/blockmanagement/DatanodeManager.java?rev=1581092&r1=1581091&r2=1581092&view=diff ============================================================================== --- hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/blockmanagement/DatanodeManager.java (original) +++ hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/blockmanagement/DatanodeManager.java Mon Mar 24 22:22:33 2014 @@ -98,6 +98,7 @@ public class DatanodeManager { private final Host2NodesMap host2DatanodeMap = new Host2NodesMap(); private final DNSToSwitchMapping dnsToSwitchMapping; + private final boolean rejectUnresolvedTopologyDN; private final int defaultXferPort; @@ -201,6 +202,10 @@ public class DatanodeManager { conf.getClass(DFSConfigKeys.NET_TOPOLOGY_NODE_SWITCH_MAPPING_IMPL_KEY, ScriptBasedMapping.class, DNSToSwitchMapping.class), conf); + this.rejectUnresolvedTopologyDN = conf.getBoolean( + DFSConfigKeys.DFS_REJECT_UNRESOLVED_DN_TOPOLOGY_MAPPING_KEY, + DFSConfigKeys.DFS_REJECT_UNRESOLVED_DN_TOPOLOGY_MAPPING_DEFAULT); + // If the dns to switch mapping supports cache, resolve network // locations of those hosts in the include list and store the mapping // in the cache; so future calls to resolve will be fast. @@ -391,7 +396,8 @@ public class DatanodeManager { node = getDatanodeByHost(host); } if (node == null) { - String networkLocation = resolveNetworkLocation(dnId); + String networkLocation = + resolveNetworkLocationWithFallBackToDefaultLocation(dnId); // If the current cluster doesn't contain the node, fallback to // something machine local and then rack local. @@ -626,9 +632,36 @@ public class DatanodeManager { return new HashMap (this.datanodesSoftwareVersions); } } - - /* Resolve a node's network location */ - private String resolveNetworkLocation (DatanodeID node) { + + /** + * Resolve a node's network location. If the DNS to switch mapping fails + * then this method guarantees default rack location. + * @param node to resolve to network location + * @return network location path + */ + private String resolveNetworkLocationWithFallBackToDefaultLocation ( + DatanodeID node) { + String networkLocation; + try { + networkLocation = resolveNetworkLocation(node); + } catch (UnresolvedTopologyException e) { + LOG.error("Unresolved topology mapping. Using " + + NetworkTopology.DEFAULT_RACK + " for host " + node.getHostName()); + networkLocation = NetworkTopology.DEFAULT_RACK; + } + return networkLocation; + } + + /** + * Resolve a node's network location. If the DNS to switch mapping fails, + * then this method throws UnresolvedTopologyException. + * @param node to resolve to network location + * @return network location path. + * @throws UnresolvedTopologyException if the DNS to switch mapping fails + * to resolve network location. + */ + private String resolveNetworkLocation (DatanodeID node) + throws UnresolvedTopologyException { List names = new ArrayList(1); if (dnsToSwitchMapping instanceof CachedDNSToSwitchMapping) { names.add(node.getIpAddr()); @@ -640,9 +673,9 @@ public class DatanodeManager { List rName = dnsToSwitchMapping.resolve(names); String networkLocation; if (rName == null) { - LOG.error("The resolve call returned null! Using " + - NetworkTopology.DEFAULT_RACK + " for host " + names); - networkLocation = NetworkTopology.DEFAULT_RACK; + LOG.error("The resolve call returned null!"); + throw new UnresolvedTopologyException( + "Unresolved topology mapping for host " + node.getHostName()); } else { networkLocation = rName.get(0); } @@ -754,9 +787,11 @@ public class DatanodeManager { * @param nodeReg the datanode registration * @throws DisallowedDatanodeException if the registration request is * denied because the datanode does not match includes/excludes + * @throws UnresolvedTopologyException if the registration request is + * denied because resolving datanode network location fails. */ public void registerDatanode(DatanodeRegistration nodeReg) - throws DisallowedDatanodeException { + throws DisallowedDatanodeException, UnresolvedTopologyException { InetAddress dnAddress = Server.getRemoteIp(); if (dnAddress != null) { // Mostly called inside an RPC, update ip and peer hostname @@ -838,7 +873,13 @@ public class DatanodeManager { nodeS.setDisallowed(false); // Node is in the include list // resolve network location - nodeS.setNetworkLocation(resolveNetworkLocation(nodeS)); + if(this.rejectUnresolvedTopologyDN) + { + nodeS.setNetworkLocation(resolveNetworkLocation(nodeS)); + } else { + nodeS.setNetworkLocation( + resolveNetworkLocationWithFallBackToDefaultLocation(nodeS)); + } getNetworkTopology().add(nodeS); // also treat the registration message as a heartbeat @@ -860,7 +901,13 @@ public class DatanodeManager { = new DatanodeDescriptor(nodeReg, NetworkTopology.DEFAULT_RACK); boolean success = false; try { - nodeDescr.setNetworkLocation(resolveNetworkLocation(nodeDescr)); + // resolve network location + if(this.rejectUnresolvedTopologyDN) { + nodeDescr.setNetworkLocation(resolveNetworkLocation(nodeDescr)); + } else { + nodeDescr.setNetworkLocation( + resolveNetworkLocationWithFallBackToDefaultLocation(nodeDescr)); + } networktopology.add(nodeDescr); nodeDescr.setSoftwareVersion(nodeReg.getSoftwareVersion()); Modified: hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/main/resources/hdfs-default.xml URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/main/resources/hdfs-default.xml?rev=1581092&r1=1581091&r2=1581092&view=diff ============================================================================== --- hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/main/resources/hdfs-default.xml (original) +++ hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/main/resources/hdfs-default.xml Mon Mar 24 22:22:33 2014 @@ -1841,4 +1841,19 @@ - + + dfs.namenode.reject-unresolved-dn-topology-mapping + false + + If the value is set to true, then namenode will reject datanode + registration if the topology mapping for a datanode is not resolved and + NULL is returned (script defined by net.topology.script.file.name fails + to execute). Otherwise, datanode will be registered and the default rack + will be assigned as the topology path. Topology paths are important for + data resiliency, since they define fault domains. Thus it may be unwanted + behavior to allow datanode registration with the default rack if the + resolving topology failed. + + + + \ No newline at end of file Modified: hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/blockmanagement/TestDatanodeManager.java URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/blockmanagement/TestDatanodeManager.java?rev=1581092&r1=1581091&r2=1581092&view=diff ============================================================================== --- hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/blockmanagement/TestDatanodeManager.java (original) +++ hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/blockmanagement/TestDatanodeManager.java Mon Mar 24 22:22:33 2014 @@ -21,21 +21,29 @@ package org.apache.hadoop.hdfs.server.bl import java.io.IOException; import java.util.HashMap; import java.util.Iterator; +import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Random; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.fs.CommonConfigurationKeysPublic; +import org.apache.hadoop.hdfs.DFSConfigKeys; import org.apache.hadoop.hdfs.server.namenode.FSNamesystem; import org.apache.hadoop.hdfs.server.protocol.DatanodeRegistration; +import org.apache.hadoop.net.DNSToSwitchMapping; +import org.junit.Assert; import org.junit.Test; import org.mockito.Mockito; -import org.mortbay.log.Log; import static org.junit.Assert.*; public class TestDatanodeManager { - + + public static final Log LOG = LogFactory.getLog(TestDatanodeManager.class); + //The number of times the registration / removal of nodes should happen final int NUM_ITERATIONS = 500; @@ -57,7 +65,7 @@ public class TestDatanodeManager { Random rng = new Random(); int seed = rng.nextInt(); rng = new Random(seed); - Log.info("Using seed " + seed + " for testing"); + LOG.info("Using seed " + seed + " for testing"); //A map of the Storage IDs to the DN registration it was registered with HashMap sIdToDnReg = @@ -76,7 +84,7 @@ public class TestDatanodeManager { it.next(); } DatanodeRegistration toRemove = it.next().getValue(); - Log.info("Removing node " + toRemove.getDatanodeUuid() + " ip " + + LOG.info("Removing node " + toRemove.getDatanodeUuid() + " ip " + toRemove.getXferAddr() + " version : " + toRemove.getSoftwareVersion()); //Remove that random node @@ -110,7 +118,7 @@ public class TestDatanodeManager { Mockito.when(dr.getSoftwareVersion()).thenReturn( "version" + rng.nextInt(5)); - Log.info("Registering node storageID: " + dr.getDatanodeUuid() + + LOG.info("Registering node storageID: " + dr.getDatanodeUuid() + ", version: " + dr.getSoftwareVersion() + ", IP address: " + dr.getXferAddr()); @@ -136,7 +144,7 @@ public class TestDatanodeManager { } } for(Entry entry: mapToCheck.entrySet()) { - Log.info("Still in map: " + entry.getKey() + " has " + LOG.info("Still in map: " + entry.getKey() + " has " + entry.getValue()); } assertEquals("The map of version counts returned by DatanodeManager was" @@ -144,5 +152,62 @@ public class TestDatanodeManager { mapToCheck.size()); } } + + @Test (timeout = 100000) + public void testRejectUnresolvedDatanodes() throws IOException { + //Create the DatanodeManager which will be tested + FSNamesystem fsn = Mockito.mock(FSNamesystem.class); + Mockito.when(fsn.hasWriteLock()).thenReturn(true); + + Configuration conf = new Configuration(); + + //Set configuration property for rejecting unresolved topology mapping + conf.setBoolean( + DFSConfigKeys.DFS_REJECT_UNRESOLVED_DN_TOPOLOGY_MAPPING_KEY, true); + + //set TestDatanodeManager.MyResolver to be used for topology resolving + conf.setClass( + CommonConfigurationKeysPublic.NET_TOPOLOGY_NODE_SWITCH_MAPPING_IMPL_KEY, + TestDatanodeManager.MyResolver.class, DNSToSwitchMapping.class); + + //create DatanodeManager + DatanodeManager dm = new DatanodeManager(Mockito.mock(BlockManager.class), + fsn, conf); + + //storageID to register. + String storageID = "someStorageID-123"; + + DatanodeRegistration dr = Mockito.mock(DatanodeRegistration.class); + Mockito.when(dr.getDatanodeUuid()).thenReturn(storageID); + + try { + //Register this node + dm.registerDatanode(dr); + Assert.fail("Expected an UnresolvedTopologyException"); + } catch (UnresolvedTopologyException ute) { + LOG.info("Expected - topology is not resolved and " + + "registration is rejected."); + } catch (Exception e) { + Assert.fail("Expected an UnresolvedTopologyException"); + } + } + + /** + * MyResolver class provides resolve method which always returns null + * in order to simulate unresolved topology mapping. + */ + public static class MyResolver implements DNSToSwitchMapping { + @Override + public List resolve(List names) { + return null; + } + @Override + public void reloadCachedMappings() { + } + + @Override + public void reloadCachedMappings(List names) { + } + } }