diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/placement/QueuePlacementRuleUtils.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/placement/QueuePlacementRuleUtils.java index adee5d7e79a..9cab9c5253e 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/placement/QueuePlacementRuleUtils.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/placement/QueuePlacementRuleUtils.java @@ -36,6 +36,9 @@ public static final String PRIMARY_GROUP_MAPPING = "%primary_group"; + public static final String SECONDARY_GROUP_MAPPING = + "%secondary_group"; + private QueuePlacementRuleUtils() { } @@ -100,7 +103,9 @@ public static QueueMappingEntity validateAndGetQueueMapping( public static boolean isStaticQueueMapping(QueueMappingEntity mapping) { return !mapping.getQueue().contains(CURRENT_USER_MAPPING) && !mapping - .getQueue().contains(PRIMARY_GROUP_MAPPING); + .getQueue().contains(PRIMARY_GROUP_MAPPING) + && !mapping + .getQueue().contains(SECONDARY_GROUP_MAPPING); } public static QueuePath extractQueuePath(String queueName) diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/placement/UserGroupMappingPlacementRule.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/placement/UserGroupMappingPlacementRule.java index 43a3043b4d0..06ed42cab68 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/placement/UserGroupMappingPlacementRule.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/placement/UserGroupMappingPlacementRule.java @@ -54,9 +54,13 @@ public static final String PRIMARY_GROUP_MAPPING = "%primary_group"; + public static final String SECONDARY_GROUP_MAPPING = + "%secondary_group"; + private boolean overrideWithQueueMappings = false; private List mappings = null; private Groups groups; + private CapacitySchedulerQueueManager queueManager; @Private public static class QueueMapping { @@ -163,6 +167,28 @@ private ApplicationPlacementContext getPlacementForUser(String user) return getPlacementContext(mapping, user); } else if (mapping.queue.equals(PRIMARY_GROUP_MAPPING)) { return getPlacementContext(mapping, groups.getGroups(user).get(0)); + } else if (mapping.queue.equals(SECONDARY_GROUP_MAPPING)) { + List groupsList = + groups.getGroups(user); + String secondaryGroup = null; + // Traverse all secondary groups (as there could be more than one + // and position is not guaranteed) and ensure there is queue with + // the same name + for (int i = + 1; i < groupsList.size(); i++) { + if (this.queueManager.getQueue(groupsList.get(i)) != null) { + secondaryGroup = groupsList.get(i); + break; + } + } + if (secondaryGroup != null) { + return getPlacementContext(mapping, secondaryGroup); + } else { + LOG.debug( + "User {} is not associated with any Secondary Group. Hence it may use the 'default' queue", + user); + return null; + } } else { return getPlacementContext(mapping); } @@ -251,8 +277,8 @@ public boolean initialize(ResourceScheduler scheduler) // Get new user/group mappings List newMappings = new ArrayList<>(); - CapacitySchedulerQueueManager queueManager = - schedulerContext.getCapacitySchedulerQueueManager(); + queueManager = + schedulerContext.getCapacitySchedulerQueueManager(); // check if mappings refer to valid queues for (QueueMapping mapping : queueMappings) { @@ -365,10 +391,12 @@ private static QueueMapping validateAndGetAutoCreatedQueueMapping( } private static boolean isStaticQueueMapping(QueueMapping mapping) { - return !mapping.getQueue().contains( - UserGroupMappingPlacementRule.CURRENT_USER_MAPPING) && !mapping - .getQueue().contains( - UserGroupMappingPlacementRule.PRIMARY_GROUP_MAPPING); + return !mapping.getQueue() + .contains(UserGroupMappingPlacementRule.CURRENT_USER_MAPPING) + && !mapping.getQueue() + .contains(UserGroupMappingPlacementRule.PRIMARY_GROUP_MAPPING) + && !mapping.getQueue() + .contains(UserGroupMappingPlacementRule.SECONDARY_GROUP_MAPPING); } private static class QueuePath { @@ -443,4 +471,10 @@ private static void validateParentQueue(CSQueue parentQueue, public List getQueueMappings() { return mappings; } + + @VisibleForTesting + public void setQueueManager(CapacitySchedulerQueueManager queueManager) { + this.queueManager = + queueManager; + } } diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/placement/TestUserGroupMappingPlacementRule.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/placement/TestUserGroupMappingPlacementRule.java index a6143ba6cbb..0720daac267 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/placement/TestUserGroupMappingPlacementRule.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/placement/TestUserGroupMappingPlacementRule.java @@ -18,6 +18,9 @@ package org.apache.hadoop.yarn.server.resourcemanager.placement; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + import java.util.Arrays; import org.apache.hadoop.fs.CommonConfigurationKeys; @@ -28,6 +31,8 @@ import org.apache.hadoop.yarn.exceptions.YarnException; import org.apache.hadoop.yarn.server.resourcemanager.placement.UserGroupMappingPlacementRule.QueueMapping; import org.apache.hadoop.yarn.server.resourcemanager.placement.UserGroupMappingPlacementRule.QueueMapping.MappingType; +import org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity.CSQueue; +import org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity.CapacitySchedulerQueueManager; import org.apache.hadoop.yarn.server.resourcemanager.scheduler.fair.SimpleGroupsMapping; import org.apache.hadoop.yarn.util.Records; import org.junit.Assert; @@ -54,6 +59,10 @@ private void verifyQueueMapping(QueueMapping queueMapping, String inputUser, Groups groups = new Groups(conf); UserGroupMappingPlacementRule rule = new UserGroupMappingPlacementRule( overwrite, Arrays.asList(queueMapping), groups); + CapacitySchedulerQueueManager queueManager = + mock(CapacitySchedulerQueueManager.class); + when(queueManager.getQueue("asubgroup2")).thenReturn(mock(CSQueue.class)); + rule.setQueueManager(queueManager); ApplicationSubmissionContext asc = Records.newRecord( ApplicationSubmissionContext.class); asc.setQueue(inputQueue); @@ -64,7 +73,7 @@ private void verifyQueueMapping(QueueMapping queueMapping, String inputUser, @Test public void testMapping() throws YarnException { - // simple base case for mapping user to queue + verifyQueueMapping(new QueueMapping(MappingType.USER, "a", "q1"), "a", "q1"); verifyQueueMapping(new QueueMapping(MappingType.GROUP, "agroup", "q1"), "a", "q1"); @@ -74,6 +83,9 @@ public void testMapping() throws YarnException { "a", "a"); verifyQueueMapping(new QueueMapping(MappingType.USER, "%user", "%primary_group"), "a", "agroup"); + verifyQueueMapping( + new QueueMapping(MappingType.USER, "%user", "%secondary_group"), "a", + "asubgroup2"); verifyQueueMapping(new QueueMapping(MappingType.GROUP, "asubgroup1", "q1"), "a", "q1");