From 21515d4100d52dc125a4f8ae2e422232c1f2394a Mon Sep 17 00:00:00 2001 From: Sunil Date: Thu, 10 Nov 2016 22:54:44 +0530 Subject: [PATCH] YARN-3955 --- .../apache/hadoop/yarn/security/AccessType.java | 1 + .../yarn/security/ConfiguredYarnAuthorizer.java | 4 +- .../hadoop/yarn/security/PrivilegedEntity.java | 3 +- .../conf/capacity-scheduler.xml | 12 + .../server/resourcemanager/ClientRMService.java | 13 + .../yarn/server/resourcemanager/RMAppManager.java | 12 + .../resourcemanager/scheduler/SchedulerUtils.java | 2 +- .../scheduler/capacity/AbstractCSQueue.java | 9 + .../scheduler/capacity/CSQueue.java | 10 + .../scheduler/capacity/CapacityScheduler.java | 24 ++ .../capacity/CapacitySchedulerConfiguration.java | 38 ++- .../capacity/CapacitySchedulerContext.java | 3 + .../scheduler/capacity/LeafQueue.java | 26 ++ .../capacity/PriorityACLConfiguration.java | 270 +++++++++++++++++++++ .../resourcemanager/security/QueueACLsManager.java | 28 +++ .../yarn/server/resourcemanager/ACLsTestBase.java | 4 +- .../capacity/TestApplicationPriorityACLs.java | 175 +++++++++++++ 17 files changed, 628 insertions(+), 6 deletions(-) create mode 100644 hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/PriorityACLConfiguration.java create mode 100644 hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/TestApplicationPriorityACLs.java diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/security/AccessType.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/security/AccessType.java index 32459b9..38c2836 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/security/AccessType.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/security/AccessType.java @@ -30,4 +30,5 @@ // queue SUBMIT_APP, ADMINISTER_QUEUE, + ACCESS_PRIORITY } \ No newline at end of file diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/security/ConfiguredYarnAuthorizer.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/security/ConfiguredYarnAuthorizer.java index 36c5214..f380298 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/security/ConfiguredYarnAuthorizer.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/security/ConfiguredYarnAuthorizer.java @@ -84,8 +84,8 @@ private boolean checkPermissionInternal(AccessType accessType, if (!queueName.contains(".")) { return ret; } - String parentQueueName = - queueName.substring(0, queueName.lastIndexOf(".")); + String parentQueueName = queueName.substring(0, + queueName.lastIndexOf(".")); return checkPermissionInternal(accessType, new PrivilegedEntity(target.getType(), parentQueueName), user); } diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/security/PrivilegedEntity.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/security/PrivilegedEntity.java index 580bdf4..bfbbbac 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/security/PrivilegedEntity.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/security/PrivilegedEntity.java @@ -34,7 +34,8 @@ public class PrivilegedEntity { public enum EntityType { - QUEUE + QUEUE, + PRIORITY } EntityType type; diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/conf/capacity-scheduler.xml b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/conf/capacity-scheduler.xml index 6ac726e..b5ab317 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/conf/capacity-scheduler.xml +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/conf/capacity-scheduler.xml @@ -98,6 +98,18 @@ + yarn.scheduler.capacity.root.default.acl_access_priority + [max_priority=0 user=*] + + The ACL of who can submit jobs with configured priority. + 'max_priority' indicates the upper range of priority to which this + ACL configuration is applicable for. + 'user/group' will indicate the user or group for which this priority + is valid to submit application. + + + + yarn.scheduler.capacity.node-locality-delay 40 diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/ClientRMService.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/ClientRMService.java index c8af526..81b50d0 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/ClientRMService.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/ClientRMService.java @@ -140,6 +140,7 @@ import org.apache.hadoop.yarn.factory.providers.RecordFactoryProvider; import org.apache.hadoop.yarn.ipc.RPCUtil; import org.apache.hadoop.yarn.ipc.YarnRPC; +import org.apache.hadoop.yarn.security.AccessType; import org.apache.hadoop.yarn.security.client.RMDelegationTokenIdentifier; import org.apache.hadoop.yarn.server.resourcemanager.RMAuditLogger.AuditConstants; import org.apache.hadoop.yarn.server.resourcemanager.nodelabels.RMNodeLabelsManager; @@ -1598,6 +1599,18 @@ public UpdateApplicationPriorityResponse updateApplicationPriority( RMApp application = verifyUserAccessForRMApp(applicationId, callerUGI, AuditConstants.UPDATE_APP_PRIORITY); + if (!queueACLsManager.checkAccess(callerUGI, AccessType.ACCESS_PRIORITY, + application, newAppPriority)) { + RMAuditLogger.logFailure(callerUGI.getShortUserName(), + AuditConstants.UPDATE_APP_PRIORITY, + "User doesn't have permissions to " + + ApplicationAccessType.MODIFY_APP.toString(), + "ClientRMService", AuditConstants.UNAUTHORIZED_USER, applicationId); + throw RPCUtil.getRemoteException(new AccessControlException( + "User " + callerUGI.getShortUserName() + " cannot change priority to " + + newAppPriority + " on " + applicationId + " due to ACLs.")); + } + UpdateApplicationPriorityResponse response = recordFactory .newRecordInstance(UpdateApplicationPriorityResponse.class); // Update priority only when app is tracked by the scheduler diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/RMAppManager.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/RMAppManager.java index 7144421..5ac3aad 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/RMAppManager.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/RMAppManager.java @@ -44,6 +44,7 @@ import org.apache.hadoop.yarn.exceptions.YarnException; import org.apache.hadoop.yarn.ipc.RPCUtil; import org.apache.hadoop.yarn.security.AccessRequest; +import org.apache.hadoop.yarn.security.AccessType; import org.apache.hadoop.yarn.security.YarnAuthorizationProvider; import org.apache.hadoop.yarn.server.resourcemanager.RMAuditLogger.AuditConstants; import org.apache.hadoop.yarn.server.resourcemanager.recovery.RMStateStore; @@ -386,6 +387,17 @@ private RMAppImpl createAndPopulateNewRMApp( "User " + user + " does not have permission to submit " + applicationId + " to queue " + submissionContext.getQueue())); } + + // Check for Priority ACLs also. + Priority priority = submissionContext.getPriority(); + if (null != csqueue && !authorizer.checkPermission( + new AccessRequest(csqueue.getPriorityPrivilegedEntity(priority), + userUgi, AccessType.ACCESS_PRIORITY, applicationId.toString(), + appName, Server.getRemoteAddress(), null))) { + throw RPCUtil.getRemoteException(new AccessControlException( + "User " + user + " does not have permission to submit " + + applicationId + " for priority:" + priority)); + } } // fail the submission if configured application timeout value is invalid diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/SchedulerUtils.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/SchedulerUtils.java index c999e26..6af5be3 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/SchedulerUtils.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/SchedulerUtils.java @@ -379,7 +379,7 @@ public static AccessType toAccessType(QueueACL acl) { } return null; } - + public static boolean checkResourceRequestMatchingNodePartition( String requestedPartition, String nodePartition, SchedulingMode schedulingMode) { diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/AbstractCSQueue.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/AbstractCSQueue.java index 7e18b29..24be36f 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/AbstractCSQueue.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/AbstractCSQueue.java @@ -24,6 +24,7 @@ import java.util.Iterator; import java.util.Map; import java.util.Set; +import java.util.TreeMap; import java.util.concurrent.locks.ReentrantReadWriteLock; import com.google.common.annotations.VisibleForTesting; @@ -105,6 +106,9 @@ protected ReentrantReadWriteLock.ReadLock readLock; protected ReentrantReadWriteLock.WriteLock writeLock; + // All priority ACLs entities have to be stored in a map. + protected Map priorityEntities = new TreeMap<>(); + public AbstractCSQueue(CapacitySchedulerContext cs, String queueName, CSQueue parent, CSQueue old) throws IOException { this.labelManager = cs.getRMContext().getNodeLabelManager(); @@ -216,6 +220,11 @@ public void setParent(CSQueue newParentQueue) { } @Override + public PrivilegedEntity getPriorityPrivilegedEntity(Priority priority) { + return priorityEntities.get(priority); + } + + @Override public boolean hasAccess(QueueACL acl, UserGroupInformation user) { return authorizer.checkPermission( new AccessRequest(queueEntity, user, SchedulerUtils.toAccessType(acl), diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/CSQueue.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/CSQueue.java index e5cbd04..2d9fc10 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/CSQueue.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/CSQueue.java @@ -31,6 +31,7 @@ import org.apache.hadoop.yarn.api.records.ApplicationAttemptId; import org.apache.hadoop.yarn.api.records.ApplicationId; import org.apache.hadoop.yarn.api.records.ContainerStatus; +import org.apache.hadoop.yarn.api.records.Priority; import org.apache.hadoop.yarn.api.records.QueueACL; import org.apache.hadoop.yarn.api.records.QueueState; import org.apache.hadoop.yarn.api.records.Resource; @@ -355,4 +356,13 @@ boolean accept(Resource cluster, void apply(Resource cluster, ResourceCommitRequest request); + + /** + * Get privileged entity object corresponding to priority. + * + * @param priority + * of the application + * @return privileged entity object corresponding to priority + */ + public PrivilegedEntity getPriorityPrivilegedEntity(Priority priority); } diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/CapacityScheduler.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/CapacityScheduler.java index af51f3c..4b14579 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/CapacityScheduler.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/CapacityScheduler.java @@ -47,6 +47,7 @@ import org.apache.hadoop.security.AccessControlException; import org.apache.hadoop.security.Groups; import org.apache.hadoop.security.UserGroupInformation; +import org.apache.hadoop.security.authorize.AccessControlList; import org.apache.hadoop.util.Time; import org.apache.hadoop.yarn.api.records.ApplicationAttemptId; import org.apache.hadoop.yarn.api.records.ApplicationId; @@ -68,6 +69,7 @@ import org.apache.hadoop.yarn.exceptions.YarnException; import org.apache.hadoop.yarn.exceptions.YarnRuntimeException; import org.apache.hadoop.yarn.proto.YarnServiceProtos.SchedulerResourceTypes; +import org.apache.hadoop.yarn.security.AccessType; import org.apache.hadoop.yarn.security.Permission; import org.apache.hadoop.yarn.security.YarnAuthorizationProvider; import org.apache.hadoop.yarn.server.resourcemanager.RMContext; @@ -622,6 +624,7 @@ private void initializeQueues(CapacitySchedulerConfiguration conf) LOG.info("Initialized root queue " + root); updatePlacementRules(); setQueueAcls(authorizer, queues); + setPriorityAcls(authorizer, queues); // Notify Preemption Manager preemptionManager.refreshQueues(null, root); @@ -653,6 +656,7 @@ private void reinitializeQueues(CapacitySchedulerConfiguration newConf) labelManager.reinitializeQueueLabels(getQueueToLabels()); setQueueAcls(authorizer, queues); + setPriorityAcls(authorizer, queues); // Notify Preemption Manager preemptionManager.refreshQueues(null, root); @@ -670,6 +674,26 @@ public static void setQueueAcls(YarnAuthorizationProvider authorizer, authorizer.setPermission(permissions, UserGroupInformation.getCurrentUser()); } + public static void setPriorityAcls(YarnAuthorizationProvider authorizer, + Map queues) throws IOException { + List permissions = new ArrayList<>(); + for (CSQueue queue : queues.values()) { + if (queue instanceof LeafQueue) { + LeafQueue lQueue = (LeafQueue) queue; + + for (Entry entry : lQueue.getPriorityACLs() + .entrySet()) { + Map acl = new HashMap<>(); + acl.put(AccessType.ACCESS_PRIORITY, entry.getValue()); + permissions.add( + new Permission(lQueue.getPriorityPrivilegedEntity(entry.getKey()), acl)); + } + } + } + authorizer.setPermission(permissions, + UserGroupInformation.getCurrentUser()); + } + private Map> getQueueToLabels() { Map> queueToLabels = new HashMap>(); for (CSQueue queue : queues.values()) { diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/CapacitySchedulerConfiguration.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/CapacitySchedulerConfiguration.java index c153c26..8ef5e3b 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/CapacitySchedulerConfiguration.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/CapacitySchedulerConfiguration.java @@ -38,6 +38,7 @@ import org.apache.hadoop.security.authorize.AccessControlList; import org.apache.hadoop.util.ReflectionUtils; import org.apache.hadoop.util.StringUtils; +import org.apache.hadoop.yarn.api.records.Priority; import org.apache.hadoop.yarn.api.records.QueueACL; import org.apache.hadoop.yarn.api.records.QueueState; import org.apache.hadoop.yarn.api.records.ReservationACL; @@ -49,6 +50,7 @@ import org.apache.hadoop.yarn.server.resourcemanager.placement.UserGroupMappingPlacementRule.QueueMapping; import org.apache.hadoop.yarn.server.resourcemanager.reservation.ReservationSchedulerConfiguration; import org.apache.hadoop.yarn.server.resourcemanager.scheduler.SchedulerUtils; +import org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity.PriorityACLConfiguration.PriorityACLConfig; import org.apache.hadoop.yarn.server.resourcemanager.scheduler.policy.FairOrderingPolicy; import org.apache.hadoop.yarn.server.resourcemanager.scheduler.policy.FifoOrderingPolicy; import org.apache.hadoop.yarn.server.resourcemanager.scheduler.policy.OrderingPolicy; @@ -63,7 +65,7 @@ private static final Log LOG = LogFactory.getLog(CapacitySchedulerConfiguration.class); - + private static final String CS_CONFIGURATION_FILE = "capacity-scheduler.xml"; @Private @@ -274,6 +276,8 @@ @Private public static final boolean DEFAULT_LAZY_PREEMPTION_ENABLED = false; + PriorityACLConfiguration priorityACLConfig = new PriorityACLConfiguration(); + public CapacitySchedulerConfiguration() { this(new Configuration()); } @@ -588,6 +592,10 @@ private static String getAclKey(ReservationACL acl) { return "acl_" + StringUtils.toLowerCase(acl.toString()); } + private static String getAclKey(AccessType acl) { + return "acl_" + StringUtils.toLowerCase(acl.toString()); + } + @Override public Map getReservationAcls(String queue) { @@ -613,6 +621,11 @@ private void setAcl(String queue, ReservationACL acl, String aclString) { set(queuePrefix + getAclKey(acl), aclString); } + private void setAcl(String queue, AccessType acl, String aclString) { + String queuePrefix = getQueuePrefix(queue); + set(queuePrefix + getAclKey(acl), aclString); + } + public Map getAcls(String queue) { Map acls = new HashMap(); @@ -636,6 +649,29 @@ public void setReservationAcls(String queue, } } + @VisibleForTesting + public void setPriorityAcls(String queue, Priority priority, + String[] acls) { + StringBuilder aclString = new StringBuilder(); + + for (int i = 0; i < acls.length; i++) { + aclString.append("[max_priority=" + priority.getPriority() + " " + + PriorityACLConfig.values()[i] + "=" + acls[i].trim() + "]"); + } + + setAcl(queue, AccessType.ACCESS_PRIORITY, aclString.toString()); + } + + public Map getPriorityAcls(String queue, + Priority clusterMaxPriority) { + String queuePrefix = getQueuePrefix(queue); + String defaultAcl = ALL_ACL; + String aclString = get( + queuePrefix + getAclKey(AccessType.ACCESS_PRIORITY), defaultAcl); + + return priorityACLConfig.getPriorityAcl(clusterMaxPriority, aclString); + } + public String[] getQueues(String queue) { LOG.debug("CSConf - getQueues called for: queuePrefix=" + getQueuePrefix(queue)); String[] queues = getStrings(getQueuePrefix(queue) + QUEUES); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/CapacitySchedulerContext.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/CapacitySchedulerContext.java index c41a7bf..1a52eda 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/CapacitySchedulerContext.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/CapacitySchedulerContext.java @@ -23,6 +23,7 @@ import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.yarn.api.records.ApplicationAttemptId; import org.apache.hadoop.yarn.api.records.NodeId; +import org.apache.hadoop.yarn.api.records.Priority; import org.apache.hadoop.yarn.api.records.Resource; import org.apache.hadoop.yarn.server.resourcemanager.RMContext; import org.apache.hadoop.yarn.server.resourcemanager.scheduler.activities.ActivitiesManager; @@ -83,4 +84,6 @@ ResourceUsage getClusterResourceUsage(); ActivitiesManager getActivitiesManager(); + + Priority getMaxClusterLevelAppPriority(); } diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/LeafQueue.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/LeafQueue.java index 161957f..6a14519 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/LeafQueue.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/LeafQueue.java @@ -20,6 +20,7 @@ import java.io.IOException; import java.util.*; +import java.util.Map.Entry; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock; @@ -50,6 +51,8 @@ import org.apache.hadoop.yarn.factory.providers.RecordFactoryProvider; import org.apache.hadoop.yarn.nodelabels.CommonNodeLabelsManager; import org.apache.hadoop.yarn.security.AccessType; +import org.apache.hadoop.yarn.security.PrivilegedEntity; +import org.apache.hadoop.yarn.security.PrivilegedEntity.EntityType; import org.apache.hadoop.yarn.server.resourcemanager.RMServerUtils; import org.apache.hadoop.yarn.server.resourcemanager.nodelabels.RMNodeLabelsManager; import org.apache.hadoop.yarn.server.resourcemanager.rmcontainer.RMContainer; @@ -139,6 +142,9 @@ private Map> ignorePartitionExclusivityRMContainers = new ConcurrentHashMap<>(); + Map priorityAcls = + new HashMap(); + @SuppressWarnings({ "unchecked", "rawtypes" }) public LeafQueue(CapacitySchedulerContext cs, String queueName, CSQueue parent, CSQueue old) throws IOException { @@ -199,6 +205,16 @@ protected void setupQueueConfigs(Resource clusterResource) conf.getMaximumApplicationMasterResourcePerQueuePercent( getQueuePath()); + priorityAcls = conf.getPriorityAcls(getQueuePath(), + scheduler.getMaxClusterLevelAppPriority()); + for (Entry entry : priorityAcls.entrySet()) { + Priority priority = entry.getKey(); + StringBuilder str = new StringBuilder(getQueueName()); + str.append("_").append(priority.getPriority()); + priorityEntities.put(priority, + new PrivilegedEntity(EntityType.PRIORITY, str.toString())); + } + if (!SchedulerUtils.checkQueueLabelExpression(this.accessibleLabels, this.defaultLabelExpression, null)) { throw new IOException( @@ -491,6 +507,16 @@ private User getUserAndAddIfAbsent(String userName) { } } + @Private + public Map getPriorityACLs() { + try { + readLock.lock(); + return priorityAcls; + } finally { + readLock.unlock(); + } + } + @Override public void reinitialize( CSQueue newlyParsedQueue, Resource clusterResource) diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/PriorityACLConfiguration.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/PriorityACLConfiguration.java new file mode 100644 index 0000000..740e592 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/PriorityACLConfiguration.java @@ -0,0 +1,270 @@ +/** +* 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.capacity; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.hadoop.classification.InterfaceAudience.Private; +import org.apache.hadoop.security.authorize.AccessControlList; +import org.apache.hadoop.util.StringUtils; +import org.apache.hadoop.yarn.api.records.Priority; + +public class PriorityACLConfiguration { + + private static final Log LOG = + LogFactory.getLog(PriorityACLConfiguration.class); + + public enum PriorityACLConfig { + USER(1), GROUP(2), MAX_PRIORITY(3), DEFAULT_PRIORITY(4); + + private final int id; + + PriorityACLConfig(int id) { + this.id = id; + } + + public int getId() { + return this.id; + } + } + + public static final String PATTERN_FOR_PRIORITY_ACL = "\\[([^\\]]+)"; + + @Private + public static final String ALL_ACL = "*"; + + @Private + public static final String NONE_ACL = " "; + + public HashMap getPriorityAcl( + Priority clusterMaxPriority, String aclString) { + + Map> map = new HashMap<>(); + Matcher matcher = Pattern.compile(PATTERN_FOR_PRIORITY_ACL) + .matcher(aclString); + + /* + * Each ACL group will be separated by "[]". Syntax of each ACL group could + * be like below "max-priority=a1 user=b1,b2 default-priority=c1" + */ + while (matcher.find()) { + // Get the first ACL sub-group. + String aclSubGroup = matcher.group(1); + if (aclSubGroup.trim().isEmpty()) { + continue; + } + + /* + * Internal tracking storage (map) needs key as 'priority' and value as + * ' '. So save priority after initial parsing so that + * for USER or GROUP parsing and storage, user saved priority as key. + */ + Priority max_priority = null; + for (String kvPair : aclSubGroup.trim().split(" +")) { + /* + * There are 3 possible options for key here: 1. user/group 2. + * max-priority 3. default-priority + * + * Categorize ACL map with max-priority as key and keep acl string as + * "user1,user2 group" format. + */ + String[] splits = kvPair.split("="); + + // Ensure that each ACL sub string is key value pair separated by '='. + if (splits != null && splits.length > 1) { + max_priority = parsePriorityACLType(map, max_priority, splits); + + // If max_priority is higher to clusterMaxPriority, its better to + // handle here. + if (max_priority.getPriority() > clusterMaxPriority.getPriority()) { + LOG.warn("ACL configuration for '" + max_priority + + "' is greater that cluster max priority. Resetting ACLs to " + + clusterMaxPriority); + max_priority = Priority + .newInstance(clusterMaxPriority.getPriority()); + } + } + } + } + + // Consider default case where no ACLs are configured and also case where + // ACLs to be added till cluster max priority. + handleDefaultConfigForACLs(map, aclString, clusterMaxPriority); + + // Finally output map will have priority as key. Here value is acl string. + // Value could be a join of user and group. + HashMap output = new HashMap<>(); + createACLStringPerPriority(output, map); + + return output; + } + + /* + * This method will help to append different types of ACLs keys against one + * priority. For eg,USER will be appended with GROUP as "user2,user4 group1". + */ + private void createACLStringPerPriority( + HashMap output, + Map> map) { + for (Entry> entry : map.entrySet()) { + Priority priority = entry.getKey(); + List acls = entry.getValue(); + + String finalACL = new String(); + String userACL = acls.get(0).toString(); + + // If any of user/group is *, consider it as acceptable for all. + // "user" is at index 0, and "group" is at index 1. + if (userACL.trim().equals(ALL_ACL)) { + finalACL = ALL_ACL; + } else if (userACL.equals(NONE_ACL)) { + finalACL = NONE_ACL; + } else { + + // Get USER segment + if (!userACL.trim().isEmpty()) { + // skip last appended "," + finalACL = acls.get(0).substring(0, acls.get(0).length() - 1); + } + + // Get GROUP segment if any + String groupACL = acls.get(1).toString(); + if (!groupACL.trim().isEmpty()) { + finalACL = finalACL + " " + + acls.get(1).substring(0, acls.get(1).length() - 1); + } + } + + // Here ACL will look like "user1,user2 group" in ideal cases. + output.put(priority, new AccessControlList(finalACL.trim())); + } + } + + /* + * Parse different types of ACLs sub parts for on priority group and store in + * a map for later processing. + */ + private Priority parsePriorityACLType(Map> map, + Priority max_priority, String[] splits) { + // Here splits will have the key value pair at index 0 and 1 respectively. + // To parse all keys, its better to convert to PriorityACLConfig enum. + PriorityACLConfig aclType = PriorityACLConfig + .valueOf(StringUtils.toUpperCase(splits[0].trim())); + switch (aclType) { + case MAX_PRIORITY : + max_priority = Priority.newInstance(Integer.parseInt(splits[1])); + break; + case USER : + createACLStringForPriority(map, max_priority, splits[1], + PriorityACLConfig.USER); + break; + case GROUP : + createACLStringForPriority(map, max_priority, splits[1], + PriorityACLConfig.GROUP); + break; + case DEFAULT_PRIORITY : + // ToDO + break; + } + return max_priority; + } + + /* + * This method will help to append user/group acl string against given + * priority. For example "user1,user2 group1,group2" + */ + private void createACLStringForPriority( + Map> map, Priority max_priority, + String value, PriorityACLConfig type) { + + // Ideally max_priority shouldn't be null. + if (null == max_priority) { + return; + } + + // Fill ACL for each possible priority entries. + for (int i = 0; i <= max_priority.getPriority(); i++) { + Priority currPriority = Priority.newInstance(i); + List aclList = map.get(currPriority); + if (aclList == null) { + aclList = new ArrayList<>(); + aclList.add(new StringBuilder()); + aclList.add(new StringBuilder()); + map.put(currPriority, aclList); + } + + // ACL strings could be generate for USER or GRUOP. + // aclList in map contains two entries. 1. USER, 2. GROUP. + StringBuilder aclTypeName = aclList.get(type.getId() - 1); + if (aclTypeName.equals(ALL_ACL)) { + return; + } + + if (value.trim().equals(ALL_ACL)) { + aclTypeName.setLength(0); + aclTypeName.append(ALL_ACL); + return; + } + + // Append a space as delim. + aclTypeName.append(value.trim()).append(","); + } + } + + private void handleDefaultConfigForACLs( + Map> map, String aclString, + Priority clusterMaxPriority) { + // If there are no configurations for ACL, then ALL_ACL can be + // set for all priorities. + if (map.isEmpty()) { + setDefaultACLTillConfiguredPriority(map, 0, + clusterMaxPriority.getPriority(), ALL_ACL); + } else { + // Find the max priority to which ACLs are configured. Remaining + // priorities till Cluster max priority should be set as NONE_ACL. + int configuredMaxPriority = 0; + for (Entry> entry : map.entrySet()) { + if (entry.getKey().getPriority() > configuredMaxPriority) { + configuredMaxPriority = entry.getKey().getPriority(); + } + } + setDefaultACLTillConfiguredPriority(map, configuredMaxPriority + 1, + clusterMaxPriority.getPriority(), NONE_ACL); + } + } + + private void setDefaultACLTillConfiguredPriority( + Map> map, int fromThisPriority, + int tillThisPriority, String acl) { + for (int i = fromThisPriority; i <= tillThisPriority; i++) { + Priority priority = Priority.newInstance(i); + List aclList = new ArrayList<>(); + aclList.add(new StringBuilder(acl)); + map.put(priority, aclList); + } + } +} diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/security/QueueACLsManager.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/security/QueueACLsManager.java index c9d55f1..ea477d6 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/security/QueueACLsManager.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/security/QueueACLsManager.java @@ -22,10 +22,13 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.ipc.Server; import org.apache.hadoop.security.UserGroupInformation; +import org.apache.hadoop.yarn.api.records.Priority; import org.apache.hadoop.yarn.api.records.QueueACL; import org.apache.hadoop.yarn.conf.YarnConfiguration; import org.apache.hadoop.yarn.security.AccessRequest; +import org.apache.hadoop.yarn.security.AccessType; import org.apache.hadoop.yarn.security.YarnAuthorizationProvider; import org.apache.hadoop.yarn.server.resourcemanager.rmapp.RMApp; import org.apache.hadoop.yarn.server.resourcemanager.scheduler.ResourceScheduler; @@ -80,4 +83,29 @@ public boolean checkAccess(UserGroupInformation callerUGI, QueueACL acl, return scheduler.checkAccess(callerUGI, acl, app.getQueue()); } } + + public boolean checkAccess(UserGroupInformation callerUGI, AccessType acl, + RMApp app, Priority newAppPriority) { + if (!isACLsEnable) { + return true; + } + + if (scheduler instanceof CapacityScheduler) { + CSQueue queue = ((CapacityScheduler) scheduler).getQueue(app.getQueue()); + if (queue == null) { + // Application exists but the associated queue does not exist. + // This may be due to queue is removed after RM restarts. Here, we + // choose to allow users to be able to view the apps for removed queue. + LOG.error("Queue " + app.getQueue() + " does not exist for " + + app.getApplicationId()); + return true; + } + return authorizer.checkPermission( + new AccessRequest(queue.getPriorityPrivilegedEntity(newAppPriority), + callerUGI, acl, app.getApplicationId().toString(), app.getName(), + Server.getRemoteAddress(), null)); + } + + return true; + } } diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/ACLsTestBase.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/ACLsTestBase.java index e661703..53e23ae 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/ACLsTestBase.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/ACLsTestBase.java @@ -43,6 +43,7 @@ protected static final String COMMON_USER = "common_user"; protected static final String QUEUE_A_USER = "queueA_user"; protected static final String QUEUE_B_USER = "queueB_user"; + protected static final String QUEUE_A_GROUP = "queueA_group"; protected static final String ROOT_ADMIN = "root_admin"; protected static final String QUEUE_A_ADMIN = "queueA_admin"; protected static final String QUEUE_B_ADMIN = "queueB_admin"; @@ -53,7 +54,7 @@ protected static final Log LOG = LogFactory.getLog(TestApplicationACLs.class); - MockRM resourceManager; + protected MockRM resourceManager; Configuration conf; YarnRPC rpc; InetSocketAddress rmAddress; @@ -68,6 +69,7 @@ public void setup() throws InterruptedException, IOException { AccessControlList adminACL = new AccessControlList(""); conf.set(YarnConfiguration.YARN_ADMIN_ACL, adminACL.getAclString()); + conf.setInt(YarnConfiguration.MAX_CLUSTER_LEVEL_APPLICATION_PRIORITY, 10); resourceManager = new MockRM(conf) { protected ClientRMService createClientRMService() { diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/TestApplicationPriorityACLs.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/TestApplicationPriorityACLs.java new file mode 100644 index 0000000..72b8136 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/TestApplicationPriorityACLs.java @@ -0,0 +1,175 @@ +/** +* 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.capacity; + + +import java.io.IOException; + +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.ipc.RemoteException; +import org.apache.hadoop.security.AccessControlException; +import org.apache.hadoop.yarn.api.ApplicationClientProtocol; +import org.apache.hadoop.yarn.api.protocolrecords.GetApplicationReportRequest; +import org.apache.hadoop.yarn.api.protocolrecords.GetApplicationReportResponse; +import org.apache.hadoop.yarn.api.protocolrecords.GetNewApplicationRequest; +import org.apache.hadoop.yarn.api.protocolrecords.SubmitApplicationRequest; +import org.apache.hadoop.yarn.api.records.ApplicationId; +import org.apache.hadoop.yarn.api.records.ApplicationSubmissionContext; +import org.apache.hadoop.yarn.api.records.ContainerLaunchContext; +import org.apache.hadoop.yarn.api.records.Priority; +import org.apache.hadoop.yarn.api.records.Resource; +import org.apache.hadoop.yarn.conf.YarnConfiguration; +import org.apache.hadoop.yarn.exceptions.YarnException; +import org.apache.hadoop.yarn.server.resourcemanager.ACLsTestBase; +import org.apache.hadoop.yarn.server.resourcemanager.rmapp.RMAppState; +import org.apache.hadoop.yarn.server.utils.BuilderUtils; +import org.junit.Assert; +import org.junit.Test; + + +public class TestApplicationPriorityACLs extends ACLsTestBase { + + @Test + public void testApplicationACLs() throws Exception { + verifyAppSubmitWithPrioritySuccess(QUEUE_A_USER, QUEUEA, 5, true); + verifyAppSubmitWithPriorityFailure(QUEUE_A_USER, QUEUEA, 6, true); + } + + private void verifyAppSubmitWithPrioritySuccess(String submitter, + String queueName, int priority, boolean setupACLs) throws Exception { + ApplicationSubmissionContext submissionContext = prepareForAppSubmission( + submitter, queueName, priority, setupACLs); + submitAppToRMWithValidAcl(submitter, submissionContext); + + // Ideally get app report here and check the priority. + verifyAppPriorityIsAccepted(submitter, submissionContext.getApplicationId(), + priority); + } + + private void verifyAppSubmitWithPriorityFailure(String submitter, + String queueName, int priority, boolean setupACLs) throws Exception { + ApplicationSubmissionContext submissionContext = prepareForAppSubmission( + submitter, queueName, priority, setupACLs); + submitAppToRMWithInValidAcl(submitter, submissionContext); + } + + private ApplicationSubmissionContext prepareForAppSubmission(String submitter, + String queueName, int priority, boolean setupACLs) throws Exception { + + GetNewApplicationRequest newAppRequest = GetNewApplicationRequest + .newInstance(); + + ApplicationClientProtocol submitterClient = getRMClientForUser(submitter); + ApplicationId applicationId = submitterClient + .getNewApplication(newAppRequest).getApplicationId(); + + Resource resource = BuilderUtils.newResource(1024, 1); + + ContainerLaunchContext amContainerSpec = ContainerLaunchContext + .newInstance(null, null, null, null, null, null); + ApplicationSubmissionContext appSubmissionContext = ApplicationSubmissionContext + .newInstance(applicationId, "applicationName", queueName, null, + amContainerSpec, false, true, 1, resource, "applicationType"); + appSubmissionContext.setApplicationId(applicationId); + appSubmissionContext.setQueue(queueName); + appSubmissionContext.setPriority(Priority.newInstance(priority)); + + return appSubmissionContext; + } + + private void submitAppToRMWithValidAcl(String submitter, + ApplicationSubmissionContext appSubmissionContext) + throws YarnException, IOException, InterruptedException { + ApplicationClientProtocol submitterClient = getRMClientForUser(submitter); + SubmitApplicationRequest submitRequest = SubmitApplicationRequest + .newInstance(appSubmissionContext); + submitterClient.submitApplication(submitRequest); + resourceManager.waitForState(appSubmissionContext.getApplicationId(), + RMAppState.ACCEPTED); + } + + private void submitAppToRMWithInValidAcl(String submitter, + ApplicationSubmissionContext appSubmissionContext) + throws YarnException, IOException, InterruptedException { + ApplicationClientProtocol submitterClient = getRMClientForUser(submitter); + SubmitApplicationRequest submitRequest = SubmitApplicationRequest + .newInstance(appSubmissionContext); + try { + submitterClient.submitApplication(submitRequest); + } catch (YarnException ex) { + Assert.assertTrue(ex.getCause() instanceof RemoteException); + } + } + + private void verifyAppPriorityIsAccepted(String submitter, + ApplicationId applicationId, int priority) + throws IOException, InterruptedException { + ApplicationClientProtocol submitterClient = getRMClientForUser(submitter); + + GetApplicationReportRequest request = GetApplicationReportRequest + .newInstance(applicationId); + try { + GetApplicationReportResponse response = submitterClient + .getApplicationReport(request); + Assert.assertEquals(response.getApplicationReport().getPriority(), + Priority.newInstance(priority)); + } catch (YarnException e) { + Assert.fail("Application submission should not fail."); + } + } + + private void verifyAppPriorityIsRejected(String submitter, + ApplicationId applicationId, int priority) + throws IOException, InterruptedException { + ApplicationClientProtocol submitterClient = getRMClientForUser(submitter); + + GetApplicationReportRequest request = GetApplicationReportRequest + .newInstance(applicationId); + try { + GetApplicationReportResponse response = submitterClient + .getApplicationReport(request); + Assert.assertNotEquals(response.getApplicationReport().getPriority(), + Priority.newInstance(priority)); + } catch (Exception ex) { + Assert.assertTrue(ex instanceof AccessControlException); + } + } + + @Override + protected Configuration createConfiguration() { + CapacitySchedulerConfiguration csConf = new CapacitySchedulerConfiguration(); + csConf.setQueues(CapacitySchedulerConfiguration.ROOT, + new String[]{QUEUEA, QUEUEB}); + + csConf.setCapacity(CapacitySchedulerConfiguration.ROOT + "." + QUEUEA, 50f); + csConf.setCapacity(CapacitySchedulerConfiguration.ROOT + "." + QUEUEB, 50f); + + int priorityFive = 5; + String[] acls = new String[2]; + acls[0] = QUEUE_A_USER; + acls[1] = QUEUE_A_GROUP; + csConf.setPriorityAcls(CapacitySchedulerConfiguration.ROOT + "." + QUEUEA, + Priority.newInstance(priorityFive), acls); + + csConf.setBoolean(YarnConfiguration.YARN_ACL_ENABLE, true); + csConf.set(YarnConfiguration.RM_SCHEDULER, + CapacityScheduler.class.getName()); + + return csConf; + } +} -- 2.7.4 (Apple Git-66)