diff --git a/hadoop-yarn-project/CHANGES.txt b/hadoop-yarn-project/CHANGES.txt
index 41802ae8536..c2f16d524d6 100644
--- a/hadoop-yarn-project/CHANGES.txt
+++ b/hadoop-yarn-project/CHANGES.txt
@@ -107,6 +107,10 @@ Release 2.9.0 - UNRELEASED
YARN-4496. Improve HA ResourceManager Failover detection on the client.
(Jian He via xgong)
+ YARN-3542. Refactored existing CPU cgroups support to use the newer and
+ integrated ResourceHandler mechanism, and also deprecated the old
+ LCEResourceHandler inteface hierarchy. (Varun Vasudev via vinodkv)
+
OPTIMIZATIONS
BUG FIXES
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/conf/YarnConfiguration.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/conf/YarnConfiguration.java
index 23c29692a0d..e214a86c629 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/conf/YarnConfiguration.java
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/conf/YarnConfiguration.java
@@ -938,6 +938,18 @@ public class YarnConfiguration extends Configuration {
DEFAULT_NM_MEMORY_RESOURCE_CGROUPS_SOFT_LIMIT_PERCENTAGE =
90.0f;
+ @Private
+ public static final String NM_CPU_RESOURCE_PREFIX = NM_PREFIX
+ + "resource.cpu.";
+
+ /** Enable cpu isolation. */
+ @Private
+ public static final String NM_CPU_RESOURCE_ENABLED =
+ NM_CPU_RESOURCE_PREFIX + "enabled";
+
+ @Private
+ public static final boolean DEFAULT_NM_CPU_RESOURCE_ENABLED = false;
+
/**
* Prefix for disk configurations. Work in progress: This configuration
* parameter may be changed/removed in the future.
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/test/java/org/apache/hadoop/yarn/conf/TestYarnConfigurationFields.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/test/java/org/apache/hadoop/yarn/conf/TestYarnConfigurationFields.java
index 0e508ed2e30..529d63b0182 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/test/java/org/apache/hadoop/yarn/conf/TestYarnConfigurationFields.java
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/test/java/org/apache/hadoop/yarn/conf/TestYarnConfigurationFields.java
@@ -111,6 +111,8 @@ public class TestYarnConfigurationFields extends TestConfigurationFieldsBase {
.add(YarnConfiguration.NM_DISK_RESOURCE_ENABLED);
configurationPrefixToSkipCompare
.add(YarnConfiguration.NM_MEMORY_RESOURCE_PREFIX);
+ configurationPrefixToSkipCompare
+ .add(YarnConfiguration.NM_CPU_RESOURCE_ENABLED);
// Set by container-executor.cfg
configurationPrefixToSkipCompare.add(YarnConfiguration.NM_USER_HOME_DIR);
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/LinuxContainerExecutor.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/LinuxContainerExecutor.java
index ff82e972fd2..1367b13ab8d 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/LinuxContainerExecutor.java
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/LinuxContainerExecutor.java
@@ -49,6 +49,7 @@ import org.apache.hadoop.yarn.server.nodemanager.executor.ContainerSignalContext
import org.apache.hadoop.yarn.server.nodemanager.executor.ContainerStartContext;
import org.apache.hadoop.yarn.server.nodemanager.executor.DeletionAsUserContext;
import org.apache.hadoop.yarn.server.nodemanager.executor.LocalizerStartContext;
+import org.apache.hadoop.yarn.server.nodemanager.util.CgroupsLCEResourcesHandler;
import org.apache.hadoop.yarn.server.nodemanager.util.DefaultLCEResourcesHandler;
import org.apache.hadoop.yarn.server.nodemanager.util.LCEResourcesHandler;
import org.apache.hadoop.yarn.util.ConverterUtils;
@@ -95,10 +96,7 @@ public class LinuxContainerExecutor extends ContainerExecutor {
public void setConf(Configuration conf) {
super.setConf(conf);
- resourcesHandler = ReflectionUtils.newInstance(
- conf.getClass(YarnConfiguration.NM_LINUX_CONTAINER_RESOURCES_HANDLER,
- DefaultLCEResourcesHandler.class, LCEResourcesHandler.class), conf);
- resourcesHandler.setConf(conf);
+ resourcesHandler = getResourcesHandler(conf);
if (conf.get(YarnConfiguration.NM_CONTAINER_EXECUTOR_SCHED_PRIORITY)
!= null) {
@@ -122,6 +120,23 @@ public class LinuxContainerExecutor extends ContainerExecutor {
}
}
+ private LCEResourcesHandler getResourcesHandler(Configuration conf) {
+ LCEResourcesHandler handler = ReflectionUtils.newInstance(
+ conf.getClass(YarnConfiguration.NM_LINUX_CONTAINER_RESOURCES_HANDLER,
+ DefaultLCEResourcesHandler.class, LCEResourcesHandler.class), conf);
+
+ // Stop using CgroupsLCEResourcesHandler
+ // use the resource handler chain instead
+ // ResourceHandlerModule will create the cgroup cpu module if
+ // CgroupsLCEResourcesHandler is set
+ if (handler instanceof CgroupsLCEResourcesHandler) {
+ handler =
+ ReflectionUtils.newInstance(DefaultLCEResourcesHandler.class, conf);
+ }
+ handler.setConf(conf);
+ return handler;
+ }
+
void verifyUsernamePattern(String user) {
if (!UserGroupInformation.isSecurityEnabled() &&
!nonsecureLocalUserPattern.matcher(user).matches()) {
@@ -184,7 +199,12 @@ public class LinuxContainerExecutor extends ContainerExecutor {
try {
resourceHandlerChain = ResourceHandlerModule
.getConfiguredResourceHandlerChain(conf);
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Resource handler chain enabled = " + (resourceHandlerChain
+ == null));
+ }
if (resourceHandlerChain != null) {
+ LOG.debug("Bootstrapping resource handler chain");
resourceHandlerChain.bootstrap(conf);
}
} catch (ResourceHandlerException e) {
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/resources/CGroupsCpuResourceHandlerImpl.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/resources/CGroupsCpuResourceHandlerImpl.java
new file mode 100644
index 00000000000..0071c7e65c9
--- /dev/null
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/resources/CGroupsCpuResourceHandlerImpl.java
@@ -0,0 +1,235 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.resources;
+
+import com.google.common.annotations.VisibleForTesting;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.hadoop.classification.InterfaceAudience;
+import org.apache.hadoop.classification.InterfaceStability;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.yarn.api.records.ContainerId;
+import org.apache.hadoop.yarn.api.records.Resource;
+import org.apache.hadoop.yarn.conf.YarnConfiguration;
+import org.apache.hadoop.yarn.server.nodemanager.containermanager.container.Container;
+import org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.privileged.PrivilegedOperation;
+import org.apache.hadoop.yarn.server.nodemanager.util.NodeManagerHardwareUtils;
+import org.apache.hadoop.yarn.util.ResourceCalculatorPlugin;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * An implementation for using CGroups to restrict CPU usage on Linux. The
+ * implementation supports 3 different controls - restrict usage of all YARN
+ * containers, restrict relative usage of individual YARN containers and
+ * restrict usage of individual YARN containers. Admins can set the overall CPU
+ * to be used by all YARN containers - this is implemented by setting
+ * cpu.cfs_period_us and cpu.cfs_quota_us to the ratio desired. If strict
+ * resource usage mode is not enabled, cpu.shares is set for individual
+ * containers - this prevents containers from exceeding the overall limit for
+ * YARN containers but individual containers can use as much of the CPU as
+ * available(under the YARN limit). If strict resource usage is enabled, then
+ * container can only use the percentage of CPU allocated to them and this is
+ * again implemented using cpu.cfs_period_us and cpu.cfs_quota_us.
+ *
+ */
+@InterfaceStability.Unstable
+@InterfaceAudience.Private
+public class CGroupsCpuResourceHandlerImpl implements CpuResourceHandler {
+
+ static final Log LOG = LogFactory.getLog(CGroupsCpuResourceHandlerImpl.class);
+
+ private CGroupsHandler cGroupsHandler;
+ private boolean strictResourceUsageMode = false;
+ private float yarnProcessors;
+ private int nodeVCores;
+ private static final CGroupsHandler.CGroupController CPU =
+ CGroupsHandler.CGroupController.CPU;
+
+ @VisibleForTesting
+ static final int MAX_QUOTA_US = 1000 * 1000;
+ @VisibleForTesting
+ static final int MIN_PERIOD_US = 1000;
+ @VisibleForTesting
+ static final int CPU_DEFAULT_WEIGHT = 1024; // set by kernel
+
+ CGroupsCpuResourceHandlerImpl(CGroupsHandler cGroupsHandler) {
+ this.cGroupsHandler = cGroupsHandler;
+ }
+
+ @Override
+ public List bootstrap(Configuration conf)
+ throws ResourceHandlerException {
+ return bootstrap(
+ ResourceCalculatorPlugin.getResourceCalculatorPlugin(null, conf), conf);
+ }
+
+ @VisibleForTesting
+ List bootstrap(
+ ResourceCalculatorPlugin plugin, Configuration conf)
+ throws ResourceHandlerException {
+ this.strictResourceUsageMode = conf.getBoolean(
+ YarnConfiguration.NM_LINUX_CONTAINER_CGROUPS_STRICT_RESOURCE_USAGE,
+ YarnConfiguration.DEFAULT_NM_LINUX_CONTAINER_CGROUPS_STRICT_RESOURCE_USAGE);
+ this.cGroupsHandler.mountCGroupController(CPU);
+ nodeVCores = NodeManagerHardwareUtils.getVCores(plugin, conf);
+
+ // cap overall usage to the number of cores allocated to YARN
+ yarnProcessors = NodeManagerHardwareUtils.getContainersCPUs(plugin, conf);
+ int systemProcessors = NodeManagerHardwareUtils.getNodeCPUs(plugin, conf);
+ boolean existingCpuLimits;
+ try {
+ existingCpuLimits =
+ cpuLimitsExist(cGroupsHandler.getPathForCGroup(CPU, ""));
+ } catch (IOException ie) {
+ throw new ResourceHandlerException(ie);
+ }
+ if (systemProcessors != (int) yarnProcessors) {
+ LOG.info("YARN containers restricted to " + yarnProcessors + " cores");
+ int[] limits = getOverallLimits(yarnProcessors);
+ cGroupsHandler
+ .updateCGroupParam(CPU, "", CGroupsHandler.CGROUP_CPU_PERIOD_US,
+ String.valueOf(limits[0]));
+ cGroupsHandler
+ .updateCGroupParam(CPU, "", CGroupsHandler.CGROUP_CPU_QUOTA_US,
+ String.valueOf(limits[1]));
+ } else if (existingCpuLimits) {
+ LOG.info("Removing CPU constraints for YARN containers.");
+ cGroupsHandler
+ .updateCGroupParam(CPU, "", CGroupsHandler.CGROUP_CPU_QUOTA_US,
+ String.valueOf(-1));
+ }
+ return null;
+ }
+
+ @InterfaceAudience.Private
+ public static boolean cpuLimitsExist(String path)
+ throws IOException {
+ File quotaFile = new File(path,
+ CPU.getName() + "." + CGroupsHandler.CGROUP_CPU_QUOTA_US);
+ if (quotaFile.exists()) {
+ String contents = FileUtils.readFileToString(quotaFile, "UTF-8");
+ int quotaUS = Integer.parseInt(contents.trim());
+ if (quotaUS != -1) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @VisibleForTesting
+ @InterfaceAudience.Private
+ public static int[] getOverallLimits(float yarnProcessors) {
+
+ int[] ret = new int[2];
+
+ if (yarnProcessors < 0.01f) {
+ throw new IllegalArgumentException("Number of processors can't be <= 0.");
+ }
+
+ int quotaUS = MAX_QUOTA_US;
+ int periodUS = (int) (MAX_QUOTA_US / yarnProcessors);
+ if (yarnProcessors < 1.0f) {
+ periodUS = MAX_QUOTA_US;
+ quotaUS = (int) (periodUS * yarnProcessors);
+ if (quotaUS < MIN_PERIOD_US) {
+ LOG.warn("The quota calculated for the cgroup was too low."
+ + " The minimum value is " + MIN_PERIOD_US
+ + ", calculated value is " + quotaUS
+ + ". Setting quota to minimum value.");
+ quotaUS = MIN_PERIOD_US;
+ }
+ }
+
+ // cfs_period_us can't be less than 1000 microseconds
+ // if the value of periodUS is less than 1000, we can't really use cgroups
+ // to limit cpu
+ if (periodUS < MIN_PERIOD_US) {
+ LOG.warn("The period calculated for the cgroup was too low."
+ + " The minimum value is " + MIN_PERIOD_US
+ + ", calculated value is " + periodUS
+ + ". Using all available CPU.");
+ periodUS = MAX_QUOTA_US;
+ quotaUS = -1;
+ }
+
+ ret[0] = periodUS;
+ ret[1] = quotaUS;
+ return ret;
+ }
+
+ @Override
+ public List preStart(Container container)
+ throws ResourceHandlerException {
+
+ String cgroupId = container.getContainerId().toString();
+ Resource containerResource = container.getResource();
+ cGroupsHandler.createCGroup(CPU, cgroupId);
+ try {
+ int containerVCores = containerResource.getVirtualCores();
+ int cpuShares = CPU_DEFAULT_WEIGHT * containerVCores;
+ cGroupsHandler
+ .updateCGroupParam(CPU, cgroupId, CGroupsHandler.CGROUP_CPU_SHARES,
+ String.valueOf(cpuShares));
+ if (strictResourceUsageMode) {
+ if (nodeVCores != containerVCores) {
+ float containerCPU =
+ (containerVCores * yarnProcessors) / (float) nodeVCores;
+ int[] limits = getOverallLimits(containerCPU);
+ cGroupsHandler.updateCGroupParam(CPU, cgroupId,
+ CGroupsHandler.CGROUP_CPU_PERIOD_US, String.valueOf(limits[0]));
+ cGroupsHandler.updateCGroupParam(CPU, cgroupId,
+ CGroupsHandler.CGROUP_CPU_QUOTA_US, String.valueOf(limits[1]));
+ }
+ }
+ } catch (ResourceHandlerException re) {
+ cGroupsHandler.deleteCGroup(CPU, cgroupId);
+ LOG.warn("Could not update cgroup for container", re);
+ throw re;
+ }
+ List ret = new ArrayList<>();
+ ret.add(new PrivilegedOperation(
+ PrivilegedOperation.OperationType.ADD_PID_TO_CGROUP,
+ PrivilegedOperation.CGROUP_ARG_PREFIX + cGroupsHandler
+ .getPathForCGroupTasks(CPU, cgroupId)));
+ return ret;
+ }
+
+ @Override
+ public List reacquireContainer(ContainerId containerId)
+ throws ResourceHandlerException {
+ return null;
+ }
+
+ @Override
+ public List postComplete(ContainerId containerId)
+ throws ResourceHandlerException {
+ cGroupsHandler.deleteCGroup(CPU, containerId.toString());
+ return null;
+ }
+
+ @Override public List teardown()
+ throws ResourceHandlerException {
+ return null;
+ }
+}
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/resources/CGroupsHandler.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/resources/CGroupsHandler.java
index d86c5f2375a..eefaabdad84 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/resources/CGroupsHandler.java
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/resources/CGroupsHandler.java
@@ -58,6 +58,10 @@ public interface CGroupsHandler {
String CGROUP_PARAM_MEMORY_SWAPPINESS = "swappiness";
+ String CGROUP_CPU_PERIOD_US = "cfs_period_us";
+ String CGROUP_CPU_QUOTA_US = "cfs_quota_us";
+ String CGROUP_CPU_SHARES = "shares";
+
/**
* Mounts a cgroup controller
* @param controller - the controller being mounted
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/resources/CpuResourceHandler.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/resources/CpuResourceHandler.java
new file mode 100644
index 00000000000..b253ce59fa9
--- /dev/null
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/resources/CpuResourceHandler.java
@@ -0,0 +1,32 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.resources;
+
+import org.apache.hadoop.classification.InterfaceAudience;
+import org.apache.hadoop.classification.InterfaceStability;
+
+/**
+ * Resource handler for cpu resources.
+ */
+@InterfaceAudience.Private
+@InterfaceStability.Unstable
+public interface CpuResourceHandler extends ResourceHandler {
+
+}
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/resources/ResourceHandlerModule.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/resources/ResourceHandlerModule.java
index da70536e6c6..7507a82e74d 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/resources/ResourceHandlerModule.java
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/resources/ResourceHandlerModule.java
@@ -21,11 +21,15 @@
package org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.resources;
import com.google.common.annotations.VisibleForTesting;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.classification.InterfaceAudience;
import org.apache.hadoop.classification.InterfaceStability;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.yarn.conf.YarnConfiguration;
import org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.privileged.PrivilegedOperationExecutor;
+import org.apache.hadoop.yarn.server.nodemanager.util.CgroupsLCEResourcesHandler;
+import org.apache.hadoop.yarn.server.nodemanager.util.DefaultLCEResourcesHandler;
import java.util.ArrayList;
import java.util.List;
@@ -38,6 +42,7 @@ import java.util.List;
@InterfaceAudience.Private
@InterfaceStability.Unstable
public class ResourceHandlerModule {
+ static final Log LOG = LogFactory.getLog(ResourceHandlerModule.class);
private static volatile ResourceHandlerChain resourceHandlerChain;
/**
@@ -52,6 +57,8 @@ public class ResourceHandlerModule {
cGroupsBlkioResourceHandler;
private static volatile CGroupsMemoryResourceHandlerImpl
cGroupsMemoryResourceHandler;
+ private static volatile CGroupsCpuResourceHandlerImpl
+ cGroupsCpuResourceHandler;
/**
* Returns an initialized, thread-safe CGroupsHandler instance.
@@ -70,6 +77,30 @@ public class ResourceHandlerModule {
return cGroupsHandler;
}
+ private static CGroupsCpuResourceHandlerImpl getcGroupsCpuResourceHandler(
+ Configuration conf) throws ResourceHandlerException {
+ boolean cgroupsCpuEnabled =
+ conf.getBoolean(YarnConfiguration.NM_CPU_RESOURCE_ENABLED,
+ YarnConfiguration.DEFAULT_NM_CPU_RESOURCE_ENABLED);
+ boolean cgroupsLCEResourcesHandlerEnabled =
+ conf.getClass(YarnConfiguration.NM_LINUX_CONTAINER_RESOURCES_HANDLER,
+ DefaultLCEResourcesHandler.class)
+ .equals(CgroupsLCEResourcesHandler.class);
+ if (cgroupsCpuEnabled || cgroupsLCEResourcesHandlerEnabled) {
+ if (cGroupsCpuResourceHandler == null) {
+ synchronized (CpuResourceHandler.class) {
+ if (cGroupsCpuResourceHandler == null) {
+ LOG.debug("Creating new cgroups cpu handler");
+ cGroupsCpuResourceHandler =
+ new CGroupsCpuResourceHandlerImpl(getCGroupsHandler(conf));
+ return cGroupsCpuResourceHandler;
+ }
+ }
+ }
+ }
+ return null;
+ }
+
private static TrafficControlBandwidthHandlerImpl
getTrafficControlBandwidthHandler(Configuration conf)
throws ResourceHandlerException {
@@ -78,6 +109,7 @@ public class ResourceHandlerModule {
if (trafficControlBandwidthHandler == null) {
synchronized (OutboundBandwidthResourceHandler.class) {
if (trafficControlBandwidthHandler == null) {
+ LOG.debug("Creating new traffic control bandwidth handler");
trafficControlBandwidthHandler = new
TrafficControlBandwidthHandlerImpl(PrivilegedOperationExecutor
.getInstance(conf), getCGroupsHandler(conf),
@@ -113,6 +145,7 @@ public class ResourceHandlerModule {
if (cGroupsBlkioResourceHandler == null) {
synchronized (DiskResourceHandler.class) {
if (cGroupsBlkioResourceHandler == null) {
+ LOG.debug("Creating new cgroups blkio handler");
cGroupsBlkioResourceHandler =
new CGroupsBlkioResourceHandlerImpl(getCGroupsHandler(conf));
}
@@ -158,6 +191,7 @@ public class ResourceHandlerModule {
addHandlerIfNotNull(handlerList, getOutboundBandwidthResourceHandler(conf));
addHandlerIfNotNull(handlerList, getDiskResourceHandler(conf));
addHandlerIfNotNull(handlerList, getMemoryResourceHandler(conf));
+ addHandlerIfNotNull(handlerList, getcGroupsCpuResourceHandler(conf));
resourceHandlerChain = new ResourceHandlerChain(handlerList);
}
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/util/CgroupsLCEResourcesHandler.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/util/CgroupsLCEResourcesHandler.java
index da39fa2b018..f04fcd20e72 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/util/CgroupsLCEResourcesHandler.java
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/util/CgroupsLCEResourcesHandler.java
@@ -39,7 +39,6 @@ import java.util.regex.Pattern;
import com.google.common.annotations.VisibleForTesting;
-import org.apache.commons.io.FileUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.conf.Configuration;
@@ -50,10 +49,20 @@ import org.apache.hadoop.yarn.api.records.Resource;
import org.apache.hadoop.yarn.conf.YarnConfiguration;
import org.apache.hadoop.yarn.server.nodemanager.LinuxContainerExecutor;
import org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.privileged.PrivilegedOperation;
+import org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.resources.CGroupsCpuResourceHandlerImpl;
import org.apache.hadoop.yarn.util.Clock;
import org.apache.hadoop.yarn.util.ResourceCalculatorPlugin;
import org.apache.hadoop.yarn.util.SystemClock;
+/**
+ * Resource handler that lets you setup cgroups
+ * to to handle cpu isolation. Please look at the ResourceHandlerModule
+ * and CGroupsCpuResourceHandlerImpl classes which let you isolate multiple
+ * resources using cgroups.
+ * Deprecated - please look at ResourceHandlerModule and
+ * CGroupsCpuResourceHandlerImpl
+ */
+@Deprecated
public class CgroupsLCEResourcesHandler implements LCEResourcesHandler {
final static Log LOG = LogFactory
@@ -73,8 +82,6 @@ public class CgroupsLCEResourcesHandler implements LCEResourcesHandler {
private final String CPU_PERIOD_US = "cfs_period_us";
private final String CPU_QUOTA_US = "cfs_quota_us";
private final int CPU_DEFAULT_WEIGHT = 1024; // set by kernel
- private final int MAX_QUOTA_US = 1000 * 1000;
- private final int MIN_PERIOD_US = 1000;
private final Map controllerPaths; // Controller -> path
private long deleteCgroupTimeout;
@@ -163,65 +170,18 @@ public class CgroupsLCEResourcesHandler implements LCEResourcesHandler {
int[] limits = getOverallLimits(yarnProcessors);
updateCgroup(CONTROLLER_CPU, "", CPU_PERIOD_US, String.valueOf(limits[0]));
updateCgroup(CONTROLLER_CPU, "", CPU_QUOTA_US, String.valueOf(limits[1]));
- } else if (cpuLimitsExist()) {
+ } else if (CGroupsCpuResourceHandlerImpl.cpuLimitsExist(
+ pathForCgroup(CONTROLLER_CPU, ""))) {
LOG.info("Removing CPU constraints for YARN containers.");
updateCgroup(CONTROLLER_CPU, "", CPU_QUOTA_US, String.valueOf(-1));
}
}
- boolean cpuLimitsExist() throws IOException {
- String path = pathForCgroup(CONTROLLER_CPU, "");
- File quotaFile = new File(path, CONTROLLER_CPU + "." + CPU_QUOTA_US);
- if (quotaFile.exists()) {
- String contents = FileUtils.readFileToString(quotaFile, "UTF-8");
- int quotaUS = Integer.parseInt(contents.trim());
- if (quotaUS != -1) {
- return true;
- }
- }
- return false;
- }
-
- @VisibleForTesting
int[] getOverallLimits(float yarnProcessors) {
-
- int[] ret = new int[2];
-
- if (yarnProcessors < 0.01f) {
- throw new IllegalArgumentException("Number of processors can't be <= 0.");
- }
-
- int quotaUS = MAX_QUOTA_US;
- int periodUS = (int) (MAX_QUOTA_US / yarnProcessors);
- if (yarnProcessors < 1.0f) {
- periodUS = MAX_QUOTA_US;
- quotaUS = (int) (periodUS * yarnProcessors);
- if (quotaUS < MIN_PERIOD_US) {
- LOG
- .warn("The quota calculated for the cgroup was too low. The minimum value is "
- + MIN_PERIOD_US + ", calculated value is " + quotaUS
- + ". Setting quota to minimum value.");
- quotaUS = MIN_PERIOD_US;
- }
- }
-
- // cfs_period_us can't be less than 1000 microseconds
- // if the value of periodUS is less than 1000, we can't really use cgroups
- // to limit cpu
- if (periodUS < MIN_PERIOD_US) {
- LOG
- .warn("The period calculated for the cgroup was too low. The minimum value is "
- + MIN_PERIOD_US + ", calculated value is " + periodUS
- + ". Using all available CPU.");
- periodUS = MAX_QUOTA_US;
- quotaUS = -1;
- }
-
- ret[0] = periodUS;
- ret[1] = quotaUS;
- return ret;
+ return CGroupsCpuResourceHandlerImpl.getOverallLimits(yarnProcessors);
}
+
boolean isCpuWeightEnabled() {
return this.cpuWeightEnabled;
}
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/util/DefaultLCEResourcesHandler.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/util/DefaultLCEResourcesHandler.java
index 9fb87074e2b..df2cc523ff6 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/util/DefaultLCEResourcesHandler.java
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/util/DefaultLCEResourcesHandler.java
@@ -25,6 +25,7 @@ import org.apache.hadoop.yarn.api.records.ContainerId;
import org.apache.hadoop.yarn.api.records.Resource;
import org.apache.hadoop.yarn.server.nodemanager.LinuxContainerExecutor;
+@Deprecated
public class DefaultLCEResourcesHandler implements LCEResourcesHandler {
final static Log LOG = LogFactory
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/util/LCEResourcesHandler.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/util/LCEResourcesHandler.java
index 34f7f31c327..b2d219dac54 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/util/LCEResourcesHandler.java
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/util/LCEResourcesHandler.java
@@ -25,6 +25,7 @@ import org.apache.hadoop.yarn.api.records.ContainerId;
import org.apache.hadoop.yarn.api.records.Resource;
import org.apache.hadoop.yarn.server.nodemanager.LinuxContainerExecutor;
+@Deprecated
public interface LCEResourcesHandler extends Configurable {
void init(LinuxContainerExecutor lce) throws IOException;
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/resources/TestCGroupsCpuResourceHandlerImpl.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/resources/TestCGroupsCpuResourceHandlerImpl.java
new file mode 100644
index 00000000000..119235ca2d0
--- /dev/null
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/resources/TestCGroupsCpuResourceHandlerImpl.java
@@ -0,0 +1,297 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.resources;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.yarn.api.records.ContainerId;
+import org.apache.hadoop.yarn.api.records.Resource;
+import org.apache.hadoop.yarn.conf.YarnConfiguration;
+import org.apache.hadoop.yarn.server.nodemanager.containermanager.container.Container;
+import org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.privileged.PrivilegedOperation;
+import org.apache.hadoop.yarn.util.ResourceCalculatorPlugin;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+import java.io.File;
+import java.util.List;
+
+import static org.mockito.Mockito.*;
+import static org.mockito.Mockito.times;
+
+public class TestCGroupsCpuResourceHandlerImpl {
+
+ private CGroupsHandler mockCGroupsHandler;
+ private CGroupsCpuResourceHandlerImpl cGroupsCpuResourceHandler;
+ private ResourceCalculatorPlugin plugin;
+ final int numProcessors = 4;
+
+ @Before
+ public void setup() {
+ mockCGroupsHandler = mock(CGroupsHandler.class);
+ cGroupsCpuResourceHandler =
+ new CGroupsCpuResourceHandlerImpl(mockCGroupsHandler);
+
+ plugin = mock(ResourceCalculatorPlugin.class);
+ Mockito.doReturn(numProcessors).when(plugin).getNumProcessors();
+ Mockito.doReturn(numProcessors).when(plugin).getNumCores();
+ }
+
+ @Test
+ public void testBootstrap() throws Exception {
+ Configuration conf = new YarnConfiguration();
+
+ List ret =
+ cGroupsCpuResourceHandler.bootstrap(plugin, conf);
+ verify(mockCGroupsHandler, times(1))
+ .mountCGroupController(CGroupsHandler.CGroupController.CPU);
+ verify(mockCGroupsHandler, times(0))
+ .updateCGroupParam(CGroupsHandler.CGroupController.CPU, "",
+ CGroupsHandler.CGROUP_CPU_PERIOD_US, "");
+ verify(mockCGroupsHandler, times(0))
+ .updateCGroupParam(CGroupsHandler.CGroupController.CPU, "",
+ CGroupsHandler.CGROUP_CPU_QUOTA_US, "");
+ Assert.assertNull(ret);
+ }
+
+ @Test
+ public void testBootstrapLimits() throws Exception {
+ Configuration conf = new YarnConfiguration();
+
+ int cpuPerc = 80;
+ conf.setInt(YarnConfiguration.NM_RESOURCE_PERCENTAGE_PHYSICAL_CPU_LIMIT,
+ cpuPerc);
+ int period = (CGroupsCpuResourceHandlerImpl.MAX_QUOTA_US * 100) / (cpuPerc
+ * numProcessors);
+ List ret =
+ cGroupsCpuResourceHandler.bootstrap(plugin, conf);
+ verify(mockCGroupsHandler, times(1))
+ .mountCGroupController(CGroupsHandler.CGroupController.CPU);
+ verify(mockCGroupsHandler, times(1))
+ .updateCGroupParam(CGroupsHandler.CGroupController.CPU, "",
+ CGroupsHandler.CGROUP_CPU_PERIOD_US, String.valueOf(period));
+ verify(mockCGroupsHandler, times(1))
+ .updateCGroupParam(CGroupsHandler.CGroupController.CPU, "",
+ CGroupsHandler.CGROUP_CPU_QUOTA_US,
+ String.valueOf(CGroupsCpuResourceHandlerImpl.MAX_QUOTA_US));
+ Assert.assertNull(ret);
+ }
+
+ @Test
+ public void testBootstrapExistingLimits() throws Exception {
+ File existingLimit = new File(CGroupsHandler.CGroupController.CPU.getName()
+ + "." + CGroupsHandler.CGROUP_CPU_QUOTA_US);
+ try {
+ FileUtils.write(existingLimit, "10000"); // value doesn't matter
+ when(mockCGroupsHandler
+ .getPathForCGroup(CGroupsHandler.CGroupController.CPU, ""))
+ .thenReturn(".");
+ Configuration conf = new YarnConfiguration();
+
+ List ret =
+ cGroupsCpuResourceHandler.bootstrap(plugin, conf);
+ verify(mockCGroupsHandler, times(1))
+ .mountCGroupController(CGroupsHandler.CGroupController.CPU);
+ verify(mockCGroupsHandler, times(1))
+ .updateCGroupParam(CGroupsHandler.CGroupController.CPU, "",
+ CGroupsHandler.CGROUP_CPU_QUOTA_US, "-1");
+ Assert.assertNull(ret);
+ } finally {
+ FileUtils.deleteQuietly(existingLimit);
+ }
+ }
+
+ @Test
+ public void testPreStart() throws Exception {
+ String id = "container_01_01";
+ String path = "test-path/" + id;
+ ContainerId mockContainerId = mock(ContainerId.class);
+ when(mockContainerId.toString()).thenReturn(id);
+ Container mockContainer = mock(Container.class);
+ when(mockContainer.getContainerId()).thenReturn(mockContainerId);
+ when(mockCGroupsHandler
+ .getPathForCGroupTasks(CGroupsHandler.CGroupController.CPU, id))
+ .thenReturn(path);
+ when(mockContainer.getResource()).thenReturn(Resource.newInstance(1024, 2));
+
+ List ret =
+ cGroupsCpuResourceHandler.preStart(mockContainer);
+ verify(mockCGroupsHandler, times(1))
+ .createCGroup(CGroupsHandler.CGroupController.CPU, id);
+ verify(mockCGroupsHandler, times(1))
+ .updateCGroupParam(CGroupsHandler.CGroupController.CPU, id,
+ CGroupsHandler.CGROUP_CPU_SHARES, String
+ .valueOf(CGroupsCpuResourceHandlerImpl.CPU_DEFAULT_WEIGHT * 2));
+
+ // don't set quota or period
+ verify(mockCGroupsHandler, never())
+ .updateCGroupParam(eq(CGroupsHandler.CGroupController.CPU), eq(id),
+ eq(CGroupsHandler.CGROUP_CPU_PERIOD_US), anyString());
+ verify(mockCGroupsHandler, never())
+ .updateCGroupParam(eq(CGroupsHandler.CGroupController.CPU), eq(id),
+ eq(CGroupsHandler.CGROUP_CPU_QUOTA_US), anyString());
+ Assert.assertNotNull(ret);
+ Assert.assertEquals(1, ret.size());
+ PrivilegedOperation op = ret.get(0);
+ Assert.assertEquals(PrivilegedOperation.OperationType.ADD_PID_TO_CGROUP,
+ op.getOperationType());
+ List args = op.getArguments();
+ Assert.assertEquals(1, args.size());
+ Assert.assertEquals(PrivilegedOperation.CGROUP_ARG_PREFIX + path,
+ args.get(0));
+ }
+
+ @Test
+ public void testPreStartStrictUsage() throws Exception {
+ String id = "container_01_01";
+ String path = "test-path/" + id;
+ ContainerId mockContainerId = mock(ContainerId.class);
+ when(mockContainerId.toString()).thenReturn(id);
+ Container mockContainer = mock(Container.class);
+ when(mockContainer.getContainerId()).thenReturn(mockContainerId);
+ when(mockCGroupsHandler
+ .getPathForCGroupTasks(CGroupsHandler.CGroupController.CPU, id))
+ .thenReturn(path);
+ when(mockContainer.getResource()).thenReturn(Resource.newInstance(1024, 1));
+ Configuration conf = new YarnConfiguration();
+ conf.setBoolean(
+ YarnConfiguration.NM_LINUX_CONTAINER_CGROUPS_STRICT_RESOURCE_USAGE,
+ true);
+ cGroupsCpuResourceHandler.bootstrap(plugin, conf);
+ int defaultVCores = 8;
+ float share = (float) numProcessors / (float) defaultVCores;
+ List ret =
+ cGroupsCpuResourceHandler.preStart(mockContainer);
+ verify(mockCGroupsHandler, times(1))
+ .createCGroup(CGroupsHandler.CGroupController.CPU, id);
+ verify(mockCGroupsHandler, times(1))
+ .updateCGroupParam(CGroupsHandler.CGroupController.CPU, id,
+ CGroupsHandler.CGROUP_CPU_SHARES,
+ String.valueOf(CGroupsCpuResourceHandlerImpl.CPU_DEFAULT_WEIGHT));
+ // set quota and period
+ verify(mockCGroupsHandler, times(1))
+ .updateCGroupParam(CGroupsHandler.CGroupController.CPU, id,
+ CGroupsHandler.CGROUP_CPU_PERIOD_US,
+ String.valueOf(CGroupsCpuResourceHandlerImpl.MAX_QUOTA_US));
+ verify(mockCGroupsHandler, times(1))
+ .updateCGroupParam(CGroupsHandler.CGroupController.CPU, id,
+ CGroupsHandler.CGROUP_CPU_QUOTA_US, String.valueOf(
+ (int) (CGroupsCpuResourceHandlerImpl.MAX_QUOTA_US * share)));
+ Assert.assertNotNull(ret);
+ Assert.assertEquals(1, ret.size());
+ PrivilegedOperation op = ret.get(0);
+ Assert.assertEquals(PrivilegedOperation.OperationType.ADD_PID_TO_CGROUP,
+ op.getOperationType());
+ List args = op.getArguments();
+ Assert.assertEquals(1, args.size());
+ Assert.assertEquals(PrivilegedOperation.CGROUP_ARG_PREFIX + path,
+ args.get(0));
+ }
+
+ @Test
+ public void testPreStartRestrictedContainers() throws Exception {
+ String id = "container_01_01";
+ String path = "test-path/" + id;
+ int defaultVCores = 8;
+ Configuration conf = new YarnConfiguration();
+ conf.setBoolean(
+ YarnConfiguration.NM_LINUX_CONTAINER_CGROUPS_STRICT_RESOURCE_USAGE,
+ true);
+ int cpuPerc = 75;
+ conf.setInt(YarnConfiguration.NM_RESOURCE_PERCENTAGE_PHYSICAL_CPU_LIMIT,
+ cpuPerc);
+ cGroupsCpuResourceHandler.bootstrap(plugin, conf);
+ verify(mockCGroupsHandler, times(1))
+ .updateCGroupParam(CGroupsHandler.CGroupController.CPU, "",
+ CGroupsHandler.CGROUP_CPU_PERIOD_US, String.valueOf("333333"));
+ verify(mockCGroupsHandler, times(1))
+ .updateCGroupParam(CGroupsHandler.CGroupController.CPU, "",
+ CGroupsHandler.CGROUP_CPU_QUOTA_US,
+ String.valueOf(CGroupsCpuResourceHandlerImpl.MAX_QUOTA_US));
+ float yarnCores = (cpuPerc * numProcessors) / 100;
+ int[] containerVCores = { 2, 4 };
+ for (int cVcores : containerVCores) {
+ ContainerId mockContainerId = mock(ContainerId.class);
+ when(mockContainerId.toString()).thenReturn(id);
+ Container mockContainer = mock(Container.class);
+ when(mockContainer.getContainerId()).thenReturn(mockContainerId);
+ when(mockCGroupsHandler
+ .getPathForCGroupTasks(CGroupsHandler.CGroupController.CPU, id))
+ .thenReturn(path);
+ when(mockContainer.getResource())
+ .thenReturn(Resource.newInstance(1024, cVcores));
+ when(mockCGroupsHandler
+ .getPathForCGroupTasks(CGroupsHandler.CGroupController.CPU, id))
+ .thenReturn(path);
+
+ float share = (cVcores * yarnCores) / defaultVCores;
+ int quotaUS;
+ int periodUS;
+ if (share > 1.0f) {
+ quotaUS = CGroupsCpuResourceHandlerImpl.MAX_QUOTA_US;
+ periodUS =
+ (int) ((float) CGroupsCpuResourceHandlerImpl.MAX_QUOTA_US / share);
+ } else {
+ quotaUS = (int) (CGroupsCpuResourceHandlerImpl.MAX_QUOTA_US * share);
+ periodUS = CGroupsCpuResourceHandlerImpl.MAX_QUOTA_US;
+ }
+ cGroupsCpuResourceHandler.preStart(mockContainer);
+ verify(mockCGroupsHandler, times(1))
+ .updateCGroupParam(CGroupsHandler.CGroupController.CPU, id,
+ CGroupsHandler.CGROUP_CPU_SHARES, String.valueOf(
+ CGroupsCpuResourceHandlerImpl.CPU_DEFAULT_WEIGHT * cVcores));
+ // set quota and period
+ verify(mockCGroupsHandler, times(1))
+ .updateCGroupParam(CGroupsHandler.CGroupController.CPU, id,
+ CGroupsHandler.CGROUP_CPU_PERIOD_US, String.valueOf(periodUS));
+ verify(mockCGroupsHandler, times(1))
+ .updateCGroupParam(CGroupsHandler.CGroupController.CPU, id,
+ CGroupsHandler.CGROUP_CPU_QUOTA_US, String.valueOf(quotaUS));
+ }
+ }
+
+ @Test
+ public void testReacquireContainer() throws Exception {
+ ContainerId containerIdMock = mock(ContainerId.class);
+ Assert.assertNull(
+ cGroupsCpuResourceHandler.reacquireContainer(containerIdMock));
+ }
+
+ @Test
+ public void testPostComplete() throws Exception {
+ String id = "container_01_01";
+ ContainerId mockContainerId = mock(ContainerId.class);
+ when(mockContainerId.toString()).thenReturn(id);
+ Assert.assertNull(cGroupsCpuResourceHandler.postComplete(mockContainerId));
+ verify(mockCGroupsHandler, times(1))
+ .deleteCGroup(CGroupsHandler.CGroupController.CPU, id);
+ }
+
+ @Test
+ public void testTeardown() throws Exception {
+ Assert.assertNull(cGroupsCpuResourceHandler.teardown());
+ }
+
+ @Test
+ public void testStrictResourceUsage() throws Exception {
+ Assert.assertNull(cGroupsCpuResourceHandler.teardown());
+ }
+}
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/util/TestCgroupsLCEResourcesHandler.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/util/TestCgroupsLCEResourcesHandler.java
index cfab65c25fc..34c9ad1299a 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/util/TestCgroupsLCEResourcesHandler.java
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/util/TestCgroupsLCEResourcesHandler.java
@@ -37,6 +37,7 @@ import java.util.List;
import java.util.Scanner;
import java.util.concurrent.CountDownLatch;
+@Deprecated
public class TestCgroupsLCEResourcesHandler {
static File cgroupDir = null;