|
@@ -0,0 +1,639 @@
|
|
|
+/**
|
|
|
+ * 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;
|
|
|
+
|
|
|
+import static org.junit.Assert.assertEquals;
|
|
|
+import static org.junit.Assert.assertTrue;
|
|
|
+
|
|
|
+import java.io.StringReader;
|
|
|
+import java.util.HashSet;
|
|
|
+import java.util.Set;
|
|
|
+
|
|
|
+import javax.ws.rs.core.MediaType;
|
|
|
+import javax.xml.parsers.DocumentBuilder;
|
|
|
+import javax.xml.parsers.DocumentBuilderFactory;
|
|
|
+
|
|
|
+import org.apache.hadoop.yarn.api.records.NodeLabel;
|
|
|
+import org.apache.hadoop.yarn.conf.YarnConfiguration;
|
|
|
+import org.apache.hadoop.yarn.server.resourcemanager.MockRM;
|
|
|
+import org.apache.hadoop.yarn.server.resourcemanager.ResourceManager;
|
|
|
+import org.apache.hadoop.yarn.server.resourcemanager.nodelabels.RMNodeLabelsManager;
|
|
|
+import org.apache.hadoop.yarn.server.resourcemanager.scheduler.ResourceScheduler;
|
|
|
+import org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity.CapacityScheduler;
|
|
|
+import org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity.CapacitySchedulerConfiguration;
|
|
|
+import org.apache.hadoop.yarn.webapp.GenericExceptionHandler;
|
|
|
+import org.apache.hadoop.yarn.webapp.JerseyTestBase;
|
|
|
+import org.apache.hadoop.yarn.webapp.WebServicesTestUtils;
|
|
|
+import org.codehaus.jettison.json.JSONArray;
|
|
|
+import org.codehaus.jettison.json.JSONException;
|
|
|
+import org.codehaus.jettison.json.JSONObject;
|
|
|
+import org.junit.Assert;
|
|
|
+import org.junit.Before;
|
|
|
+import org.junit.Test;
|
|
|
+import org.w3c.dom.Document;
|
|
|
+import org.w3c.dom.Element;
|
|
|
+import org.w3c.dom.NodeList;
|
|
|
+import org.xml.sax.InputSource;
|
|
|
+
|
|
|
+import com.google.common.collect.ImmutableSet;
|
|
|
+import com.google.inject.Guice;
|
|
|
+import com.google.inject.Injector;
|
|
|
+import com.google.inject.servlet.GuiceServletContextListener;
|
|
|
+import com.google.inject.servlet.ServletModule;
|
|
|
+import com.sun.jersey.api.client.ClientResponse;
|
|
|
+import com.sun.jersey.api.client.WebResource;
|
|
|
+import com.sun.jersey.guice.spi.container.servlet.GuiceContainer;
|
|
|
+import com.sun.jersey.test.framework.WebAppDescriptor;
|
|
|
+
|
|
|
+public class TestRMWebServicesForCSWithPartitions extends JerseyTestBase {
|
|
|
+ private static final String DEFAULT_PARTITION = "";
|
|
|
+ private static final String CAPACITIES = "capacities";
|
|
|
+ private static final String RESOURCE_USAGES_BY_PARTITION =
|
|
|
+ "resourceUsagesByPartition";
|
|
|
+ private static final String QUEUE_CAPACITIES_BY_PARTITION =
|
|
|
+ "queueCapacitiesByPartition";
|
|
|
+ private static final String QUEUE_C = "Qc";
|
|
|
+ private static final String LEAF_QUEUE_C1 = "Qc1";
|
|
|
+ private static final String LEAF_QUEUE_C2 = "Qc2";
|
|
|
+ private static final String QUEUE_B = "Qb";
|
|
|
+ private static final String QUEUE_A = "Qa";
|
|
|
+ private static final String LABEL_LY = "Ly";
|
|
|
+ private static final String LABEL_LX = "Lx";
|
|
|
+ private static final ImmutableSet<String> CLUSTER_LABELS =
|
|
|
+ ImmutableSet.of(LABEL_LX, LABEL_LY, DEFAULT_PARTITION);
|
|
|
+ private static MockRM rm;
|
|
|
+ private CapacitySchedulerConfiguration csConf;
|
|
|
+ private YarnConfiguration conf;
|
|
|
+
|
|
|
+ private Injector injector = Guice.createInjector(new ServletModule() {
|
|
|
+ @Override
|
|
|
+ protected void configureServlets() {
|
|
|
+ bind(JAXBContextResolver.class);
|
|
|
+ bind(RMWebServices.class);
|
|
|
+ bind(GenericExceptionHandler.class);
|
|
|
+ csConf = new CapacitySchedulerConfiguration();
|
|
|
+ setupQueueConfiguration(csConf, rm);
|
|
|
+ conf = new YarnConfiguration(csConf);
|
|
|
+ conf.setClass(YarnConfiguration.RM_SCHEDULER, CapacityScheduler.class,
|
|
|
+ ResourceScheduler.class);
|
|
|
+ rm = new MockRM(conf);
|
|
|
+ Set<NodeLabel> labels = new HashSet<NodeLabel>();
|
|
|
+ labels.add(NodeLabel.newInstance(LABEL_LX));
|
|
|
+ labels.add(NodeLabel.newInstance(LABEL_LY));
|
|
|
+ try {
|
|
|
+ RMNodeLabelsManager nodeLabelManager =
|
|
|
+ rm.getRMContext().getNodeLabelManager();
|
|
|
+ nodeLabelManager.addToCluserNodeLabels(labels);
|
|
|
+ } catch (Exception e) {
|
|
|
+ Assert.fail();
|
|
|
+ }
|
|
|
+ bind(ResourceManager.class).toInstance(rm);
|
|
|
+ serve("/*").with(GuiceContainer.class);
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ public class GuiceServletConfig extends GuiceServletContextListener {
|
|
|
+ @Override
|
|
|
+ protected Injector getInjector() {
|
|
|
+ return injector;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private static void setupQueueConfiguration(
|
|
|
+ CapacitySchedulerConfiguration conf, ResourceManager rm) {
|
|
|
+
|
|
|
+ // Define top-level queues
|
|
|
+ conf.setQueues(CapacitySchedulerConfiguration.ROOT,
|
|
|
+ new String[] { QUEUE_A, QUEUE_B, QUEUE_C });
|
|
|
+ String interMediateQueueC =
|
|
|
+ CapacitySchedulerConfiguration.ROOT + "." + QUEUE_C;
|
|
|
+ conf.setQueues(interMediateQueueC,
|
|
|
+ new String[] { LEAF_QUEUE_C1, LEAF_QUEUE_C2 });
|
|
|
+ conf.setCapacityByLabel(CapacitySchedulerConfiguration.ROOT, LABEL_LX, 100);
|
|
|
+ conf.setCapacityByLabel(CapacitySchedulerConfiguration.ROOT, LABEL_LY, 100);
|
|
|
+
|
|
|
+ String leafQueueA = CapacitySchedulerConfiguration.ROOT + "." + QUEUE_A;
|
|
|
+ conf.setCapacity(leafQueueA, 30);
|
|
|
+ conf.setMaximumCapacity(leafQueueA, 50);
|
|
|
+
|
|
|
+ String leafQueueB = CapacitySchedulerConfiguration.ROOT + "." + QUEUE_B;
|
|
|
+ conf.setCapacity(leafQueueB, 30);
|
|
|
+ conf.setMaximumCapacity(leafQueueB, 50);
|
|
|
+
|
|
|
+ conf.setCapacity(interMediateQueueC, 40);
|
|
|
+ conf.setMaximumCapacity(interMediateQueueC, 50);
|
|
|
+
|
|
|
+ String leafQueueC1 = interMediateQueueC + "." + LEAF_QUEUE_C1;
|
|
|
+ conf.setCapacity(leafQueueC1, 50);
|
|
|
+ conf.setMaximumCapacity(leafQueueC1, 60);
|
|
|
+
|
|
|
+ String leafQueueC2 = interMediateQueueC + "." + LEAF_QUEUE_C2;
|
|
|
+ conf.setCapacity(leafQueueC2, 50);
|
|
|
+ conf.setMaximumCapacity(leafQueueC2, 70);
|
|
|
+
|
|
|
+ // Define label specific configuration
|
|
|
+ conf.setAccessibleNodeLabels(leafQueueA, ImmutableSet.of(DEFAULT_PARTITION));
|
|
|
+ conf.setAccessibleNodeLabels(leafQueueB, ImmutableSet.of(LABEL_LX));
|
|
|
+ conf.setAccessibleNodeLabels(interMediateQueueC,
|
|
|
+ ImmutableSet.of(LABEL_LX, LABEL_LY));
|
|
|
+ conf.setAccessibleNodeLabels(leafQueueC1,
|
|
|
+ ImmutableSet.of(LABEL_LX, LABEL_LY));
|
|
|
+ conf.setAccessibleNodeLabels(leafQueueC2,
|
|
|
+ ImmutableSet.of(LABEL_LX, LABEL_LY));
|
|
|
+ conf.setDefaultNodeLabelExpression(leafQueueB, LABEL_LX);
|
|
|
+ conf.setDefaultNodeLabelExpression(leafQueueC1, LABEL_LX);
|
|
|
+ conf.setDefaultNodeLabelExpression(leafQueueC2, LABEL_LY);
|
|
|
+
|
|
|
+ conf.setCapacityByLabel(leafQueueB, LABEL_LX, 30);
|
|
|
+ conf.setCapacityByLabel(interMediateQueueC, LABEL_LX, 70);
|
|
|
+ conf.setCapacityByLabel(leafQueueC1, LABEL_LX, 40);
|
|
|
+ conf.setCapacityByLabel(leafQueueC2, LABEL_LX, 60);
|
|
|
+
|
|
|
+ conf.setCapacityByLabel(interMediateQueueC, LABEL_LY, 100);
|
|
|
+ conf.setCapacityByLabel(leafQueueC1, LABEL_LY, 50);
|
|
|
+ conf.setCapacityByLabel(leafQueueC2, LABEL_LY, 50);
|
|
|
+ conf.setMaximumCapacityByLabel(leafQueueC1, LABEL_LY, 75);
|
|
|
+ conf.setMaximumCapacityByLabel(leafQueueC2, LABEL_LY, 75);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Before
|
|
|
+ @Override
|
|
|
+ public void setUp() throws Exception {
|
|
|
+ super.setUp();
|
|
|
+ }
|
|
|
+
|
|
|
+ public TestRMWebServicesForCSWithPartitions() {
|
|
|
+ super(new WebAppDescriptor.Builder(
|
|
|
+ "org.apache.hadoop.yarn.server.resourcemanager.webapp")
|
|
|
+ .contextListenerClass(GuiceServletConfig.class)
|
|
|
+ .filterClass(com.google.inject.servlet.GuiceFilter.class)
|
|
|
+ .contextPath("jersey-guice-filter").servletPath("/").build());
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ public void testSchedulerPartitions() throws JSONException, Exception {
|
|
|
+ WebResource r = resource();
|
|
|
+ ClientResponse response =
|
|
|
+ r.path("ws").path("v1").path("cluster").path("scheduler")
|
|
|
+ .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
|
|
|
+ assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType());
|
|
|
+ JSONObject json = response.getEntity(JSONObject.class);
|
|
|
+ verifySchedulerInfoJson(json);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ public void testSchedulerPartitionsSlash() throws JSONException, Exception {
|
|
|
+ WebResource r = resource();
|
|
|
+ ClientResponse response =
|
|
|
+ r.path("ws").path("v1").path("cluster").path("scheduler/")
|
|
|
+ .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
|
|
|
+ assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType());
|
|
|
+ JSONObject json = response.getEntity(JSONObject.class);
|
|
|
+ verifySchedulerInfoJson(json);
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ public void testSchedulerPartitionsDefault() throws JSONException, Exception {
|
|
|
+ WebResource r = resource();
|
|
|
+ ClientResponse response = r.path("ws").path("v1").path("cluster")
|
|
|
+ .path("scheduler").get(ClientResponse.class);
|
|
|
+ assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType());
|
|
|
+ JSONObject json = response.getEntity(JSONObject.class);
|
|
|
+ verifySchedulerInfoJson(json);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ public void testSchedulerPartitionsXML() throws JSONException, Exception {
|
|
|
+ WebResource r = resource();
|
|
|
+ ClientResponse response =
|
|
|
+ r.path("ws").path("v1").path("cluster").path("scheduler")
|
|
|
+ .accept(MediaType.APPLICATION_XML).get(ClientResponse.class);
|
|
|
+ assertEquals(MediaType.APPLICATION_XML_TYPE, response.getType());
|
|
|
+ String xml = response.getEntity(String.class);
|
|
|
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
|
|
|
+ DocumentBuilder db = dbf.newDocumentBuilder();
|
|
|
+ InputSource is = new InputSource();
|
|
|
+ is.setCharacterStream(new StringReader(xml));
|
|
|
+ Document dom = db.parse(is);
|
|
|
+ verifySchedulerInfoXML(dom);
|
|
|
+ }
|
|
|
+
|
|
|
+ private void verifySchedulerInfoXML(Document dom) throws Exception {
|
|
|
+ NodeList scheduler = dom.getElementsByTagName("scheduler");
|
|
|
+ assertEquals("incorrect number of elements", 1, scheduler.getLength());
|
|
|
+ NodeList schedulerInfo = dom.getElementsByTagName("schedulerInfo");
|
|
|
+ assertEquals("incorrect number of elements", 1, schedulerInfo.getLength());
|
|
|
+ for (int i = 0; i < schedulerInfo.getLength(); i++) {
|
|
|
+ Element element = (Element) schedulerInfo.item(i);
|
|
|
+ NodeList children = element.getChildNodes();
|
|
|
+ for (int j = 0; j < children.getLength(); j++) {
|
|
|
+ Element schedulerInfoElem = (Element) children.item(j);
|
|
|
+ if (schedulerInfoElem.getTagName().equals("queues")) {
|
|
|
+ NodeList qListInfos = schedulerInfoElem.getChildNodes();
|
|
|
+ for (int k = 0; k < qListInfos.getLength(); k++) {
|
|
|
+ Element qElem2 = (Element) qListInfos.item(k);
|
|
|
+ String queue =
|
|
|
+ WebServicesTestUtils.getXmlString(qElem2, "queueName");
|
|
|
+ switch (queue) {
|
|
|
+ case QUEUE_A:
|
|
|
+ verifyQueueAInfoXML(qElem2);
|
|
|
+ break;
|
|
|
+ case QUEUE_B:
|
|
|
+ verifyQueueBInfoXML(qElem2);
|
|
|
+ break;
|
|
|
+ case QUEUE_C:
|
|
|
+ verifyQueueCInfoXML(qElem2);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ Assert.fail("Unexpected queue" + queue);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else if (schedulerInfoElem.getTagName().equals(CAPACITIES)) {
|
|
|
+ NodeList capacitiesListInfos = schedulerInfoElem.getChildNodes();
|
|
|
+ assertEquals("incorrect number of partitions", 3,
|
|
|
+ capacitiesListInfos.getLength());
|
|
|
+ for (int k = 0; k < capacitiesListInfos.getLength(); k++) {
|
|
|
+ Element partitionCapacitiesInfo =
|
|
|
+ (Element) capacitiesListInfos.item(k);
|
|
|
+ String partitionName = WebServicesTestUtils
|
|
|
+ .getXmlString(partitionCapacitiesInfo, "partitionName");
|
|
|
+ assertTrue("invalid PartitionCapacityInfo",
|
|
|
+ CLUSTER_LABELS.contains(partitionName));
|
|
|
+ verifyPartitionCapacityInfoXML(partitionCapacitiesInfo, 100, 0, 100,
|
|
|
+ 100, 0, 100);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void verifyQueueAInfoXML(Element queueElem) {
|
|
|
+ NodeList children = queueElem.getChildNodes();
|
|
|
+ for (int j = 0; j < children.getLength(); j++) {
|
|
|
+ Element queueChildElem = (Element) children.item(j);
|
|
|
+ if (queueChildElem.getTagName().equals(CAPACITIES)) {
|
|
|
+ NodeList capacitiesListInfos = queueChildElem.getChildNodes();
|
|
|
+ assertEquals("incorrect number of partitions", 1,
|
|
|
+ capacitiesListInfos.getLength());
|
|
|
+ Element partitionCapacitiesInfo = (Element) capacitiesListInfos.item(0);
|
|
|
+ String partitionName = WebServicesTestUtils
|
|
|
+ .getXmlString(partitionCapacitiesInfo, "partitionName");
|
|
|
+ assertTrue("invalid PartitionCapacityInfo",
|
|
|
+ partitionName.isEmpty());
|
|
|
+ verifyPartitionCapacityInfoXML(partitionCapacitiesInfo, 30, 0, 50, 30,
|
|
|
+ 0, 50);
|
|
|
+ } else if (queueChildElem.getTagName().equals("resources")) {
|
|
|
+ verifyResourceUsageInfoXML(queueChildElem);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void verifyQueueBInfoXML(Element queueElem) {
|
|
|
+ assertEquals("Invalid default Label expression", LABEL_LX,
|
|
|
+ WebServicesTestUtils.getXmlString(queueElem,
|
|
|
+ "defaultNodeLabelExpression"));
|
|
|
+ NodeList children = queueElem.getChildNodes();
|
|
|
+ for (int j = 0; j < children.getLength(); j++) {
|
|
|
+ Element queueChildElem = (Element) children.item(j);
|
|
|
+ if (queueChildElem.getTagName().equals(CAPACITIES)) {
|
|
|
+ NodeList capacitiesListInfos = queueChildElem.getChildNodes();
|
|
|
+ assertEquals("incorrect number of partitions", 2,
|
|
|
+ capacitiesListInfos.getLength());
|
|
|
+ for (int k = 0; k < capacitiesListInfos.getLength(); k++) {
|
|
|
+ Element partitionCapacitiesInfo =
|
|
|
+ (Element) capacitiesListInfos.item(k);
|
|
|
+ String partitionName = WebServicesTestUtils
|
|
|
+ .getXmlString(partitionCapacitiesInfo, "partitionName");
|
|
|
+ switch (partitionName) {
|
|
|
+ case LABEL_LX:
|
|
|
+ verifyPartitionCapacityInfoXML(partitionCapacitiesInfo, 30, 0, 100,
|
|
|
+ 30, 0, 100);
|
|
|
+ break;
|
|
|
+ case DEFAULT_PARTITION:
|
|
|
+ verifyPartitionCapacityInfoXML(partitionCapacitiesInfo, 30, 0, 50,
|
|
|
+ 30, 0, 50);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ Assert.fail("Unexpected partition" + partitionName);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else if (queueChildElem.getTagName().equals("resources")) {
|
|
|
+ verifyResourceUsageInfoXML(queueChildElem);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ assertEquals("Node Labels are not matching", LABEL_LX,
|
|
|
+ WebServicesTestUtils.getXmlString(queueElem, "nodeLabels"));
|
|
|
+ }
|
|
|
+
|
|
|
+ private void verifyQueueCInfoXML(Element queueElem) {
|
|
|
+ NodeList children = queueElem.getChildNodes();
|
|
|
+ for (int j = 0; j < children.getLength(); j++) {
|
|
|
+ Element queueChildElem = (Element) children.item(j);
|
|
|
+ if (queueChildElem.getTagName().equals(CAPACITIES)) {
|
|
|
+ verifyQcCapacitiesInfoXML(queueChildElem, 70, 100, 70, 100, 100, 100,
|
|
|
+ 100, 100, 40, 50, 40, 50);
|
|
|
+ } else if (queueChildElem.getTagName().equals("resources")) {
|
|
|
+ verifyResourceUsageInfoXML(queueChildElem);
|
|
|
+ } else if (queueChildElem.getTagName().equals("queues")) {
|
|
|
+ NodeList qListInfos = queueChildElem.getChildNodes();
|
|
|
+ for (int k = 0; k < qListInfos.getLength(); k++) {
|
|
|
+ Element qElem2 = (Element) qListInfos.item(k);
|
|
|
+ String queue = WebServicesTestUtils.getXmlString(qElem2, "queueName");
|
|
|
+ switch (queue) {
|
|
|
+ case LEAF_QUEUE_C1:
|
|
|
+ assertEquals("Invalid default Label expression", LABEL_LX,
|
|
|
+ WebServicesTestUtils.getXmlString(qElem2,
|
|
|
+ "defaultNodeLabelExpression"));
|
|
|
+ NodeList queuec1Children = qElem2.getChildNodes();
|
|
|
+ for (int l = 0; l < queuec1Children.getLength(); l++) {
|
|
|
+ Element queueC1ChildElem = (Element) queuec1Children.item(l);
|
|
|
+ if (queueC1ChildElem.getTagName().equals(CAPACITIES)) {
|
|
|
+ verifyQcCapacitiesInfoXML(queueC1ChildElem, 40, 100, 28, 100,
|
|
|
+ 50, 75, 50, 75, 50, 60, 20, 30);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case LEAF_QUEUE_C2:
|
|
|
+ assertEquals("Invalid default Label expression", LABEL_LY,
|
|
|
+ WebServicesTestUtils.getXmlString(qElem2,
|
|
|
+ "defaultNodeLabelExpression"));
|
|
|
+ NodeList queuec2Children = qElem2.getChildNodes();
|
|
|
+ for (int l = 0; l < queuec2Children.getLength(); l++) {
|
|
|
+ Element queueC2ChildElem = (Element) queuec2Children.item(l);
|
|
|
+ if (queueC2ChildElem.getTagName().equals(CAPACITIES)) {
|
|
|
+ verifyQcCapacitiesInfoXML(queueC2ChildElem, 60, 100, 42, 100,
|
|
|
+ 50, 75, 50, 75, 50, 70, 20, 35);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ Assert.fail("Unexpected queue" + queue);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void verifyQcCapacitiesInfoXML(Element partitionCapacitiesElem,
|
|
|
+ float lxCaps, float lxMaxCaps, float lxAbsCaps, float lxAbsMaxCaps,
|
|
|
+ float lyCaps, float lyMaxCaps, float lyAbsCaps, float lyAbsMaxCaps,
|
|
|
+ float defCaps, float defMaxCaps, float defAbsCaps, float defAbsMaxCaps) {
|
|
|
+ NodeList capacitiesListInfos = partitionCapacitiesElem.getChildNodes();
|
|
|
+ assertEquals("incorrect number of partitions", 3,
|
|
|
+ capacitiesListInfos.getLength());
|
|
|
+ for (int k = 0; k < capacitiesListInfos.getLength(); k++) {
|
|
|
+ Element partitionCapacitiesInfo = (Element) capacitiesListInfos.item(k);
|
|
|
+ String partitionName = WebServicesTestUtils
|
|
|
+ .getXmlString(partitionCapacitiesInfo, "partitionName");
|
|
|
+ switch (partitionName) {
|
|
|
+ case LABEL_LX:
|
|
|
+ verifyPartitionCapacityInfoXML(partitionCapacitiesInfo, lxCaps, 0,
|
|
|
+ lxMaxCaps, lxAbsCaps, 0, lxAbsMaxCaps);
|
|
|
+ break;
|
|
|
+ case LABEL_LY:
|
|
|
+ verifyPartitionCapacityInfoXML(partitionCapacitiesInfo, lyCaps, 0,
|
|
|
+ lyMaxCaps, lyAbsCaps, 0, lyAbsMaxCaps);
|
|
|
+ break;
|
|
|
+ case DEFAULT_PARTITION:
|
|
|
+ verifyPartitionCapacityInfoXML(partitionCapacitiesInfo, defCaps, 0,
|
|
|
+ defMaxCaps, defAbsCaps, 0, defAbsMaxCaps);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ Assert.fail("Unexpected partition" + partitionName);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void verifyResourceUsageInfoXML(Element queueChildElem) {
|
|
|
+ NodeList resourceUsageInfo = queueChildElem.getChildNodes();
|
|
|
+ assertEquals("incorrect number of partitions", 1,
|
|
|
+ resourceUsageInfo.getLength());
|
|
|
+ Element partitionResourceUsageInfo = (Element) resourceUsageInfo.item(0);
|
|
|
+ String partitionName = WebServicesTestUtils
|
|
|
+ .getXmlString(partitionResourceUsageInfo, "partitionName");
|
|
|
+ assertTrue("invalid PartitionCapacityInfo",
|
|
|
+ DEFAULT_PARTITION.equals(partitionName));
|
|
|
+ }
|
|
|
+
|
|
|
+ private void verifyPartitionCapacityInfoXML(Element partitionInfo,
|
|
|
+ float capacity, float usedCapacity, float maxCapacity,
|
|
|
+ float absoluteCapacity, float absoluteUsedCapacity,
|
|
|
+ float absoluteMaxCapacity) {
|
|
|
+ assertEquals("capacity doesn't match", capacity,
|
|
|
+ WebServicesTestUtils.getXmlFloat(partitionInfo, "capacity"), 1e-3f);
|
|
|
+ assertEquals("capacity doesn't match", usedCapacity,
|
|
|
+ WebServicesTestUtils.getXmlFloat(partitionInfo, "usedCapacity"), 1e-3f);
|
|
|
+ assertEquals("capacity doesn't match", maxCapacity,
|
|
|
+ WebServicesTestUtils.getXmlFloat(partitionInfo, "maxCapacity"), 1e-3f);
|
|
|
+ assertEquals("capacity doesn't match", absoluteCapacity,
|
|
|
+ WebServicesTestUtils.getXmlFloat(partitionInfo, "absoluteCapacity"),
|
|
|
+ 1e-3f);
|
|
|
+ assertEquals("capacity doesn't match", absoluteUsedCapacity,
|
|
|
+ WebServicesTestUtils.getXmlFloat(partitionInfo, "absoluteUsedCapacity"),
|
|
|
+ 1e-3f);
|
|
|
+ assertEquals("capacity doesn't match", absoluteMaxCapacity,
|
|
|
+ WebServicesTestUtils.getXmlFloat(partitionInfo, "absoluteMaxCapacity"),
|
|
|
+ 1e-3f);
|
|
|
+ }
|
|
|
+
|
|
|
+ private void verifySchedulerInfoJson(JSONObject json)
|
|
|
+ throws JSONException, Exception {
|
|
|
+ assertEquals("incorrect number of elements", 1, json.length());
|
|
|
+ JSONObject info = json.getJSONObject("scheduler");
|
|
|
+ assertEquals("incorrect number of elements", 1, info.length());
|
|
|
+ info = info.getJSONObject("schedulerInfo");
|
|
|
+ assertEquals("incorrect number of elements", 8, info.length());
|
|
|
+ JSONObject capacitiesJsonObject = info.getJSONObject(CAPACITIES);
|
|
|
+ JSONArray partitionsCapsArray =
|
|
|
+ capacitiesJsonObject.getJSONArray(QUEUE_CAPACITIES_BY_PARTITION);
|
|
|
+ assertEquals("incorrect number of elements", CLUSTER_LABELS.size(),
|
|
|
+ partitionsCapsArray.length());
|
|
|
+ for (int i = 0; i < partitionsCapsArray.length(); i++) {
|
|
|
+ JSONObject partitionInfo = partitionsCapsArray.getJSONObject(i);
|
|
|
+ String partitionName = partitionInfo.getString("partitionName");
|
|
|
+ assertTrue("Unknown partition received",
|
|
|
+ CLUSTER_LABELS.contains(partitionName));
|
|
|
+ verifyPartitionCapacityInfoJson(partitionInfo, 100, 0, 100, 100, 0, 100);
|
|
|
+ }
|
|
|
+ JSONObject jsonQueuesObject = info.getJSONObject("queues");
|
|
|
+ JSONArray queuesArray = jsonQueuesObject.getJSONArray("queue");
|
|
|
+ for (int i = 0; i < queuesArray.length(); i++) {
|
|
|
+ JSONObject queueJson = queuesArray.getJSONObject(i);
|
|
|
+ String queue = queueJson.getString("queueName");
|
|
|
+
|
|
|
+ assertEquals("Partition resourceInfo is wrong", 1,
|
|
|
+ queueJson.getJSONObject("resources")
|
|
|
+ .getJSONArray(RESOURCE_USAGES_BY_PARTITION).length());
|
|
|
+
|
|
|
+ JSONObject resourcesJsonObject = queueJson.getJSONObject("resources");
|
|
|
+ JSONArray partitionsResourcesArray =
|
|
|
+ resourcesJsonObject.getJSONArray("resourceUsagesByPartition");
|
|
|
+ assertEquals("incorrect number of elements", 1,
|
|
|
+ partitionsResourcesArray.length());
|
|
|
+
|
|
|
+ capacitiesJsonObject = queueJson.getJSONObject(CAPACITIES);
|
|
|
+ partitionsCapsArray =
|
|
|
+ capacitiesJsonObject.getJSONArray(QUEUE_CAPACITIES_BY_PARTITION);
|
|
|
+
|
|
|
+ JSONObject partitionInfo = null;
|
|
|
+ String partitionName = null;
|
|
|
+ switch (queue) {
|
|
|
+ case QUEUE_A:
|
|
|
+ assertEquals("incorrect number of partitions", 1,
|
|
|
+ partitionsCapsArray.length());
|
|
|
+ partitionInfo = partitionsCapsArray.getJSONObject(0);
|
|
|
+ partitionName = partitionInfo.getString("partitionName");
|
|
|
+ verifyPartitionCapacityInfoJson(partitionInfo, 30, 0, 50, 30, 0, 50);
|
|
|
+ assertEquals("incorrect number of elements", 5,
|
|
|
+ partitionsResourcesArray.getJSONObject(0).length());
|
|
|
+ break;
|
|
|
+ case QUEUE_B:
|
|
|
+ assertEquals("Invalid default Label expression", LABEL_LX,
|
|
|
+ queueJson.getString("defaultNodeLabelExpression"));
|
|
|
+ assertEquals("incorrect number of elements", 5,
|
|
|
+ partitionsResourcesArray.getJSONObject(0).length());
|
|
|
+ verifyAccesibleNodeLabels(queueJson, ImmutableSet.of(LABEL_LX));
|
|
|
+ assertEquals("incorrect number of partitions", 2,
|
|
|
+ partitionsCapsArray.length());
|
|
|
+ for (int j = 0; j < partitionsCapsArray.length(); j++) {
|
|
|
+ partitionInfo = partitionsCapsArray.getJSONObject(j);
|
|
|
+ partitionName = partitionInfo.getString("partitionName");
|
|
|
+ switch (partitionName) {
|
|
|
+ case LABEL_LX:
|
|
|
+ verifyPartitionCapacityInfoJson(partitionInfo, 30, 0, 100, 30, 0,
|
|
|
+ 100);
|
|
|
+ break;
|
|
|
+ case DEFAULT_PARTITION:
|
|
|
+ verifyPartitionCapacityInfoJson(partitionInfo, 30, 0, 50, 30, 0,
|
|
|
+ 50);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ Assert.fail("Unexpected partition" + partitionName);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case QUEUE_C:
|
|
|
+ verifyAccesibleNodeLabels(queueJson,
|
|
|
+ ImmutableSet.of(LABEL_LX, LABEL_LY));
|
|
|
+ assertEquals("incorrect number of elements", 4,
|
|
|
+ partitionsResourcesArray.getJSONObject(0).length());
|
|
|
+ verifyQcPartitionsCapacityInfoJson(partitionsCapsArray, 70, 100, 70,
|
|
|
+ 100, 100, 100, 100, 100, 40, 50, 40, 50);
|
|
|
+ verifySubQueuesOfQc(queueJson);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ Assert.fail("Unexpected queue" + queue);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void verifyAccesibleNodeLabels(JSONObject queueJson,
|
|
|
+ Set<String> accesibleNodeLabels) throws JSONException {
|
|
|
+ JSONArray nodeLabels = queueJson.getJSONArray("nodeLabels");
|
|
|
+ assertEquals("number of accessible Node Labels not matching",
|
|
|
+ accesibleNodeLabels.size(), nodeLabels.length());
|
|
|
+ for (int i = 0; i < nodeLabels.length(); i++) {
|
|
|
+ assertTrue("Invalid accessible node label : " + nodeLabels.getString(i),
|
|
|
+ accesibleNodeLabels.contains(nodeLabels.getString(i)));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void verifySubQueuesOfQc(JSONObject queueCJson) throws JSONException {
|
|
|
+ JSONObject jsonQueuesObject = queueCJson.getJSONObject("queues");
|
|
|
+ JSONArray queuesArray = jsonQueuesObject.getJSONArray("queue");
|
|
|
+ for (int i = 0; i < queuesArray.length(); i++) {
|
|
|
+ JSONObject queueJson = queuesArray.getJSONObject(i);
|
|
|
+ String queue = queueJson.getString("queueName");
|
|
|
+
|
|
|
+ JSONObject capacitiesJsonObject = queueJson.getJSONObject(CAPACITIES);
|
|
|
+ JSONArray partitionsCapsArray =
|
|
|
+ capacitiesJsonObject.getJSONArray(QUEUE_CAPACITIES_BY_PARTITION);
|
|
|
+ switch (queue) {
|
|
|
+ case LEAF_QUEUE_C1:
|
|
|
+ verifyAccesibleNodeLabels(queueJson,
|
|
|
+ ImmutableSet.of(LABEL_LX, LABEL_LY));
|
|
|
+ assertEquals("Invalid default Label expression", LABEL_LX,
|
|
|
+ queueJson.getString("defaultNodeLabelExpression"));
|
|
|
+ verifyQcPartitionsCapacityInfoJson(partitionsCapsArray, 40, 100, 28,
|
|
|
+ 100, 50, 75, 50, 75, 50, 60, 20, 30);
|
|
|
+ break;
|
|
|
+ case LEAF_QUEUE_C2:
|
|
|
+ verifyAccesibleNodeLabels(queueJson,
|
|
|
+ ImmutableSet.of(LABEL_LX, LABEL_LY));
|
|
|
+ assertEquals("Invalid default Label expression", LABEL_LY,
|
|
|
+ queueJson.getString("defaultNodeLabelExpression"));
|
|
|
+ verifyQcPartitionsCapacityInfoJson(partitionsCapsArray, 60, 100, 42,
|
|
|
+ 100, 50, 75, 50, 75, 50, 70, 20, 35);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ Assert.fail("Unexpected queue" + queue);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void verifyQcPartitionsCapacityInfoJson(JSONArray partitionsCapsArray,
|
|
|
+ float lxCaps, float lxMaxCaps, float lxAbsCaps, float lxAbsMaxCaps,
|
|
|
+ float lyCaps, float lyMaxCaps, float lyAbsCaps, float lyAbsMaxCaps,
|
|
|
+ float defCaps, float defMaxCaps, float defAbsCaps, float defAbsMaxCaps)
|
|
|
+ throws JSONException {
|
|
|
+ assertEquals("incorrect number of partitions", CLUSTER_LABELS.size(),
|
|
|
+ partitionsCapsArray.length());
|
|
|
+ for (int j = 0; j < partitionsCapsArray.length(); j++) {
|
|
|
+ JSONObject partitionInfo = partitionsCapsArray.getJSONObject(j);
|
|
|
+ String partitionName = partitionInfo.getString("partitionName");
|
|
|
+ switch (partitionName) {
|
|
|
+ case LABEL_LX:
|
|
|
+ verifyPartitionCapacityInfoJson(partitionInfo, lxCaps, 0, lxMaxCaps,
|
|
|
+ lxAbsCaps, 0, lxAbsMaxCaps);
|
|
|
+ break;
|
|
|
+ case LABEL_LY:
|
|
|
+ verifyPartitionCapacityInfoJson(partitionInfo, lyCaps, 0, lyMaxCaps,
|
|
|
+ lyAbsCaps, 0, lyAbsMaxCaps);
|
|
|
+ break;
|
|
|
+ case DEFAULT_PARTITION:
|
|
|
+ verifyPartitionCapacityInfoJson(partitionInfo, defCaps, 0, defMaxCaps,
|
|
|
+ defAbsCaps, 0, defAbsMaxCaps);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ Assert.fail("Unexpected partition" + partitionName);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void verifyPartitionCapacityInfoJson(
|
|
|
+ JSONObject partitionCapacityInfoJson, float capacity, float usedCapacity,
|
|
|
+ float maxCapacity, float absoluteCapacity, float absoluteUsedCapacity,
|
|
|
+ float absoluteMaxCapacity) throws JSONException {
|
|
|
+ assertEquals("capacity doesn't match", capacity,
|
|
|
+ (float) partitionCapacityInfoJson.getDouble("capacity"), 1e-3f);
|
|
|
+ assertEquals("capacity doesn't match", usedCapacity,
|
|
|
+ (float) partitionCapacityInfoJson.getDouble("usedCapacity"), 1e-3f);
|
|
|
+ assertEquals("capacity doesn't match", maxCapacity,
|
|
|
+ (float) partitionCapacityInfoJson.getDouble("maxCapacity"), 1e-3f);
|
|
|
+ assertEquals("capacity doesn't match", absoluteCapacity,
|
|
|
+ (float) partitionCapacityInfoJson.getDouble("absoluteCapacity"), 1e-3f);
|
|
|
+ assertEquals("capacity doesn't match", absoluteUsedCapacity,
|
|
|
+ (float) partitionCapacityInfoJson.getDouble("absoluteUsedCapacity"),
|
|
|
+ 1e-3f);
|
|
|
+ assertEquals("capacity doesn't match", absoluteMaxCapacity,
|
|
|
+ (float) partitionCapacityInfoJson.getDouble("absoluteMaxCapacity"),
|
|
|
+ 1e-3f);
|
|
|
+ }
|
|
|
+}
|