diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/AdminService.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/AdminService.java index 75717652d9..d5e2b3f8c4 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/AdminService.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/AdminService.java @@ -92,6 +92,8 @@ import org.apache.hadoop.yarn.server.resourcemanager.resource.DynamicResourceConfiguration; import org.apache.hadoop.yarn.server.resourcemanager.rmnode.RMNode; import org.apache.hadoop.yarn.server.resourcemanager.rmnode.RMNodeResourceUpdateEvent; +import org.apache.hadoop.yarn.server.resourcemanager.scheduler.MutableConfScheduler; +import org.apache.hadoop.yarn.server.resourcemanager.scheduler.ResourceScheduler; import org.apache.hadoop.yarn.server.resourcemanager.security.authorize.RMPolicyProvider; import com.google.common.annotations.VisibleForTesting; @@ -385,6 +387,12 @@ public RefreshQueuesResponse refreshQueues(RefreshQueuesRequest request) RefreshQueuesResponse response = recordFactory.newRecordInstance(RefreshQueuesResponse.class); try { + ResourceScheduler scheduler = rmContext.getScheduler(); + if (scheduler instanceof MutableConfScheduler + && ((MutableConfScheduler) scheduler).isConfigurationMutable()) { + throw new IOException("Scheduler configuration is mutable. " + + operation + " is not allowed in this scenario."); + } refreshQueues(); RMAuditLogger.logSuccess(user.getShortUserName(), operation, "AdminService"); @@ -394,7 +402,7 @@ public RefreshQueuesResponse refreshQueues(RefreshQueuesRequest request) } } - private void refreshQueues() throws IOException, YarnException { + public void refreshQueues() throws IOException, YarnException { rmContext.getScheduler().reinitialize(getConfig(), this.rmContext); // refresh the reservation system ReservationSystem rSystem = rmContext.getReservationSystem(); diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/MutableConfScheduler.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/MutableConfScheduler.java index 027d9441b5..6589c2e34c 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/MutableConfScheduler.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/MutableConfScheduler.java @@ -19,6 +19,7 @@ import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.security.UserGroupInformation; +import org.apache.hadoop.yarn.exceptions.YarnException; import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.SchedConfUpdateInfo; import java.io.IOException; @@ -33,10 +34,11 @@ * Update the scheduler's configuration. * @param user Caller of this update * @param confUpdate configuration update - * @throws IOException if update is invalid + * @throws IOException if scheduler could not be reinitialized + * @throws YarnException if reservation system could not be reinitialized */ void updateConfiguration(UserGroupInformation user, - SchedConfUpdateInfo confUpdate) throws IOException; + SchedConfUpdateInfo confUpdate) throws IOException, YarnException; /** * Get the scheduler configuration. @@ -50,4 +52,10 @@ void updateConfiguration(UserGroupInformation user, * @return the queue object */ Queue getQueue(String queueName); + + /** + * Return whether the scheduler configuration is mutable. + * @return whether scheduler configuration is mutable or not. + */ + boolean isConfigurationMutable(); } diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/MutableConfigurationProvider.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/MutableConfigurationProvider.java index 6b8306c80c..c2da3d0f99 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/MutableConfigurationProvider.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/MutableConfigurationProvider.java @@ -19,6 +19,7 @@ package org.apache.hadoop.yarn.server.resourcemanager.scheduler; import org.apache.hadoop.security.UserGroupInformation; +import org.apache.hadoop.yarn.exceptions.YarnException; import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.SchedConfUpdateInfo; import java.io.IOException; @@ -33,8 +34,9 @@ * @param user User issuing the request * @param confUpdate Key-value pairs for configurations to be updated. * @throws IOException if scheduler could not be reinitialized + * @throws YarnException if reservation system could not be reinitialized */ void mutateConfiguration(UserGroupInformation user, SchedConfUpdateInfo - confUpdate) throws IOException; + confUpdate) throws IOException, YarnException; } diff --git 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 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 9299c4ac7e..39d7550f9e 100644 --- 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 +++ 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 @@ -2493,8 +2493,8 @@ public boolean moveReservedContainer(RMContainer toBeMovedContainer, @Override public void updateConfiguration(UserGroupInformation user, - SchedConfUpdateInfo confUpdate) throws IOException { - if (csConfProvider instanceof MutableConfigurationProvider) { + SchedConfUpdateInfo confUpdate) throws IOException, YarnException { + if (isConfigurationMutable()) { ((MutableConfigurationProvider) csConfProvider).mutateConfiguration( user, confUpdate); } else { @@ -2502,4 +2502,9 @@ public void updateConfiguration(UserGroupInformation user, "provider does not support updating configuration."); } } + + @Override + public boolean isConfigurationMutable() { + return csConfProvider instanceof MutableConfigurationProvider; + } } diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/conf/MutableCSConfigurationProvider.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/conf/MutableCSConfigurationProvider.java index eb9726078f..139f8bd548 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/conf/MutableCSConfigurationProvider.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/conf/MutableCSConfigurationProvider.java @@ -23,6 +23,7 @@ import org.apache.hadoop.security.AccessControlException; import org.apache.hadoop.security.UserGroupInformation; import org.apache.hadoop.yarn.conf.YarnConfiguration; +import org.apache.hadoop.yarn.exceptions.YarnException; import org.apache.hadoop.yarn.server.resourcemanager.RMContext; import org.apache.hadoop.yarn.server.resourcemanager.scheduler.ConfigurationMutationACLPolicy; import org.apache.hadoop.yarn.server.resourcemanager.scheduler.ConfigurationMutationACLPolicyFactory; @@ -53,7 +54,6 @@ private YarnConfigurationStore confStore; private ConfigurationMutationACLPolicy aclMutationPolicy; private RMContext rmContext; - private Configuration conf; public MutableCSConfigurationProvider(RMContext rmContext) { this.rmContext = rmContext; @@ -85,7 +85,6 @@ public void init(Configuration config) throws IOException { this.aclMutationPolicy = ConfigurationMutationACLPolicyFactory .getPolicy(config); aclMutationPolicy.init(config, rmContext); - this.conf = config; } @Override @@ -98,7 +97,7 @@ public CapacitySchedulerConfiguration loadConfiguration(Configuration @Override public void mutateConfiguration(UserGroupInformation user, - SchedConfUpdateInfo confUpdate) throws IOException { + SchedConfUpdateInfo confUpdate) throws IOException, YarnException { if (!aclMutationPolicy.isMutationAllowed(user, confUpdate)) { throw new AccessControlException("User is not admin of all modified" + " queues."); @@ -115,8 +114,8 @@ public void mutateConfiguration(UserGroupInformation user, } } try { - rmContext.getScheduler().reinitialize(conf, rmContext); - } catch (IOException e) { + rmContext.getRMAdminService().refreshQueues(); + } catch (IOException | YarnException e) { schedConf = oldConf; confStore.confirmMutation(id, false); throw e; diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/TestRMAdminService.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/TestRMAdminService.java index 8d00ae071e..f5bb898364 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/TestRMAdminService.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/TestRMAdminService.java @@ -182,6 +182,29 @@ public void testAdminRefreshQueuesWithFileSystemBasedConfigurationProvider() } @Test + public void testAdminRefreshQueuesWithMutableSchedulerConfiguration() { + configuration.set(CapacitySchedulerConfiguration.CS_CONF_PROVIDER, + CapacitySchedulerConfiguration.STORE_CS_CONF_PROVIDER); + + try { + rm = new MockRM(configuration); + rm.init(configuration); + rm.start(); + } catch (Exception ex) { + fail("Should not get any exceptions"); + } + + try { + rm.adminService.refreshQueues(RefreshQueuesRequest.newInstance()); + fail("Expected exception while calling refreshQueues when scheduler" + + " configuration is mutable."); + } catch (Exception ex) { + assertTrue(ex.getMessage().endsWith("Scheduler configuration is " + + "mutable. refreshQueues is not allowed in this scenario.")); + } + } + + @Test public void testAdminRefreshNodesWithoutConfiguration() throws IOException, YarnException { configuration.set(YarnConfiguration.RM_CONFIGURATION_PROVIDER_CLASS, diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/conf/TestMutableCSConfigurationProvider.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/conf/TestMutableCSConfigurationProvider.java index 32167815a6..29c8e14bb7 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/conf/TestMutableCSConfigurationProvider.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/conf/TestMutableCSConfigurationProvider.java @@ -20,6 +20,8 @@ import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.security.UserGroupInformation; +import org.apache.hadoop.yarn.exceptions.YarnException; +import org.apache.hadoop.yarn.server.resourcemanager.AdminService; import org.apache.hadoop.yarn.server.resourcemanager.RMContext; import org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity.CapacityScheduler; import org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity.CapacitySchedulerConfiguration; @@ -34,7 +36,6 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; -import static org.mockito.Matchers.any; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; @@ -50,6 +51,7 @@ private SchedConfUpdateInfo goodUpdate; private SchedConfUpdateInfo badUpdate; private CapacityScheduler cs; + private AdminService adminService; private static final UserGroupInformation TEST_USER = UserGroupInformation .createUserForTesting("testUser", new String[] {}); @@ -61,6 +63,8 @@ public void setUp() { when(rmContext.getScheduler()).thenReturn(cs); when(cs.getConfiguration()).thenReturn( new CapacitySchedulerConfiguration()); + adminService = mock(AdminService.class); + when(rmContext.getRMAdminService()).thenReturn(adminService); confProvider = new MutableCSConfigurationProvider(rmContext); goodUpdate = new SchedConfUpdateInfo(); Map goodUpdateMap = new HashMap<>(); @@ -78,22 +82,20 @@ public void setUp() { } @Test - public void testInMemoryBackedProvider() throws IOException { + public void testInMemoryBackedProvider() throws IOException, YarnException { Configuration conf = new Configuration(); confProvider.init(conf); assertNull(confProvider.loadConfiguration(conf) .get("yarn.scheduler.capacity.root.a.goodKey")); - doNothing().when(cs).reinitialize(any(Configuration.class), - any(RMContext.class)); + doNothing().when(adminService).refreshQueues(); confProvider.mutateConfiguration(TEST_USER, goodUpdate); assertEquals("goodVal", confProvider.loadConfiguration(conf) .get("yarn.scheduler.capacity.root.a.goodKey")); assertNull(confProvider.loadConfiguration(conf).get( "yarn.scheduler.capacity.root.a.badKey")); - doThrow(new IOException()).when(cs).reinitialize(any(Configuration.class), - any(RMContext.class)); + doThrow(new IOException()).when(adminService).refreshQueues(); try { confProvider.mutateConfiguration(TEST_USER, badUpdate); } catch (IOException e) {