YARN-2729. Support script based NodeLabelsProvider Interface in Distributed Node Label Configuration Setup. (Naganarasimha G R via rohithsharmaks)
(cherry picked from commit 5acdde4744
)
This commit is contained in:
parent
06ecc37e82
commit
33455fa415
|
@ -186,6 +186,9 @@ Release 2.8.0 - UNRELEASED
|
||||||
YARN-3739. Add reservation system recovery to RM recovery process.
|
YARN-3739. Add reservation system recovery to RM recovery process.
|
||||||
(Subru Krishnan via adhoot)
|
(Subru Krishnan via adhoot)
|
||||||
|
|
||||||
|
YARN-2729. Support script based NodeLabelsProvider Interface in Distributed Node Label
|
||||||
|
Configuration Setup. (Naganarasimha G R via rohithsharmaks)
|
||||||
|
|
||||||
IMPROVEMENTS
|
IMPROVEMENTS
|
||||||
|
|
||||||
YARN-644. Basic null check is not performed on passed in arguments before
|
YARN-644. Basic null check is not performed on passed in arguments before
|
||||||
|
|
|
@ -2112,6 +2112,12 @@ public class YarnConfiguration extends Configuration {
|
||||||
NODELABEL_CONFIGURATION_TYPE, DEFAULT_NODELABEL_CONFIGURATION_TYPE));
|
NODELABEL_CONFIGURATION_TYPE, DEFAULT_NODELABEL_CONFIGURATION_TYPE));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Private
|
||||||
|
public static boolean areNodeLabelsEnabled(
|
||||||
|
Configuration conf) {
|
||||||
|
return conf.getBoolean(NODE_LABELS_ENABLED, DEFAULT_NODE_LABELS_ENABLED);
|
||||||
|
}
|
||||||
|
|
||||||
private static final String NM_NODE_LABELS_PREFIX = NM_PREFIX
|
private static final String NM_NODE_LABELS_PREFIX = NM_PREFIX
|
||||||
+ "node-labels.";
|
+ "node-labels.";
|
||||||
|
|
||||||
|
@ -2120,6 +2126,7 @@ public class YarnConfiguration extends Configuration {
|
||||||
|
|
||||||
// whitelist names for the yarn.nodemanager.node-labels.provider
|
// whitelist names for the yarn.nodemanager.node-labels.provider
|
||||||
public static final String CONFIG_NODE_LABELS_PROVIDER = "config";
|
public static final String CONFIG_NODE_LABELS_PROVIDER = "config";
|
||||||
|
public static final String SCRIPT_NODE_LABELS_PROVIDER = "script";
|
||||||
|
|
||||||
private static final String NM_NODE_LABELS_PROVIDER_PREFIX =
|
private static final String NM_NODE_LABELS_PROVIDER_PREFIX =
|
||||||
NM_NODE_LABELS_PREFIX + "provider.";
|
NM_NODE_LABELS_PREFIX + "provider.";
|
||||||
|
@ -2145,8 +2152,8 @@ public class YarnConfiguration extends Configuration {
|
||||||
public static final long DEFAULT_NM_NODE_LABELS_PROVIDER_FETCH_TIMEOUT_MS =
|
public static final long DEFAULT_NM_NODE_LABELS_PROVIDER_FETCH_TIMEOUT_MS =
|
||||||
DEFAULT_NM_NODE_LABELS_PROVIDER_FETCH_INTERVAL_MS * 2;
|
DEFAULT_NM_NODE_LABELS_PROVIDER_FETCH_INTERVAL_MS * 2;
|
||||||
|
|
||||||
public static final String NM_PROVIDER_CONFIGURED_NODE_LABELS =
|
public static final String NM_PROVIDER_CONFIGURED_NODE_PARTITION =
|
||||||
NM_NODE_LABELS_PROVIDER_PREFIX + "configured-node-labels";
|
NM_NODE_LABELS_PROVIDER_PREFIX + "configured-node-partition";
|
||||||
|
|
||||||
private static final String RM_NODE_LABELS_PREFIX = RM_PREFIX
|
private static final String RM_NODE_LABELS_PREFIX = RM_PREFIX
|
||||||
+ "node-labels.";
|
+ "node-labels.";
|
||||||
|
@ -2174,6 +2181,15 @@ public class YarnConfiguration extends Configuration {
|
||||||
public static final float DEFAULT_AM_BLACKLISTING_DISABLE_THRESHOLD = 0.8f;
|
public static final float DEFAULT_AM_BLACKLISTING_DISABLE_THRESHOLD = 0.8f;
|
||||||
|
|
||||||
|
|
||||||
|
private static final String NM_SCRIPT_BASED_NODE_LABELS_PROVIDER_PREFIX =
|
||||||
|
NM_NODE_LABELS_PROVIDER_PREFIX + "script.";
|
||||||
|
|
||||||
|
public static final String NM_SCRIPT_BASED_NODE_LABELS_PROVIDER_PATH =
|
||||||
|
NM_SCRIPT_BASED_NODE_LABELS_PROVIDER_PREFIX + "path";
|
||||||
|
|
||||||
|
public static final String NM_SCRIPT_BASED_NODE_LABELS_PROVIDER_SCRIPT_OPTS =
|
||||||
|
NM_SCRIPT_BASED_NODE_LABELS_PROVIDER_PREFIX + "opts";
|
||||||
|
|
||||||
public YarnConfiguration() {
|
public YarnConfiguration() {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
|
@ -216,9 +216,7 @@ public class CommonNodeLabelsManager extends AbstractService {
|
||||||
@Override
|
@Override
|
||||||
protected void serviceInit(Configuration conf) throws Exception {
|
protected void serviceInit(Configuration conf) throws Exception {
|
||||||
// set if node labels enabled
|
// set if node labels enabled
|
||||||
nodeLabelsEnabled =
|
nodeLabelsEnabled = YarnConfiguration.areNodeLabelsEnabled(conf);
|
||||||
conf.getBoolean(YarnConfiguration.NODE_LABELS_ENABLED,
|
|
||||||
YarnConfiguration.DEFAULT_NODE_LABELS_ENABLED);
|
|
||||||
|
|
||||||
isCentralizedNodeLabelConfiguration =
|
isCentralizedNodeLabelConfiguration =
|
||||||
YarnConfiguration.isCentralizedNodeLabelConfiguration(conf);
|
YarnConfiguration.isCentralizedNodeLabelConfiguration(conf);
|
||||||
|
|
|
@ -2169,14 +2169,14 @@
|
||||||
<!-- Distributed Node Labels Configuration -->
|
<!-- Distributed Node Labels Configuration -->
|
||||||
<property>
|
<property>
|
||||||
<description>
|
<description>
|
||||||
When node labels "yarn.node-labels.configuration-type" is
|
When "yarn.node-labels.configuration-type" parameter in RM is configured as
|
||||||
of type "distributed" Administrators can configure the source of the
|
"distributed", Administrators can configure in NM, the provider for the
|
||||||
node labels provider by configuring this parameter. Administrators can
|
node labels by configuring this parameter. Administrators can
|
||||||
specify either "config" or the class name of the provider. Configured
|
specify "config", "script" or the class name of the provider. Configured
|
||||||
class needs to extend
|
class needs to extend
|
||||||
org.apache.hadoop.yarn.server.nodemanager.nodelabels.NodeLabelsProvider.
|
org.apache.hadoop.yarn.server.nodemanager.nodelabels.NodeLabelsProvider.
|
||||||
If "config" is specified then, "ConfigurationNodeLabelsProvider" will
|
If "config" is specified then "ConfigurationNodeLabelsProvider" and
|
||||||
be used.
|
"script" then "ScriptNodeLabelsProvider" will be used.
|
||||||
</description>
|
</description>
|
||||||
<name>yarn.nodemanager.node-labels.provider</name>
|
<name>yarn.nodemanager.node-labels.provider</name>
|
||||||
</property>
|
</property>
|
||||||
|
@ -2207,9 +2207,9 @@
|
||||||
<description>
|
<description>
|
||||||
When node labels "yarn.nodemanager.node-labels.provider"
|
When node labels "yarn.nodemanager.node-labels.provider"
|
||||||
is of type "config" then ConfigurationNodeLabelsProvider fetches the
|
is of type "config" then ConfigurationNodeLabelsProvider fetches the
|
||||||
labels this parameter.
|
partition from this parameter.
|
||||||
</description>
|
</description>
|
||||||
<name>yarn.nodemanager.node-labels.provider.configured-node-labels</name>
|
<name>yarn.nodemanager.node-labels.provider.configured-node-partition</name>
|
||||||
</property>
|
</property>
|
||||||
|
|
||||||
<property>
|
<property>
|
||||||
|
@ -2248,6 +2248,18 @@
|
||||||
<name>yarn.resourcemanager.node-labels.provider.fetch-interval-ms</name>
|
<name>yarn.resourcemanager.node-labels.provider.fetch-interval-ms</name>
|
||||||
<value>1800000</value>
|
<value>1800000</value>
|
||||||
</property>
|
</property>
|
||||||
|
|
||||||
|
<property>
|
||||||
|
<description>The Node Label script to run. Script output Lines starting with
|
||||||
|
"NODE_PARTITION:" will be considered for Node Labels. In case of multiple
|
||||||
|
lines having the pattern, last one will be considered</description>
|
||||||
|
<name>yarn.nodemanager.node-labels.provider.script.path</name>
|
||||||
|
</property>
|
||||||
|
|
||||||
|
<property>
|
||||||
|
<description>The arguments to pass to the Node label script.</description>
|
||||||
|
<name>yarn.nodemanager.node-labels.provider.script.opts</name>
|
||||||
|
</property>
|
||||||
<!-- Other Configuration -->
|
<!-- Other Configuration -->
|
||||||
|
|
||||||
<property>
|
<property>
|
||||||
|
|
|
@ -65,6 +65,7 @@ import org.apache.hadoop.yarn.server.nodemanager.containermanager.container.Cont
|
||||||
import org.apache.hadoop.yarn.server.nodemanager.metrics.NodeManagerMetrics;
|
import org.apache.hadoop.yarn.server.nodemanager.metrics.NodeManagerMetrics;
|
||||||
import org.apache.hadoop.yarn.server.nodemanager.nodelabels.ConfigurationNodeLabelsProvider;
|
import org.apache.hadoop.yarn.server.nodemanager.nodelabels.ConfigurationNodeLabelsProvider;
|
||||||
import org.apache.hadoop.yarn.server.nodemanager.nodelabels.NodeLabelsProvider;
|
import org.apache.hadoop.yarn.server.nodemanager.nodelabels.NodeLabelsProvider;
|
||||||
|
import org.apache.hadoop.yarn.server.nodemanager.nodelabels.ScriptBasedNodeLabelsProvider;
|
||||||
import org.apache.hadoop.yarn.server.nodemanager.recovery.NMLeveldbStateStoreService;
|
import org.apache.hadoop.yarn.server.nodemanager.recovery.NMLeveldbStateStoreService;
|
||||||
import org.apache.hadoop.yarn.server.nodemanager.recovery.NMNullStateStoreService;
|
import org.apache.hadoop.yarn.server.nodemanager.recovery.NMNullStateStoreService;
|
||||||
import org.apache.hadoop.yarn.server.nodemanager.recovery.NMStateStoreService;
|
import org.apache.hadoop.yarn.server.nodemanager.recovery.NMStateStoreService;
|
||||||
|
@ -137,18 +138,21 @@ public class NodeManager extends CompositeService
|
||||||
case YarnConfiguration.CONFIG_NODE_LABELS_PROVIDER:
|
case YarnConfiguration.CONFIG_NODE_LABELS_PROVIDER:
|
||||||
provider = new ConfigurationNodeLabelsProvider();
|
provider = new ConfigurationNodeLabelsProvider();
|
||||||
break;
|
break;
|
||||||
|
case YarnConfiguration.SCRIPT_NODE_LABELS_PROVIDER:
|
||||||
|
provider = new ScriptBasedNodeLabelsProvider();
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
try {
|
try {
|
||||||
Class<? extends NodeLabelsProvider> labelsProviderClass =
|
Class<? extends NodeLabelsProvider> labelsProviderClass =
|
||||||
conf.getClass(YarnConfiguration.NM_NODE_LABELS_PROVIDER_CONFIG, null,
|
conf.getClass(YarnConfiguration.NM_NODE_LABELS_PROVIDER_CONFIG,
|
||||||
NodeLabelsProvider.class);
|
null, NodeLabelsProvider.class);
|
||||||
provider = labelsProviderClass.newInstance();
|
provider = labelsProviderClass.newInstance();
|
||||||
} catch (InstantiationException | IllegalAccessException
|
} catch (InstantiationException | IllegalAccessException
|
||||||
| RuntimeException e) {
|
| RuntimeException e) {
|
||||||
LOG.error("Failed to create NodeLabelsProvider based on Configuration",
|
LOG.error("Failed to create NodeLabelsProvider based on Configuration",
|
||||||
e);
|
e);
|
||||||
throw new IOException("Failed to create NodeLabelsProvider : "
|
throw new IOException(
|
||||||
+ e.getMessage(), e);
|
"Failed to create NodeLabelsProvider : " + e.getMessage(), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (LOG.isDebugEnabled()) {
|
if (LOG.isDebugEnabled()) {
|
||||||
|
@ -315,7 +319,7 @@ public class NodeManager extends CompositeService
|
||||||
nodeStatusUpdater =
|
nodeStatusUpdater =
|
||||||
createNodeStatusUpdater(context, dispatcher, nodeHealthChecker);
|
createNodeStatusUpdater(context, dispatcher, nodeHealthChecker);
|
||||||
} else {
|
} else {
|
||||||
addService(nodeLabelsProvider);
|
addIfService(nodeLabelsProvider);
|
||||||
nodeStatusUpdater =
|
nodeStatusUpdater =
|
||||||
createNodeStatusUpdater(context, dispatcher, nodeHealthChecker,
|
createNodeStatusUpdater(context, dispatcher, nodeHealthChecker,
|
||||||
nodeLabelsProvider);
|
nodeLabelsProvider);
|
||||||
|
|
|
@ -976,7 +976,12 @@ public class NodeStatusUpdaterImpl extends AbstractService implements
|
||||||
.append(StringUtils.join(",", previousNodeLabels)).append("}");
|
.append(StringUtils.join(",", previousNodeLabels)).append("}");
|
||||||
} else {
|
} else {
|
||||||
// case where provider is set but RM did not accept the Node Labels
|
// case where provider is set but RM did not accept the Node Labels
|
||||||
LOG.error(regNMResponse.getDiagnosticsMessage());
|
String errorMsgFromRM = regNMResponse.getDiagnosticsMessage();
|
||||||
|
LOG.error(
|
||||||
|
"NodeLabels sent from NM while registration were rejected by RM. "
|
||||||
|
+ ((errorMsgFromRM == null)
|
||||||
|
? "Seems like RM is configured with Centralized Labels."
|
||||||
|
: "And with message " + regNMResponse.getDiagnosticsMessage()));
|
||||||
}
|
}
|
||||||
return successfulNodeLabelsRegistrationMsg.toString();
|
return successfulNodeLabelsRegistrationMsg.toString();
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@ import java.util.concurrent.locks.ReadWriteLock;
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||||
|
|
||||||
import org.apache.hadoop.conf.Configuration;
|
import org.apache.hadoop.conf.Configuration;
|
||||||
|
import org.apache.hadoop.service.AbstractService;
|
||||||
import org.apache.hadoop.yarn.api.records.NodeLabel;
|
import org.apache.hadoop.yarn.api.records.NodeLabel;
|
||||||
import org.apache.hadoop.yarn.conf.YarnConfiguration;
|
import org.apache.hadoop.yarn.conf.YarnConfiguration;
|
||||||
import org.apache.hadoop.yarn.nodelabels.CommonNodeLabelsManager;
|
import org.apache.hadoop.yarn.nodelabels.CommonNodeLabelsManager;
|
||||||
|
@ -34,7 +35,8 @@ import org.apache.hadoop.yarn.nodelabels.CommonNodeLabelsManager;
|
||||||
* Provides base implementation of NodeLabelsProvider with Timer and expects
|
* Provides base implementation of NodeLabelsProvider with Timer and expects
|
||||||
* subclass to provide TimerTask which can fetch NodeLabels
|
* subclass to provide TimerTask which can fetch NodeLabels
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractNodeLabelsProvider extends NodeLabelsProvider {
|
public abstract class AbstractNodeLabelsProvider extends AbstractService
|
||||||
|
implements NodeLabelsProvider {
|
||||||
public static final long DISABLE_NODE_LABELS_PROVIDER_FETCH_TIMER = -1;
|
public static final long DISABLE_NODE_LABELS_PROVIDER_FETCH_TIMER = -1;
|
||||||
|
|
||||||
// Delay after which timer task are triggered to fetch NodeLabels
|
// Delay after which timer task are triggered to fetch NodeLabels
|
||||||
|
@ -94,9 +96,15 @@ public abstract class AbstractNodeLabelsProvider extends NodeLabelsProvider {
|
||||||
if (nodeLabelsScheduler != null) {
|
if (nodeLabelsScheduler != null) {
|
||||||
nodeLabelsScheduler.cancel();
|
nodeLabelsScheduler.cancel();
|
||||||
}
|
}
|
||||||
|
cleanUp();
|
||||||
super.serviceStop();
|
super.serviceStop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* method for subclasses to cleanup.
|
||||||
|
*/
|
||||||
|
protected abstract void cleanUp() throws Exception ;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Returns output from provider.
|
* @return Returns output from provider.
|
||||||
*/
|
*/
|
||||||
|
@ -119,6 +127,15 @@ public abstract class AbstractNodeLabelsProvider extends NodeLabelsProvider {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Set<NodeLabel> convertToNodeLabelSet(String partitionNodeLabel) {
|
||||||
|
if (null == partitionNodeLabel) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
Set<NodeLabel> labels = new HashSet<NodeLabel>();
|
||||||
|
labels.add(NodeLabel.newInstance(partitionNodeLabel));
|
||||||
|
return labels;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used only by tests to access the timer task directly
|
* Used only by tests to access the timer task directly
|
||||||
*
|
*
|
||||||
|
@ -128,16 +145,5 @@ public abstract class AbstractNodeLabelsProvider extends NodeLabelsProvider {
|
||||||
return timerTask;
|
return timerTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Set<NodeLabel> convertToNodeLabelSet(Set<String> nodeLabels) {
|
|
||||||
if (null == nodeLabels) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
Set<NodeLabel> labels = new HashSet<NodeLabel>();
|
|
||||||
for (String label : nodeLabels) {
|
|
||||||
labels.add(NodeLabel.newInstance(label));
|
|
||||||
}
|
|
||||||
return labels;
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract TimerTask createTimerTask();
|
public abstract TimerTask createTimerTask();
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,14 +19,11 @@
|
||||||
package org.apache.hadoop.yarn.server.nodemanager.nodelabels;
|
package org.apache.hadoop.yarn.server.nodemanager.nodelabels;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.TimerTask;
|
import java.util.TimerTask;
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
import org.apache.hadoop.conf.Configuration;
|
import org.apache.hadoop.conf.Configuration;
|
||||||
import org.apache.hadoop.util.StringUtils;
|
|
||||||
import org.apache.hadoop.yarn.conf.YarnConfiguration;
|
import org.apache.hadoop.yarn.conf.YarnConfiguration;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -43,13 +40,9 @@ public class ConfigurationNodeLabelsProvider extends AbstractNodeLabelsProvider
|
||||||
|
|
||||||
private void updateNodeLabelsFromConfig(Configuration conf)
|
private void updateNodeLabelsFromConfig(Configuration conf)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
String confLabelString =
|
String configuredNodePartition =
|
||||||
conf.get(YarnConfiguration.NM_PROVIDER_CONFIGURED_NODE_LABELS, null);
|
conf.get(YarnConfiguration.NM_PROVIDER_CONFIGURED_NODE_PARTITION, null);
|
||||||
String[] nodeLabelsFromConfiguration =
|
setNodeLabels(convertToNodeLabelSet(configuredNodePartition));
|
||||||
(confLabelString == null || confLabelString.isEmpty()) ? new String[] {}
|
|
||||||
: StringUtils.getStrings(confLabelString);
|
|
||||||
setNodeLabels(convertToNodeLabelSet(new HashSet<String>(
|
|
||||||
Arrays.asList(nodeLabelsFromConfiguration))));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ConfigurationMonitorTimerTask extends TimerTask {
|
private class ConfigurationMonitorTimerTask extends TimerTask {
|
||||||
|
@ -67,4 +60,9 @@ public class ConfigurationNodeLabelsProvider extends AbstractNodeLabelsProvider
|
||||||
public TimerTask createTimerTask() {
|
public TimerTask createTimerTask() {
|
||||||
return new ConfigurationMonitorTimerTask();
|
return new ConfigurationMonitorTimerTask();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void cleanUp() throws Exception {
|
||||||
|
//No cleanup Req!
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,18 +20,13 @@ package org.apache.hadoop.yarn.server.nodemanager.nodelabels;
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.apache.hadoop.service.AbstractService;
|
|
||||||
import org.apache.hadoop.yarn.api.records.NodeLabel;
|
import org.apache.hadoop.yarn.api.records.NodeLabel;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface which will be responsible for fetching the labels
|
* Interface which will be responsible for fetching the labels
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public abstract class NodeLabelsProvider extends AbstractService {
|
public interface NodeLabelsProvider {
|
||||||
|
|
||||||
public NodeLabelsProvider(String name) {
|
|
||||||
super(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides the labels. LabelProvider is expected to give same Labels
|
* Provides the labels. LabelProvider is expected to give same Labels
|
||||||
|
|
|
@ -0,0 +1,190 @@
|
||||||
|
/**
|
||||||
|
* 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.nodelabels;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.Timer;
|
||||||
|
import java.util.TimerTask;
|
||||||
|
|
||||||
|
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.util.Shell.ShellCommandExecutor;
|
||||||
|
import org.apache.hadoop.yarn.api.records.NodeLabel;
|
||||||
|
import org.apache.hadoop.yarn.conf.YarnConfiguration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The class which provides functionality of getting the labels of the node
|
||||||
|
* using the configured node labels provider script. "NODE_PARTITION:" is the
|
||||||
|
* pattern which will be used to search node label partition from the out put of
|
||||||
|
* the NodeLabels provider script
|
||||||
|
*/
|
||||||
|
public class ScriptBasedNodeLabelsProvider extends AbstractNodeLabelsProvider {
|
||||||
|
/** Absolute path to the node labels script. */
|
||||||
|
private String nodeLabelsScriptPath;
|
||||||
|
|
||||||
|
/** Time after which the script should be timed out */
|
||||||
|
private long scriptTimeout;
|
||||||
|
|
||||||
|
/** ShellCommandExecutor used to execute monitoring script */
|
||||||
|
ShellCommandExecutor shexec = null;
|
||||||
|
|
||||||
|
/** Pattern used for searching in the output of the node labels script */
|
||||||
|
public static final String NODE_LABEL_PARTITION_PATTERN = "NODE_PARTITION:";
|
||||||
|
|
||||||
|
private String[] scriptArgs;
|
||||||
|
|
||||||
|
public ScriptBasedNodeLabelsProvider() {
|
||||||
|
super(ScriptBasedNodeLabelsProvider.class.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Method which initializes the values for the script path and interval time.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected void serviceInit(Configuration conf) throws Exception {
|
||||||
|
super.serviceInit(conf);
|
||||||
|
this.nodeLabelsScriptPath =
|
||||||
|
conf.get(YarnConfiguration.NM_SCRIPT_BASED_NODE_LABELS_PROVIDER_PATH);
|
||||||
|
this.scriptTimeout =
|
||||||
|
conf.getLong(YarnConfiguration.NM_NODE_LABELS_PROVIDER_FETCH_TIMEOUT_MS,
|
||||||
|
YarnConfiguration.DEFAULT_NM_NODE_LABELS_PROVIDER_FETCH_TIMEOUT_MS);
|
||||||
|
scriptArgs = conf.getStrings(
|
||||||
|
YarnConfiguration.NM_SCRIPT_BASED_NODE_LABELS_PROVIDER_SCRIPT_OPTS,
|
||||||
|
new String[] {});
|
||||||
|
|
||||||
|
verifyConfiguredScript();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method used to determine if or not node labels fetching script is
|
||||||
|
* configured and whether it is fit to run. Returns true if following
|
||||||
|
* conditions are met:
|
||||||
|
*
|
||||||
|
* <ol>
|
||||||
|
* <li>Path to Node Labels fetch script is not empty</li>
|
||||||
|
* <li>Node Labels fetch script file exists</li>
|
||||||
|
* </ol>
|
||||||
|
*
|
||||||
|
* @param conf
|
||||||
|
* @return true if node labels script can be run.
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
private void verifyConfiguredScript()
|
||||||
|
throws IOException {
|
||||||
|
boolean invalidConfiguration = false;
|
||||||
|
if (nodeLabelsScriptPath == null
|
||||||
|
|| nodeLabelsScriptPath.trim().isEmpty()) {
|
||||||
|
invalidConfiguration = true;
|
||||||
|
} else {
|
||||||
|
File f = new File(nodeLabelsScriptPath);
|
||||||
|
invalidConfiguration = !f.exists() || !FileUtil.canExecute(f);
|
||||||
|
}
|
||||||
|
if (invalidConfiguration) {
|
||||||
|
throw new IOException(
|
||||||
|
"Distributed Node labels provider script \"" + nodeLabelsScriptPath
|
||||||
|
+ "\" is not configured properly. Please check whether the script "
|
||||||
|
+ "path exists, owner and the access rights are suitable for NM "
|
||||||
|
+ "process to execute it");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method used to terminate the Node Labels Fetch script.
|
||||||
|
*
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void cleanUp() {
|
||||||
|
if (shexec != null) {
|
||||||
|
Process p = shexec.getProcess();
|
||||||
|
if (p != null) {
|
||||||
|
p.destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TimerTask createTimerTask() {
|
||||||
|
return new NodeLabelsScriptRunner();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class which is used by the {@link Timer} class to periodically execute the
|
||||||
|
* node labels script.
|
||||||
|
*/
|
||||||
|
private class NodeLabelsScriptRunner extends TimerTask {
|
||||||
|
|
||||||
|
private final Log LOG = LogFactory.getLog(NodeLabelsScriptRunner.class);
|
||||||
|
|
||||||
|
public NodeLabelsScriptRunner() {
|
||||||
|
ArrayList<String> execScript = new ArrayList<String>();
|
||||||
|
execScript.add(nodeLabelsScriptPath);
|
||||||
|
if (scriptArgs != null) {
|
||||||
|
execScript.addAll(Arrays.asList(scriptArgs));
|
||||||
|
}
|
||||||
|
shexec = new ShellCommandExecutor(
|
||||||
|
execScript.toArray(new String[execScript.size()]), null, null,
|
||||||
|
scriptTimeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
shexec.execute();
|
||||||
|
setNodeLabels(fetchLabelsFromScriptOutput(shexec.getOutput()));
|
||||||
|
} catch (Exception e) {
|
||||||
|
if (shexec.isTimedOut()) {
|
||||||
|
LOG.warn("Node Labels script timed out, Caught exception : "
|
||||||
|
+ e.getMessage(), e);
|
||||||
|
} else {
|
||||||
|
LOG.warn("Execution of Node Labels script failed, Caught exception : "
|
||||||
|
+ e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method which collect lines from the output string which begins with
|
||||||
|
* Patterns provided.
|
||||||
|
*
|
||||||
|
* @param scriptOutput string
|
||||||
|
* @return true if output string has error pattern in it.
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
private Set<NodeLabel> fetchLabelsFromScriptOutput(String scriptOutput)
|
||||||
|
throws IOException {
|
||||||
|
String nodePartitionLabel = null;
|
||||||
|
String[] splits = scriptOutput.split("\n");
|
||||||
|
for (String line : splits) {
|
||||||
|
String trimmedLine = line.trim();
|
||||||
|
if (trimmedLine.startsWith(NODE_LABEL_PARTITION_PATTERN)) {
|
||||||
|
nodePartitionLabel =
|
||||||
|
trimmedLine.substring(NODE_LABEL_PARTITION_PATTERN.length());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return convertToNodeLabelSet(nodePartitionLabel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -192,14 +192,10 @@ public class TestNodeStatusUpdaterForLabels extends NodeLabelTestBase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class DummyNodeLabelsProvider extends NodeLabelsProvider {
|
public static class DummyNodeLabelsProvider implements NodeLabelsProvider {
|
||||||
|
|
||||||
private Set<NodeLabel> nodeLabels = CommonNodeLabelsManager.EMPTY_NODELABEL_SET;
|
private Set<NodeLabel> nodeLabels = CommonNodeLabelsManager.EMPTY_NODELABEL_SET;
|
||||||
|
|
||||||
public DummyNodeLabelsProvider() {
|
|
||||||
super(DummyNodeLabelsProvider.class.getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized Set<NodeLabel> getNodeLabels() {
|
public synchronized Set<NodeLabel> getNodeLabels() {
|
||||||
return nodeLabels;
|
return nodeLabels;
|
||||||
|
|
|
@ -51,8 +51,11 @@ public class TestConfigurationNodeLabelsProvider extends NodeLabelTestBase {
|
||||||
|
|
||||||
private ConfigurationNodeLabelsProvider nodeLabelsProvider;
|
private ConfigurationNodeLabelsProvider nodeLabelsProvider;
|
||||||
|
|
||||||
|
private static ClassLoader classContextClassLoader;
|
||||||
|
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
public static void create() {
|
public static void create() {
|
||||||
|
classContextClassLoader = Thread.currentThread().getContextClassLoader();
|
||||||
loader =
|
loader =
|
||||||
new XMLPathClassLoader(
|
new XMLPathClassLoader(
|
||||||
TestConfigurationNodeLabelsProvider.class.getClassLoader());
|
TestConfigurationNodeLabelsProvider.class.getClassLoader());
|
||||||
|
@ -75,9 +78,14 @@ public class TestConfigurationNodeLabelsProvider extends NodeLabelTestBase {
|
||||||
|
|
||||||
@AfterClass
|
@AfterClass
|
||||||
public static void remove() throws Exception {
|
public static void remove() throws Exception {
|
||||||
|
if (classContextClassLoader != null) {
|
||||||
|
// testcases will fail after testcases present in this class, as
|
||||||
|
// yarn-site.xml will be deleted
|
||||||
|
Thread.currentThread().setContextClassLoader(classContextClassLoader);
|
||||||
|
}
|
||||||
if (testRootDir.exists()) {
|
if (testRootDir.exists()) {
|
||||||
FileContext.getLocalFSFileContext().delete(
|
FileContext.getLocalFSFileContext()
|
||||||
new Path(testRootDir.getAbsolutePath()), true);
|
.delete(new Path(testRootDir.getAbsolutePath()), true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,25 +93,25 @@ public class TestConfigurationNodeLabelsProvider extends NodeLabelTestBase {
|
||||||
public void testNodeLabelsFromConfig() throws IOException,
|
public void testNodeLabelsFromConfig() throws IOException,
|
||||||
InterruptedException {
|
InterruptedException {
|
||||||
Configuration conf = new Configuration();
|
Configuration conf = new Configuration();
|
||||||
modifyConf("A,B,CX");
|
modifyConf("A");
|
||||||
nodeLabelsProvider.init(conf);
|
nodeLabelsProvider.init(conf);
|
||||||
// test for ensuring labels are set during initialization of the class
|
// test for ensuring labels are set during initialization of the class
|
||||||
nodeLabelsProvider.start();
|
nodeLabelsProvider.start();
|
||||||
assertNLCollectionEquals(toNodeLabelSet("A", "B", "CX"),
|
assertNLCollectionEquals(toNodeLabelSet("A"),
|
||||||
nodeLabelsProvider.getNodeLabels());
|
nodeLabelsProvider.getNodeLabels());
|
||||||
|
|
||||||
// test for valid Modification
|
// test for valid Modification
|
||||||
TimerTask timerTask = nodeLabelsProvider.getTimerTask();
|
TimerTask timerTask = nodeLabelsProvider.getTimerTask();
|
||||||
modifyConf("X,y,Z");
|
modifyConf("X");
|
||||||
timerTask.run();
|
timerTask.run();
|
||||||
assertNLCollectionEquals(toNodeLabelSet("X", "y", "Z"),
|
assertNLCollectionEquals(toNodeLabelSet("X"),
|
||||||
nodeLabelsProvider.getNodeLabels());
|
nodeLabelsProvider.getNodeLabels());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testConfigForNoTimer() throws Exception {
|
public void testConfigForNoTimer() throws Exception {
|
||||||
Configuration conf = new Configuration();
|
Configuration conf = new Configuration();
|
||||||
modifyConf("A,B,CX");
|
modifyConf("A");
|
||||||
conf.setLong(YarnConfiguration.NM_NODE_LABELS_PROVIDER_FETCH_INTERVAL_MS,
|
conf.setLong(YarnConfiguration.NM_NODE_LABELS_PROVIDER_FETCH_INTERVAL_MS,
|
||||||
AbstractNodeLabelsProvider.DISABLE_NODE_LABELS_PROVIDER_FETCH_TIMER);
|
AbstractNodeLabelsProvider.DISABLE_NODE_LABELS_PROVIDER_FETCH_TIMER);
|
||||||
nodeLabelsProvider.init(conf);
|
nodeLabelsProvider.init(conf);
|
||||||
|
@ -114,14 +122,14 @@ public class TestConfigurationNodeLabelsProvider extends NodeLabelTestBase {
|
||||||
nodeLabelsProvider.nodeLabelsScheduler);
|
nodeLabelsProvider.nodeLabelsScheduler);
|
||||||
// Ensure that even though timer is not run, node labels are fetched at least once so
|
// Ensure that even though timer is not run, node labels are fetched at least once so
|
||||||
// that NM registers/updates Labels with RM
|
// that NM registers/updates Labels with RM
|
||||||
assertNLCollectionEquals(toNodeLabelSet("A", "B", "CX"),
|
assertNLCollectionEquals(toNodeLabelSet("A"),
|
||||||
nodeLabelsProvider.getNodeLabels());
|
nodeLabelsProvider.getNodeLabels());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testConfigTimer() throws Exception {
|
public void testConfigTimer() throws Exception {
|
||||||
Configuration conf = new Configuration();
|
Configuration conf = new Configuration();
|
||||||
modifyConf("A,B,CX");
|
modifyConf("A");
|
||||||
conf.setLong(YarnConfiguration.NM_NODE_LABELS_PROVIDER_FETCH_INTERVAL_MS,
|
conf.setLong(YarnConfiguration.NM_NODE_LABELS_PROVIDER_FETCH_INTERVAL_MS,
|
||||||
1000);
|
1000);
|
||||||
nodeLabelsProvider.init(conf);
|
nodeLabelsProvider.init(conf);
|
||||||
|
@ -129,11 +137,11 @@ public class TestConfigurationNodeLabelsProvider extends NodeLabelTestBase {
|
||||||
// Ensure that even though timer is not run, node labels are fetched at
|
// Ensure that even though timer is not run, node labels are fetched at
|
||||||
// least once so
|
// least once so
|
||||||
// that NM registers/updates Labels with RM
|
// that NM registers/updates Labels with RM
|
||||||
assertNLCollectionEquals(toNodeLabelSet("A", "B", "CX"),
|
assertNLCollectionEquals(toNodeLabelSet("A"),
|
||||||
nodeLabelsProvider.getNodeLabels());
|
nodeLabelsProvider.getNodeLabels());
|
||||||
modifyConf("X,y,Z");
|
modifyConf("X");
|
||||||
Thread.sleep(1500);
|
Thread.sleep(1500);
|
||||||
assertNLCollectionEquals(toNodeLabelSet("X", "y", "Z"),
|
assertNLCollectionEquals(toNodeLabelSet("X"),
|
||||||
nodeLabelsProvider.getNodeLabels());
|
nodeLabelsProvider.getNodeLabels());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -141,7 +149,7 @@ public class TestConfigurationNodeLabelsProvider extends NodeLabelTestBase {
|
||||||
private static void modifyConf(String nodeLabels)
|
private static void modifyConf(String nodeLabels)
|
||||||
throws FileNotFoundException, IOException {
|
throws FileNotFoundException, IOException {
|
||||||
Configuration conf = new Configuration();
|
Configuration conf = new Configuration();
|
||||||
conf.set(YarnConfiguration.NM_PROVIDER_CONFIGURED_NODE_LABELS, nodeLabels);
|
conf.set(YarnConfiguration.NM_PROVIDER_CONFIGURED_NODE_PARTITION, nodeLabels);
|
||||||
FileOutputStream confStream = new FileOutputStream(nodeLabelsConfigFile);
|
FileOutputStream confStream = new FileOutputStream(nodeLabelsConfigFile);
|
||||||
conf.writeXml(confStream);
|
conf.writeXml(confStream);
|
||||||
IOUtils.closeQuietly(confStream);
|
IOUtils.closeQuietly(confStream);
|
||||||
|
|
|
@ -0,0 +1,209 @@
|
||||||
|
/**
|
||||||
|
* 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.nodelabels;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.util.TimerTask;
|
||||||
|
|
||||||
|
import org.apache.hadoop.conf.Configuration;
|
||||||
|
import org.apache.hadoop.fs.FileContext;
|
||||||
|
import org.apache.hadoop.fs.FileUtil;
|
||||||
|
import org.apache.hadoop.fs.Path;
|
||||||
|
import org.apache.hadoop.service.ServiceStateException;
|
||||||
|
import org.apache.hadoop.util.Shell;
|
||||||
|
import org.apache.hadoop.yarn.conf.YarnConfiguration;
|
||||||
|
import org.apache.hadoop.yarn.nodelabels.NodeLabelTestBase;
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class TestScriptBasedNodeLabelsProvider extends NodeLabelTestBase {
|
||||||
|
|
||||||
|
protected static File testRootDir = new File("target",
|
||||||
|
TestScriptBasedNodeLabelsProvider.class.getName() + "-localDir")
|
||||||
|
.getAbsoluteFile();
|
||||||
|
|
||||||
|
private final File nodeLabelsScriptFile =
|
||||||
|
new File(testRootDir, Shell.appendScriptExtension("failingscript"));
|
||||||
|
|
||||||
|
private ScriptBasedNodeLabelsProvider nodeLabelsProvider;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setup() {
|
||||||
|
testRootDir.mkdirs();
|
||||||
|
nodeLabelsProvider = new ScriptBasedNodeLabelsProvider();
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() throws Exception {
|
||||||
|
if (testRootDir.exists()) {
|
||||||
|
FileContext.getLocalFSFileContext()
|
||||||
|
.delete(new Path(testRootDir.getAbsolutePath()), true);
|
||||||
|
}
|
||||||
|
if (nodeLabelsProvider != null) {
|
||||||
|
nodeLabelsProvider.stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Configuration getConfForNodeLabelScript() {
|
||||||
|
Configuration conf = new Configuration();
|
||||||
|
conf.set(YarnConfiguration.NM_SCRIPT_BASED_NODE_LABELS_PROVIDER_PATH,
|
||||||
|
nodeLabelsScriptFile.getAbsolutePath());
|
||||||
|
// set bigger interval so that test cases can be run
|
||||||
|
conf.setLong(YarnConfiguration.NM_NODE_LABELS_PROVIDER_FETCH_INTERVAL_MS,
|
||||||
|
1 * 60 * 60 * 1000l);
|
||||||
|
conf.setLong(YarnConfiguration.NM_NODE_LABELS_PROVIDER_FETCH_TIMEOUT_MS,
|
||||||
|
1000);
|
||||||
|
return conf;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void writeNodeLabelsScriptFile(String scriptStr,
|
||||||
|
boolean setExecutable) throws IOException {
|
||||||
|
PrintWriter pw = null;
|
||||||
|
try {
|
||||||
|
FileUtil.setWritable(nodeLabelsScriptFile, true);
|
||||||
|
FileUtil.setReadable(nodeLabelsScriptFile, true);
|
||||||
|
pw = new PrintWriter(new FileOutputStream(nodeLabelsScriptFile));
|
||||||
|
pw.println(scriptStr);
|
||||||
|
pw.flush();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
Assert.fail();
|
||||||
|
} finally {
|
||||||
|
if (null != pw) {
|
||||||
|
pw.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FileUtil.setExecutable(nodeLabelsScriptFile, setExecutable);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNodeLabelsScriptRunnerCreation() throws IOException {
|
||||||
|
// If no script configured then initialization of service should fail
|
||||||
|
ScriptBasedNodeLabelsProvider nodeLabelsProvider =
|
||||||
|
new ScriptBasedNodeLabelsProvider();
|
||||||
|
initilizeServiceFailTest(
|
||||||
|
"Expected to fail fast when no script is configured and "
|
||||||
|
+ "ScriptBasedNodeLabelsProvider service is inited",
|
||||||
|
nodeLabelsProvider);
|
||||||
|
|
||||||
|
// If script configured is blank then initialization of service should fail
|
||||||
|
nodeLabelsProvider = new ScriptBasedNodeLabelsProvider();
|
||||||
|
Configuration conf = new Configuration();
|
||||||
|
conf.set(YarnConfiguration.NM_SCRIPT_BASED_NODE_LABELS_PROVIDER_PATH, "");
|
||||||
|
initilizeServiceFailTest(
|
||||||
|
"Expected to fail fast when script path configuration is blank"
|
||||||
|
+ "and ScriptBasedNodeLabelsProvider service is inited.",
|
||||||
|
nodeLabelsProvider);
|
||||||
|
|
||||||
|
// If script configured is not executable then no timertask /
|
||||||
|
// NodeLabelsScriptRunner initialized
|
||||||
|
nodeLabelsProvider = new ScriptBasedNodeLabelsProvider();
|
||||||
|
writeNodeLabelsScriptFile("", false);
|
||||||
|
initilizeServiceFailTest(
|
||||||
|
"Expected to fail fast when script is not executable"
|
||||||
|
+ "and ScriptBasedNodeLabelsProvider service is inited.",
|
||||||
|
nodeLabelsProvider);
|
||||||
|
|
||||||
|
// If configured script is executable then timertask /
|
||||||
|
// NodeLabelsScriptRunner should be initialized
|
||||||
|
nodeLabelsProvider = new ScriptBasedNodeLabelsProvider();
|
||||||
|
writeNodeLabelsScriptFile("", true);
|
||||||
|
nodeLabelsProvider.init(getConfForNodeLabelScript());
|
||||||
|
nodeLabelsProvider.start();
|
||||||
|
Assert
|
||||||
|
.assertNotNull("Node Label Script runner should be started when script"
|
||||||
|
+ " is executable", nodeLabelsProvider.getTimerTask());
|
||||||
|
nodeLabelsProvider.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initilizeServiceFailTest(String message,
|
||||||
|
ScriptBasedNodeLabelsProvider nodeLabelsProvider) {
|
||||||
|
try {
|
||||||
|
nodeLabelsProvider.init(new Configuration());
|
||||||
|
Assert.fail(message);
|
||||||
|
} catch (ServiceStateException ex) {
|
||||||
|
Assert.assertEquals("IOException was expected", IOException.class,
|
||||||
|
ex.getCause().getClass());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testConfigForNoTimer() throws Exception {
|
||||||
|
Configuration conf = getConfForNodeLabelScript();
|
||||||
|
conf.setLong(YarnConfiguration.NM_NODE_LABELS_PROVIDER_FETCH_INTERVAL_MS,
|
||||||
|
AbstractNodeLabelsProvider.DISABLE_NODE_LABELS_PROVIDER_FETCH_TIMER);
|
||||||
|
String normalScript = "echo NODE_PARTITION:X86";
|
||||||
|
writeNodeLabelsScriptFile(normalScript, true);
|
||||||
|
nodeLabelsProvider.init(conf);
|
||||||
|
nodeLabelsProvider.start();
|
||||||
|
Assert.assertNull(
|
||||||
|
"Timer is not expected to be created when interval is configured as -1",
|
||||||
|
nodeLabelsProvider.nodeLabelsScheduler);
|
||||||
|
// Ensure that even though timer is not run script is run at least once so
|
||||||
|
// that NM registers/updates Labels with RM
|
||||||
|
assertNLCollectionEquals(toNodeLabelSet("X86"),
|
||||||
|
nodeLabelsProvider.getNodeLabels());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNodeLabelsScript() throws Exception {
|
||||||
|
String scriptWithoutLabels = "";
|
||||||
|
String normalScript = "echo NODE_PARTITION:Windows";
|
||||||
|
String scrptWithMultipleLinesHavingNodeLabels =
|
||||||
|
"echo NODE_PARTITION:RAM\n echo NODE_PARTITION:JDK1_6";
|
||||||
|
String timeOutScript = Shell.WINDOWS
|
||||||
|
? "@echo off\nping -n 4 127.0.0.1 >nul\n" + "echo NODE_PARTITION:ALL"
|
||||||
|
: "sleep 4\necho NODE_PARTITION:ALL";
|
||||||
|
|
||||||
|
writeNodeLabelsScriptFile(scriptWithoutLabels, true);
|
||||||
|
nodeLabelsProvider.init(getConfForNodeLabelScript());
|
||||||
|
nodeLabelsProvider.start();
|
||||||
|
Thread.sleep(500l);
|
||||||
|
TimerTask timerTask = nodeLabelsProvider.getTimerTask();
|
||||||
|
timerTask.run();
|
||||||
|
Assert.assertNull(
|
||||||
|
"Node Label Script runner should return null when script doesnt "
|
||||||
|
+ "give any Labels output",
|
||||||
|
nodeLabelsProvider.getNodeLabels());
|
||||||
|
|
||||||
|
writeNodeLabelsScriptFile(normalScript, true);
|
||||||
|
timerTask.run();
|
||||||
|
assertNLCollectionEquals(toNodeLabelSet("Windows"),
|
||||||
|
nodeLabelsProvider.getNodeLabels());
|
||||||
|
|
||||||
|
// multiple lines with partition tag then the last line's partition info
|
||||||
|
// needs to be taken.
|
||||||
|
writeNodeLabelsScriptFile(scrptWithMultipleLinesHavingNodeLabels, true);
|
||||||
|
timerTask.run();
|
||||||
|
assertNLCollectionEquals(toNodeLabelSet("JDK1_6"),
|
||||||
|
nodeLabelsProvider.getNodeLabels());
|
||||||
|
|
||||||
|
// timeout script.
|
||||||
|
writeNodeLabelsScriptFile(timeOutScript, true);
|
||||||
|
timerTask.run();
|
||||||
|
|
||||||
|
Assert.assertNotEquals("Node Labels should not be set after timeout ",
|
||||||
|
toNodeLabelSet("ALL"), nodeLabelsProvider.getNodeLabels());
|
||||||
|
}
|
||||||
|
}
|
|
@ -149,10 +149,12 @@ public class ResourceTrackerService extends AbstractService implements
|
||||||
YarnConfiguration.RM_NODEMANAGER_MINIMUM_VERSION,
|
YarnConfiguration.RM_NODEMANAGER_MINIMUM_VERSION,
|
||||||
YarnConfiguration.DEFAULT_RM_NODEMANAGER_MINIMUM_VERSION);
|
YarnConfiguration.DEFAULT_RM_NODEMANAGER_MINIMUM_VERSION);
|
||||||
|
|
||||||
|
if (YarnConfiguration.areNodeLabelsEnabled(conf)) {
|
||||||
isDistributedNodeLabelsConf =
|
isDistributedNodeLabelsConf =
|
||||||
YarnConfiguration.isDistributedNodeLabelConfiguration(conf);
|
YarnConfiguration.isDistributedNodeLabelConfiguration(conf);
|
||||||
isDelegatedCentralizedNodeLabelsConf = YarnConfiguration
|
isDelegatedCentralizedNodeLabelsConf =
|
||||||
.isDelegatedCentralizedNodeLabelConfiguration(conf);
|
YarnConfiguration.isDelegatedCentralizedNodeLabelConfiguration(conf);
|
||||||
|
}
|
||||||
|
|
||||||
super.serviceInit(conf);
|
super.serviceInit(conf);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue