diff --git a/hadoop-hdfs-project/hadoop-hdfs-client/src/main/java/org/apache/hadoop/hdfs/protocol/DatanodeInfo.java b/hadoop-hdfs-project/hadoop-hdfs-client/src/main/java/org/apache/hadoop/hdfs/protocol/DatanodeInfo.java index f9b71895b63..e04abdde753 100644 --- a/hadoop-hdfs-project/hadoop-hdfs-client/src/main/java/org/apache/hadoop/hdfs/protocol/DatanodeInfo.java +++ b/hadoop-hdfs-project/hadoop-hdfs-client/src/main/java/org/apache/hadoop/hdfs/protocol/DatanodeInfo.java @@ -59,7 +59,9 @@ public class DatanodeInfo extends DatanodeID implements Node { public enum AdminStates { NORMAL("In Service"), DECOMMISSION_INPROGRESS("Decommission In Progress"), - DECOMMISSIONED("Decommissioned"); + DECOMMISSIONED("Decommissioned"), + ENTERING_MAINTENANCE("Entering Maintenance"), + IN_MAINTENANCE("In Maintenance"); final String value; @@ -378,6 +380,10 @@ public String getDatanodeReport() { buffer.append("Decommissioned\n"); } else if (isDecommissionInProgress()) { buffer.append("Decommission in progress\n"); + } else if (isInMaintenance()) { + buffer.append("In maintenance\n"); + } else if (isEnteringMaintenance()) { + buffer.append("Entering maintenance\n"); } else { buffer.append("Normal\n"); } @@ -430,6 +436,10 @@ public String dumpDatanode() { buffer.append(" DD"); } else if (isDecommissionInProgress()) { buffer.append(" DP"); + } else if (isInMaintenance()) { + buffer.append(" IM"); + } else if (isEnteringMaintenance()) { + buffer.append(" EM"); } else { buffer.append(" IN"); } @@ -488,6 +498,53 @@ public void setDecommissioned() { adminState = AdminStates.DECOMMISSIONED; } + /** + * Put a node to maintenance mode. + */ + public void startMaintenance() { + adminState = AdminStates.ENTERING_MAINTENANCE; + } + + /** + * Put a node to maintenance mode. + */ + public void setInMaintenance() { + adminState = AdminStates.IN_MAINTENANCE; + } + + /** + * Take the node out of maintenance mode. + */ + public void stopMaintenance() { + adminState = null; + } + + /** + * Returns true if the node is is entering_maintenance + */ + public boolean isEnteringMaintenance() { + return adminState == AdminStates.ENTERING_MAINTENANCE; + } + + /** + * Returns true if the node is in maintenance + */ + public boolean isInMaintenance() { + return adminState == AdminStates.IN_MAINTENANCE; + } + + /** + * Returns true if the node is entering or in maintenance + */ + public boolean isMaintenance() { + return (adminState == AdminStates.ENTERING_MAINTENANCE || + adminState == AdminStates.IN_MAINTENANCE); + } + + public boolean isInService() { + return getAdminState() == AdminStates.NORMAL; + } + /** * Retrieves the admin state of this node. */ diff --git a/hadoop-hdfs-project/hadoop-hdfs-client/src/main/java/org/apache/hadoop/hdfs/protocolPB/PBHelperClient.java b/hadoop-hdfs-project/hadoop-hdfs-client/src/main/java/org/apache/hadoop/hdfs/protocolPB/PBHelperClient.java index 56ec6c01fd3..a05567bf8df 100644 --- a/hadoop-hdfs-project/hadoop-hdfs-client/src/main/java/org/apache/hadoop/hdfs/protocolPB/PBHelperClient.java +++ b/hadoop-hdfs-project/hadoop-hdfs-client/src/main/java/org/apache/hadoop/hdfs/protocolPB/PBHelperClient.java @@ -269,6 +269,10 @@ public static DatanodeInfoProto.AdminState convert( case DECOMMISSION_INPROGRESS: return DatanodeInfoProto.AdminState.DECOMMISSION_INPROGRESS; case DECOMMISSIONED: return DatanodeInfoProto.AdminState.DECOMMISSIONED; + case ENTERING_MAINTENANCE: + return DatanodeInfoProto.AdminState.ENTERING_MAINTENANCE; + case IN_MAINTENANCE: + return DatanodeInfoProto.AdminState.IN_MAINTENANCE; default: return DatanodeInfoProto.AdminState.NORMAL; } } @@ -623,6 +627,10 @@ public static AdminStates convert(AdminState adminState) { return AdminStates.DECOMMISSION_INPROGRESS; case DECOMMISSIONED: return AdminStates.DECOMMISSIONED; + case ENTERING_MAINTENANCE: + return AdminStates.ENTERING_MAINTENANCE; + case IN_MAINTENANCE: + return AdminStates.IN_MAINTENANCE; case NORMAL: default: return AdminStates.NORMAL; diff --git a/hadoop-hdfs-project/hadoop-hdfs-client/src/main/proto/hdfs.proto b/hadoop-hdfs-project/hadoop-hdfs-client/src/main/proto/hdfs.proto index 0db8a3f5084..f939ec34d23 100644 --- a/hadoop-hdfs-project/hadoop-hdfs-client/src/main/proto/hdfs.proto +++ b/hadoop-hdfs-project/hadoop-hdfs-client/src/main/proto/hdfs.proto @@ -92,6 +92,8 @@ message DatanodeInfoProto { NORMAL = 0; DECOMMISSION_INPROGRESS = 1; DECOMMISSIONED = 2; + ENTERING_MAINTENANCE = 3; + IN_MAINTENANCE = 4; } optional AdminState adminState = 10 [default = NORMAL]; diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/namenode/TestNameNodeMXBean.java b/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/namenode/TestNameNodeMXBean.java index 78cf4569873..dc8bea75db6 100644 --- a/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/namenode/TestNameNodeMXBean.java +++ b/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/namenode/TestNameNodeMXBean.java @@ -27,6 +27,7 @@ import org.apache.hadoop.hdfs.DFSTestUtil; 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.DatanodeDescriptor; import org.apache.hadoop.hdfs.server.blockmanagement.DatanodeManager; @@ -56,6 +57,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; /** @@ -93,6 +95,12 @@ public void testNameNodeMXBeanInfo() throws Exception { dd.setUpgradeDomain(upgradeDomain); String dnXferAddrWithUpgradeDomainSet = dd.getXferAddr(); + // Put the second DN to maintenance state. + DatanodeDescriptor maintenanceNode = dm.getDatanode( + cluster.getDataNodes().get(1).getDatanodeId()); + maintenanceNode.setInMaintenance(); + String dnXferAddrInMaintenance = maintenanceNode.getXferAddr(); + FSNamesystem fsn = cluster.getNameNode().namesystem; MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); @@ -151,6 +159,10 @@ public void testNameNodeMXBeanInfo() throws Exception { } else { assertTrue(liveNode.get("upgradeDomain").equals(upgradeDomain)); } + // "adminState" is set to maintenance only for the specific dn. + boolean inMaintenance = liveNode.get("adminState").equals( + DatanodeInfo.AdminStates.IN_MAINTENANCE.toString()); + assertFalse(xferAddr.equals(dnXferAddrInMaintenance) ^ inMaintenance); } assertEquals(fsn.getLiveNodes(), alivenodeinfo); // get attribute deadnodeinfo @@ -164,7 +176,8 @@ public void testNameNodeMXBeanInfo() throws Exception { // get attribute NameJournalStatus String nameJournalStatus = (String) (mbs.getAttribute(mxbeanName, "NameJournalStatus")); - assertEquals("Bad value for NameJournalStatus", fsn.getNameJournalStatus(), nameJournalStatus); + assertEquals("Bad value for NameJournalStatus", + fsn.getNameJournalStatus(), nameJournalStatus); // get attribute JournalTransactionInfo String journalTxnInfo = (String) mbs.getAttribute(mxbeanName, "JournalTransactionInfo"); @@ -172,11 +185,13 @@ public void testNameNodeMXBeanInfo() throws Exception { journalTxnInfo); // get attribute "CompileInfo" String compileInfo = (String) mbs.getAttribute(mxbeanName, "CompileInfo"); - assertEquals("Bad value for CompileInfo", fsn.getCompileInfo(), compileInfo); + assertEquals("Bad value for CompileInfo", fsn.getCompileInfo(), + compileInfo); // get attribute CorruptFiles String corruptFiles = (String) (mbs.getAttribute(mxbeanName, "CorruptFiles")); - assertEquals("Bad value for CorruptFiles", fsn.getCorruptFiles(), corruptFiles); + assertEquals("Bad value for CorruptFiles", fsn.getCorruptFiles(), + corruptFiles); // get attribute NameDirStatuses String nameDirStatuses = (String) (mbs.getAttribute(mxbeanName, "NameDirStatuses")); @@ -188,7 +203,8 @@ public void testNameNodeMXBeanInfo() throws Exception { File nameDir = new File(nameDirUri); System.out.println("Checking for the presence of " + nameDir + " in active name dirs."); - assertTrue(statusMap.get("active").containsKey(nameDir.getAbsolutePath())); + assertTrue(statusMap.get("active").containsKey( + nameDir.getAbsolutePath())); } assertEquals(2, statusMap.get("active").size()); assertEquals(0, statusMap.get("failed").size());