diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/RMActiveServiceContext.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/RMActiveServiceContext.java index 6ee3a4c..60d9c9d 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/RMActiveServiceContext.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/RMActiveServiceContext.java @@ -43,6 +43,7 @@ import org.apache.hadoop.yarn.server.resourcemanager.rmcontainer.ContainerAllocationExpirer; import org.apache.hadoop.yarn.server.resourcemanager.rmnode.RMNode; import org.apache.hadoop.yarn.server.resourcemanager.scheduler.ResourceScheduler; +import org.apache.hadoop.yarn.server.resourcemanager.scheduler.constraint.PlacementConstraintManager; import org.apache.hadoop.yarn.server.resourcemanager.scheduler.distributed.QueueLimitCalculator; import org.apache.hadoop.yarn.server.resourcemanager.security.AMRMTokenSecretManager; import org.apache.hadoop.yarn.server.resourcemanager.security.ClientToAMTokenSecretManagerInRM; @@ -109,6 +110,7 @@ private RMAppLifetimeMonitor rmAppLifetimeMonitor; private QueueLimitCalculator queueLimitCalculator; private AllocationTagsManager allocationTagsManager; + private PlacementConstraintManager placementConstraintManager; public RMActiveServiceContext() { queuePlacementManager = new PlacementManager(); @@ -413,6 +415,19 @@ public void setAllocationTagsManager( @Private @Unstable + public PlacementConstraintManager getPlacementConstraintManager() { + return placementConstraintManager; + } + + @Private + @Unstable + public void setPlacementConstraintManager( + PlacementConstraintManager placementConstraintManager) { + this.placementConstraintManager = placementConstraintManager; + } + + @Private + @Unstable public RMDelegatedNodeLabelsUpdater getRMDelegatedNodeLabelsUpdater() { return rmDelegatedNodeLabelsUpdater; } diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/RMContext.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/RMContext.java index 62899d9..85f1812 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/RMContext.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/RMContext.java @@ -43,7 +43,7 @@ import org.apache.hadoop.yarn.server.resourcemanager.rmcontainer.ContainerAllocationExpirer; import org.apache.hadoop.yarn.server.resourcemanager.rmnode.RMNode; import org.apache.hadoop.yarn.server.resourcemanager.scheduler.ResourceScheduler; - +import org.apache.hadoop.yarn.server.resourcemanager.scheduler.constraint.PlacementConstraintManager; import org.apache.hadoop.yarn.server.resourcemanager.scheduler.distributed.QueueLimitCalculator; import org.apache.hadoop.yarn.server.resourcemanager.security.AMRMTokenSecretManager; import org.apache.hadoop.yarn.server.resourcemanager.security.ClientToAMTokenSecretManagerInRM; @@ -67,7 +67,7 @@ RMStateStore getStateStore(); ConcurrentMap getRMApps(); - + ConcurrentMap getSystemCredentialsForApps(); ConcurrentMap getInactiveRMNodes(); @@ -79,13 +79,13 @@ AMLivelinessMonitor getAMFinishingMonitor(); ContainerAllocationExpirer getContainerAllocationExpirer(); - + DelegationTokenRenewer getDelegationTokenRenewer(); AMRMTokenSecretManager getAMRMTokenSecretManager(); RMContainerTokenSecretManager getContainerTokenSecretManager(); - + NMTokenSecretManagerInRM getNMTokenSecretManager(); ResourceScheduler getScheduler(); @@ -126,9 +126,9 @@ void setRMTimelineCollectorManager( ConfigurationProvider getConfigurationProvider(); boolean isWorkPreservingRecoveryEnabled(); - + RMNodeLabelsManager getNodeLabelManager(); - + public void setNodeLabelManager(RMNodeLabelsManager mgr); RMDelegatedNodeLabelsUpdater getRMDelegatedNodeLabelsUpdater(); @@ -141,11 +141,11 @@ void setRMDelegatedNodeLabelsUpdater( ReservationSystem getReservationSystem(); boolean isSchedulerReadyForAllocatingContainers(); - + Configuration getYarnConfiguration(); - + PlacementManager getQueuePlacementManager(); - + void setQueuePlacementManager(PlacementManager placementMgr); void setLeaderElectorService(EmbeddedElector elector); @@ -171,4 +171,9 @@ void setRMDelegatedNodeLabelsUpdater( AllocationTagsManager getAllocationTagsManager(); void setAllocationTagsManager(AllocationTagsManager allocationTagsManager); + + PlacementConstraintManager getPlacementConstraintsManager(); + + void setPlacementConstraintsManager( + PlacementConstraintManager placementConstraintManager); } diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/RMContextImpl.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/RMContextImpl.java index 315fdc1..c1382ea 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/RMContextImpl.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/RMContextImpl.java @@ -49,7 +49,7 @@ import org.apache.hadoop.yarn.server.resourcemanager.rmcontainer.ContainerAllocationExpirer; import org.apache.hadoop.yarn.server.resourcemanager.rmnode.RMNode; import org.apache.hadoop.yarn.server.resourcemanager.scheduler.ResourceScheduler; - +import org.apache.hadoop.yarn.server.resourcemanager.scheduler.constraint.PlacementConstraintManager; import org.apache.hadoop.yarn.server.resourcemanager.scheduler.distributed.QueueLimitCalculator; import org.apache.hadoop.yarn.server.resourcemanager.security.AMRMTokenSecretManager; import org.apache.hadoop.yarn.server.resourcemanager.security.ClientToAMTokenSecretManagerInRM; @@ -516,6 +516,18 @@ public void setAllocationTagsManager( } @Override + public PlacementConstraintManager getPlacementConstraintsManager() { + return activeServiceContext.getPlacementConstraintManager(); + } + + @Override + public void setPlacementConstraintsManager( + PlacementConstraintManager placementConstraintManager) { + activeServiceContext + .setPlacementConstraintManager(placementConstraintManager); + } + + @Override public RMDelegatedNodeLabelsUpdater getRMDelegatedNodeLabelsUpdater() { return activeServiceContext.getRMDelegatedNodeLabelsUpdater(); } diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/ResourceManager.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/ResourceManager.java index 8d1000e..3d7606d 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/ResourceManager.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/ResourceManager.java @@ -94,6 +94,8 @@ import org.apache.hadoop.yarn.server.resourcemanager.rmnode.RMNodeEventType; import org.apache.hadoop.yarn.server.resourcemanager.scheduler.QueueMetrics; import org.apache.hadoop.yarn.server.resourcemanager.scheduler.ResourceScheduler; +import org.apache.hadoop.yarn.server.resourcemanager.scheduler.constraint.MemoryPlacementConstraintManager; +import org.apache.hadoop.yarn.server.resourcemanager.scheduler.constraint.PlacementConstraintManagerService; import org.apache.hadoop.yarn.server.resourcemanager.scheduler.event.SchedulerEvent; import org.apache.hadoop.yarn.server.resourcemanager.scheduler.event.SchedulerEventType; import org.apache.hadoop.yarn.server.resourcemanager.security.DelegationTokenRenewer; @@ -495,6 +497,11 @@ protected RMNodeLabelsManager createNodeLabelManager() protected AllocationTagsManager createAllocationTagsManager() { return new AllocationTagsManager(); } + + protected PlacementConstraintManagerService createPlacementConstraintManager() { + // Use the in memory Placement Constraint Manager. + return new MemoryPlacementConstraintManager(); + } protected DelegationTokenRenewer createDelegationTokenRenewer() { return new DelegationTokenRenewer(); @@ -618,6 +625,12 @@ protected void serviceInit(Configuration configuration) throws Exception { createAllocationTagsManager(); rmContext.setAllocationTagsManager(allocationTagsManager); + // TODO: Enable on flag? + PlacementConstraintManagerService placementConstraintManager = + createPlacementConstraintManager(); + addService(placementConstraintManager); + rmContext.setPlacementConstraintsManager(placementConstraintManager); + RMDelegatedNodeLabelsUpdater delegatedNodeLabelsUpdater = createRMDelegatedNodeLabelsUpdater(); if (delegatedNodeLabelsUpdater != null) { diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/constraint/MemoryPlacementConstraintManager.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/constraint/MemoryPlacementConstraintManager.java new file mode 100644 index 0000000..7ee888f --- /dev/null +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/constraint/MemoryPlacementConstraintManager.java @@ -0,0 +1,257 @@ +/* + * * + * 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.scheduler.constraint; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.locks.ReentrantReadWriteLock; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.apache.hadoop.classification.InterfaceAudience; +import org.apache.hadoop.classification.InterfaceStability; +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.yarn.api.records.ApplicationId; +import org.apache.hadoop.yarn.api.resource.PlacementConstraint; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * In memory implementation of the {@link PlacementConstraintManagerService}. + */ +@InterfaceAudience.Private +@InterfaceStability.Unstable +public class MemoryPlacementConstraintManager + extends PlacementConstraintManagerService { + + private static final Logger LOG = + LoggerFactory.getLogger(MemoryPlacementConstraintManager.class); + + private ReentrantReadWriteLock.ReadLock readLock; + private ReentrantReadWriteLock.WriteLock writeLock; + + /** + * Stores the global constraints that will be manipulated by the cluster + * admin. The key of each entry is the tag that will enable the corresponding + * constraint. + */ + private Map globalConstraints; + /** + * Stores the constraints for each application, along with the allocation tags + * that will enable each of the constraints for a given application. + */ + private Map> appConstraints; + + public MemoryPlacementConstraintManager() { + ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); + readLock = lock.readLock(); + writeLock = lock.writeLock(); + } + + @Override + protected void serviceInit(Configuration conf) throws Exception { + this.globalConstraints = new HashMap<>(); + this.appConstraints = new HashMap<>(); + super.serviceInit(conf); + } + + @Override + public void registerApplication(ApplicationId appId, + Map, PlacementConstraint> constraintMap) { + // Check if app already exists. If not, prepare its constraint map. + Map constraintsForApp = new HashMap<>(); + try { + readLock.lock(); + if (appConstraints.get(appId) != null) { + LOG.warn("Application {} has already been registered.", appId); + return; + } + // Go over each sourceTag-constraint pair, validate it, and add it to the + // constraint map for this app. + for (Map.Entry, PlacementConstraint> entry : constraintMap + .entrySet()) { + Set sourceTags = entry.getKey(); + PlacementConstraint constraint = entry.getValue(); + if (validateConstraint(sourceTags, constraint)) { + String sourceTag = getValidSourceTag(sourceTags); + if (constraintsForApp.putIfAbsent(sourceTag, constraint) != null) { + LOG.info("Skipping constraint {} for app {}. " + + "There is already a constraint associated with tag {}.", + constraint, appId, sourceTag); + } + } + } + } finally { + readLock.unlock(); + } + + if (constraintsForApp.isEmpty()) { + LOG.info("No constraints will be added for application {}.", appId); + return; + } + // Update appConstraints. + try { + writeLock.lock(); + appConstraints.put(appId, constraintsForApp); + } finally { + writeLock.unlock(); + } + } + + @Override + public void addApplicationConstraint(ApplicationId appId, + Set sourceTags, PlacementConstraint placementConstraint, + boolean replace) { + try { + writeLock.lock(); + Map constraintsForApp = + appConstraints.get(appId); + if (constraintsForApp == null) { + LOG.info("Cannot add constraint to application {}, as it has not " + + "been registered yet.", appId); + return; + } + + addConstraintToMap(constraintsForApp, sourceTags, placementConstraint, + replace); + } finally { + writeLock.unlock(); + } + } + + @Override + public void addGlobalConstraint(Set sourceTags, + PlacementConstraint placementConstraint, boolean replace) { + try { + writeLock.lock(); + addConstraintToMap(globalConstraints, sourceTags, placementConstraint, + replace); + } finally { + writeLock.unlock(); + } + } + + /** + * Helper method that adds a constraint to a map for a given source tag. + * Assumes there is already a lock on the constraint map. + * + * @param constraintMap constraint map to which the constraint will be added + * @param sourceTags the source tags that will enable this constraint + * @param placementConstraint the new constraint to be added + * @param replace if true, an existing constraint for these sourceTags will be + * replaced with the new one + */ + private void addConstraintToMap( + Map constraintMap, Set sourceTags, + PlacementConstraint placementConstraint, boolean replace) { + if (validateConstraint(sourceTags, placementConstraint)) { + String sourceTag = getValidSourceTag(sourceTags); + if (constraintMap.get(sourceTag) == null || replace) { + constraintMap.put(sourceTag, placementConstraint); + } + } + } + + @Override + public Map, PlacementConstraint> getAppConstraints( + ApplicationId appId) { + try { + readLock.lock(); + if (appConstraints.get(appId) == null) { + LOG.info("Application {} is not registered in the Placement " + + "Constraint Manager.", appId); + return null; + } + + // Copy to a new map and return an unmodifiable version of it. + // Each key of the map is a set with a single source tag. + Map, PlacementConstraint> constraintMap = + appConstraints.get(appId).entrySet().stream() + .collect(Collectors.toMap( + e -> Stream.of(e.getKey()).collect(Collectors.toSet()), + e -> e.getValue())); + + return Collections.unmodifiableMap(constraintMap); + } finally { + readLock.unlock(); + } + } + + @Override + public PlacementConstraint getAppConstraint(ApplicationId appId, + Set sourceTags) { + if (!validateSourceTags(sourceTags)) { + return null; + } + String sourceTag = getValidSourceTag(sourceTags); + try { + readLock.lock(); + if (appConstraints.get(appId) == null) { + LOG.info("Application {} is not registered in the Placement " + + "Constraint Manager.", appId); + return null; + } + return appConstraints.get(appId).get(sourceTag); + } finally { + readLock.unlock(); + } + } + + @Override + public PlacementConstraint getGlobalConstraint(Set sourceTags) { + if (!validateSourceTags(sourceTags)) { + return null; + } + String sourceTag = getValidSourceTag(sourceTags); + try { + readLock.lock(); + return globalConstraints.get(sourceTag); + } finally { + readLock.unlock(); + } + } + + @Override + public void unregisterApplication(ApplicationId appId) { + try { + writeLock.lock(); + appConstraints.remove(appId); + } finally { + writeLock.unlock(); + } + } + + @Override + public void removeGlobalConstraint(Set sourceTags) { + if (!validateSourceTags(sourceTags)) { + return; + } + String sourceTag = getValidSourceTag(sourceTags); + try { + writeLock.lock(); + appConstraints.remove(sourceTag); + } finally { + writeLock.unlock(); + } + } +} diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/constraint/PlacementConstraintManager.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/constraint/PlacementConstraintManager.java new file mode 100644 index 0000000..a6d86f1 --- /dev/null +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/constraint/PlacementConstraintManager.java @@ -0,0 +1,135 @@ +/* + * * + * 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.scheduler.constraint; + +import java.util.Map; +import java.util.Set; + +import org.apache.hadoop.classification.InterfaceAudience; +import org.apache.hadoop.classification.InterfaceStability; +import org.apache.hadoop.yarn.api.records.ApplicationId; +import org.apache.hadoop.yarn.api.resource.PlacementConstraint; + +/** + * Interface for storing and retrieving placement constraints (see + * {@link PlacementConstraint}). + */ +@InterfaceAudience.Private +@InterfaceStability.Unstable +public interface PlacementConstraintManager { + + /** + * Register all placement constraints of an application. + * + * @param appId the application ID + * @param constraintMap the map of allocation tags to constraints for this + * application + */ + void registerApplication(ApplicationId appId, + Map, PlacementConstraint> constraintMap); + + /** + * Add a placement constraint for a given application and a given set of + * (source) allocation tags. The constraint will be used on Scheduling + * Requests that carry this set of allocation tags. + * TODO: Support merge and not only replace when adding a constraint. + * + * @param appId the application ID + * @param sourceTags the set of allocation tags that will enable this + * constraint + * @param placementConstraint the constraint + * @param replace if true, an existing constraint for these tags will be + * replaced by the given one + */ + void addApplicationConstraint(ApplicationId appId, Set sourceTags, + PlacementConstraint placementConstraint, boolean replace); + + /** + * Add a placement constraint that will be used globally. These constraints + * are added by the cluster administrator. + * TODO: Support merge and not only replace when adding a constraint. + * + * @param sourceTags the allocation tags that will enable this constraint + * @param placementConstraint the constraint + * @param replace if true, an existing constraint for these tags will be + * replaced by the given one + */ + void addGlobalConstraint(Set sourceTags, + PlacementConstraint placementConstraint, boolean replace); + + /** + * Retrieve all constraints for a given application, along with the allocation + * tags that enable each constraint. + * + * @param appId the application ID + * @return the constraints for this application with the associated tags + */ + Map, PlacementConstraint> getAppConstraints(ApplicationId appId); + + /** + * Retrieve the placement constraint that is associated with a set of + * allocation tags for a given application. + * + * @param appId the application ID + * @param sourceTags the allocation tags that enable this constraint + * @return the constraint + */ + PlacementConstraint getAppConstraint(ApplicationId appId, + Set sourceTags); + + /** + * Retrieve a global constraint that is associated with a given set of + * allocation tags. + * + * @param sourceTags the allocation tags that enable this constraint + * @return the constraint + */ + PlacementConstraint getGlobalConstraint(Set sourceTags); + + /** + * Remove the constraints that correspond to a given application. + * + * @param appId the application that will be removed. + */ + void unregisterApplication(ApplicationId appId); + + /** + * Remove a global constraint that is associated with the given allocation + * tags. + * + * @param sourceTags the allocation tags + */ + void removeGlobalConstraint(Set sourceTags); + + /** + * Validate a placement constraint and the set of allocation tags that will + * enable it. + * + * @param sourceTags the associated allocation tags + * @param placementConstraint the constraint + * @return true if constraint and tags are valid + */ + default boolean validateConstraint(Set sourceTags, + PlacementConstraint placementConstraint) { + return true; + } + +} diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/constraint/PlacementConstraintManagerService.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/constraint/PlacementConstraintManagerService.java new file mode 100644 index 0000000..ad31299 --- /dev/null +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/constraint/PlacementConstraintManagerService.java @@ -0,0 +1,92 @@ +/* + * * + * 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.scheduler.constraint; + +import java.util.Set; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.hadoop.classification.InterfaceAudience; +import org.apache.hadoop.classification.InterfaceStability; +import org.apache.hadoop.service.AbstractService; +import org.apache.hadoop.yarn.api.resource.PlacementConstraint; + +/** + * The service that implements the {@link PlacementConstraintManager} interface. + */ +@InterfaceAudience.Private +@InterfaceStability.Unstable +public abstract class PlacementConstraintManagerService extends AbstractService + implements PlacementConstraintManager { + + protected static final Log LOG = + LogFactory.getLog(PlacementConstraintManagerService.class); + + private PlacementConstraintManager placementConstraintManager = null; + + public PlacementConstraintManagerService() { + super(PlacementConstraintManagerService.class.getName()); + } + + @Override + public boolean validateConstraint(Set sourceTags, + PlacementConstraint placementConstraint) { + if (!validateSourceTags(sourceTags)) { + return false; + } + // TODO: Perform actual validation of the constraint (in YARN-6621). + // TODO: Perform satisfiability check for constraint. + return true; + } + + /** + * Validates whether the allocation tags that will enable a constraint have + * the expected format. At the moment we support a single allocation tag per + * constraint. + * + * @param sourceTags the source allocation tags + * @return true if the tags have the expected format + */ + protected boolean validateSourceTags(Set sourceTags) { + if (sourceTags.isEmpty()) { + LOG.warn("A placement constraint cannot be associated with an empty " + + "set of tags."); + return false; + } + if (sourceTags.size() > 1) { + LOG.warn("Only a single tag can be associated with a placement " + + "constraint currently."); + return false; + } + return true; + } + + /** + * This method will return a single allocation tag. It should be called after + * validating the tags by calling {@link #validateSourceTags}. + * + * @param sourceTags the source allocation tags + * @return the single source tag + */ + protected String getValidSourceTag(Set sourceTags) { + return sourceTags.iterator().next(); + } +}