|
@@ -29,8 +29,10 @@ import org.apache.hadoop.hdfs.MiniDFSCluster;
|
|
|
import org.apache.hadoop.hdfs.MiniDFSNNTopology;
|
|
|
import org.apache.hadoop.hdfs.protocol.DatanodeInfo;
|
|
|
import org.apache.hadoop.hdfs.protocol.HdfsConstants.SafeModeAction;
|
|
|
+import org.apache.hadoop.hdfs.server.blockmanagement.CombinedHostFileManager;
|
|
|
import org.apache.hadoop.hdfs.server.blockmanagement.DatanodeDescriptor;
|
|
|
import org.apache.hadoop.hdfs.server.blockmanagement.DatanodeManager;
|
|
|
+import org.apache.hadoop.hdfs.server.blockmanagement.HostConfigManager;
|
|
|
import org.apache.hadoop.hdfs.server.datanode.DataNode;
|
|
|
import org.apache.hadoop.hdfs.server.namenode.ha.HATestUtil;
|
|
|
import org.apache.hadoop.hdfs.server.namenode.top.TopConf;
|
|
@@ -38,10 +40,13 @@ import org.apache.hadoop.hdfs.util.HostsFileWriter;
|
|
|
import org.apache.hadoop.io.nativeio.NativeIO;
|
|
|
import org.apache.hadoop.io.nativeio.NativeIO.POSIX.NoMlockCacheManipulator;
|
|
|
import org.apache.hadoop.net.ServerSocketUtil;
|
|
|
+import org.apache.hadoop.util.Time;
|
|
|
import org.apache.hadoop.util.VersionInfo;
|
|
|
import org.codehaus.jackson.map.ObjectMapper;
|
|
|
import org.junit.Test;
|
|
|
import org.mortbay.util.ajax.JSON;
|
|
|
+import org.slf4j.Logger;
|
|
|
+import org.slf4j.LoggerFactory;
|
|
|
|
|
|
import javax.management.MBeanServer;
|
|
|
import javax.management.ObjectName;
|
|
@@ -51,6 +56,7 @@ import java.net.BindException;
|
|
|
import java.net.URI;
|
|
|
import java.util.ArrayList;
|
|
|
import java.util.Collection;
|
|
|
+import java.util.HashMap;
|
|
|
import java.util.List;
|
|
|
import java.util.Map;
|
|
|
import java.util.concurrent.TimeUnit;
|
|
@@ -67,6 +73,9 @@ import static org.junit.Assert.fail;
|
|
|
*/
|
|
|
public class TestNameNodeMXBean {
|
|
|
|
|
|
+ private static final Logger LOG =
|
|
|
+ LoggerFactory.getLogger(TestNameNodeMXBean.class);
|
|
|
+
|
|
|
/**
|
|
|
* Used to assert equality between doubles
|
|
|
*/
|
|
@@ -167,10 +176,10 @@ public class TestNameNodeMXBean {
|
|
|
assertFalse(xferAddr.equals(dnXferAddrInMaintenance) ^ inMaintenance);
|
|
|
}
|
|
|
assertEquals(fsn.getLiveNodes(), alivenodeinfo);
|
|
|
- // get attribute deadnodeinfo
|
|
|
- String deadnodeinfo = (String) (mbs.getAttribute(mxbeanName,
|
|
|
+ // get attributes DeadNodes
|
|
|
+ String deadNodeInfo = (String) (mbs.getAttribute(mxbeanName,
|
|
|
"DeadNodes"));
|
|
|
- assertEquals(fsn.getDeadNodes(), deadnodeinfo);
|
|
|
+ assertEquals(fsn.getDeadNodes(), deadNodeInfo);
|
|
|
// get attribute NodeUsage
|
|
|
String nodeUsage = (String) (mbs.getAttribute(mxbeanName,
|
|
|
"NodeUsage"));
|
|
@@ -282,16 +291,16 @@ public class TestNameNodeMXBean {
|
|
|
Uninterruptibles.sleepUninterruptibly(1, TimeUnit.SECONDS);
|
|
|
}
|
|
|
|
|
|
- // get attribute deadnodeinfo
|
|
|
- String deadnodeinfo = (String) (mbs.getAttribute(mxbeanName,
|
|
|
+ // get attribute DeadNodes
|
|
|
+ String deadNodeInfo = (String) (mbs.getAttribute(mxbeanName,
|
|
|
"DeadNodes"));
|
|
|
- assertEquals(fsn.getDeadNodes(), deadnodeinfo);
|
|
|
+ assertEquals(fsn.getDeadNodes(), deadNodeInfo);
|
|
|
Map<String, Map<String, Object>> deadNodes =
|
|
|
- (Map<String, Map<String, Object>>) JSON.parse(deadnodeinfo);
|
|
|
+ (Map<String, Map<String, Object>>) JSON.parse(deadNodeInfo);
|
|
|
assertTrue(deadNodes.size() > 0);
|
|
|
for (Map<String, Object> deadNode : deadNodes.values()) {
|
|
|
assertTrue(deadNode.containsKey("lastContact"));
|
|
|
- assertTrue(deadNode.containsKey("decommissioned"));
|
|
|
+ assertTrue(deadNode.containsKey("adminState"));
|
|
|
assertTrue(deadNode.containsKey("xferaddr"));
|
|
|
}
|
|
|
} finally {
|
|
@@ -302,6 +311,106 @@ public class TestNameNodeMXBean {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ @Test (timeout = 120000)
|
|
|
+ public void testMaintenanceNodes() throws Exception {
|
|
|
+ LOG.info("Starting testMaintenanceNodes");
|
|
|
+ int expirationInMs = 30 * 1000;
|
|
|
+ Configuration conf = new Configuration();
|
|
|
+ conf.setInt(DFSConfigKeys.DFS_HEARTBEAT_INTERVAL_KEY, 1);
|
|
|
+ conf.setInt(DFSConfigKeys.DFS_NAMENODE_HEARTBEAT_RECHECK_INTERVAL_KEY,
|
|
|
+ expirationInMs);
|
|
|
+ conf.setClass(DFSConfigKeys.DFS_NAMENODE_HOSTS_PROVIDER_CLASSNAME_KEY,
|
|
|
+ CombinedHostFileManager.class, HostConfigManager.class);
|
|
|
+ MiniDFSCluster cluster = null;
|
|
|
+ HostsFileWriter hostsFileWriter = new HostsFileWriter();
|
|
|
+ hostsFileWriter.initialize(conf, "temp/TestNameNodeMXBean");
|
|
|
+
|
|
|
+ try {
|
|
|
+ cluster = new MiniDFSCluster.Builder(conf).numDataNodes(3).build();
|
|
|
+ cluster.waitActive();
|
|
|
+
|
|
|
+ FSNamesystem fsn = cluster.getNameNode().namesystem;
|
|
|
+ MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
|
|
|
+ ObjectName mxbeanName = new ObjectName(
|
|
|
+ "Hadoop:service=NameNode,name=NameNodeInfo");
|
|
|
+
|
|
|
+ List<String> hosts = new ArrayList<>();
|
|
|
+ for(DataNode dn : cluster.getDataNodes()) {
|
|
|
+ hosts.add(dn.getDisplayName());
|
|
|
+ }
|
|
|
+ hostsFileWriter.initIncludeHosts(hosts.toArray(
|
|
|
+ new String[hosts.size()]));
|
|
|
+ fsn.getBlockManager().getDatanodeManager().refreshNodes(conf);
|
|
|
+
|
|
|
+ // 1. Verify nodes for DatanodeReportType.LIVE state
|
|
|
+ String liveNodesInfo = (String) (mbs.getAttribute(mxbeanName,
|
|
|
+ "LiveNodes"));
|
|
|
+ LOG.info("Live Nodes: " + liveNodesInfo);
|
|
|
+ Map<String, Map<String, Object>> liveNodes =
|
|
|
+ (Map<String, Map<String, Object>>) JSON.parse(liveNodesInfo);
|
|
|
+ assertEquals(fsn.getLiveNodes(), liveNodesInfo);
|
|
|
+ assertEquals(fsn.getNumLiveDataNodes(), liveNodes.size());
|
|
|
+
|
|
|
+ for (Map<String, Object> liveNode : liveNodes.values()) {
|
|
|
+ assertTrue(liveNode.containsKey("lastContact"));
|
|
|
+ assertTrue(liveNode.containsKey("xferaddr"));
|
|
|
+ }
|
|
|
+
|
|
|
+ // Add the 1st DataNode to Maintenance list
|
|
|
+ Map<String, Long> maintenanceNodes = new HashMap<>();
|
|
|
+ maintenanceNodes.put(cluster.getDataNodes().get(0).getDisplayName(),
|
|
|
+ Time.monotonicNow() + expirationInMs);
|
|
|
+ hostsFileWriter.initOutOfServiceHosts(null, maintenanceNodes);
|
|
|
+ fsn.getBlockManager().getDatanodeManager().refreshNodes(conf);
|
|
|
+
|
|
|
+ boolean recheck = true;
|
|
|
+ while (recheck) {
|
|
|
+ // 2. Verify nodes for DatanodeReportType.ENTERING_MAINTENANCE state
|
|
|
+ String enteringMaintenanceNodesInfo =
|
|
|
+ (String) (mbs.getAttribute(mxbeanName, "EnteringMaintenanceNodes"));
|
|
|
+ Map<String, Map<String, Object>> enteringMaintenanceNodes =
|
|
|
+ (Map<String, Map<String, Object>>) JSON.parse(
|
|
|
+ enteringMaintenanceNodesInfo);
|
|
|
+ if (enteringMaintenanceNodes.size() <= 0) {
|
|
|
+ LOG.info("Waiting for a node to Enter Maintenance state!");
|
|
|
+ Uninterruptibles.sleepUninterruptibly(1, TimeUnit.SECONDS);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ LOG.info("Nodes entering Maintenance: " + enteringMaintenanceNodesInfo);
|
|
|
+ recheck = false;
|
|
|
+ assertEquals(fsn.getEnteringMaintenanceNodes(),
|
|
|
+ enteringMaintenanceNodesInfo);
|
|
|
+ assertEquals(fsn.getNumEnteringMaintenanceDataNodes(),
|
|
|
+ enteringMaintenanceNodes.size());
|
|
|
+ assertEquals(0, fsn.getNumInMaintenanceLiveDataNodes());
|
|
|
+ assertEquals(0, fsn.getNumInMaintenanceDeadDataNodes());
|
|
|
+ }
|
|
|
+
|
|
|
+ // Wait for the DecommissionManager to complete check
|
|
|
+ // and perform state transition
|
|
|
+ while (fsn.getNumInMaintenanceLiveDataNodes() != 1) {
|
|
|
+ Uninterruptibles.sleepUninterruptibly(1, TimeUnit.SECONDS);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 3. Verify nodes for AdminStates.IN_MAINTENANCE state
|
|
|
+ String enteringMaintenanceNodesInfo =
|
|
|
+ (String) (mbs.getAttribute(mxbeanName, "EnteringMaintenanceNodes"));
|
|
|
+ Map<String, Map<String, Object>> enteringMaintenanceNodes =
|
|
|
+ (Map<String, Map<String, Object>>) JSON.parse(
|
|
|
+ enteringMaintenanceNodesInfo);
|
|
|
+ assertEquals(0, enteringMaintenanceNodes.size());
|
|
|
+ assertEquals(fsn.getEnteringMaintenanceNodes(),
|
|
|
+ enteringMaintenanceNodesInfo);
|
|
|
+ assertEquals(1, fsn.getNumInMaintenanceLiveDataNodes());
|
|
|
+ assertEquals(0, fsn.getNumInMaintenanceDeadDataNodes());
|
|
|
+ } finally {
|
|
|
+ if (cluster != null) {
|
|
|
+ cluster.shutdown();
|
|
|
+ }
|
|
|
+ hostsFileWriter.cleanup();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
@Test(timeout=120000)
|
|
|
@SuppressWarnings("unchecked")
|
|
|
public void testTopUsers() throws Exception {
|