|
@@ -25,6 +25,7 @@ import org.apache.commons.logging.Log;
|
|
|
import org.apache.commons.logging.LogFactory;
|
|
|
import org.apache.hadoop.conf.Configuration;
|
|
|
import org.apache.hadoop.fs.FileUtil;
|
|
|
+import org.apache.hadoop.fs.Path;
|
|
|
import org.apache.hadoop.yarn.conf.YarnConfiguration;
|
|
|
import org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.privileged.PrivilegedOperation;
|
|
|
import org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.privileged.PrivilegedOperationException;
|
|
@@ -42,10 +43,11 @@ import java.nio.file.Files;
|
|
|
import java.security.Permission;
|
|
|
import java.util.Collections;
|
|
|
import java.util.LinkedHashMap;
|
|
|
-import java.util.List;
|
|
|
import java.util.Map;
|
|
|
+import java.util.Set;
|
|
|
import java.util.UUID;
|
|
|
|
|
|
+import static org.junit.Assert.assertTrue;
|
|
|
import static org.mockito.Matchers.eq;
|
|
|
import static org.mockito.Mockito.mock;
|
|
|
import static org.mockito.Mockito.verify;
|
|
@@ -60,7 +62,6 @@ public class TestCGroupsHandlerImpl {
|
|
|
LogFactory.getLog(TestCGroupsHandlerImpl.class);
|
|
|
|
|
|
private PrivilegedOperationExecutor privilegedOperationExecutorMock;
|
|
|
- private Configuration conf;
|
|
|
private String tmpPath;
|
|
|
private String hierarchy;
|
|
|
private CGroupsHandler.CGroupController controller;
|
|
@@ -69,36 +70,143 @@ public class TestCGroupsHandlerImpl {
|
|
|
@Before
|
|
|
public void setup() {
|
|
|
privilegedOperationExecutorMock = mock(PrivilegedOperationExecutor.class);
|
|
|
- conf = new YarnConfiguration();
|
|
|
+
|
|
|
+ // Prepare test directory
|
|
|
tmpPath = System.getProperty("test.build.data") + "/cgroups";
|
|
|
+ File tmpDir = new File(tmpPath);
|
|
|
+ FileUtils.deleteQuietly(tmpDir);
|
|
|
+ assertTrue(tmpDir.mkdirs());
|
|
|
+
|
|
|
//no leading or trailing slashes here
|
|
|
hierarchy = "test-hadoop-yarn";
|
|
|
|
|
|
+ // Sample subsystem. Not used by all the tests
|
|
|
+ controller = CGroupsHandler.CGroupController.NET_CLS;
|
|
|
+ controllerPath =
|
|
|
+ new File(new File(tmpPath, controller.getName()), hierarchy)
|
|
|
+ .getAbsolutePath();
|
|
|
+ }
|
|
|
+
|
|
|
+ @After
|
|
|
+ public void teardown() {
|
|
|
+ FileUtil.fullyDelete(new File(tmpPath));
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Security manager simulating access denied.
|
|
|
+ */
|
|
|
+ private class MockSecurityManagerDenyWrite extends SecurityManager {
|
|
|
+ @Override
|
|
|
+ public void checkPermission(Permission perm) {
|
|
|
+ if(perm.getActions().equals("write")) {
|
|
|
+ throw new SecurityException("Mock not allowed");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Create configuration to mount cgroups that do not exist.
|
|
|
+ * @return configuration object
|
|
|
+ */
|
|
|
+ private YarnConfiguration createMountConfiguration() {
|
|
|
+ YarnConfiguration conf = new YarnConfiguration();
|
|
|
conf.set(YarnConfiguration.NM_LINUX_CONTAINER_CGROUPS_HIERARCHY, hierarchy);
|
|
|
conf.setBoolean(YarnConfiguration.NM_LINUX_CONTAINER_CGROUPS_MOUNT, true);
|
|
|
conf.set(YarnConfiguration.NM_LINUX_CONTAINER_CGROUPS_MOUNT_PATH, tmpPath);
|
|
|
- controller = CGroupsHandler.CGroupController.NET_CLS;
|
|
|
- controllerPath = new StringBuffer(tmpPath).append('/')
|
|
|
- .append(controller.getName()).append('/').append(hierarchy).toString();
|
|
|
+ return conf;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Create configuration where the cgroups are premounted.
|
|
|
+ * @param myHierarchy Yarn cgroup
|
|
|
+ * @return configuration object
|
|
|
+ */
|
|
|
+ private Configuration createNoMountConfiguration(String myHierarchy) {
|
|
|
+ Configuration confNoMount = new Configuration();
|
|
|
+ confNoMount.set(YarnConfiguration.NM_LINUX_CONTAINER_CGROUPS_HIERARCHY,
|
|
|
+ myHierarchy);
|
|
|
+ confNoMount.setBoolean(YarnConfiguration.NM_LINUX_CONTAINER_CGROUPS_MOUNT,
|
|
|
+ false);
|
|
|
+ return confNoMount;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Create an empty mtab file. No cgroups are premounted
|
|
|
+ * @return mtab file
|
|
|
+ * @throws IOException could not create file
|
|
|
+ */
|
|
|
+ private File createEmptyCgroups() throws IOException {
|
|
|
+ File emptyMtab = new File(tmpPath, "mtab");
|
|
|
+ assertTrue("New file should have been created", emptyMtab.createNewFile());
|
|
|
+ return emptyMtab;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Create simulated cgroups mount point.
|
|
|
+ * @param parentDir cgroups mount point
|
|
|
+ * @param cpuAcct simulate newer Linux behavior by mounting cpu with cpuacct
|
|
|
+ * @return simulated mtab file location
|
|
|
+ * @throws IOException mtab file was not created
|
|
|
+ */
|
|
|
+ public static File createPremountedCgroups(File parentDir, boolean cpuAcct)
|
|
|
+ throws IOException {
|
|
|
+ // Mark an empty directory called 'cp' cgroup. It is processed before 'cpu'
|
|
|
+ String cpuMtabContentMissing =
|
|
|
+ "none " + parentDir.getAbsolutePath()
|
|
|
+ + "/cp cgroup rw,relatime,cpu 0 0\n";
|
|
|
+
|
|
|
+ File cpuCgroup = new File(parentDir, "cpu");
|
|
|
+ String cpuMtabContent =
|
|
|
+ "none " + cpuCgroup.getAbsolutePath()
|
|
|
+ + " cgroup rw,relatime,cpu"
|
|
|
+ + (cpuAcct ? ",cpuacct" :"")
|
|
|
+ + " 0 0\n";
|
|
|
+ assertTrue("Directory should be created", cpuCgroup.mkdirs());
|
|
|
+
|
|
|
+ File blkioCgroup = new File(parentDir, "blkio");
|
|
|
+ String blkioMtabContent =
|
|
|
+ "none " + blkioCgroup.getAbsolutePath()
|
|
|
+ + " cgroup rw,relatime,blkio 0 0\n";
|
|
|
+ assertTrue("Directory should be created", blkioCgroup.mkdirs());
|
|
|
+
|
|
|
+ File mockMtab = new File(parentDir, UUID.randomUUID().toString());
|
|
|
+ if (!mockMtab.exists()) {
|
|
|
+ if (!mockMtab.createNewFile()) {
|
|
|
+ String message = "Could not create file " + mockMtab.getAbsolutePath();
|
|
|
+ throw new IOException(message);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ FileWriter mtabWriter = new FileWriter(mockMtab.getAbsoluteFile());
|
|
|
+ mtabWriter.write(cpuMtabContentMissing);
|
|
|
+ mtabWriter.write(cpuMtabContent);
|
|
|
+ mtabWriter.write(blkioMtabContent);
|
|
|
+ mtabWriter.close();
|
|
|
+ mockMtab.deleteOnExit();
|
|
|
+ return mockMtab;
|
|
|
}
|
|
|
|
|
|
@Test
|
|
|
- public void testMountController() {
|
|
|
- CGroupsHandler cGroupsHandler = null;
|
|
|
+ public void testMountController() throws IOException {
|
|
|
+ File parentDir = new File(tmpPath);
|
|
|
+ File cgroup = new File(parentDir, controller.getName());
|
|
|
+ assertTrue("cgroup dir should be cerated", cgroup.mkdirs());
|
|
|
//Since we enabled (deferred) cgroup controller mounting, no interactions
|
|
|
//should have occurred, with this mock
|
|
|
verifyZeroInteractions(privilegedOperationExecutorMock);
|
|
|
+ File emptyMtab = createEmptyCgroups();
|
|
|
|
|
|
try {
|
|
|
- cGroupsHandler = new CGroupsHandlerImpl(conf,
|
|
|
- privilegedOperationExecutorMock);
|
|
|
+ CGroupsHandler cGroupsHandler = new CGroupsHandlerImpl(
|
|
|
+ createMountConfiguration(),
|
|
|
+ privilegedOperationExecutorMock,
|
|
|
+ emptyMtab.getAbsolutePath());
|
|
|
PrivilegedOperation expectedOp = new PrivilegedOperation(
|
|
|
PrivilegedOperation.OperationType.MOUNT_CGROUPS);
|
|
|
//This is expected to be of the form :
|
|
|
//net_cls=<mount_path>/net_cls
|
|
|
- StringBuffer controllerKV = new StringBuffer(controller.getName())
|
|
|
- .append('=').append(tmpPath).append('/').append(controller.getName());
|
|
|
- expectedOp.appendArgs(hierarchy, controllerKV.toString());
|
|
|
+ String controllerKV = controller.getName() + "=" + tmpPath
|
|
|
+ + Path.SEPARATOR + controller.getName();
|
|
|
+ expectedOp.appendArgs(hierarchy, controllerKV);
|
|
|
|
|
|
cGroupsHandler.initializeCGroupController(controller);
|
|
|
try {
|
|
@@ -117,79 +225,90 @@ public class TestCGroupsHandlerImpl {
|
|
|
verifyNoMoreInteractions(privilegedOperationExecutorMock);
|
|
|
} catch (PrivilegedOperationException e) {
|
|
|
LOG.error("Caught exception: " + e);
|
|
|
- Assert.assertTrue("Unexpected PrivilegedOperationException from mock!",
|
|
|
+ assertTrue("Unexpected PrivilegedOperationException from mock!",
|
|
|
false);
|
|
|
}
|
|
|
} catch (ResourceHandlerException e) {
|
|
|
LOG.error("Caught exception: " + e);
|
|
|
- Assert.assertTrue("Unexpected ResourceHandler Exception!", false);
|
|
|
+ assertTrue("Unexpected ResourceHandler Exception!", false);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@Test
|
|
|
- public void testCGroupPaths() {
|
|
|
+ public void testCGroupPaths() throws IOException {
|
|
|
//As per junit behavior, we expect a new mock object to be available
|
|
|
//in this test.
|
|
|
verifyZeroInteractions(privilegedOperationExecutorMock);
|
|
|
CGroupsHandler cGroupsHandler = null;
|
|
|
+ File mtab = createEmptyCgroups();
|
|
|
+
|
|
|
+ // Lets manually create a path to (partially) simulate a controller mounted
|
|
|
+ // later in the test. This is required because the handler uses a mocked
|
|
|
+ // privileged operation executor
|
|
|
+ assertTrue("Sample subsystem should be created",
|
|
|
+ new File(controllerPath).mkdirs());
|
|
|
+
|
|
|
try {
|
|
|
- cGroupsHandler = new CGroupsHandlerImpl(conf,
|
|
|
- privilegedOperationExecutorMock);
|
|
|
+ cGroupsHandler = new CGroupsHandlerImpl(createMountConfiguration(),
|
|
|
+ privilegedOperationExecutorMock, mtab.getAbsolutePath());
|
|
|
cGroupsHandler.initializeCGroupController(controller);
|
|
|
} catch (ResourceHandlerException e) {
|
|
|
LOG.error("Caught exception: " + e);
|
|
|
- Assert.assertTrue(
|
|
|
+ assertTrue(
|
|
|
"Unexpected ResourceHandlerException when mounting controller!",
|
|
|
false);
|
|
|
}
|
|
|
|
|
|
String testCGroup = "container_01";
|
|
|
- String expectedPath = new StringBuffer(controllerPath).append('/')
|
|
|
- .append(testCGroup).toString();
|
|
|
+ String expectedPath =
|
|
|
+ controllerPath + Path.SEPARATOR + testCGroup;
|
|
|
String path = cGroupsHandler.getPathForCGroup(controller, testCGroup);
|
|
|
Assert.assertEquals(expectedPath, path);
|
|
|
|
|
|
- String expectedPathTasks = new StringBuffer(expectedPath).append('/')
|
|
|
- .append(CGroupsHandler.CGROUP_FILE_TASKS).toString();
|
|
|
+ String expectedPathTasks = expectedPath + Path.SEPARATOR
|
|
|
+ + CGroupsHandler.CGROUP_FILE_TASKS;
|
|
|
path = cGroupsHandler.getPathForCGroupTasks(controller, testCGroup);
|
|
|
Assert.assertEquals(expectedPathTasks, path);
|
|
|
|
|
|
String param = CGroupsHandler.CGROUP_PARAM_CLASSID;
|
|
|
- String expectedPathParam = new StringBuffer(expectedPath).append('/')
|
|
|
- .append(controller.getName()).append('.').append(param).toString();
|
|
|
+ String expectedPathParam = expectedPath + Path.SEPARATOR
|
|
|
+ + controller.getName() + "." + param;
|
|
|
path = cGroupsHandler.getPathForCGroupParam(controller, testCGroup, param);
|
|
|
Assert.assertEquals(expectedPathParam, path);
|
|
|
}
|
|
|
|
|
|
@Test
|
|
|
- public void testCGroupOperations() {
|
|
|
+ public void testCGroupOperations() throws IOException {
|
|
|
//As per junit behavior, we expect a new mock object to be available
|
|
|
//in this test.
|
|
|
verifyZeroInteractions(privilegedOperationExecutorMock);
|
|
|
CGroupsHandler cGroupsHandler = null;
|
|
|
+ File mtab = createEmptyCgroups();
|
|
|
+
|
|
|
+ // Lets manually create a path to (partially) simulate a controller mounted
|
|
|
+ // later in the test. This is required because the handler uses a mocked
|
|
|
+ // privileged operation executor
|
|
|
+ assertTrue("Sample subsystem should be created",
|
|
|
+ new File(controllerPath).mkdirs());
|
|
|
|
|
|
try {
|
|
|
- cGroupsHandler = new CGroupsHandlerImpl(conf,
|
|
|
- privilegedOperationExecutorMock);
|
|
|
+ cGroupsHandler = new CGroupsHandlerImpl(createMountConfiguration(),
|
|
|
+ privilegedOperationExecutorMock, mtab.getAbsolutePath());
|
|
|
cGroupsHandler.initializeCGroupController(controller);
|
|
|
} catch (ResourceHandlerException e) {
|
|
|
LOG.error("Caught exception: " + e);
|
|
|
- Assert.assertTrue(
|
|
|
+ assertTrue(
|
|
|
"Unexpected ResourceHandlerException when mounting controller!",
|
|
|
false);
|
|
|
}
|
|
|
- //Lets manually create a path to (partially) simulate a mounted controller
|
|
|
- //this is required because the handler uses a mocked privileged operation
|
|
|
- //executor
|
|
|
- new File(controllerPath).mkdirs();
|
|
|
|
|
|
String testCGroup = "container_01";
|
|
|
- String expectedPath = new StringBuffer(controllerPath).append('/')
|
|
|
- .append(testCGroup).toString();
|
|
|
+ String expectedPath = controllerPath
|
|
|
+ + Path.SEPARATOR + testCGroup;
|
|
|
try {
|
|
|
String path = cGroupsHandler.createCGroup(controller, testCGroup);
|
|
|
|
|
|
- Assert.assertTrue(new File(expectedPath).exists());
|
|
|
+ assertTrue(new File(expectedPath).exists());
|
|
|
Assert.assertEquals(expectedPath, path);
|
|
|
|
|
|
//update param and read param tests.
|
|
@@ -202,11 +321,12 @@ public class TestCGroupsHandlerImpl {
|
|
|
|
|
|
cGroupsHandler
|
|
|
.updateCGroupParam(controller, testCGroup, param, paramValue);
|
|
|
- String paramPath = new StringBuffer(expectedPath).append('/')
|
|
|
- .append(controller.getName()).append('.').append(param).toString();
|
|
|
+ String paramPath = expectedPath
|
|
|
+ + Path.SEPARATOR + controller.getName()
|
|
|
+ + "." + param;
|
|
|
File paramFile = new File(paramPath);
|
|
|
|
|
|
- Assert.assertTrue(paramFile.exists());
|
|
|
+ assertTrue(paramFile.exists());
|
|
|
try {
|
|
|
Assert.assertEquals(paramValue, new String(Files.readAllBytes(
|
|
|
paramFile.toPath())));
|
|
@@ -233,52 +353,6 @@ public class TestCGroupsHandlerImpl {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- public static File createMockCgroupMount(File parentDir, String type)
|
|
|
- throws IOException {
|
|
|
- return createMockCgroupMount(parentDir, type, "hadoop-yarn");
|
|
|
- }
|
|
|
-
|
|
|
- private static File createMockCgroupMount(File parentDir, String type,
|
|
|
- String hierarchy) throws IOException {
|
|
|
- File cgroupMountDir =
|
|
|
- new File(parentDir.getAbsolutePath(), type + "/" + hierarchy);
|
|
|
- FileUtils.deleteQuietly(cgroupMountDir);
|
|
|
- if (!cgroupMountDir.mkdirs()) {
|
|
|
- String message =
|
|
|
- "Could not create dir " + cgroupMountDir.getAbsolutePath();
|
|
|
- throw new IOException(message);
|
|
|
- }
|
|
|
- return cgroupMountDir;
|
|
|
- }
|
|
|
-
|
|
|
- public static File createMockMTab(File parentDir) throws IOException {
|
|
|
- String cpuMtabContent =
|
|
|
- "none " + parentDir.getAbsolutePath()
|
|
|
- + "/cpu cgroup rw,relatime,cpu 0 0\n";
|
|
|
- // Mark an empty directory called 'cp' cgroup. It is processed before 'cpu'
|
|
|
- String cpuMtabContentMissing =
|
|
|
- "none " + parentDir.getAbsolutePath()
|
|
|
- + "/cp cgroup rw,relatime,cpu 0 0\n";
|
|
|
- String blkioMtabContent =
|
|
|
- "none " + parentDir.getAbsolutePath()
|
|
|
- + "/blkio cgroup rw,relatime,blkio 0 0\n";
|
|
|
-
|
|
|
- File mockMtab = new File(parentDir, UUID.randomUUID().toString());
|
|
|
- if (!mockMtab.exists()) {
|
|
|
- if (!mockMtab.createNewFile()) {
|
|
|
- String message = "Could not create file " + mockMtab.getAbsolutePath();
|
|
|
- throw new IOException(message);
|
|
|
- }
|
|
|
- }
|
|
|
- FileWriter mtabWriter = new FileWriter(mockMtab.getAbsoluteFile());
|
|
|
- mtabWriter.write(cpuMtabContentMissing);
|
|
|
- mtabWriter.write(cpuMtabContent);
|
|
|
- mtabWriter.write(blkioMtabContent);
|
|
|
- mtabWriter.close();
|
|
|
- mockMtab.deleteOnExit();
|
|
|
- return mockMtab;
|
|
|
- }
|
|
|
-
|
|
|
/**
|
|
|
* Tests whether mtab parsing works as expected with a valid hierarchy set.
|
|
|
* @throws Exception the test will fail
|
|
@@ -288,24 +362,20 @@ public class TestCGroupsHandlerImpl {
|
|
|
// Initialize mtab and cgroup dir
|
|
|
File parentDir = new File(tmpPath);
|
|
|
// create mock cgroup
|
|
|
- File cpuCgroupMountDir = createMockCgroupMount(parentDir, "cpu",
|
|
|
- hierarchy);
|
|
|
- Assert.assertTrue(cpuCgroupMountDir.exists());
|
|
|
- File blkioCgroupMountDir = createMockCgroupMount(parentDir,
|
|
|
- "blkio", hierarchy);
|
|
|
- Assert.assertTrue(blkioCgroupMountDir.exists());
|
|
|
- File mockMtabFile = createMockMTab(parentDir);
|
|
|
+ File mockMtabFile = createPremountedCgroups(parentDir, false);
|
|
|
|
|
|
// Run mtabs parsing
|
|
|
+ Map<String, Set<String>> newMtab =
|
|
|
+ CGroupsHandlerImpl.parseMtab(mockMtabFile.getAbsolutePath());
|
|
|
Map<CGroupsHandler.CGroupController, String> controllerPaths =
|
|
|
CGroupsHandlerImpl.initializeControllerPathsFromMtab(
|
|
|
- mockMtabFile.getAbsolutePath(), hierarchy);
|
|
|
+ newMtab);
|
|
|
|
|
|
// Verify
|
|
|
Assert.assertEquals(2, controllerPaths.size());
|
|
|
- Assert.assertTrue(controllerPaths
|
|
|
+ assertTrue(controllerPaths
|
|
|
.containsKey(CGroupsHandler.CGroupController.CPU));
|
|
|
- Assert.assertTrue(controllerPaths
|
|
|
+ assertTrue(controllerPaths
|
|
|
.containsKey(CGroupsHandler.CGroupController.BLKIO));
|
|
|
String cpuDir = controllerPaths.get(CGroupsHandler.CGroupController.CPU);
|
|
|
String blkioDir =
|
|
@@ -314,17 +384,6 @@ public class TestCGroupsHandlerImpl {
|
|
|
Assert.assertEquals(parentDir.getAbsolutePath() + "/blkio", blkioDir);
|
|
|
}
|
|
|
|
|
|
- /**
|
|
|
- * Tests whether mtab parsing works as expected with an empty hierarchy set.
|
|
|
- * @throws Exception the test will fail
|
|
|
- */
|
|
|
- @Test
|
|
|
- public void testPreMountedController() throws Exception {
|
|
|
- testPreMountedControllerInitialization("hadoop-yarn");
|
|
|
- testPreMountedControllerInitialization("");
|
|
|
- testPreMountedControllerInitialization("/");
|
|
|
- }
|
|
|
-
|
|
|
/**
|
|
|
* Tests whether mtab parsing works as expected with the specified hierarchy.
|
|
|
* @param myHierarchy path to local cgroup hierarchy
|
|
@@ -334,64 +393,57 @@ public class TestCGroupsHandlerImpl {
|
|
|
throws Exception {
|
|
|
// Initialize mount point
|
|
|
File parentDir = new File(tmpPath);
|
|
|
- FileUtils.deleteQuietly(parentDir);
|
|
|
- Assert.assertTrue("Could not create dirs", parentDir.mkdirs());
|
|
|
- File mtab = createMockMTab(parentDir);
|
|
|
+ File mtab = createPremountedCgroups(parentDir, false);
|
|
|
File mountPoint = new File(parentDir, "cpu");
|
|
|
- File cpuCgroupMountDir = createMockCgroupMount(
|
|
|
- parentDir, "cpu", myHierarchy);
|
|
|
|
|
|
// Initialize Yarn classes
|
|
|
- Configuration confNoMount = new Configuration();
|
|
|
- confNoMount.set(YarnConfiguration.NM_LINUX_CONTAINER_CGROUPS_HIERARCHY,
|
|
|
- myHierarchy);
|
|
|
- confNoMount.setBoolean(YarnConfiguration.NM_LINUX_CONTAINER_CGROUPS_MOUNT,
|
|
|
- false);
|
|
|
+ Configuration confNoMount = createNoMountConfiguration(myHierarchy);
|
|
|
CGroupsHandlerImpl cGroupsHandler = new CGroupsHandlerImpl(confNoMount,
|
|
|
privilegedOperationExecutorMock, mtab.getAbsolutePath());
|
|
|
|
|
|
-
|
|
|
+ File cpuCgroupMountDir = new File(
|
|
|
+ cGroupsHandler.getPathForCGroup(CGroupsHandler.CGroupController.CPU,
|
|
|
+ ""));
|
|
|
// Test that a missing yarn hierarchy will be created automatically
|
|
|
if (!cpuCgroupMountDir.equals(mountPoint)) {
|
|
|
- Assert.assertTrue("Could not delete cgroups", cpuCgroupMountDir.delete());
|
|
|
- Assert.assertTrue("Directory should be deleted",
|
|
|
+ assertTrue("Directory should be deleted",
|
|
|
!cpuCgroupMountDir.exists());
|
|
|
}
|
|
|
cGroupsHandler.initializeCGroupController(
|
|
|
CGroupsHandler.CGroupController.CPU);
|
|
|
- Assert.assertTrue("Cgroups not writable", cpuCgroupMountDir.exists() &&
|
|
|
+ assertTrue("Cgroups not writable", cpuCgroupMountDir.exists() &&
|
|
|
cpuCgroupMountDir.canWrite());
|
|
|
|
|
|
// Test that an inaccessible yarn hierarchy results in an exception
|
|
|
- Assert.assertTrue(cpuCgroupMountDir.setWritable(false));
|
|
|
+ assertTrue(cpuCgroupMountDir.setWritable(false));
|
|
|
try {
|
|
|
cGroupsHandler.initializeCGroupController(
|
|
|
CGroupsHandler.CGroupController.CPU);
|
|
|
Assert.fail("An inaccessible path should result in an exception");
|
|
|
} catch (Exception e) {
|
|
|
- Assert.assertTrue("Unexpected exception " + e.getClass().toString(),
|
|
|
+ assertTrue("Unexpected exception " + e.getClass().toString(),
|
|
|
e instanceof ResourceHandlerException);
|
|
|
} finally {
|
|
|
- Assert.assertTrue("Could not revert writable permission",
|
|
|
+ assertTrue("Could not revert writable permission",
|
|
|
cpuCgroupMountDir.setWritable(true));
|
|
|
}
|
|
|
|
|
|
// Test that a non-accessible mount directory results in an exception
|
|
|
if (!cpuCgroupMountDir.equals(mountPoint)) {
|
|
|
- Assert.assertTrue("Could not delete cgroups", cpuCgroupMountDir.delete());
|
|
|
- Assert.assertTrue("Directory should be deleted",
|
|
|
+ assertTrue("Could not delete cgroups", cpuCgroupMountDir.delete());
|
|
|
+ assertTrue("Directory should be deleted",
|
|
|
!cpuCgroupMountDir.exists());
|
|
|
}
|
|
|
- Assert.assertTrue(mountPoint.setWritable(false));
|
|
|
+ assertTrue(mountPoint.setWritable(false));
|
|
|
try {
|
|
|
cGroupsHandler.initializeCGroupController(
|
|
|
CGroupsHandler.CGroupController.CPU);
|
|
|
Assert.fail("An inaccessible path should result in an exception");
|
|
|
} catch (Exception e) {
|
|
|
- Assert.assertTrue("Unexpected exception " + e.getClass().toString(),
|
|
|
+ assertTrue("Unexpected exception " + e.getClass().toString(),
|
|
|
e instanceof ResourceHandlerException);
|
|
|
} finally {
|
|
|
- Assert.assertTrue("Could not revert writable permission",
|
|
|
+ assertTrue("Could not revert writable permission",
|
|
|
mountPoint.setWritable(true));
|
|
|
}
|
|
|
|
|
@@ -399,7 +451,7 @@ public class TestCGroupsHandlerImpl {
|
|
|
if (!cpuCgroupMountDir.equals(mountPoint)) {
|
|
|
Assert.assertFalse("Could not delete cgroups",
|
|
|
cpuCgroupMountDir.delete());
|
|
|
- Assert.assertTrue("Directory should be deleted",
|
|
|
+ assertTrue("Directory should be deleted",
|
|
|
!cpuCgroupMountDir.exists());
|
|
|
SecurityManager manager = System.getSecurityManager();
|
|
|
System.setSecurityManager(new MockSecurityManagerDenyWrite());
|
|
@@ -408,7 +460,7 @@ public class TestCGroupsHandlerImpl {
|
|
|
CGroupsHandler.CGroupController.CPU);
|
|
|
Assert.fail("An inaccessible path should result in an exception");
|
|
|
} catch (Exception e) {
|
|
|
- Assert.assertTrue("Unexpected exception " + e.getClass().toString(),
|
|
|
+ assertTrue("Unexpected exception " + e.getClass().toString(),
|
|
|
e instanceof ResourceHandlerException);
|
|
|
} finally {
|
|
|
System.setSecurityManager(manager);
|
|
@@ -419,18 +471,18 @@ public class TestCGroupsHandlerImpl {
|
|
|
if (!cpuCgroupMountDir.equals(mountPoint)) {
|
|
|
Assert.assertFalse("Could not delete cgroups",
|
|
|
cpuCgroupMountDir.delete());
|
|
|
- Assert.assertTrue("Directory should be deleted",
|
|
|
+ assertTrue("Directory should be deleted",
|
|
|
!cpuCgroupMountDir.exists());
|
|
|
}
|
|
|
FileUtils.deleteQuietly(mountPoint);
|
|
|
- Assert.assertTrue("cgroups mount point should be deleted",
|
|
|
+ assertTrue("cgroups mount point should be deleted",
|
|
|
!mountPoint.exists());
|
|
|
try {
|
|
|
cGroupsHandler.initializeCGroupController(
|
|
|
CGroupsHandler.CGroupController.CPU);
|
|
|
Assert.fail("An inaccessible path should result in an exception");
|
|
|
} catch (Exception e) {
|
|
|
- Assert.assertTrue("Unexpected exception " + e.getClass().toString(),
|
|
|
+ assertTrue("Unexpected exception " + e.getClass().toString(),
|
|
|
e instanceof ResourceHandlerException);
|
|
|
}
|
|
|
}
|
|
@@ -442,19 +494,19 @@ public class TestCGroupsHandlerImpl {
|
|
|
File memory = new File(tmpPath, "memory");
|
|
|
try {
|
|
|
CGroupsHandlerImpl handler = new CGroupsHandlerImpl(
|
|
|
- conf,
|
|
|
+ createNoMountConfiguration(tmpPath),
|
|
|
privilegedOperationExecutorMock);
|
|
|
- Map<String, List<String>> cgroups = new LinkedHashMap<>();
|
|
|
+ Map<String, Set<String>> cgroups = new LinkedHashMap<>();
|
|
|
|
|
|
Assert.assertTrue("temp dir should be created", cpu.mkdirs());
|
|
|
Assert.assertTrue("temp dir should be created", memory.mkdirs());
|
|
|
Assert.assertFalse("temp dir should not be created", cpuNoExist.exists());
|
|
|
|
|
|
cgroups.put(
|
|
|
- memory.getAbsolutePath(), Collections.singletonList("memory"));
|
|
|
+ memory.getAbsolutePath(), Collections.singleton("memory"));
|
|
|
cgroups.put(
|
|
|
- cpuNoExist.getAbsolutePath(), Collections.singletonList("cpu"));
|
|
|
- cgroups.put(cpu.getAbsolutePath(), Collections.singletonList("cpu"));
|
|
|
+ cpuNoExist.getAbsolutePath(), Collections.singleton("cpu"));
|
|
|
+ cgroups.put(cpu.getAbsolutePath(), Collections.singleton("cpu"));
|
|
|
String selectedCPU = handler.findControllerInMtab("cpu", cgroups);
|
|
|
Assert.assertEquals("Wrong CPU mount point selected",
|
|
|
cpu.getAbsolutePath(), selectedCPU);
|
|
@@ -464,17 +516,61 @@ public class TestCGroupsHandlerImpl {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- @After
|
|
|
- public void teardown() {
|
|
|
- FileUtil.fullyDelete(new File(tmpPath));
|
|
|
+ /**
|
|
|
+ * Tests whether mtab parsing works as expected with an empty hierarchy set.
|
|
|
+ * @throws Exception the test will fail
|
|
|
+ */
|
|
|
+ @Test
|
|
|
+ public void testPreMountedControllerEmpty() throws Exception {
|
|
|
+ testPreMountedControllerInitialization("");
|
|
|
}
|
|
|
|
|
|
- private class MockSecurityManagerDenyWrite extends SecurityManager {
|
|
|
- @Override
|
|
|
- public void checkPermission(Permission perm) {
|
|
|
- if(perm.getActions().equals("write")) {
|
|
|
- throw new SecurityException("Mock not allowed");
|
|
|
- }
|
|
|
- }
|
|
|
+ /**
|
|
|
+ * Tests whether mtab parsing works as expected with a / hierarchy set.
|
|
|
+ * @throws Exception the test will fail
|
|
|
+ */
|
|
|
+ @Test
|
|
|
+ public void testPreMountedControllerRoot() throws Exception {
|
|
|
+ testPreMountedControllerInitialization("/");
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Tests whether mtab parsing works as expected with the specified hierarchy.
|
|
|
+ * @throws Exception the test will fail
|
|
|
+ */
|
|
|
+ @Test
|
|
|
+ public void testRemount()
|
|
|
+ throws Exception {
|
|
|
+ // Initialize mount point
|
|
|
+ File parentDir = new File(tmpPath);
|
|
|
+
|
|
|
+ final String oldMountPointDir = "oldmount";
|
|
|
+ final String newMountPointDir = "newmount";
|
|
|
+
|
|
|
+ File oldMountPoint = new File(parentDir, oldMountPointDir);
|
|
|
+ File mtab = createPremountedCgroups(
|
|
|
+ oldMountPoint, true);
|
|
|
+
|
|
|
+ File newMountPoint = new File(parentDir, newMountPointDir);
|
|
|
+ assertTrue("Could not create dirs",
|
|
|
+ new File(newMountPoint, "cpu").mkdirs());
|
|
|
+
|
|
|
+ // Initialize Yarn classes
|
|
|
+ Configuration confMount = createMountConfiguration();
|
|
|
+ confMount.set(YarnConfiguration.NM_LINUX_CONTAINER_CGROUPS_MOUNT_PATH,
|
|
|
+ parentDir.getAbsolutePath() + Path.SEPARATOR + newMountPointDir);
|
|
|
+ CGroupsHandlerImpl cGroupsHandler = new CGroupsHandlerImpl(confMount,
|
|
|
+ privilegedOperationExecutorMock, mtab.getAbsolutePath());
|
|
|
+
|
|
|
+ cGroupsHandler.initializeCGroupController(
|
|
|
+ CGroupsHandler.CGroupController.CPU);
|
|
|
+
|
|
|
+ ArgumentCaptor<PrivilegedOperation> opCaptor = ArgumentCaptor.forClass(
|
|
|
+ PrivilegedOperation.class);
|
|
|
+ verify(privilegedOperationExecutorMock)
|
|
|
+ .executePrivilegedOperation(opCaptor.capture(), eq(false));
|
|
|
+ File hierarchyFile =
|
|
|
+ new File(new File(newMountPoint, "cpu"), this.hierarchy);
|
|
|
+ assertTrue("Yarn cgroup should exist", hierarchyFile.exists());
|
|
|
}
|
|
|
}
|