YARN-8559. Expose mutable-conf scheduler's configuration in RM /scheduler-conf endpoint. Contributed by Weiwei Yang.
This commit is contained in:
parent
b0a364171d
commit
0420ca5a6f
|
@ -18,6 +18,7 @@
|
||||||
|
|
||||||
package org.apache.hadoop.yarn.server.resourcemanager.scheduler;
|
package org.apache.hadoop.yarn.server.resourcemanager.scheduler;
|
||||||
|
|
||||||
|
import org.apache.hadoop.conf.Configuration;
|
||||||
import org.apache.hadoop.security.UserGroupInformation;
|
import org.apache.hadoop.security.UserGroupInformation;
|
||||||
import org.apache.hadoop.yarn.webapp.dao.SchedConfUpdateInfo;
|
import org.apache.hadoop.yarn.webapp.dao.SchedConfUpdateInfo;
|
||||||
|
|
||||||
|
@ -58,6 +59,12 @@ public interface MutableConfigurationProvider {
|
||||||
*/
|
*/
|
||||||
void confirmPendingMutation(boolean isValid) throws Exception;
|
void confirmPendingMutation(boolean isValid) throws Exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns scheduler configuration cached in this provider.
|
||||||
|
* @return scheduler configuration.
|
||||||
|
*/
|
||||||
|
Configuration getConfiguration();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Closes the configuration provider, releasing any required resources.
|
* Closes the configuration provider, releasing any required resources.
|
||||||
* @throws IOException on failure to close
|
* @throws IOException on failure to close
|
||||||
|
|
|
@ -122,6 +122,11 @@ public class MutableCSConfigurationProvider implements CSConfigurationProvider,
|
||||||
return new CapacitySchedulerConfiguration(loadedConf, false);
|
return new CapacitySchedulerConfiguration(loadedConf, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Configuration getConfiguration() {
|
||||||
|
return new Configuration(schedConf);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ConfigurationMutationACLPolicy getAclMutationPolicy() {
|
public ConfigurationMutationACLPolicy getAclMutationPolicy() {
|
||||||
return aclMutationPolicy;
|
return aclMutationPolicy;
|
||||||
|
|
|
@ -188,6 +188,7 @@ import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.ResourceInfo;
|
||||||
import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.SchedulerInfo;
|
import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.SchedulerInfo;
|
||||||
import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.SchedulerTypeInfo;
|
import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.SchedulerTypeInfo;
|
||||||
import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.StatisticsItemInfo;
|
import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.StatisticsItemInfo;
|
||||||
|
import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.ConfInfo;
|
||||||
import org.apache.hadoop.yarn.server.security.ApplicationACLsManager;
|
import org.apache.hadoop.yarn.server.security.ApplicationACLsManager;
|
||||||
import org.apache.hadoop.yarn.server.utils.BuilderUtils;
|
import org.apache.hadoop.yarn.server.utils.BuilderUtils;
|
||||||
import org.apache.hadoop.yarn.server.webapp.WebServices;
|
import org.apache.hadoop.yarn.server.webapp.WebServices;
|
||||||
|
@ -2531,4 +2532,44 @@ public class RMWebServices extends WebServices implements RMWebServiceProtocol {
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Path("/scheduler-conf")
|
||||||
|
@Produces({ MediaType.APPLICATION_JSON + "; " + JettyUtils.UTF_8,
|
||||||
|
MediaType.APPLICATION_XML + "; " + JettyUtils.UTF_8 })
|
||||||
|
public Response getSchedulerConfiguration(@Context HttpServletRequest hsr)
|
||||||
|
throws AuthorizationException {
|
||||||
|
init();
|
||||||
|
// Only admin user is allowed to read scheduler conf,
|
||||||
|
// in order to avoid leaking sensitive info, such as ACLs
|
||||||
|
UserGroupInformation callerUGI = getCallerUserGroupInformation(hsr, true);
|
||||||
|
ApplicationACLsManager aclsManager = rm.getApplicationACLsManager();
|
||||||
|
if (aclsManager.areACLsEnabled()) {
|
||||||
|
if (callerUGI == null || !aclsManager.isAdmin(callerUGI)) {
|
||||||
|
String msg = "Only admins can carry out this operation.";
|
||||||
|
throw new ForbiddenException(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ResourceScheduler scheduler = rm.getResourceScheduler();
|
||||||
|
if (scheduler instanceof MutableConfScheduler
|
||||||
|
&& ((MutableConfScheduler) scheduler).isConfigurationMutable()) {
|
||||||
|
MutableConfigurationProvider mutableConfigurationProvider =
|
||||||
|
((MutableConfScheduler) scheduler).getMutableConfProvider();
|
||||||
|
// We load the cached configuration from configuration store,
|
||||||
|
// this should be the conf properties used by the scheduler.
|
||||||
|
Configuration schedulerConf = mutableConfigurationProvider
|
||||||
|
.getConfiguration();
|
||||||
|
return Response.status(Status.OK)
|
||||||
|
.entity(new ConfInfo(schedulerConf))
|
||||||
|
.build();
|
||||||
|
} else {
|
||||||
|
return Response.status(Status.BAD_REQUEST).entity(
|
||||||
|
"This API only supports to retrieve scheduler configuration"
|
||||||
|
+ " from a mutable-conf scheduler, underneath scheduler "
|
||||||
|
+ scheduler.getClass().getSimpleName()
|
||||||
|
+ " is not an instance of MutableConfScheduler")
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,72 @@
|
||||||
|
/**
|
||||||
|
* 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.webapp.dao;
|
||||||
|
|
||||||
|
import org.apache.hadoop.conf.Configuration;
|
||||||
|
|
||||||
|
import javax.xml.bind.annotation.XmlAccessType;
|
||||||
|
import javax.xml.bind.annotation.XmlAccessorType;
|
||||||
|
import javax.xml.bind.annotation.XmlRootElement;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
@XmlRootElement(name = "configuration")
|
||||||
|
@XmlAccessorType(XmlAccessType.FIELD)
|
||||||
|
public class ConfInfo {
|
||||||
|
|
||||||
|
protected ArrayList<ConfItem> property = new ArrayList<>();
|
||||||
|
|
||||||
|
public ConfInfo() {
|
||||||
|
} // JAXB needs this
|
||||||
|
|
||||||
|
public ConfInfo(Configuration conf) {
|
||||||
|
conf.forEach(entry ->
|
||||||
|
add(new ConfItem(entry.getKey(), entry.getValue())));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void add(ConfItem confItem) {
|
||||||
|
property.add(confItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<ConfItem> getItems() {
|
||||||
|
return property;
|
||||||
|
}
|
||||||
|
|
||||||
|
@XmlAccessorType(XmlAccessType.FIELD)
|
||||||
|
public static class ConfItem {
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
private String value;
|
||||||
|
|
||||||
|
public ConfItem() {
|
||||||
|
// JAXB needs this
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConfItem(String name, String value){
|
||||||
|
this.name = name;
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getKey() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -39,6 +39,9 @@ import org.apache.hadoop.yarn.webapp.JerseyTestBase;
|
||||||
import org.apache.hadoop.yarn.webapp.dao.QueueConfigInfo;
|
import org.apache.hadoop.yarn.webapp.dao.QueueConfigInfo;
|
||||||
import org.apache.hadoop.yarn.webapp.dao.SchedConfUpdateInfo;
|
import org.apache.hadoop.yarn.webapp.dao.SchedConfUpdateInfo;
|
||||||
import org.apache.hadoop.yarn.webapp.util.YarnWebServiceUtils;
|
import org.apache.hadoop.yarn.webapp.util.YarnWebServiceUtils;
|
||||||
|
import org.codehaus.jettison.json.JSONArray;
|
||||||
|
import org.codehaus.jettison.json.JSONException;
|
||||||
|
import org.codehaus.jettison.json.JSONObject;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
@ -54,6 +57,7 @@ import java.util.Map;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertNull;
|
import static org.junit.Assert.assertNull;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test scheduler configuration mutation via REST API.
|
* Test scheduler configuration mutation via REST API.
|
||||||
|
@ -153,8 +157,40 @@ public class TestRMWebServicesConfigurationMutation extends JerseyTestBase {
|
||||||
.contextPath("jersey-guice-filter").servletPath("/").build());
|
.contextPath("jersey-guice-filter").servletPath("/").build());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private CapacitySchedulerConfiguration getSchedulerConf()
|
||||||
|
throws JSONException {
|
||||||
|
WebResource r = resource();
|
||||||
|
ClientResponse response =
|
||||||
|
r.path("ws").path("v1").path("cluster")
|
||||||
|
.queryParam("user.name", userName).path("scheduler-conf")
|
||||||
|
.accept(MediaType.APPLICATION_JSON)
|
||||||
|
.get(ClientResponse.class);
|
||||||
|
assertEquals(Status.OK.getStatusCode(), response.getStatus());
|
||||||
|
JSONObject json = response.getEntity(JSONObject.class);
|
||||||
|
JSONArray items = (JSONArray) json.get("property");
|
||||||
|
CapacitySchedulerConfiguration parsedConf =
|
||||||
|
new CapacitySchedulerConfiguration();
|
||||||
|
for (int i=0; i<items.length(); i++) {
|
||||||
|
JSONObject obj = (JSONObject) items.get(i);
|
||||||
|
parsedConf.set(obj.get("name").toString(),
|
||||||
|
obj.get("value").toString());
|
||||||
|
}
|
||||||
|
return parsedConf;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetSchedulerConf() throws Exception {
|
||||||
|
CapacitySchedulerConfiguration orgConf = getSchedulerConf();
|
||||||
|
assertNotNull(orgConf);
|
||||||
|
assertEquals(3, orgConf.getQueues("root").length);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAddNestedQueue() throws Exception {
|
public void testAddNestedQueue() throws Exception {
|
||||||
|
CapacitySchedulerConfiguration orgConf = getSchedulerConf();
|
||||||
|
assertNotNull(orgConf);
|
||||||
|
assertEquals(3, orgConf.getQueues("root").length);
|
||||||
|
|
||||||
WebResource r = resource();
|
WebResource r = resource();
|
||||||
|
|
||||||
ClientResponse response;
|
ClientResponse response;
|
||||||
|
@ -194,6 +230,10 @@ public class TestRMWebServicesConfigurationMutation extends JerseyTestBase {
|
||||||
0.01f);
|
0.01f);
|
||||||
assertEquals(75.0f, newCSConf.getNonLabeledQueueCapacity("root.d.d2"),
|
assertEquals(75.0f, newCSConf.getNonLabeledQueueCapacity("root.d.d2"),
|
||||||
0.01f);
|
0.01f);
|
||||||
|
|
||||||
|
CapacitySchedulerConfiguration newConf = getSchedulerConf();
|
||||||
|
assertNotNull(newConf);
|
||||||
|
assertEquals(4, newConf.getQueues("root").length);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -4445,6 +4445,7 @@ Please note that this feature is currently in the alpha stage and is subject to
|
||||||
|
|
||||||
### HTTP Operations Supported
|
### HTTP Operations Supported
|
||||||
|
|
||||||
|
* GET
|
||||||
* PUT
|
* PUT
|
||||||
|
|
||||||
### Elements of the *sched-conf* object
|
### Elements of the *sched-conf* object
|
||||||
|
@ -4456,6 +4457,45 @@ Please note that this feature is currently in the alpha stage and is subject to
|
||||||
| remove-queue | string | Full path name of a queue to remove |
|
| remove-queue | string | Full path name of a queue to remove |
|
||||||
| global-updates | map | Map of key value pairs to update scheduler's global configuration |
|
| global-updates | map | Map of key value pairs to update scheduler's global configuration |
|
||||||
|
|
||||||
|
### GET Request Examples
|
||||||
|
|
||||||
|
Get requests are used to retrieve the scheduler's configuration that is currently loaded into scheduler's context.
|
||||||
|
|
||||||
|
**XML response**
|
||||||
|
|
||||||
|
HTTP Request:
|
||||||
|
|
||||||
|
Accept: application/xml
|
||||||
|
Content-Type: application/xml
|
||||||
|
GET http://rm-http-address:port/ws/v1/cluster/scheduler-conf
|
||||||
|
|
||||||
|
Response Header:
|
||||||
|
|
||||||
|
TTP/1.1 200 OK
|
||||||
|
Content-Type: application/xml; charset=utf-8
|
||||||
|
Transfer-Encoding: chunked
|
||||||
|
|
||||||
|
Response Body:
|
||||||
|
|
||||||
|
|
||||||
|
```xml
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
|
<configuration>
|
||||||
|
<property>
|
||||||
|
<name>yarn.scheduler.capacity.root.queues</name>
|
||||||
|
<value>default</value>
|
||||||
|
</property>
|
||||||
|
<property>
|
||||||
|
<name>yarn.scheduler.capacity.maximum-applications</name>
|
||||||
|
<value>10000</value>
|
||||||
|
</property>
|
||||||
|
<property>
|
||||||
|
<name>yarn.scheduler.capacity.root.default.capacity</name>
|
||||||
|
<value>100</value>
|
||||||
|
</property>
|
||||||
|
</configuration>
|
||||||
|
```
|
||||||
|
|
||||||
### PUT Request Examples
|
### PUT Request Examples
|
||||||
|
|
||||||
Put requests are used to modify the scheduler configuration. A successful mutation results in a 200 response. A malformed request or one which resulted in an invalid scheduler configuration results in a 400 response.
|
Put requests are used to modify the scheduler configuration. A successful mutation results in a 200 response. A malformed request or one which resulted in an invalid scheduler configuration results in a 400 response.
|
||||||
|
|
Loading…
Reference in New Issue