YARN-11221. [Federation] Add replaceLabelsOnNodes, replaceLabelsOnNode REST APIs for Router. (#5302)

This commit is contained in:
slfan1989 2023-02-28 01:34:39 +08:00 committed by GitHub
parent a90238c0b8
commit 8798b94ee1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 367 additions and 5 deletions

View File

@ -44,6 +44,11 @@ public class NodeToLabelsEntry {
this.labels = labels; this.labels = labels;
} }
public NodeToLabelsEntry(String nodeId, Collection<String> pLabels) {
this.nodeId = nodeId;
this.labels.addAll(pLabels);
}
public String getNodeId() { public String getNodeId() {
return nodeId; return nodeId;
} }

View File

@ -147,6 +147,10 @@ public final class RouterMetrics {
private MutableGaugeInt numRefreshSuperUserGroupsConfigurationFailedRetrieved; private MutableGaugeInt numRefreshSuperUserGroupsConfigurationFailedRetrieved;
@Metric("# of refreshUserToGroupsMappings failed to be retrieved") @Metric("# of refreshUserToGroupsMappings failed to be retrieved")
private MutableGaugeInt numRefreshUserToGroupsMappingsFailedRetrieved; private MutableGaugeInt numRefreshUserToGroupsMappingsFailedRetrieved;
@Metric("# of replaceLabelsOnNodes failed to be retrieved")
private MutableGaugeInt numReplaceLabelsOnNodesFailedRetrieved;
@Metric("# of replaceLabelsOnNode failed to be retrieved")
private MutableGaugeInt numReplaceLabelsOnNodeFailedRetrieved;
@Metric("# of addToClusterNodeLabels failed to be retrieved") @Metric("# of addToClusterNodeLabels failed to be retrieved")
private MutableGaugeInt numAddToClusterNodeLabelsFailedRetrieved; private MutableGaugeInt numAddToClusterNodeLabelsFailedRetrieved;
@Metric("# of removeFromClusterNodeLabels failed to be retrieved") @Metric("# of removeFromClusterNodeLabels failed to be retrieved")
@ -257,6 +261,10 @@ public final class RouterMetrics {
private MutableRate totalSucceededRefreshSuperUserGroupsConfigurationRetrieved; private MutableRate totalSucceededRefreshSuperUserGroupsConfigurationRetrieved;
@Metric("Total number of successful Retrieved RefreshUserToGroupsMappings and latency(ms)") @Metric("Total number of successful Retrieved RefreshUserToGroupsMappings and latency(ms)")
private MutableRate totalSucceededRefreshUserToGroupsMappingsRetrieved; private MutableRate totalSucceededRefreshUserToGroupsMappingsRetrieved;
@Metric("Total number of successful Retrieved ReplaceLabelsOnNodes and latency(ms)")
private MutableRate totalSucceededReplaceLabelsOnNodesRetrieved;
@Metric("Total number of successful Retrieved ReplaceLabelsOnNode and latency(ms)")
private MutableRate totalSucceededReplaceLabelsOnNodeRetrieved;
@Metric("Total number of successful Retrieved GetSchedulerInfo and latency(ms)") @Metric("Total number of successful Retrieved GetSchedulerInfo and latency(ms)")
private MutableRate totalSucceededGetSchedulerInfoRetrieved; private MutableRate totalSucceededGetSchedulerInfoRetrieved;
@Metric("Total number of successful Retrieved AddToClusterNodeLabels and latency(ms)") @Metric("Total number of successful Retrieved AddToClusterNodeLabels and latency(ms)")
@ -320,6 +328,8 @@ public final class RouterMetrics {
private MutableQuantiles getSchedulerInfoRetrievedLatency; private MutableQuantiles getSchedulerInfoRetrievedLatency;
private MutableQuantiles refreshSuperUserGroupsConfLatency; private MutableQuantiles refreshSuperUserGroupsConfLatency;
private MutableQuantiles refreshUserToGroupsMappingsLatency; private MutableQuantiles refreshUserToGroupsMappingsLatency;
private MutableQuantiles replaceLabelsOnNodesLatency;
private MutableQuantiles replaceLabelsOnNodeLatency;
private MutableQuantiles addToClusterNodeLabelsLatency; private MutableQuantiles addToClusterNodeLabelsLatency;
private MutableQuantiles removeFromClusterNodeLabelsLatency; private MutableQuantiles removeFromClusterNodeLabelsLatency;
@ -514,6 +524,12 @@ public final class RouterMetrics {
refreshUserToGroupsMappingsLatency = registry.newQuantiles("refreshUserToGroupsMappingsLatency", refreshUserToGroupsMappingsLatency = registry.newQuantiles("refreshUserToGroupsMappingsLatency",
"latency of refresh user to groups mappings timeouts", "ops", "latency", 10); "latency of refresh user to groups mappings timeouts", "ops", "latency", 10);
replaceLabelsOnNodesLatency = registry.newQuantiles("replaceLabelsOnNodesLatency",
"latency of replace labels on nodes timeouts", "ops", "latency", 10);
replaceLabelsOnNodeLatency = registry.newQuantiles("replaceLabelsOnNodeLatency",
"latency of replace labels on node timeouts", "ops", "latency", 10);
addToClusterNodeLabelsLatency = registry.newQuantiles("addToClusterNodeLabelsLatency", addToClusterNodeLabelsLatency = registry.newQuantiles("addToClusterNodeLabelsLatency",
"latency of add cluster nodelabels timeouts", "ops", "latency", 10); "latency of add cluster nodelabels timeouts", "ops", "latency", 10);
@ -810,6 +826,16 @@ public final class RouterMetrics {
return totalSucceededRefreshSuperUserGroupsConfigurationRetrieved.lastStat().numSamples(); return totalSucceededRefreshSuperUserGroupsConfigurationRetrieved.lastStat().numSamples();
} }
@VisibleForTesting
public long getNumSucceededReplaceLabelsOnNodesRetrieved() {
return totalSucceededReplaceLabelsOnNodesRetrieved.lastStat().numSamples();
}
@VisibleForTesting
public long getNumSucceededReplaceLabelsOnNodeRetrieved() {
return totalSucceededReplaceLabelsOnNodeRetrieved.lastStat().numSamples();
}
@VisibleForTesting @VisibleForTesting
public double getLatencySucceededAppsCreated() { public double getLatencySucceededAppsCreated() {
return totalSucceededAppsCreated.lastStat().mean(); return totalSucceededAppsCreated.lastStat().mean();
@ -1080,6 +1106,16 @@ public final class RouterMetrics {
return totalSucceededRefreshSuperUserGroupsConfigurationRetrieved.lastStat().mean(); return totalSucceededRefreshSuperUserGroupsConfigurationRetrieved.lastStat().mean();
} }
@VisibleForTesting
public double getLatencySucceededReplaceLabelsOnNodesRetrieved() {
return totalSucceededReplaceLabelsOnNodesRetrieved.lastStat().mean();
}
@VisibleForTesting
public double getLatencySucceededReplaceLabelsOnNodeRetrieved() {
return totalSucceededReplaceLabelsOnNodeRetrieved.lastStat().mean();
}
@VisibleForTesting @VisibleForTesting
public int getAppsFailedCreated() { public int getAppsFailedCreated() {
return numAppsFailedCreated.value(); return numAppsFailedCreated.value();
@ -1286,6 +1322,14 @@ public final class RouterMetrics {
return numRefreshUserToGroupsMappingsFailedRetrieved.value(); return numRefreshUserToGroupsMappingsFailedRetrieved.value();
} }
public int getNumReplaceLabelsOnNodesFailedRetrieved() {
return numReplaceLabelsOnNodesFailedRetrieved.value();
}
public int getNumReplaceLabelsOnNodeFailedRetrieved() {
return numReplaceLabelsOnNodeFailedRetrieved.value();
}
public int getNumAddToClusterNodeLabelsFailedRetrieved() { public int getNumAddToClusterNodeLabelsFailedRetrieved() {
return numAddToClusterNodeLabelsFailedRetrieved.value(); return numAddToClusterNodeLabelsFailedRetrieved.value();
} }
@ -1597,6 +1641,16 @@ public final class RouterMetrics {
refreshUserToGroupsMappingsLatency.add(duration); refreshUserToGroupsMappingsLatency.add(duration);
} }
public void succeededReplaceLabelsOnNodesRetrieved(long duration) {
totalSucceededReplaceLabelsOnNodesRetrieved.add(duration);
replaceLabelsOnNodesLatency.add(duration);
}
public void succeededReplaceLabelsOnNodeRetrieved(long duration) {
totalSucceededReplaceLabelsOnNodeRetrieved.add(duration);
replaceLabelsOnNodeLatency.add(duration);
}
public void incrAppsFailedCreated() { public void incrAppsFailedCreated() {
numAppsFailedCreated.incr(); numAppsFailedCreated.incr();
} }
@ -1801,6 +1855,14 @@ public final class RouterMetrics {
numCancelDelegationTokenFailedRetrieved.incr(); numCancelDelegationTokenFailedRetrieved.incr();
} }
public void incrReplaceLabelsOnNodesFailedRetrieved() {
numReplaceLabelsOnNodesFailedRetrieved.incr();
}
public void incrReplaceLabelsOnNodeFailedRetrieved() {
numReplaceLabelsOnNodeFailedRetrieved.incr();
}
public void incrDumpSchedulerLogsFailedRetrieved() { public void incrDumpSchedulerLogsFailedRetrieved() {
numDumpSchedulerLogsFailedRetrieved.incr(); numDumpSchedulerLogsFailedRetrieved.incr();
} }

View File

@ -118,6 +118,7 @@ import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.BulkActivitiesIn
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.NodeLabelInfo; import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.NodeLabelInfo;
import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.ReservationDefinitionInfo; import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.ReservationDefinitionInfo;
import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.NodeToLabelsEntry;
import org.apache.hadoop.yarn.server.router.RouterMetrics; import org.apache.hadoop.yarn.server.router.RouterMetrics;
import org.apache.hadoop.yarn.server.router.RouterServerUtil; import org.apache.hadoop.yarn.server.router.RouterServerUtil;
import org.apache.hadoop.yarn.server.router.clientrm.ClientMethod; import org.apache.hadoop.yarn.server.router.clientrm.ClientMethod;
@ -1539,16 +1540,130 @@ public class FederationInterceptorREST extends AbstractRESTRequestInterceptor {
"getLabelsToNodes by labels = %s Failed.", StringUtils.join(labels, ",")); "getLabelsToNodes by labels = %s Failed.", StringUtils.join(labels, ","));
} }
/**
* This method replaces all the node labels for specific nodes, and it is
* reachable by using {@link RMWSConsts#REPLACE_NODE_TO_LABELS}.
*
* @see ResourceManagerAdministrationProtocol#replaceLabelsOnNode
* @param newNodeToLabels the list of new labels. It is a content param.
* @param hsr the servlet request
* @return Response containing the status code
* @throws IOException if an exception happened
*/
@Override @Override
public Response replaceLabelsOnNodes(NodeToLabelsEntryList newNodeToLabels, public Response replaceLabelsOnNodes(NodeToLabelsEntryList newNodeToLabels,
HttpServletRequest hsr) throws IOException { HttpServletRequest hsr) throws IOException {
throw new NotImplementedException("Code is not implemented");
// Step1. Check the parameters to ensure that the parameters are not empty.
if (newNodeToLabels == null) {
routerMetrics.incrReplaceLabelsOnNodesFailedRetrieved();
throw new IllegalArgumentException("Parameter error, newNodeToLabels must not be empty.");
}
List<NodeToLabelsEntry> nodeToLabelsEntries = newNodeToLabels.getNodeToLabels();
if (CollectionUtils.isEmpty(nodeToLabelsEntries)) {
routerMetrics.incrReplaceLabelsOnNodesFailedRetrieved();
throw new IllegalArgumentException("Parameter error, " +
"nodeToLabelsEntries must not be empty.");
}
try {
// Step2. We map the NodeId and NodeToLabelsEntry in the request.
Map<String, NodeToLabelsEntry> nodeIdToLabels = new HashMap<>();
newNodeToLabels.getNodeToLabels().stream().forEach(nodeIdToLabel -> {
String nodeId = nodeIdToLabel.getNodeId();
nodeIdToLabels.put(nodeId, nodeIdToLabel);
});
// Step3. We map SubCluster with NodeToLabelsEntryList
Map<SubClusterInfo, NodeToLabelsEntryList> subClusterToNodeToLabelsEntryList =
new HashMap<>();
nodeIdToLabels.forEach((nodeId, nodeToLabelsEntry) -> {
SubClusterInfo subClusterInfo = getNodeSubcluster(nodeId);
NodeToLabelsEntryList nodeToLabelsEntryList = subClusterToNodeToLabelsEntryList.
getOrDefault(subClusterInfo, new NodeToLabelsEntryList());
nodeToLabelsEntryList.getNodeToLabels().add(nodeToLabelsEntry);
subClusterToNodeToLabelsEntryList.put(subClusterInfo, nodeToLabelsEntryList);
});
// Step4. Traverse the subCluster and call the replaceLabelsOnNodes interface.
long startTime = clock.getTime();
final HttpServletRequest hsrCopy = clone(hsr);
StringBuilder builder = new StringBuilder();
subClusterToNodeToLabelsEntryList.forEach((subCluster, nodeToLabelsEntryList) -> {
SubClusterId subClusterId = subCluster.getSubClusterId();
try {
DefaultRequestInterceptorREST interceptor = getOrCreateInterceptorForSubCluster(
subCluster.getSubClusterId(), subCluster.getRMWebServiceAddress());
interceptor.replaceLabelsOnNodes(nodeToLabelsEntryList, hsrCopy);
builder.append("subCluster-").append(subClusterId.getId()).append(":Success,");
} catch (Exception e) {
LOG.error("replaceLabelsOnNodes Failed. subClusterId = {}.", subClusterId, e);
builder.append("subCluster-").append(subClusterId.getId()).append(":Failed,");
}
});
long stopTime = clock.getTime();
routerMetrics.succeededReplaceLabelsOnNodesRetrieved(stopTime - startTime);
// Step5. return call result.
return Response.status(Status.OK).entity(builder.toString()).build();
} catch (NotFoundException e) {
routerMetrics.incrReplaceLabelsOnNodesFailedRetrieved();
throw e;
} catch (Exception e) {
routerMetrics.incrReplaceLabelsOnNodesFailedRetrieved();
throw e;
}
} }
/**
* This method replaces all the node labels for specific node, and it is
* reachable by using {@link RMWSConsts#NODES_NODEID_REPLACE_LABELS}.
*
* @see ResourceManagerAdministrationProtocol#replaceLabelsOnNode
* @param newNodeLabelsName the list of new labels. It is a QueryParam.
* @param hsr the servlet request
* @param nodeId the node we want to replace the node labels. It is a
* PathParam.
* @return Response containing the status code
* @throws Exception if an exception happened
*/
@Override @Override
public Response replaceLabelsOnNode(Set<String> newNodeLabelsName, public Response replaceLabelsOnNode(Set<String> newNodeLabelsName,
HttpServletRequest hsr, String nodeId) throws Exception { HttpServletRequest hsr, String nodeId) throws Exception {
throw new NotImplementedException("Code is not implemented");
// Step1. Check the parameters to ensure that the parameters are not empty.
if (StringUtils.isBlank(nodeId)) {
routerMetrics.incrReplaceLabelsOnNodeFailedRetrieved();
throw new IllegalArgumentException("Parameter error, nodeId must not be null or empty.");
}
if (CollectionUtils.isEmpty(newNodeLabelsName)) {
routerMetrics.incrReplaceLabelsOnNodeFailedRetrieved();
throw new IllegalArgumentException("Parameter error, newNodeLabelsName must not be empty.");
}
try {
// Step2. We find the subCluster according to the nodeId,
// and then call the replaceLabelsOnNode of the subCluster.
long startTime = clock.getTime();
SubClusterInfo subClusterInfo = getNodeSubcluster(nodeId);
DefaultRequestInterceptorREST interceptor = getOrCreateInterceptorForSubCluster(
subClusterInfo.getSubClusterId(), subClusterInfo.getRMWebServiceAddress());
final HttpServletRequest hsrCopy = clone(hsr);
interceptor.replaceLabelsOnNode(newNodeLabelsName, hsrCopy, nodeId);
// Step3. Return the response result.
long stopTime = clock.getTime();
routerMetrics.succeededReplaceLabelsOnNodeRetrieved(stopTime - startTime);
String msg = "subCluster#" + subClusterInfo.getSubClusterId().getId() + ":Success;";
return Response.status(Status.OK).entity(msg).build();
} catch (NotFoundException e) {
routerMetrics.incrReplaceLabelsOnNodeFailedRetrieved();
throw e;
} catch (Exception e){
routerMetrics.incrReplaceLabelsOnNodeFailedRetrieved();
throw e;
}
} }
@Override @Override

