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 5620755..dc7095a 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 @@ -1927,12 +1927,12 @@ public static boolean isDistributedNodeLabelConfiguration(Configuration conf) { private static final String NM_NODE_LABELS_PREFIX = NM_PREFIX + "node-labels."; - public static final String NM_NODE_LABELS_PROVIDER_CONFIG = + public static final String NM_NODE_LABELS_PROVIDER = NM_NODE_LABELS_PREFIX + "provider"; // whitelist names for the yarn.nodemanager.node-labels.provider - public static final String SCRIPT_NODE_LABELS_PROVIDER = "script"; - public static final String CONFIG_NODE_LABELS_PROVIDER = "config"; + public static final String NM_NODE_LABELS_PROVIDER_SCRIPT = "script"; + public static final String NM_NODE_LABELS_PROVIDER_CONFIG = "config"; private static final String NM_NODE_LABELS_PROVIDER_PREFIX = NM_NODE_LABELS_PREFIX + "provider."; @@ -1964,6 +1964,42 @@ public static boolean isDistributedNodeLabelConfiguration(Configuration conf) { public static final String NM_SCRIPT_BASED_NODE_LABELS_PROVIDER_SCRIPT_OPTS = NM_SCRIPT_BASED_NODE_LABELS_PROVIDER_PREFIX + "opts"; + private static final String RM_NODE_LABELS_PREFIX = RM_PREFIX + + "node-labels."; + + public static final String RM_NODE_LABELS_PROVIDER = + RM_NODE_LABELS_PREFIX + "provider"; + + // whitelist names for the yarn.resourcemanager.node-labels.provider + public static final String RM_NODE_LABELS_PROVIDER_SCRIPT = "script"; + + private static final String RM_NODE_LABELS_PROVIDER_PREFIX = + RM_NODE_LABELS_PREFIX + "provider."; + + public static final String RM_NODE_LABELS_PROVIDER_FETCH_INTERVAL_MS = + RM_NODE_LABELS_PROVIDER_PREFIX + "fetch-interval-ms"; + + public static final String RM_NODE_LABELS_PROVIDER_FETCH_TIMEOUT_MS = + RM_NODE_LABELS_PROVIDER_PREFIX + "fetch-timeout-ms"; + + public static final long DEFAULT_RM_NODE_LABELS_PROVIDER_FETCH_INTERVAL_MS = + 10 * 60 * 1000; + + public static final long DEFAULT_RM_NODE_LABELS_PROVIDER_FETCH_TIMEOUT_MS = + DEFAULT_RM_NODE_LABELS_PROVIDER_FETCH_INTERVAL_MS * 2; + + public static final String RM_PROVIDER_CONFIGURED_NODE_LABELS = + RM_NODE_LABELS_PROVIDER_PREFIX + "configured-node-labels"; + + private static final String RM_SCRIPT_BASED_NODE_LABELS_PROVIDER_PREFIX = + RM_NODE_LABELS_PROVIDER_PREFIX + "script."; + + public static final String RM_SCRIPT_BASED_NODE_LABELS_PROVIDER_PATH = + RM_SCRIPT_BASED_NODE_LABELS_PROVIDER_PREFIX + "path"; + + public static final String RM_SCRIPT_BASED_NODE_LABELS_PROVIDER_SCRIPT_OPTS = + RM_SCRIPT_BASED_NODE_LABELS_PROVIDER_PREFIX + "opts"; + public YarnConfiguration() { super(); } diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-common/src/main/java/org/apache/hadoop/yarn/server/nodelabels/AbstractNodeLabelsProvider.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-common/src/main/java/org/apache/hadoop/yarn/server/nodelabels/AbstractNodeLabelsProvider.java new file mode 100644 index 0000000..688f3df --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-common/src/main/java/org/apache/hadoop/yarn/server/nodelabels/AbstractNodeLabelsProvider.java @@ -0,0 +1,106 @@ +/** + * 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.nodelabels; + +import java.util.HashSet; +import java.util.Set; +import java.util.Timer; +import java.util.TimerTask; + +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.yarn.api.records.NodeLabel; + +import com.google.common.annotations.VisibleForTesting; + +/** + * Provides base implementation of NodeLabelsProvider with Timer and expects + * subclass to provide TimerTask which can fetch NodeLabels + */ +public abstract class AbstractNodeLabelsProvider extends NodeLabelsProvider { + public static final long DISABLE_NODE_LABELS_PROVIDER_FETCH_TIMER = -1; + + // Delay after which timer task are triggered to fetch NodeLabels + protected long intervalTime = DISABLE_NODE_LABELS_PROVIDER_FETCH_TIMER; + + // Timer used to schedule node labels fetching + public Timer nodeLabelsScheduler; + + public static final String NODE_LABELS_SEPRATOR = ","; + + protected TimerTask timerTask; + + @VisibleForTesting + protected long startTime = 0; + + public AbstractNodeLabelsProvider(String name) { + super(name); + } + + @Override + protected void serviceInit(Configuration conf) throws Exception { + super.serviceInit(conf); + } + + @Override + protected void serviceStart() throws Exception { + timerTask = createTimerTask(); + if (intervalTime != DISABLE_NODE_LABELS_PROVIDER_FETCH_TIMER) { + nodeLabelsScheduler = + new Timer("NodeLabelsRunner-Timer", true); + // Start the timer task and then periodically at the configured interval + // time. Illegal values for intervalTime is handled by timer api + nodeLabelsScheduler.scheduleAtFixedRate(timerTask, startTime, + intervalTime); + } + super.serviceStart(); + } + + /** + * terminate the timer + * @throws Exception + */ + @Override + protected void serviceStop() throws Exception { + if (nodeLabelsScheduler != null) { + nodeLabelsScheduler.cancel(); + } + super.serviceStop(); + } + + /** + * Used only by tests to access the timer task directly + * + * @return the timer task + */ + public TimerTask getTimerTask() { + return timerTask; + } + + protected static Set convertToNodeLabelSet(Set nodeLabels) { + if (null == nodeLabels) { + return null; + } + Set labels = new HashSet(); + for (String label : nodeLabels) { + labels.add(NodeLabel.newInstance(label)); + } + return labels; + } + + public abstract TimerTask createTimerTask(); +} diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-common/src/main/java/org/apache/hadoop/yarn/server/nodelabels/NodeLabelsProvider.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-common/src/main/java/org/apache/hadoop/yarn/server/nodelabels/NodeLabelsProvider.java new file mode 100644 index 0000000..04f1341 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-common/src/main/java/org/apache/hadoop/yarn/server/nodelabels/NodeLabelsProvider.java @@ -0,0 +1,47 @@ +/** + * 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.nodelabels; + +import java.util.Set; + +import org.apache.hadoop.service.AbstractService; +import org.apache.hadoop.yarn.api.records.NodeId; +import org.apache.hadoop.yarn.api.records.NodeLabel; + +/** + * Interface which will be responsible for fetching the labels + * + */ +public abstract class NodeLabelsProvider extends AbstractService { + + public NodeLabelsProvider(String name) { + super(name); + } + + /** + * Provides the labels. LabelProvider is expected to give same Labels + * continuously until there is a change in labels. + * If null is returned then Empty label set is assumed by the caller. + * + * @return Set of node label strings applicable for a node + */ + public abstract Set getNodeLabels(); + + public abstract Set getNodeLabels(NodeId node); +} \ No newline at end of file diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/NodeManager.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/NodeManager.java index 11ac75c..606f292 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/NodeManager.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/NodeManager.java @@ -56,12 +56,12 @@ import org.apache.hadoop.yarn.factory.providers.RecordFactoryProvider; import org.apache.hadoop.yarn.server.api.protocolrecords.LogAggregationReport; import org.apache.hadoop.yarn.server.api.records.NodeHealthStatus; +import org.apache.hadoop.yarn.server.nodelabels.NodeLabelsProvider; import org.apache.hadoop.yarn.server.nodemanager.containermanager.ContainerManagerImpl; import org.apache.hadoop.yarn.server.nodemanager.containermanager.application.Application; import org.apache.hadoop.yarn.server.nodemanager.containermanager.container.Container; 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.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.NMNullStateStoreService; @@ -119,22 +119,22 @@ protected NodeLabelsProvider createNodeLabelsProvider(Configuration conf) throws IOException { NodeLabelsProvider provider = null; String providerString = - conf.get(YarnConfiguration.NM_NODE_LABELS_PROVIDER_CONFIG, null); + conf.get(YarnConfiguration.NM_NODE_LABELS_PROVIDER, null); if (providerString == null || providerString.trim().length() == 0) { // Seems like Distributed Node Labels configuration is not enabled return provider; } switch (providerString.trim().toLowerCase()) { - case YarnConfiguration.SCRIPT_NODE_LABELS_PROVIDER: + case YarnConfiguration.NM_NODE_LABELS_PROVIDER_SCRIPT: provider = new ScriptBasedNodeLabelsProvider(); break; - case YarnConfiguration.CONFIG_NODE_LABELS_PROVIDER: + case YarnConfiguration.NM_NODE_LABELS_PROVIDER_CONFIG: provider = new ConfigurationNodeLabelsProvider(); break; default: try { Class labelsProviderClass = - conf.getClass(YarnConfiguration.NM_NODE_LABELS_PROVIDER_CONFIG, null, + conf.getClass(YarnConfiguration.NM_NODE_LABELS_PROVIDER, null, NodeLabelsProvider.class); provider = labelsProviderClass.newInstance(); } catch (InstantiationException | IllegalAccessException diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/NodeStatusUpdaterImpl.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/NodeStatusUpdaterImpl.java index 3c372a2..a74afd9 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/NodeStatusUpdaterImpl.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/NodeStatusUpdaterImpl.java @@ -70,12 +70,12 @@ import org.apache.hadoop.yarn.server.api.records.NodeAction; import org.apache.hadoop.yarn.server.api.records.NodeHealthStatus; import org.apache.hadoop.yarn.server.api.records.NodeStatus; +import org.apache.hadoop.yarn.server.nodelabels.NodeLabelsProvider; import org.apache.hadoop.yarn.server.nodemanager.NodeManager.NMContext; import org.apache.hadoop.yarn.server.nodemanager.containermanager.ContainerManagerImpl; import org.apache.hadoop.yarn.server.nodemanager.containermanager.application.ApplicationState; import org.apache.hadoop.yarn.server.nodemanager.containermanager.container.Container; import org.apache.hadoop.yarn.server.nodemanager.metrics.NodeManagerMetrics; -import org.apache.hadoop.yarn.server.nodemanager.nodelabels.NodeLabelsProvider; import org.apache.hadoop.yarn.util.Records; import org.apache.hadoop.yarn.server.nodemanager.util.NodeManagerHardwareUtils; import org.apache.hadoop.yarn.util.YarnVersionInfo; diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/nodelabels/AbstractNodeLabelsProvider.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/nodelabels/AbstractNodeLabelsProvider.java deleted file mode 100644 index bbc6710..0000000 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/nodelabels/AbstractNodeLabelsProvider.java +++ /dev/null @@ -1,146 +0,0 @@ -/** - * 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.util.HashSet; -import java.util.Set; -import java.util.Timer; -import java.util.TimerTask; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReadWriteLock; -import java.util.concurrent.locks.ReentrantReadWriteLock; - -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.yarn.api.records.NodeLabel; -import org.apache.hadoop.yarn.conf.YarnConfiguration; -import org.apache.hadoop.yarn.nodelabels.CommonNodeLabelsManager; - -import com.google.common.annotations.VisibleForTesting; - -/** - * Provides base implementation of NodeLabelsProvider with Timer and expects - * subclass to provide TimerTask which can fetch NodeLabels - */ -public abstract class AbstractNodeLabelsProvider extends NodeLabelsProvider { - public static final long DISABLE_NODE_LABELS_PROVIDER_FETCH_TIMER = -1; - - // Delay after which timer task are triggered to fetch NodeLabels - protected long intervalTime; - - // Timer used to schedule node labels fetching - protected Timer nodeLabelsScheduler; - - public static final String NODE_LABELS_SEPRATOR = ","; - - protected Lock readLock = null; - protected Lock writeLock = null; - - protected TimerTask timerTask; - - protected Set nodeLabels = - CommonNodeLabelsManager.EMPTY_NODELABEL_SET; - - @VisibleForTesting - long startTime = 0; - - public AbstractNodeLabelsProvider(String name) { - super(name); - } - - @Override - protected void serviceInit(Configuration conf) throws Exception { - this.intervalTime = - conf.getLong(YarnConfiguration.NM_NODE_LABELS_PROVIDER_FETCH_INTERVAL_MS, - YarnConfiguration.DEFAULT_NM_NODE_LABELS_PROVIDER_FETCH_INTERVAL_MS); - - ReadWriteLock readWriteLock = new ReentrantReadWriteLock(); - readLock = readWriteLock.readLock(); - writeLock = readWriteLock.writeLock(); - super.serviceInit(conf); - } - - @Override - protected void serviceStart() throws Exception { - timerTask = createTimerTask(); - if (intervalTime != DISABLE_NODE_LABELS_PROVIDER_FETCH_TIMER) { - nodeLabelsScheduler = - new Timer("DistributedNodeLabelsRunner-Timer", true); - // Start the timer task and then periodically at the configured interval - // time. Illegal values for intervalTime is handled by timer api - nodeLabelsScheduler.scheduleAtFixedRate(timerTask, startTime, - intervalTime); - } - super.serviceStart(); - } - - /** - * terminate the timer - * @throws Exception - */ - @Override - protected void serviceStop() throws Exception { - if (nodeLabelsScheduler != null) { - nodeLabelsScheduler.cancel(); - } - super.serviceStop(); - } - - /** - * @return Returns output from provider. - */ - @Override - public Set getNodeLabels() { - readLock.lock(); - try { - return nodeLabels; - } finally { - readLock.unlock(); - } - } - - protected void setNodeLabels(Set nodeLabelsSet) { - writeLock.lock(); - try { - nodeLabels = nodeLabelsSet; - } finally { - writeLock.unlock(); - } - } - - /** - * Used only by tests to access the timer task directly - * - * @return the timer task - */ - TimerTask getTimerTask() { - return timerTask; - } - - static Set convertToNodeLabelSet(Set nodeLabels) { - if (null == nodeLabels) { - return null; - } - Set labels = new HashSet(); - for (String label : nodeLabels) { - labels.add(NodeLabel.newInstance(label)); - } - return labels; - } - - public abstract TimerTask createTimerTask(); -} diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/nodelabels/AbstractNodeLabelsProviderForNM.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/nodelabels/AbstractNodeLabelsProviderForNM.java new file mode 100644 index 0000000..a7c1bca --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/nodelabels/AbstractNodeLabelsProviderForNM.java @@ -0,0 +1,94 @@ +/** + * 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.util.Set; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.yarn.api.records.NodeId; +import org.apache.hadoop.yarn.api.records.NodeLabel; +import org.apache.hadoop.yarn.conf.YarnConfiguration; +import org.apache.hadoop.yarn.exceptions.YarnRuntimeException; +import org.apache.hadoop.yarn.nodelabels.CommonNodeLabelsManager; +import org.apache.hadoop.yarn.server.nodelabels.AbstractNodeLabelsProvider; + +public abstract class AbstractNodeLabelsProviderForNM extends + AbstractNodeLabelsProvider { + + protected Lock readLock = null; + protected Lock writeLock = null; + + protected Set nodeLabels = + CommonNodeLabelsManager.EMPTY_NODELABEL_SET; + + public AbstractNodeLabelsProviderForNM(String name) { + super(name); + } + + @Override + protected void serviceInit(Configuration conf) throws Exception { + this.intervalTime = + conf.getLong(YarnConfiguration.NM_NODE_LABELS_PROVIDER_FETCH_INTERVAL_MS, + YarnConfiguration.DEFAULT_NM_NODE_LABELS_PROVIDER_FETCH_INTERVAL_MS); + + ReadWriteLock readWriteLock = new ReentrantReadWriteLock(); + readLock = readWriteLock.readLock(); + writeLock = readWriteLock.writeLock(); + super.serviceInit(conf); + } + + @Override + protected void serviceStart() throws Exception { + super.serviceStart(); + } + + @Override + protected void serviceStop() throws Exception { + super.serviceStop(); + } + + /** + * @return Returns output from provider. + */ + @Override + public Set getNodeLabels() { + readLock.lock(); + try { + return nodeLabels; + } finally { + readLock.unlock(); + } + } + + protected void setNodeLabels(Set nodeLabelsSet) { + writeLock.lock(); + try { + nodeLabels = nodeLabelsSet; + } finally { + writeLock.unlock(); + } + } + + @Override + public Set getNodeLabels(NodeId node) { + throw new YarnRuntimeException("This method can only be called by RM."); + } +} diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/nodelabels/ConfigurationNodeLabelsProvider.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/nodelabels/ConfigurationNodeLabelsProvider.java index f549d1a..aaf03d5 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/nodelabels/ConfigurationNodeLabelsProvider.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/nodelabels/ConfigurationNodeLabelsProvider.java @@ -33,7 +33,8 @@ /** * Provides Node's Labels by constantly monitoring the configuration. */ -public class ConfigurationNodeLabelsProvider extends AbstractNodeLabelsProvider { +public class ConfigurationNodeLabelsProvider extends + AbstractNodeLabelsProviderForNM { private static final Log LOG = LogFactory .getLog(ConfigurationNodeLabelsProvider.class); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/nodelabels/NodeLabelsProvider.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/nodelabels/NodeLabelsProvider.java deleted file mode 100644 index dab3709..0000000 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/nodelabels/NodeLabelsProvider.java +++ /dev/null @@ -1,44 +0,0 @@ -/** - * 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.util.Set; - -import org.apache.hadoop.service.AbstractService; -import org.apache.hadoop.yarn.api.records.NodeLabel; - -/** - * Interface which will be responsible for fetching the labels - * - */ -public abstract class NodeLabelsProvider extends AbstractService { - - public NodeLabelsProvider(String name) { - super(name); - } - - /** - * Provides the labels. LabelProvider is expected to give same Labels - * continuously until there is a change in labels. - * If null is returned then Empty label set is assumed by the caller. - * - * @return Set of node label strings applicable for a node - */ - public abstract Set getNodeLabels(); -} \ No newline at end of file diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/nodelabels/ScriptBasedNodeLabelsProvider.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/nodelabels/ScriptBasedNodeLabelsProvider.java index a1552be..db992b6 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/nodelabels/ScriptBasedNodeLabelsProvider.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/nodelabels/ScriptBasedNodeLabelsProvider.java @@ -40,7 +40,7 @@ * pattern which will be used to search node labels from the out put of the * NodeLabels provider script */ -public class ScriptBasedNodeLabelsProvider extends AbstractNodeLabelsProvider { +public class ScriptBasedNodeLabelsProvider extends AbstractNodeLabelsProviderForNM { /** Absolute path to the node labels script. */ private String nodeLabelsScript; diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/TestNodeManager.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/TestNodeManager.java index 2d390ac..0dbbaac 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/TestNodeManager.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/TestNodeManager.java @@ -25,7 +25,7 @@ import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.yarn.conf.YarnConfiguration; import org.apache.hadoop.yarn.exceptions.YarnRuntimeException; -import org.apache.hadoop.yarn.server.nodemanager.nodelabels.NodeLabelsProvider; +import org.apache.hadoop.yarn.server.nodelabels.NodeLabelsProvider; import org.junit.Assert; import org.junit.Test; @@ -72,14 +72,14 @@ public void testCreationOfNodeLabelsProviderService() // With valid className conf.set( - YarnConfiguration.NM_NODE_LABELS_PROVIDER_CONFIG, + YarnConfiguration.NM_NODE_LABELS_PROVIDER, "org.apache.hadoop.yarn.server.nodemanager.nodelabels.ConfigurationNodeLabelsProvider"); labelsProviderService = nodeManager.createNodeLabelsProvider(conf); Assert.assertNotNull("LabelsProviderService should be initialized When " + "node labels provider class is configured", labelsProviderService); // With invalid className - conf.set(YarnConfiguration.NM_NODE_LABELS_PROVIDER_CONFIG, + conf.set(YarnConfiguration.NM_NODE_LABELS_PROVIDER, "org.apache.hadoop.yarn.server.nodemanager.NodeManager"); try { labelsProviderService = nodeManager.createNodeLabelsProvider(conf); @@ -91,8 +91,8 @@ public void testCreationOfNodeLabelsProviderService() + "node labels provider class is configured", labelsProviderService); // With valid whitelisted configurations - conf.set(YarnConfiguration.NM_NODE_LABELS_PROVIDER_CONFIG, - YarnConfiguration.CONFIG_NODE_LABELS_PROVIDER); + conf.set(YarnConfiguration.NM_NODE_LABELS_PROVIDER, + YarnConfiguration.NM_NODE_LABELS_PROVIDER_CONFIG); labelsProviderService = nodeManager.createNodeLabelsProvider(conf); Assert.assertNotNull("LabelsProviderService should be initialized When " + "node labels provider class is configured", labelsProviderService); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/TestNodeStatusUpdaterForLabels.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/TestNodeStatusUpdaterForLabels.java index 21f6e53..010e017 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/TestNodeStatusUpdaterForLabels.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/TestNodeStatusUpdaterForLabels.java @@ -27,6 +27,7 @@ import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.service.ServiceOperations; +import org.apache.hadoop.yarn.api.records.NodeId; import org.apache.hadoop.yarn.api.records.NodeLabel; import org.apache.hadoop.yarn.conf.YarnConfiguration; import org.apache.hadoop.yarn.event.Dispatcher; @@ -44,7 +45,7 @@ import org.apache.hadoop.yarn.server.api.records.NodeAction; import org.apache.hadoop.yarn.server.api.records.NodeStatus; import org.apache.hadoop.yarn.server.api.records.impl.pb.MasterKeyPBImpl; -import org.apache.hadoop.yarn.server.nodemanager.nodelabels.NodeLabelsProvider; +import org.apache.hadoop.yarn.server.nodelabels.NodeLabelsProvider; import org.apache.hadoop.yarn.server.utils.YarnServerBuilderUtils; import org.junit.After; import org.junit.Assert; @@ -200,6 +201,11 @@ public DummyNodeLabelsProvider() { synchronized void setNodeLabels(Set nodeLabels) { this.nodeLabels = nodeLabels; } + + @Override + public Set getNodeLabels(NodeId node) { + return null; + } } private YarnConfiguration createNMConfigForDistributeNodeLabels() { diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/nodelabels/TestConfigurationNodeLabelsProvider.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/nodelabels/TestConfigurationNodeLabelsProvider.java index 48b0ab4..eef5089 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/nodelabels/TestConfigurationNodeLabelsProvider.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/nodelabels/TestConfigurationNodeLabelsProvider.java @@ -30,6 +30,8 @@ import org.apache.hadoop.fs.Path; import org.apache.hadoop.yarn.conf.YarnConfiguration; import org.apache.hadoop.yarn.nodelabels.NodeLabelTestBase; +import org.apache.hadoop.yarn.server.nodelabels.AbstractNodeLabelsProvider; +import org.apache.hadoop.yarn.server.nodemanager.nodelabels.ConfigurationNodeLabelsProvider; import org.junit.After; import org.junit.Assert; import org.junit.Before; diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/nodelabels/TestScriptBasedNodeLabelsProvider.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/nodelabels/TestScriptBasedNodeLabelsProvider.java index f1c16ea..ec49ada 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/nodelabels/TestScriptBasedNodeLabelsProvider.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/nodelabels/TestScriptBasedNodeLabelsProvider.java @@ -32,6 +32,8 @@ import org.apache.hadoop.util.Shell; import org.apache.hadoop.yarn.conf.YarnConfiguration; import org.apache.hadoop.yarn.nodelabels.NodeLabelTestBase; +import org.apache.hadoop.yarn.server.nodelabels.AbstractNodeLabelsProvider; +import org.apache.hadoop.yarn.server.nodemanager.nodelabels.ScriptBasedNodeLabelsProvider; import org.junit.After; import org.junit.Assert; import org.junit.Before; diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/AdminService.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/AdminService.java index 1ee8b3b..707b15f 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/AdminService.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/AdminService.java @@ -672,6 +672,7 @@ public ReplaceLabelsOnNodeResponse replaceLabelsOnNode( final String msg = "set node to labels."; checkAndThrowIfDistributedNodeLabelConfEnabled(operation); + checkAndThrowIfHasNodeLableProvider(operation); UserGroupInformation user = checkAcls(operation); checkRMStatus(user.getShortUserName(), operation, msg); @@ -717,6 +718,17 @@ private void checkAndThrowIfDistributedNodeLabelConfEnabled(String operation) } } + private void checkAndThrowIfHasNodeLableProvider(String operation) + throws YarnException { + if (rm.getRMContext().getNodeLabelsProvider() != null) { + String msg = + String.format("Error when invoke method=%s because of " + + "node label provider is not null.", operation); + LOG.error(msg); + throw RPCUtil.getRemoteException(new IOException(msg)); + } + } + @Override public CheckForDecommissioningNodesResponse checkForDecommissioningNodes( CheckForDecommissioningNodesRequest checkForDecommissioningNodesRequest) diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/RMActiveServiceContext.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/RMActiveServiceContext.java index e4c72d8..95e622f 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/RMActiveServiceContext.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/RMActiveServiceContext.java @@ -30,6 +30,7 @@ import org.apache.hadoop.yarn.api.records.NodeId; import org.apache.hadoop.yarn.conf.YarnConfiguration; import org.apache.hadoop.yarn.event.Dispatcher; +import org.apache.hadoop.yarn.server.nodelabels.NodeLabelsProvider; import org.apache.hadoop.yarn.server.resourcemanager.ahs.RMApplicationHistoryWriter; import org.apache.hadoop.yarn.server.resourcemanager.metrics.SystemMetricsPublisher; import org.apache.hadoop.yarn.server.resourcemanager.nodelabels.RMNodeLabelsManager; @@ -95,6 +96,7 @@ private RMApplicationHistoryWriter rmApplicationHistoryWriter; private SystemMetricsPublisher systemMetricsPublisher; private RMNodeLabelsManager nodeLabelManager; + private NodeLabelsProvider nodeLabelsProvider; private long epoch; private Clock systemClock = new SystemClock(); private long schedulerRecoveryStartTime = 0; @@ -420,6 +422,18 @@ public void setNodeLabelManager(RMNodeLabelsManager mgr) { @Private @Unstable + NodeLabelsProvider getNodeLabelsProvider() { + return nodeLabelsProvider; + } + + @Private + @Unstable + public void setNodeLabelsProvider(NodeLabelsProvider nodeLabelsProvider) { + this.nodeLabelsProvider = nodeLabelsProvider; + } + + @Private + @Unstable public void setSchedulerRecoveryStartAndWaitTime(long waitTime) { this.schedulerRecoveryStartTime = systemClock.getTime(); this.schedulerRecoveryWaitTime = waitTime; diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/RMContext.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/RMContext.java index bc50268..4f7e33d 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/RMContext.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/RMContext.java @@ -27,6 +27,7 @@ import org.apache.hadoop.yarn.api.records.NodeId; import org.apache.hadoop.yarn.conf.ConfigurationProvider; import org.apache.hadoop.yarn.event.Dispatcher; +import org.apache.hadoop.yarn.server.nodelabels.NodeLabelsProvider; import org.apache.hadoop.yarn.server.resourcemanager.ahs.RMApplicationHistoryWriter; import org.apache.hadoop.yarn.server.resourcemanager.metrics.SystemMetricsPublisher; import org.apache.hadoop.yarn.server.resourcemanager.nodelabels.RMNodeLabelsManager; @@ -117,6 +118,10 @@ void setRMApplicationHistoryWriter( public void setNodeLabelManager(RMNodeLabelsManager mgr); + NodeLabelsProvider getNodeLabelsProvider(); + + public void setNodeLabelsProvider(NodeLabelsProvider nodeLabelsProvider); + long getEpoch(); ReservationSystem getReservationSystem(); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/RMContextImpl.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/RMContextImpl.java index 2f9209c..8495999 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/RMContextImpl.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/RMContextImpl.java @@ -31,6 +31,7 @@ import org.apache.hadoop.yarn.api.records.NodeId; import org.apache.hadoop.yarn.conf.ConfigurationProvider; import org.apache.hadoop.yarn.event.Dispatcher; +import org.apache.hadoop.yarn.server.nodelabels.NodeLabelsProvider; import org.apache.hadoop.yarn.server.resourcemanager.ahs.RMApplicationHistoryWriter; import org.apache.hadoop.yarn.server.resourcemanager.metrics.SystemMetricsPublisher; import org.apache.hadoop.yarn.server.resourcemanager.nodelabels.RMNodeLabelsManager; @@ -400,6 +401,16 @@ public void setNodeLabelManager(RMNodeLabelsManager mgr) { activeServiceContext.setNodeLabelManager(mgr); } + @Override + public NodeLabelsProvider getNodeLabelsProvider() { + return activeServiceContext.getNodeLabelsProvider(); + } + + @Override + public void setNodeLabelsProvider(NodeLabelsProvider nodeLabelsProvider) { + activeServiceContext.setNodeLabelsProvider(nodeLabelsProvider); + } + public void setSchedulerRecoveryStartAndWaitTime(long waitTime) { activeServiceContext.setSchedulerRecoveryStartAndWaitTime(waitTime); } diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/ResourceManager.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/ResourceManager.java index c209873..b6f4d26 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/ResourceManager.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/ResourceManager.java @@ -54,6 +54,7 @@ import org.apache.hadoop.yarn.event.Dispatcher; import org.apache.hadoop.yarn.event.EventHandler; import org.apache.hadoop.yarn.exceptions.YarnRuntimeException; +import org.apache.hadoop.yarn.server.nodelabels.NodeLabelsProvider; import org.apache.hadoop.yarn.server.resourcemanager.ahs.RMApplicationHistoryWriter; import org.apache.hadoop.yarn.server.resourcemanager.amlauncher.AMLauncherEventType; import org.apache.hadoop.yarn.server.resourcemanager.amlauncher.ApplicationMasterLauncher; @@ -61,6 +62,7 @@ import org.apache.hadoop.yarn.server.resourcemanager.monitor.SchedulingEditPolicy; import org.apache.hadoop.yarn.server.resourcemanager.monitor.SchedulingMonitor; import org.apache.hadoop.yarn.server.resourcemanager.nodelabels.RMNodeLabelsManager; +import org.apache.hadoop.yarn.server.resourcemanager.nodelabels.ScriptBasedNodeLabelsProvider; import org.apache.hadoop.yarn.server.resourcemanager.recovery.NullRMStateStore; import org.apache.hadoop.yarn.server.resourcemanager.recovery.RMStateStore; import org.apache.hadoop.yarn.server.resourcemanager.recovery.RMStateStore.RMState; @@ -158,6 +160,7 @@ private WebApp webApp; private AppReportFetcher fetcher = null; protected ResourceTrackerService resourceTracker; + private NodeLabelsProvider nodeLabelsProvider; @VisibleForTesting protected String webAppAddress; @@ -258,6 +261,12 @@ protected void serviceInit(Configuration conf) throws Exception { YarnConfiguration.RM_BIND_HOST, WebAppUtils.getRMWebAppURLWithoutScheme(this.conf)); + nodeLabelsProvider = createNodeLabelsProvider(conf); + if (nodeLabelsProvider != null) { + addService(nodeLabelsProvider); + } + rmContext.setNodeLabelsProvider(nodeLabelsProvider); + super.serviceInit(this.conf); } @@ -1136,6 +1145,41 @@ protected RMSecretManagerService createRMSecretManagerService() { return new RMSecretManagerService(conf, rmContext); } + protected NodeLabelsProvider createNodeLabelsProvider(Configuration conf) + throws IOException { + NodeLabelsProvider provider = null; + String providerString = + conf.get(YarnConfiguration.RM_NODE_LABELS_PROVIDER, null); + if (providerString == null || providerString.trim().length() == 0) { + return provider; + } + switch (providerString.trim().toLowerCase()) { + case YarnConfiguration.RM_NODE_LABELS_PROVIDER_SCRIPT: + provider = new ScriptBasedNodeLabelsProvider(rmContext); + break; + default: + try { + Class labelsProviderClass = + conf.getClass(YarnConfiguration.RM_NODE_LABELS_PROVIDER, null, + NodeLabelsProvider.class); + provider = labelsProviderClass.newInstance(); + } catch (InstantiationException | IllegalAccessException + | RuntimeException e) { + LOG.error("Failed to create NodeLabelsProvider based on Configuration", + e); + throw new IOException("Failed to create NodeLabelsProvider : " + + e.getMessage(), e); + } + } + if (provider != null) { + if (LOG.isDebugEnabled()) { + LOG.debug("Centralized Node Labels is enabled" + + " with provider class as : " + provider.getClass().toString()); + } + } + return provider; + } + @Private public ClientRMService getClientRMService() { return this.clientRM; diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/ResourceTrackerService.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/ResourceTrackerService.java index 4dc5c88..9055221 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/ResourceTrackerService.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/ResourceTrackerService.java @@ -60,6 +60,7 @@ import org.apache.hadoop.yarn.server.api.records.MasterKey; import org.apache.hadoop.yarn.server.api.records.NodeAction; import org.apache.hadoop.yarn.server.api.records.NodeStatus; +import org.apache.hadoop.yarn.server.nodelabels.NodeLabelsProvider; import org.apache.hadoop.yarn.server.resourcemanager.rmapp.RMApp; import org.apache.hadoop.yarn.server.resourcemanager.rmapp.attempt.RMAppAttempt; import org.apache.hadoop.yarn.server.resourcemanager.rmapp.attempt.event.RMAppAttemptContainerFinishedEvent; @@ -107,6 +108,7 @@ private int minAllocVcores; private boolean isDistributedNodeLabelsConf; + private String nodeLabelsProvider; static { resync.setNodeAction(NodeAction.RESYNC); @@ -159,7 +161,8 @@ protected void serviceInit(Configuration conf) throws Exception { isDistributedNodeLabelsConf = YarnConfiguration.isDistributedNodeLabelConfiguration(conf); - + nodeLabelsProvider = + conf.get(YarnConfiguration.RM_NODE_LABELS_PROVIDER, null); super.serviceInit(conf); } @@ -369,6 +372,10 @@ public RegisterNodeManagerResponse registerNodeManager( response.setDiagnosticsMessage(ex.getMessage()); response.setAreNodeLabelsAcceptedByRM(false); } + } else if (!isDistributedNodeLabelsConf + && YarnConfiguration.RM_NODE_LABELS_PROVIDER_SCRIPT + .equalsIgnoreCase(nodeLabelsProvider)) { + updateNodeLabelsFromScript(nodeId); } StringBuilder message = new StringBuilder(); @@ -383,6 +390,7 @@ public RegisterNodeManagerResponse registerNodeManager( } LOG.info(message.toString()); + response.setNodeAction(NodeAction.NORMAL); response.setRMIdentifier(ResourceManager.getClusterTimeStamp()); response.setRMVersion(YarnVersionInfo.getVersion()); @@ -488,6 +496,10 @@ public NodeHeartbeatResponse nodeHeartbeat(NodeHeartbeatRequest request) nodeHeartBeatResponse.setDiagnosticsMessage(ex.getMessage()); nodeHeartBeatResponse.setAreNodeLabelsAcceptedByRM(false); } + } else if (!isDistributedNodeLabelsConf + && YarnConfiguration.RM_NODE_LABELS_PROVIDER_SCRIPT + .equalsIgnoreCase(nodeLabelsProvider)) { + updateNodeLabelsFromScript(nodeId); } return nodeHeartBeatResponse; @@ -516,6 +528,38 @@ private void updateNodeLabelsFromNMReport(Set nodeLabels, } } + private void updateNodeLabelsFromScript(NodeId nodeId) throws IOException { + NodeLabelsProvider nodeLabelsProvider = this.rmContext + .getNodeLabelsProvider(); + if (nodeLabelsProvider == null) { + return; + } + Set nodeLabels = nodeLabelsProvider.getNodeLabels(nodeId); + Set labels = new HashSet(); + for (NodeLabel nodeLabel : nodeLabels) { + labels.add(nodeLabel.getName()); + } + try { + Map> labelsUpdate = + new HashMap>(); + labelsUpdate.put(nodeId, labels); + this.rmContext.getNodeLabelManager().replaceLabelsOnNode(labelsUpdate); + if (LOG.isDebugEnabled()) { + LOG.debug("Update Node " + nodeId + " with Node Labels {" + + StringUtils.join(",", nodeLabels) + "}"); + } + } catch (IOException ex) { + StringBuilder errorMessage = new StringBuilder(); + errorMessage.append("Node Labels {") + .append(StringUtils.join(",", nodeLabels)) + .append("} for NM with ID ").append(nodeId) + .append(" was rejected from RM with exception message as : ") + .append(ex.getMessage()); + LOG.error(errorMessage, ex); + throw new IOException(errorMessage.toString(), ex); + } + } + private void populateKeys(NodeHeartbeatRequest request, NodeHeartbeatResponse nodeHeartBeatResponse) { diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/nodelabels/AbstractNodeLabelsProviderForRM.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/nodelabels/AbstractNodeLabelsProviderForRM.java new file mode 100644 index 0000000..ac613b4 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/nodelabels/AbstractNodeLabelsProviderForRM.java @@ -0,0 +1,83 @@ +package org.apache.hadoop.yarn.server.resourcemanager.nodelabels; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.yarn.api.records.NodeId; +import org.apache.hadoop.yarn.api.records.NodeLabel; +import org.apache.hadoop.yarn.conf.YarnConfiguration; +import org.apache.hadoop.yarn.exceptions.YarnRuntimeException; +import org.apache.hadoop.yarn.nodelabels.CommonNodeLabelsManager; +import org.apache.hadoop.yarn.server.nodelabels.AbstractNodeLabelsProvider; + +public abstract class AbstractNodeLabelsProviderForRM extends + AbstractNodeLabelsProvider { + + protected Lock readLock = null; + protected Lock writeLock = null; + + protected Map> nodeLabelMap = + new HashMap>(); + + public AbstractNodeLabelsProviderForRM(String name) { + super(name); + } + + @Override + protected void serviceInit(Configuration conf) throws Exception { + this.intervalTime = + conf.getLong(YarnConfiguration.RM_NODE_LABELS_PROVIDER_FETCH_INTERVAL_MS, + YarnConfiguration.DEFAULT_RM_NODE_LABELS_PROVIDER_FETCH_INTERVAL_MS); + + ReadWriteLock readWriteLock = new ReentrantReadWriteLock(); + readLock = readWriteLock.readLock(); + writeLock = readWriteLock.writeLock(); + super.serviceInit(conf); + } + + @Override + protected void serviceStart() throws Exception { + super.serviceStart(); + } + + @Override + protected void serviceStop() throws Exception { + super.serviceStop(); + } + + /** + * @return Returns output from provider. + */ + @Override + public Set getNodeLabels(NodeId node) { + readLock.lock(); + try { + Set nodeLabels = nodeLabelMap.get(node); + if (nodeLabels == null) { + nodeLabels = CommonNodeLabelsManager.EMPTY_NODELABEL_SET; + } + return nodeLabels; + } finally { + readLock.unlock(); + } + } + + protected void setNodeLabels(NodeId node, Set nodeLabelsSet) { + writeLock.lock(); + try { + nodeLabelMap.put(node, nodeLabelsSet); + } finally { + writeLock.unlock(); + } + } + + @Override + public Set getNodeLabels() { + throw new YarnRuntimeException("This method can only be called by NM."); + } +} diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/nodelabels/ScriptBasedNodeLabelsProvider.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/nodelabels/ScriptBasedNodeLabelsProvider.java new file mode 100644 index 0000000..0863ea2 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/nodelabels/ScriptBasedNodeLabelsProvider.java @@ -0,0 +1,246 @@ +/** + * 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.resourcemanager.nodelabels; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +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.NodeId; +import org.apache.hadoop.yarn.api.records.NodeLabel; +import org.apache.hadoop.yarn.conf.YarnConfiguration; +import org.apache.hadoop.yarn.nodelabels.CommonNodeLabelsManager; +import org.apache.hadoop.yarn.server.resourcemanager.RMContext; + +/** + * The class which provides functionality of getting the labels of the node + * using the configured node labels provider script. "NODE_LABELS:" is the + * pattern which will be used to search node labels from the out put of the + * NodeLabels provider script + */ +public class ScriptBasedNodeLabelsProvider extends AbstractNodeLabelsProviderForRM { + /** Absolute path to the node labels script. */ + private String nodeLabelsScript; + + /** 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_PATTERN = "NODE_LABELS:"; + + private String[] scriptArgs; + + private RMContext rmContext; + + public ScriptBasedNodeLabelsProvider(RMContext rmContext) { + super(ScriptBasedNodeLabelsProvider.class.getName()); + this.rmContext = rmContext; + } + + private Set nodeLabelsUpdated = Collections + .synchronizedSet(new HashSet()); + + /* + * Method which initializes the values for the script path and interval time. + */ + @Override + protected void serviceInit(Configuration conf) throws Exception { + super.serviceInit(conf); + this.nodeLabelsScript = + conf.get(YarnConfiguration.RM_SCRIPT_BASED_NODE_LABELS_PROVIDER_PATH); + this.scriptTimeout = + conf.getLong( + YarnConfiguration.RM_NODE_LABELS_PROVIDER_FETCH_TIMEOUT_MS, + YarnConfiguration.DEFAULT_RM_NODE_LABELS_PROVIDER_FETCH_TIMEOUT_MS); + scriptArgs = + conf.getStrings( + YarnConfiguration.RM_SCRIPT_BASED_NODE_LABELS_PROVIDER_SCRIPT_OPTS, + new String[] {}); + + verifyConfiguredScript(nodeLabelsScript); + } + + @Override + protected void serviceStart() throws Exception { + super.serviceStart(); + if (intervalTime == DISABLE_NODE_LABELS_PROVIDER_FETCH_TIMER) { + // run at-least once so that labels are set + timerTask.run(); + } + } + + /** + * 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: + * + *
    + *
  1. Path to Node Labels fetch script is not empty
  2. + *
  3. Node Labels fetch script file exists
  4. + *
+ * + * @param conf + * @return true if node labels script can be run. + * @throws IOException + */ + private void verifyConfiguredScript(String nodeLabelsFetchScriptPath) + throws IOException { + boolean invalidConfiguration = false; + if (nodeLabelsFetchScriptPath == null + || nodeLabelsFetchScriptPath.trim().isEmpty()) { + invalidConfiguration = true; + } else { + File f = new File(nodeLabelsFetchScriptPath); + invalidConfiguration = !f.exists() || !FileUtil.canExecute(f); + } + if (invalidConfiguration) { + throw new IOException("Distributed Node labels provider script \"" + + nodeLabelsScript + + "\" 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 + protected void serviceStop() throws Exception { + super.serviceStop(); + 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); + + private ArrayList execScript; + + public NodeLabelsScriptRunner() { + execScript = new ArrayList(); + execScript.add(nodeLabelsScript); + if (scriptArgs != null) { + execScript.addAll(Arrays.asList(scriptArgs)); + } + } + + @Override + public void run() { + for (NodeId node : rmContext.getRMNodes().keySet()) { + setNodeLabels(node, getNodeLabels(node)); + } + } + + /** + * 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. + */ + private Set fetchLabelsFromScriptOutput(String scriptOutput) { + Set nodeLabels = new HashSet(); + String[] splits = scriptOutput.split("\n"); + for (String line : splits) { + String trimmedLine = line.trim(); + if (trimmedLine.startsWith(NODE_LABEL_PATTERN)) { + String[] labels = + trimmedLine.substring(NODE_LABEL_PATTERN.length()).split( + NODE_LABELS_SEPRATOR); + for (String label : labels) { + nodeLabels.add(label.trim()); + } + } + } + return nodeLabels; + } + + @SuppressWarnings("unchecked") + public Set getNodeLabels(NodeId node) { + ArrayList script = (ArrayList) execScript.clone(); + script.add(node.getHost()); + ShellCommandExecutor shexec = null; + Set nodeLabels = CommonNodeLabelsManager.EMPTY_NODELABEL_SET; + try { + shexec = + new ShellCommandExecutor(script.toArray(new String[script + .size()]), null, null, scriptTimeout); + shexec.execute(); + nodeLabels = convertToNodeLabelSet(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); + } + } + return nodeLabels; + } + } + + @Override + public Set getNodeLabels(NodeId node) { + Set nodeLabels = super.getNodeLabels(node); + if (nodeLabels == CommonNodeLabelsManager.EMPTY_NODELABEL_SET + && !nodeLabelsUpdated.contains(node)) { + nodeLabelsUpdated.add(node); + nodeLabels = ((NodeLabelsScriptRunner) getTimerTask()).getNodeLabels(node); + setNodeLabels(node, nodeLabels); + } + + return nodeLabels; + } +} diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/RMWebServices.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/RMWebServices.java index b1fa80a..983a682 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/RMWebServices.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/RMWebServices.java @@ -199,6 +199,17 @@ private void checkAndThrowIfDistributedNodeLabelConfEnabled(String operation) } } + private void checkAndThrowIfHasNodeLableProvider(String operation) + throws IOException { + if (rm.getRMContext().getNodeLabelsProvider() != null) { + String msg = + String.format("Error when invoke method=%s because of " + + "node label provider is not null.", operation); + LOG.error(msg); + throw new IOException(msg); + } + } + RMWebServices(ResourceManager rm, Configuration conf, HttpServletResponse response) { this(rm, conf); @@ -890,6 +901,7 @@ private Response replaceLabelsOnNode( init(); checkAndThrowIfDistributedNodeLabelConfEnabled("replaceLabelsOnNode"); + checkAndThrowIfHasNodeLableProvider("replaceLabelsOnNode"); UserGroupInformation callerUGI = getCallerUserGroupInformation(hsr, true); if (callerUGI == null) {