|
@@ -39,7 +39,14 @@ import java.util.Map;
|
|
|
import java.util.Set;
|
|
|
import java.util.concurrent.CountDownLatch;
|
|
|
import java.util.concurrent.TimeUnit;
|
|
|
-
|
|
|
+import javax.xml.parsers.DocumentBuilderFactory;
|
|
|
+import javax.xml.transform.Transformer;
|
|
|
+import javax.xml.transform.TransformerFactory;
|
|
|
+import javax.xml.transform.dom.DOMSource;
|
|
|
+import javax.xml.transform.stream.StreamResult;
|
|
|
+import javax.xml.transform.OutputKeys;
|
|
|
+
|
|
|
+import org.apache.commons.lang3.tuple.Pair;
|
|
|
import org.apache.hadoop.conf.Configuration;
|
|
|
import org.apache.hadoop.io.IOUtils;
|
|
|
import org.apache.hadoop.metrics2.MetricsSystem;
|
|
@@ -99,14 +106,19 @@ import org.apache.hadoop.yarn.util.YarnVersionInfo;
|
|
|
import org.junit.After;
|
|
|
import org.junit.Assert;
|
|
|
import org.junit.Test;
|
|
|
+import org.w3c.dom.Document;
|
|
|
+import org.w3c.dom.Element;
|
|
|
|
|
|
public class TestResourceTrackerService extends NodeLabelTestBase {
|
|
|
|
|
|
private final static File TEMP_DIR = new File(System.getProperty(
|
|
|
"test.build.data", "/tmp"), "decommision");
|
|
|
- private final File hostFile = new File(TEMP_DIR + File.separator + "hostFile.txt");
|
|
|
+ private final File hostFile =
|
|
|
+ new File(TEMP_DIR + File.separator + "hostFile.txt");
|
|
|
private final File excludeHostFile = new File(TEMP_DIR + File.separator +
|
|
|
"excludeHostFile.txt");
|
|
|
+ private final File excludeHostXmlFile =
|
|
|
+ new File(TEMP_DIR + File.separator + "excludeHostFile.xml");
|
|
|
|
|
|
private MockRM rm;
|
|
|
|
|
@@ -291,6 +303,67 @@ public class TestResourceTrackerService extends NodeLabelTestBase {
|
|
|
Assert.assertEquals(NodeAction.SHUTDOWN, nodeHeartbeat3.getNodeAction());
|
|
|
}
|
|
|
|
|
|
+ @Test
|
|
|
+ public void testGracefulDecommissionDefaultTimeoutResolution()
|
|
|
+ throws Exception {
|
|
|
+ Configuration conf = new Configuration();
|
|
|
+ conf.set(YarnConfiguration.RM_NODES_EXCLUDE_FILE_PATH, excludeHostXmlFile
|
|
|
+ .getAbsolutePath());
|
|
|
+
|
|
|
+ writeToHostsXmlFile(excludeHostXmlFile, Pair.of("", null));
|
|
|
+ rm = new MockRM(conf);
|
|
|
+ rm.start();
|
|
|
+
|
|
|
+ int nodeMemory = 1024;
|
|
|
+ MockNM nm1 = rm.registerNode("host1:1234", nodeMemory);
|
|
|
+ MockNM nm2 = rm.registerNode("host2:5678", nodeMemory);
|
|
|
+ MockNM nm3 = rm.registerNode("host3:9101", nodeMemory);
|
|
|
+
|
|
|
+ NodeHeartbeatResponse nodeHeartbeat1 = nm1.nodeHeartbeat(true);
|
|
|
+ NodeHeartbeatResponse nodeHeartbeat2 = nm2.nodeHeartbeat(true);
|
|
|
+ NodeHeartbeatResponse nodeHeartbeat3 = nm3.nodeHeartbeat(true);
|
|
|
+
|
|
|
+ Assert.assertTrue(
|
|
|
+ NodeAction.NORMAL.equals(nodeHeartbeat1.getNodeAction()));
|
|
|
+ Assert.assertTrue(
|
|
|
+ NodeAction.NORMAL.equals(nodeHeartbeat2.getNodeAction()));
|
|
|
+ Assert.assertTrue(
|
|
|
+ NodeAction.NORMAL.equals(nodeHeartbeat3.getNodeAction()));
|
|
|
+
|
|
|
+ rm.waitForState(nm1.getNodeId(), NodeState.RUNNING);
|
|
|
+ rm.waitForState(nm2.getNodeId(), NodeState.RUNNING);
|
|
|
+ rm.waitForState(nm3.getNodeId(), NodeState.RUNNING);
|
|
|
+
|
|
|
+ // Graceful decommission both host1 and host2, with
|
|
|
+ // non default timeout for host1
|
|
|
+ final Integer nm1DecommissionTimeout = 20;
|
|
|
+ writeToHostsXmlFile(
|
|
|
+ excludeHostXmlFile,
|
|
|
+ Pair.of(nm1.getNodeId().getHost(), nm1DecommissionTimeout),
|
|
|
+ Pair.of(nm2.getNodeId().getHost(), null));
|
|
|
+ rm.getNodesListManager().refreshNodes(conf, true);
|
|
|
+ rm.waitForState(nm1.getNodeId(), NodeState.DECOMMISSIONING);
|
|
|
+ rm.waitForState(nm2.getNodeId(), NodeState.DECOMMISSIONING);
|
|
|
+ Assert.assertEquals(
|
|
|
+ nm1DecommissionTimeout, rm.getDecommissioningTimeout(nm1.getNodeId()));
|
|
|
+ Integer defaultDecTimeout =
|
|
|
+ conf.getInt(YarnConfiguration.RM_NODE_GRACEFUL_DECOMMISSION_TIMEOUT,
|
|
|
+ YarnConfiguration.DEFAULT_RM_NODE_GRACEFUL_DECOMMISSION_TIMEOUT);
|
|
|
+ Assert.assertEquals(
|
|
|
+ defaultDecTimeout, rm.getDecommissioningTimeout(nm2.getNodeId()));
|
|
|
+
|
|
|
+ // Graceful decommission host3 with a new default timeout
|
|
|
+ final Integer newDefaultDecTimeout = defaultDecTimeout + 10;
|
|
|
+ writeToHostsXmlFile(
|
|
|
+ excludeHostXmlFile, Pair.of(nm3.getNodeId().getHost(), null));
|
|
|
+ conf.setInt(YarnConfiguration.RM_NODE_GRACEFUL_DECOMMISSION_TIMEOUT,
|
|
|
+ newDefaultDecTimeout);
|
|
|
+ rm.getNodesListManager().refreshNodes(conf, true);
|
|
|
+ rm.waitForState(nm3.getNodeId(), NodeState.DECOMMISSIONING);
|
|
|
+ Assert.assertEquals(
|
|
|
+ newDefaultDecTimeout, rm.getDecommissioningTimeout(nm3.getNodeId()));
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* Graceful decommission node with running application.
|
|
|
*/
|
|
@@ -1967,16 +2040,20 @@ public class TestResourceTrackerService extends NodeLabelTestBase {
|
|
|
rm.stop();
|
|
|
}
|
|
|
|
|
|
+ private void ensureFileExists(File file) throws IOException {
|
|
|
+ if (!file.exists()) {
|
|
|
+ TEMP_DIR.mkdirs();
|
|
|
+ file.createNewFile();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
private void writeToHostsFile(String... hosts) throws IOException {
|
|
|
writeToHostsFile(hostFile, hosts);
|
|
|
}
|
|
|
|
|
|
private void writeToHostsFile(File file, String... hosts)
|
|
|
throws IOException {
|
|
|
- if (!file.exists()) {
|
|
|
- TEMP_DIR.mkdirs();
|
|
|
- file.createNewFile();
|
|
|
- }
|
|
|
+ ensureFileExists(file);
|
|
|
FileOutputStream fStream = null;
|
|
|
try {
|
|
|
fStream = new FileOutputStream(file);
|
|
@@ -1992,6 +2069,33 @@ public class TestResourceTrackerService extends NodeLabelTestBase {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ private void writeToHostsXmlFile(
|
|
|
+ File file, Pair<String, Integer>... hostsAndTimeouts) throws Exception {
|
|
|
+ ensureFileExists(file);
|
|
|
+ DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
|
|
|
+ Document doc = dbFactory.newDocumentBuilder().newDocument();
|
|
|
+ Element hosts = doc.createElement("hosts");
|
|
|
+ doc.appendChild(hosts);
|
|
|
+ for (Pair<String, Integer> hostsAndTimeout : hostsAndTimeouts) {
|
|
|
+ Element host = doc.createElement("host");
|
|
|
+ hosts.appendChild(host);
|
|
|
+ Element name = doc.createElement("name");
|
|
|
+ host.appendChild(name);
|
|
|
+ name.appendChild(doc.createTextNode(hostsAndTimeout.getLeft()));
|
|
|
+ if (hostsAndTimeout.getRight() != null) {
|
|
|
+ Element timeout = doc.createElement("timeout");
|
|
|
+ host.appendChild(timeout);
|
|
|
+ timeout.appendChild(
|
|
|
+ doc.createTextNode(hostsAndTimeout.getRight().toString())
|
|
|
+ );
|
|
|
+ }
|
|
|
+ }
|
|
|
+ TransformerFactory transformerFactory = TransformerFactory.newInstance();
|
|
|
+ Transformer transformer = transformerFactory.newTransformer();
|
|
|
+ transformer.setOutputProperty(OutputKeys.INDENT, "yes");
|
|
|
+ transformer.transform(new DOMSource(doc), new StreamResult(file));
|
|
|
+ }
|
|
|
+
|
|
|
private void checkDecommissionedNMCount(MockRM rm, int count)
|
|
|
throws InterruptedException {
|
|
|
int waitCount = 0;
|