View File

@ -534,6 +534,16 @@ public class TestRouterMetrics {
metrics.incrRenewDelegationTokenFailedRetrieved(); metrics.incrRenewDelegationTokenFailedRetrieved();
} }
public void getReplaceLabelsOnNodesFailed() {
LOG.info("Mocked: failed replaceLabelsOnNodes call");
metrics.incrReplaceLabelsOnNodesFailedRetrieved();
}
public void getReplaceLabelsOnNodeFailed() {
LOG.info("Mocked: failed ReplaceLabelOnNode call");
metrics.incrReplaceLabelsOnNodeFailedRetrieved();
}
public void getDumpSchedulerLogsFailed() { public void getDumpSchedulerLogsFailed() {
LOG.info("Mocked: failed DumpSchedulerLogs call"); LOG.info("Mocked: failed DumpSchedulerLogs call");
metrics.incrDumpSchedulerLogsFailedRetrieved(); metrics.incrDumpSchedulerLogsFailedRetrieved();
@ -779,6 +789,16 @@ public class TestRouterMetrics {
metrics.succeededRenewDelegationTokenRetrieved(duration); metrics.succeededRenewDelegationTokenRetrieved(duration);
} }
public void getNumSucceededReplaceLabelsOnNodesRetrieved(long duration) {
LOG.info("Mocked: successful ReplaceLabelsOnNodes call with duration {}", duration);
metrics.succeededReplaceLabelsOnNodesRetrieved(duration);
}
public void getNumSucceededReplaceLabelsOnNodeRetrieved(long duration) {
LOG.info("Mocked: successful ReplaceLabelOnNode call with duration {}", duration);
metrics.succeededReplaceLabelsOnNodeRetrieved(duration);
}
public void getDumpSchedulerLogsRetrieved(long duration) { public void getDumpSchedulerLogsRetrieved(long duration) {
LOG.info("Mocked: successful DumpSchedulerLogs call with duration {}", duration); LOG.info("Mocked: successful DumpSchedulerLogs call with duration {}", duration);
metrics.succeededDumpSchedulerLogsRetrieved(duration); metrics.succeededDumpSchedulerLogsRetrieved(duration);
@ -1633,6 +1653,52 @@ public class TestRouterMetrics {
metrics.getRenewDelegationTokenFailedRetrieved()); metrics.getRenewDelegationTokenFailedRetrieved());
} }
@Test
public void testReplaceLabelsOnNodesRetrieved() {
long totalGoodBefore = metrics.getNumSucceededReplaceLabelsOnNodesRetrieved();
goodSubCluster.getNumSucceededReplaceLabelsOnNodesRetrieved(150);
Assert.assertEquals(totalGoodBefore + 1,
metrics.getNumSucceededReplaceLabelsOnNodesRetrieved());
Assert.assertEquals(150,
metrics.getLatencySucceededReplaceLabelsOnNodesRetrieved(), ASSERT_DOUBLE_DELTA);
goodSubCluster.getNumSucceededReplaceLabelsOnNodesRetrieved(300);
Assert.assertEquals(totalGoodBefore + 2,
metrics.getNumSucceededReplaceLabelsOnNodesRetrieved());
Assert.assertEquals(225,
metrics.getLatencySucceededReplaceLabelsOnNodesRetrieved(), ASSERT_DOUBLE_DELTA);
}
@Test
public void testReplaceLabelsOnNodesRetrievedFailed() {
long totalBadBefore = metrics.getNumReplaceLabelsOnNodesFailedRetrieved();
badSubCluster.getReplaceLabelsOnNodesFailed();
Assert.assertEquals(totalBadBefore + 1,
metrics.getNumReplaceLabelsOnNodesFailedRetrieved());
}
@Test
public void testReplaceLabelsOnNodeRetrieved() {
long totalGoodBefore = metrics.getNumSucceededReplaceLabelsOnNodeRetrieved();
goodSubCluster.getNumSucceededReplaceLabelsOnNodeRetrieved(150);
Assert.assertEquals(totalGoodBefore + 1,
metrics.getNumSucceededReplaceLabelsOnNodeRetrieved());
Assert.assertEquals(150,
metrics.getLatencySucceededReplaceLabelsOnNodeRetrieved(), ASSERT_DOUBLE_DELTA);
goodSubCluster.getNumSucceededReplaceLabelsOnNodeRetrieved(300);
Assert.assertEquals(totalGoodBefore + 2,
metrics.getNumSucceededReplaceLabelsOnNodeRetrieved());
Assert.assertEquals(225,
metrics.getLatencySucceededReplaceLabelsOnNodeRetrieved(), ASSERT_DOUBLE_DELTA);
}
@Test
public void testReplaceLabelOnNodeRetrievedFailed() {
long totalBadBefore = metrics.getNumReplaceLabelsOnNodeFailedRetrieved();
badSubCluster.getReplaceLabelsOnNodeFailed();
Assert.assertEquals(totalBadBefore + 1,
metrics.getNumReplaceLabelsOnNodeFailedRetrieved());
}
@Test @Test
public void testDumpSchedulerLogsRetrieved() { public void testDumpSchedulerLogsRetrieved() {
long totalGoodBefore = metrics.getNumSucceededDumpSchedulerLogsRetrieved(); long totalGoodBefore = metrics.getNumSucceededDumpSchedulerLogsRetrieved();

View File

@ -137,6 +137,7 @@ import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.ReservationReque
import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.ReservationRequestsInfo; import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.ReservationRequestsInfo;
import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.ReservationUpdateResponseInfo; import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.ReservationUpdateResponseInfo;
import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.ReservationDeleteResponseInfo; import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.ReservationDeleteResponseInfo;
import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.NodeToLabelsEntryList;
import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.ActivitiesInfo; import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.ActivitiesInfo;
import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.BulkActivitiesInfo; import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.BulkActivitiesInfo;
import org.apache.hadoop.yarn.server.resourcemanager.webapp.RMWSConsts; import org.apache.hadoop.yarn.server.resourcemanager.webapp.RMWSConsts;
@ -305,9 +306,14 @@ public class MockDefaultRequestInterceptorREST
if (!isRunning) { if (!isRunning) {
throw new RuntimeException("RM is stopped"); throw new RuntimeException("RM is stopped");
} }
NodeInfo node = new NodeInfo(); NodeInfo node = null;
node.setId(nodeId); SubClusterId subCluster = getSubClusterId();
node.setLastHealthUpdate(Integer.valueOf(getSubClusterId().getId())); String subClusterId = subCluster.getId();
if (nodeId.contains(subClusterId) || nodeId.contains("test")) {
node = new NodeInfo();
node.setId(nodeId);
node.setLastHealthUpdate(Integer.valueOf(getSubClusterId().getId()));
}
return node; return node;
} }
@ -1236,7 +1242,17 @@ public class MockDefaultRequestInterceptorREST
return webSvc.dumpSchedulerLogs(time, hsr); return webSvc.dumpSchedulerLogs(time, hsr);
} }
public Response replaceLabelsOnNodes(NodeToLabelsEntryList newNodeToLabels,
HttpServletRequest hsr) throws IOException {
return super.replaceLabelsOnNodes(newNodeToLabels, hsr);
}
@Override @Override
public Response replaceLabelsOnNode(Set<String> newNodeLabelsName,
HttpServletRequest hsr, String nodeId) throws Exception {
return super.replaceLabelsOnNode(newNodeLabelsName, hsr, nodeId);
}
public ActivitiesInfo getActivities(HttpServletRequest hsr, String nodeId, String groupBy) { public ActivitiesInfo getActivities(HttpServletRequest hsr, String nodeId, String groupBy) {
if (!EnumUtils.isValidEnum(RMWSConsts.ActivitiesGroupBy.class, groupBy.toUpperCase())) { if (!EnumUtils.isValidEnum(RMWSConsts.ActivitiesGroupBy.class, groupBy.toUpperCase())) {
String errMessage = "Got invalid groupBy: " + groupBy + ", valid groupBy types: " String errMessage = "Got invalid groupBy: " + groupBy + ", valid groupBy types: "

View File

@ -99,6 +99,8 @@ import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.ReservationInfo;
import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.ReservationSubmissionRequestInfo; import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.ReservationSubmissionRequestInfo;
import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.RMQueueAclInfo; import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.RMQueueAclInfo;
import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.DelegationToken; import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.DelegationToken;
import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.NodeToLabelsEntry;
import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.NodeToLabelsEntryList;
import org.apache.hadoop.yarn.server.resourcemanager.webapp.NodeIDsInfo; import org.apache.hadoop.yarn.server.resourcemanager.webapp.NodeIDsInfo;
import org.apache.hadoop.yarn.server.router.clientrm.RouterClientRMService; import org.apache.hadoop.yarn.server.router.clientrm.RouterClientRMService;
import org.apache.hadoop.yarn.server.router.clientrm.RouterClientRMService.RequestInterceptorChainWrapper; import org.apache.hadoop.yarn.server.router.clientrm.RouterClientRMService.RequestInterceptorChainWrapper;
@ -1786,6 +1788,102 @@ public class TestFederationInterceptorREST extends BaseRouterWebServicesTest {
Assert.assertEquals(response.getStatus(), Status.OK.getStatusCode()); Assert.assertEquals(response.getStatus(), Status.OK.getStatusCode());
} }
@Test
public void testReplaceLabelsOnNodes() throws Exception {
// subCluster0 -> node0:0 -> label:NodeLabel0
// subCluster1 -> node1:1 -> label:NodeLabel1
// subCluster2 -> node2:2 -> label:NodeLabel2
// subCluster3 -> node3:3 -> label:NodeLabel3
NodeToLabelsEntryList nodeToLabelsEntryList = new NodeToLabelsEntryList();
for (int i = 0; i < NUM_SUBCLUSTER; i++) {
// labels
List<String> labels = new ArrayList<>();
labels.add("NodeLabel" + i);
// nodes
String nodeId = "node" + i + ":" + i;
NodeToLabelsEntry nodeToLabelsEntry = new NodeToLabelsEntry(nodeId, labels);
List<NodeToLabelsEntry> nodeToLabelsEntries = nodeToLabelsEntryList.getNodeToLabels();
nodeToLabelsEntries.add(nodeToLabelsEntry);
}
// one of the results:
// subCluster#0:Success;subCluster#1:Success;subCluster#3:Success;subCluster#2:Success;
// We can't confirm the complete return order.
Response response = interceptor.replaceLabelsOnNodes(nodeToLabelsEntryList, null);
Assert.assertNotNull(response);
Assert.assertEquals(200, response.getStatus());
Object entityObject = response.getEntity();
Assert.assertNotNull(entityObject);
String entityValue = String.valueOf(entityObject);
String[] entities = entityValue.split(",");
Assert.assertNotNull(entities);
Assert.assertEquals(4, entities.length);
String expectValue =
"subCluster-0:Success,subCluster-1:Success,subCluster-2:Success,subCluster-3:Success,";
for (String entity : entities) {
Assert.assertTrue(expectValue.contains(entity));
}
}
@Test
public void testReplaceLabelsOnNodesError() throws Exception {
// newNodeToLabels is null
LambdaTestUtils.intercept(IllegalArgumentException.class,
"Parameter error, newNodeToLabels must not be empty.",
() -> interceptor.replaceLabelsOnNodes(null, null));
// nodeToLabelsEntryList is Empty
NodeToLabelsEntryList nodeToLabelsEntryList = new NodeToLabelsEntryList();
LambdaTestUtils.intercept(IllegalArgumentException.class,
"Parameter error, nodeToLabelsEntries must not be empty.",
() -> interceptor.replaceLabelsOnNodes(nodeToLabelsEntryList, null));
}
@Test
public void testReplaceLabelsOnNode() throws Exception {
// subCluster3 -> node3:3 -> label:NodeLabel3
String nodeId = "node3:3";
Set<String> labels = Collections.singleton("NodeLabel3");
// We expect the following result: subCluster#3:Success;
String expectValue = "subCluster#3:Success;";
Response response = interceptor.replaceLabelsOnNode(labels, null, nodeId);
Assert.assertNotNull(response);
Assert.assertEquals(200, response.getStatus());
Object entityObject = response.getEntity();
Assert.assertNotNull(entityObject);
String entityValue = String.valueOf(entityObject);
Assert.assertNotNull(entityValue);
Assert.assertEquals(expectValue, entityValue);
}
@Test
public void testReplaceLabelsOnNodeError() throws Exception {
// newNodeToLabels is null
String nodeId = "node3:3";
Set<String> labels = Collections.singleton("NodeLabel3");
Set<String> labelsEmpty = new HashSet<>();
// nodeId is null
LambdaTestUtils.intercept(IllegalArgumentException.class,
"Parameter error, nodeId must not be null or empty.",
() -> interceptor.replaceLabelsOnNode(labels, null, null));
// labels is null
LambdaTestUtils.intercept(IllegalArgumentException.class,
"Parameter error, newNodeLabelsName must not be empty.",
() -> interceptor.replaceLabelsOnNode(null, null, nodeId));
// labels is empty
LambdaTestUtils.intercept(IllegalArgumentException.class,
"Parameter error, newNodeLabelsName must not be empty.",
() -> interceptor.replaceLabelsOnNode(labelsEmpty, null, nodeId));
}
@Test @Test
public void testDumpSchedulerLogs() throws Exception { public void testDumpSchedulerLogs() throws Exception {
HttpServletRequest mockHsr = mockHttpServletRequestByUserName("admin"); HttpServletRequest mockHsr = mockHttpServletRequestByUserName("admin");