You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@slider.apache.org by sm...@apache.org on 2014/10/16 23:06:06 UTC
git commit: SLIDER-81. Support placement of containers on labeled
YARN nodes
Repository: incubator-slider
Updated Branches:
refs/heads/develop 4dcb62cf2 -> b99019633
SLIDER-81. Support placement of containers on labeled YARN nodes
Project: http://git-wip-us.apache.org/repos/asf/incubator-slider/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-slider/commit/b9901963
Tree: http://git-wip-us.apache.org/repos/asf/incubator-slider/tree/b9901963
Diff: http://git-wip-us.apache.org/repos/asf/incubator-slider/diff/b9901963
Branch: refs/heads/develop
Commit: b9901963395a710bb67cd8e63c4d1e9d4b7cf96e
Parents: 4dcb62c
Author: Sumit Mohanty <sm...@hortonworks.com>
Authored: Thu Oct 16 13:58:56 2014 -0700
Committer: Sumit Mohanty <sm...@hortonworks.com>
Committed: Thu Oct 16 13:58:56 2014 -0700
----------------------------------------------------------------------
.../org/apache/slider/api/ResourceKeys.java | 15 +++++-
.../slider/core/launch/AbstractLauncher.java | 13 +++++
.../slider/core/launch/AppMasterLauncher.java | 1 +
.../slider/server/appmaster/state/AppState.java | 26 +++++++--
.../appmaster/state/OutstandingRequest.java | 8 +--
.../server/appmaster/state/RoleHistory.java | 24 +++++++--
.../providers/agent/TestBuildBasicAgent.groovy | 55 +++++++++++++++++++-
.../TestRoleHistoryRequestTracking.groovy | 3 +-
.../agent/tests/good/resources_with_label.json | 25 +++++++++
9 files changed, 154 insertions(+), 16 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/b9901963/slider-core/src/main/java/org/apache/slider/api/ResourceKeys.java
----------------------------------------------------------------------
diff --git a/slider-core/src/main/java/org/apache/slider/api/ResourceKeys.java b/slider-core/src/main/java/org/apache/slider/api/ResourceKeys.java
index 56961c9..f2b9d76 100644
--- a/slider-core/src/main/java/org/apache/slider/api/ResourceKeys.java
+++ b/slider-core/src/main/java/org/apache/slider/api/ResourceKeys.java
@@ -65,10 +65,21 @@ public interface ResourceKeys {
* {@value}
*/
String YARN_CORES = "yarn.vcores";
-
+
/** {@value} */
int DEF_YARN_CORES = 1;
-
+
+
+ /**
+ * Label expression that this container must satisfy
+ * {@value}
+ */
+ String YARN_LABEL_EXPRESSION = "yarn.label.expression";
+
+ /** {@value} */
+ String DEF_YARN_LABEL_EXPRESSION = null;
+
+
/**
* Constant to indicate that the requirements of a YARN resource limit
* (cores, memory, ...) should be set to the maximum allowed by
http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/b9901963/slider-core/src/main/java/org/apache/slider/core/launch/AbstractLauncher.java
----------------------------------------------------------------------
diff --git a/slider-core/src/main/java/org/apache/slider/core/launch/AbstractLauncher.java b/slider-core/src/main/java/org/apache/slider/core/launch/AbstractLauncher.java
index 0d0f1c6..0694438 100644
--- a/slider-core/src/main/java/org/apache/slider/core/launch/AbstractLauncher.java
+++ b/slider-core/src/main/java/org/apache/slider/core/launch/AbstractLauncher.java
@@ -384,5 +384,18 @@ public abstract class AbstractLauncher extends Configured {
addLocalResources(confResources);
}
+ /**
+ * Return the label expression and if not set null
+ * @param map
+ * @return
+ */
+ public String extractLabelExpression(Map<String, String> map) {
+ if (map != null) {
+ MapOperations options = new MapOperations("", map);
+ return options.getOption(ResourceKeys.YARN_LABEL_EXPRESSION, null);
+ }
+ return null;
+ }
+
}
http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/b9901963/slider-core/src/main/java/org/apache/slider/core/launch/AppMasterLauncher.java
----------------------------------------------------------------------
diff --git a/slider-core/src/main/java/org/apache/slider/core/launch/AppMasterLauncher.java b/slider-core/src/main/java/org/apache/slider/core/launch/AppMasterLauncher.java
index f1eeabd..303f777 100644
--- a/slider-core/src/main/java/org/apache/slider/core/launch/AppMasterLauncher.java
+++ b/slider-core/src/main/java/org/apache/slider/core/launch/AppMasterLauncher.java
@@ -96,6 +96,7 @@ public class AppMasterLauncher extends AbstractLauncher {
if (!applicationTags.isEmpty()) {
submissionContext.setApplicationTags(applicationTags);
}
+ submissionContext.setNodeLabelExpression(extractLabelExpression(options));
extractResourceRequirements(resource, options);
extractLogAggregationContext(resourceGlobalOptions);
}
http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/b9901963/slider-core/src/main/java/org/apache/slider/server/appmaster/state/AppState.java
----------------------------------------------------------------------
diff --git a/slider-core/src/main/java/org/apache/slider/server/appmaster/state/AppState.java b/slider-core/src/main/java/org/apache/slider/server/appmaster/state/AppState.java
index 63032b0..706b0d2 100644
--- a/slider-core/src/main/java/org/apache/slider/server/appmaster/state/AppState.java
+++ b/slider-core/src/main/java/org/apache/slider/server/appmaster/state/AppState.java
@@ -77,8 +77,10 @@ import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicInteger;
import static org.apache.slider.api.ResourceKeys.DEF_YARN_CORES;
+import static org.apache.slider.api.ResourceKeys.DEF_YARN_LABEL_EXPRESSION;
import static org.apache.slider.api.ResourceKeys.DEF_YARN_MEMORY;
import static org.apache.slider.api.ResourceKeys.YARN_CORES;
+import static org.apache.slider.api.ResourceKeys.YARN_LABEL_EXPRESSION;
import static org.apache.slider.api.ResourceKeys.YARN_MEMORY;
import static org.apache.slider.api.RoleKeys.ROLE_FAILED_INSTANCES;
import static org.apache.slider.api.RoleKeys.ROLE_FAILED_STARTING_INSTANCES;
@@ -1050,9 +1052,10 @@ public class AppState {
RoleStatus role,
Resource capability) {
buildResourceRequirements(role, capability);
+ String labelExpression = getLabelExpression(role);
//get the role history to select a suitable node, if available
AMRMClient.ContainerRequest containerRequest =
- createContainerRequest(role, capability);
+ createContainerRequest(role, capability, labelExpression);
return containerRequest;
}
@@ -1062,15 +1065,16 @@ public class AppState {
* This is where role history information will be used for placement decisions -
* @param role role
* @param resource requirements
+ * @param labelExpression label expression to satisfy
* @return the container request to submit
*/
public AMRMClient.ContainerRequest createContainerRequest(RoleStatus role,
- Resource resource) {
+ Resource resource,
+ String labelExpression) {
AMRMClient.ContainerRequest request;
- int key = role.getKey();
- request = roleHistory.requestNode(role, resource);
+ request = roleHistory.requestNode(role, resource, labelExpression);
role.incRequested();
return request;
@@ -1105,6 +1109,7 @@ public class AppState {
}
return intVal;
}
+
/**
* Build up the resource requirements for this role from the
@@ -1131,6 +1136,17 @@ public class AppState {
}
/**
+ * Extract the label expression for this role.
+ * @param role role
+ */
+ public String getLabelExpression(RoleStatus role) {
+ // Set up resource requirements from role values
+ String name = role.getName();
+ ConfTreeOperations resources = getResourcesSnapshot();
+ return resources.getComponentOpt(name, YARN_LABEL_EXPRESSION, DEF_YARN_LABEL_EXPRESSION);
+ }
+
+ /**
* add a launched container to the node map for status responses
* @param container id
* @param node node details
@@ -1614,7 +1630,7 @@ public class AppState {
Resource capability = recordFactory.newResource();
AMRMClient.ContainerRequest containerAsk =
buildContainerResourceAndRequest(role, capability);
- log.info("Container ask is {}", containerAsk);
+ log.info("Container ask is {} and label = {}", containerAsk, containerAsk.getNodeLabelExpression());
if (containerAsk.getCapability().getMemory() >
this.containerMaxMemory) {
log.warn(
http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/b9901963/slider-core/src/main/java/org/apache/slider/server/appmaster/state/OutstandingRequest.java
----------------------------------------------------------------------
diff --git a/slider-core/src/main/java/org/apache/slider/server/appmaster/state/OutstandingRequest.java b/slider-core/src/main/java/org/apache/slider/server/appmaster/state/OutstandingRequest.java
index 0d8b56c..4a05a1a 100644
--- a/slider-core/src/main/java/org/apache/slider/server/appmaster/state/OutstandingRequest.java
+++ b/slider-core/src/main/java/org/apache/slider/server/appmaster/state/OutstandingRequest.java
@@ -97,10 +97,11 @@ public final class OutstandingRequest {
* @param resource resource
* @param role role
* @param time: time to record
+ * @param labelExpression label to satisfy
* @return the request to raise
*/
public AMRMClient.ContainerRequest buildContainerRequest(Resource resource,
- RoleStatus role, long time) {
+ RoleStatus role, long time, String labelExpression) {
String[] hosts;
boolean relaxLocality;
requestedTime = time;
@@ -122,8 +123,9 @@ public final class OutstandingRequest {
hosts,
null,
pri,
- relaxLocality);
-
+ relaxLocality,
+ labelExpression);
+
return request;
}
http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/b9901963/slider-core/src/main/java/org/apache/slider/server/appmaster/state/RoleHistory.java
----------------------------------------------------------------------
diff --git a/slider-core/src/main/java/org/apache/slider/server/appmaster/state/RoleHistory.java b/slider-core/src/main/java/org/apache/slider/server/appmaster/state/RoleHistory.java
index e82162f..dca7384 100644
--- a/slider-core/src/main/java/org/apache/slider/server/appmaster/state/RoleHistory.java
+++ b/slider-core/src/main/java/org/apache/slider/server/appmaster/state/RoleHistory.java
@@ -233,7 +233,7 @@ public class RoleHistory {
/**
* Get the node instance for the specific node -creating it if needed
- * @param nodeAddr node address
+ * @param hostname node address
* @return the instance
*/
public synchronized NodeInstance getOrCreateNodeInstance(String hostname) {
@@ -495,12 +495,28 @@ public class RoleHistory {
*
* @param node node to target or null for "any"
* @param role role to request
+ * @param labelExpression label to satisfy
* @return the container priority
*/
public synchronized AMRMClient.ContainerRequest requestInstanceOnNode(
- NodeInstance node, RoleStatus role, Resource resource) {
+ NodeInstance node, RoleStatus role, Resource resource, String labelExpression) {
OutstandingRequest outstanding = outstandingRequests.addRequest(node, role.getKey());
- return outstanding.buildContainerRequest(resource, role, now());
+ return outstanding.buildContainerRequest(resource, role, now(), labelExpression);
+ }
+
+ /**
+ * Find a node for a role and request an instance on that (or a location-less
+ * instance) with a label expression
+ * @param role role status
+ * @param resource resource capabilities
+ * @param labelExpression label to satisfy
+ * @return a request ready to go
+ */
+ public synchronized AMRMClient.ContainerRequest requestNode(RoleStatus role,
+ Resource resource,
+ String labelExpression) {
+ NodeInstance node = findNodeForNewInstance(role);
+ return requestInstanceOnNode(node, role, resource, labelExpression);
}
/**
@@ -513,7 +529,7 @@ public class RoleHistory {
public synchronized AMRMClient.ContainerRequest requestNode(RoleStatus role,
Resource resource) {
NodeInstance node = findNodeForNewInstance(role);
- return requestInstanceOnNode(node, role, resource);
+ return requestInstanceOnNode(node, role, resource, null);
}
/**
http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/b9901963/slider-core/src/test/groovy/org/apache/slider/providers/agent/TestBuildBasicAgent.groovy
----------------------------------------------------------------------
diff --git a/slider-core/src/test/groovy/org/apache/slider/providers/agent/TestBuildBasicAgent.groovy b/slider-core/src/test/groovy/org/apache/slider/providers/agent/TestBuildBasicAgent.groovy
index d0129c5..7e352e9 100644
--- a/slider-core/src/test/groovy/org/apache/slider/providers/agent/TestBuildBasicAgent.groovy
+++ b/slider-core/src/test/groovy/org/apache/slider/providers/agent/TestBuildBasicAgent.groovy
@@ -243,7 +243,60 @@ class TestBuildBasicAgent extends AgentTestBase {
true, false,
false)
}
-
+
+ @Test
+ public void testLabelExpressionArgs() throws Throwable {
+ String clustername = createMiniCluster(
+ "",
+ configuration,
+ 1,
+ 1,
+ 1,
+ true,
+ false)
+
+ try {
+ buildAgentCluster(clustername,
+ [:],
+ [
+ ARG_OPTION, CONTROLLER_URL, "http://localhost",
+ ARG_PACKAGE, ".",
+ ARG_OPTION, APP_DEF, "file://" + appDef.absolutePath,
+ ARG_RESOURCES, TEST_FILES + "good/resources_with_label.json",
+ ARG_TEMPLATE, TEST_FILES + "good/appconf.json"
+ ],
+ true, false,
+ false)
+ } catch (BadConfigException exception) {
+ log.error(
+ "Build operation should not have failed with exception : \n$exception")
+ fail("Build operation should not fail")
+ }
+
+ AggregateConf instanceDefinition = loadInstanceDefinition(clustername)
+ def opt = instanceDefinition.getResourceOperations().getComponentOpt(
+ "echo",
+ ResourceKeys.YARN_LABEL_EXPRESSION,
+ null)
+ assert opt == null, "Expect null"
+
+ opt = instanceDefinition.getResourceOperations().getComponentOpt(
+ "hbase-master",
+ ResourceKeys.YARN_LABEL_EXPRESSION,
+ null)
+ assert opt == "", "Expect empty string"
+
+ opt = instanceDefinition.getResourceOperations().getComponentOpt(
+ "hbase-rs",
+ ResourceKeys.YARN_LABEL_EXPRESSION,
+ null)
+ assert opt == "coquelicot && amaranth", "Expect colors you have not heard of"
+
+ def label = instanceDefinition.getInternalOperations().get(
+ InternalKeys.INTERNAL_QUEUE)
+ assert label == null, "Default queue expected"
+ }
+
@Test
public void testUpdateBasicAgent() throws Throwable {
http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/b9901963/slider-core/src/test/groovy/org/apache/slider/server/appmaster/model/history/TestRoleHistoryRequestTracking.groovy
----------------------------------------------------------------------
diff --git a/slider-core/src/test/groovy/org/apache/slider/server/appmaster/model/history/TestRoleHistoryRequestTracking.groovy b/slider-core/src/test/groovy/org/apache/slider/server/appmaster/model/history/TestRoleHistoryRequestTracking.groovy
index 0a2ba60..8f577e5 100644
--- a/slider-core/src/test/groovy/org/apache/slider/server/appmaster/model/history/TestRoleHistoryRequestTracking.groovy
+++ b/slider-core/src/test/groovy/org/apache/slider/server/appmaster/model/history/TestRoleHistoryRequestTracking.groovy
@@ -77,7 +77,8 @@ class TestRoleHistoryRequestTracking extends BaseMockAppStateTest {
assert age3Active0 == ni
AMRMClient.ContainerRequest req = roleHistory.requestInstanceOnNode(ni,
roleStatus,
- resource)
+ resource,
+ "")
List<NodeInstance> a2 = roleHistory.cloneAvailableList(0)
assertListEquals([age2Active0], a2)
}
http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/b9901963/slider-core/src/test/resources/org/apache/slider/providers/agent/tests/good/resources_with_label.json
----------------------------------------------------------------------
diff --git a/slider-core/src/test/resources/org/apache/slider/providers/agent/tests/good/resources_with_label.json b/slider-core/src/test/resources/org/apache/slider/providers/agent/tests/good/resources_with_label.json
new file mode 100644
index 0000000..a2ce107
--- /dev/null
+++ b/slider-core/src/test/resources/org/apache/slider/providers/agent/tests/good/resources_with_label.json
@@ -0,0 +1,25 @@
+{
+ "schema": "http://example.org/specification/v2.0.0",
+
+ "global": {
+ },
+ "components": {
+ "echo": {
+ "yarn.memory": "256",
+ "yarn.component.instances": "1",
+ "yarn.role.priority":"1"
+ },
+ "hbase-master": {
+ "yarn.memory": "257",
+ "yarn.component.instances": "1",
+ "yarn.role.priority":"2",
+ "yarn.label.expression":""
+ },
+ "hbase-rs": {
+ "yarn.memory": "258",
+ "yarn.component.instances": "0",
+ "yarn.role.priority":"4",
+ "yarn.label.expression":"coquelicot && amaranth"
+ }
+ }
+}