1 /** 2 * Licensed to the Apache Software Foundation (ASF) under one 3 * or more contributor license agreements. See the NOTICE file 4 * distributed with this work for additional information 5 * regarding copyright ownership. The ASF licenses this file 6 * to you under the Apache License, Version 2.0 (the 7 * "License"); you may not use this file except in compliance 8 * with the License. You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 19 package org.apache.hadoop.yarn.server.resourcemanager.webapp; 20 21 import static org.junit.Assert.assertEquals; 22 import static org.junit.Assert.assertTrue; 23 import static org.junit.Assert.fail; 24 import static org.mockito.Matchers.anyBoolean; 25 import static org.mockito.Matchers.isA; 26 import static org.mockito.Mockito.mock; 27 import static org.mockito.Mockito.when; 28 29 import java.io.StringReader; 30 import java.util.Arrays; 31 import java.util.Collections; 32 import java.util.Set; 33 34 import javax.servlet.http.HttpServletRequest; 35 import javax.servlet.http.HttpServletResponse; 36 import javax.ws.rs.core.MediaType; 37 import javax.xml.parsers.DocumentBuilder; 38 import javax.xml.parsers.DocumentBuilderFactory; 39 40 import org.apache.hadoop.conf.Configuration; 41 import org.apache.hadoop.service.Service.STATE; 42 import org.apache.hadoop.util.VersionInfo; 43 import org.apache.hadoop.yarn.api.protocolrecords.GetApplicationsRequest; 44 import org.apache.hadoop.yarn.api.protocolrecords.GetApplicationsResponse; 45 import org.apache.hadoop.yarn.api.records.ApplicationId; 46 import org.apache.hadoop.yarn.api.records.ApplicationReport; 47 import org.apache.hadoop.yarn.api.records.QueueState; 48 import org.apache.hadoop.yarn.conf.YarnConfiguration; 49 import org.apache.hadoop.yarn.server.resourcemanager.ClientRMService; 50 import org.apache.hadoop.yarn.server.resourcemanager.ClusterMetrics; 51 import org.apache.hadoop.yarn.server.resourcemanager.MockRM; 52 import org.apache.hadoop.yarn.server.resourcemanager.RMContextImpl; 53 import org.apache.hadoop.yarn.server.resourcemanager.ResourceManager; 54 import org.apache.hadoop.yarn.server.resourcemanager.scheduler.QueueMetrics; 55 import org.apache.hadoop.yarn.server.resourcemanager.scheduler.ResourceScheduler; 56 import org.apache.hadoop.yarn.server.resourcemanager.scheduler.fifo.FifoScheduler; 57 import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.AppsInfo; 58 import org.apache.hadoop.yarn.util.YarnVersionInfo; 59 import org.apache.hadoop.yarn.webapp.GenericExceptionHandler; 60 import org.apache.hadoop.yarn.webapp.JerseyTestBase; 61 import org.apache.hadoop.yarn.webapp.WebServicesTestUtils; 62 import org.codehaus.jettison.json.JSONException; 63 import org.codehaus.jettison.json.JSONObject; 64 import org.junit.Before; 65 import org.junit.BeforeClass; 66 import org.junit.Test; 67 import org.w3c.dom.Document; 68 import org.w3c.dom.Element; 69 import org.w3c.dom.NodeList; 70 import org.xml.sax.InputSource; 71 72 import com.google.inject.Guice; 73 import com.google.inject.Injector; 74 import com.google.inject.servlet.GuiceServletContextListener; 75 import com.google.inject.servlet.ServletModule; 76 import com.sun.jersey.api.client.ClientResponse; 77 import com.sun.jersey.api.client.ClientResponse.Status; 78 import com.sun.jersey.api.client.UniformInterfaceException; 79 import com.sun.jersey.api.client.WebResource; 80 import com.sun.jersey.guice.spi.container.servlet.GuiceContainer; 81 import com.sun.jersey.test.framework.WebAppDescriptor; 82 83 public class TestRMWebServices extends JerseyTestBase { 84 85 private static MockRM rm; 86 87 private Injector injector = Guice.createInjector(new ServletModule() { 88 @Override 89 protected void configureServlets() { 90 bind(JAXBContextResolver.class); 91 bind(RMWebServices.class); 92 bind(GenericExceptionHandler.class); 93 Configuration conf = new Configuration(); 94 conf.setClass(YarnConfiguration.RM_SCHEDULER, FifoScheduler.class, 95 ResourceScheduler.class); 96 rm = new MockRM(conf); 97 bind(ResourceManager.class).toInstance(rm); 98 serve("/*").with(GuiceContainer.class); 99 } 100 }); 101 102 public class GuiceServletConfig extends GuiceServletContextListener { 103 104 @Override getInjector()105 protected Injector getInjector() { 106 return injector; 107 } 108 } 109 110 @Before 111 @Override setUp()112 public void setUp() throws Exception { 113 super.setUp(); 114 } 115 TestRMWebServices()116 public TestRMWebServices() { 117 super(new WebAppDescriptor.Builder( 118 "org.apache.hadoop.yarn.server.resourcemanager.webapp") 119 .contextListenerClass(GuiceServletConfig.class) 120 .filterClass(com.google.inject.servlet.GuiceFilter.class) 121 .contextPath("jersey-guice-filter").servletPath("/").build()); 122 } 123 124 @BeforeClass initClusterMetrics()125 public static void initClusterMetrics() { 126 ClusterMetrics clusterMetrics = ClusterMetrics.getMetrics(); 127 clusterMetrics.incrDecommisionedNMs(); 128 clusterMetrics.incrNumActiveNodes(); 129 clusterMetrics.incrNumLostNMs(); 130 clusterMetrics.incrNumRebootedNMs(); 131 clusterMetrics.incrNumUnhealthyNMs(); 132 } 133 134 @Test testInfoXML()135 public void testInfoXML() throws JSONException, Exception { 136 WebResource r = resource(); 137 ClientResponse response = r.path("ws").path("v1").path("cluster") 138 .path("info").accept("application/xml").get(ClientResponse.class); 139 assertEquals(MediaType.APPLICATION_XML_TYPE, response.getType()); 140 String xml = response.getEntity(String.class); 141 verifyClusterInfoXML(xml); 142 } 143 144 @Test testInvalidUri()145 public void testInvalidUri() throws JSONException, Exception { 146 WebResource r = resource(); 147 String responseStr = ""; 148 try { 149 responseStr = r.path("ws").path("v1").path("cluster").path("bogus") 150 .accept(MediaType.APPLICATION_JSON).get(String.class); 151 fail("should have thrown exception on invalid uri"); 152 } catch (UniformInterfaceException ue) { 153 ClientResponse response = ue.getResponse(); 154 assertEquals(Status.NOT_FOUND, response.getClientResponseStatus()); 155 156 WebServicesTestUtils.checkStringMatch( 157 "error string exists and shouldn't", "", responseStr); 158 } 159 } 160 161 @Test testInvalidUri2()162 public void testInvalidUri2() throws JSONException, Exception { 163 WebResource r = resource(); 164 String responseStr = ""; 165 try { 166 responseStr = r.accept(MediaType.APPLICATION_JSON).get(String.class); 167 fail("should have thrown exception on invalid uri"); 168 } catch (UniformInterfaceException ue) { 169 ClientResponse response = ue.getResponse(); 170 assertEquals(Status.NOT_FOUND, response.getClientResponseStatus()); 171 WebServicesTestUtils.checkStringMatch( 172 "error string exists and shouldn't", "", responseStr); 173 } 174 } 175 176 @Test testInvalidAccept()177 public void testInvalidAccept() throws JSONException, Exception { 178 WebResource r = resource(); 179 String responseStr = ""; 180 try { 181 responseStr = r.path("ws").path("v1").path("cluster") 182 .accept(MediaType.TEXT_PLAIN).get(String.class); 183 fail("should have thrown exception on invalid uri"); 184 } catch (UniformInterfaceException ue) { 185 ClientResponse response = ue.getResponse(); 186 assertEquals(Status.INTERNAL_SERVER_ERROR, 187 response.getClientResponseStatus()); 188 WebServicesTestUtils.checkStringMatch( 189 "error string exists and shouldn't", "", responseStr); 190 } 191 } 192 193 @Test testCluster()194 public void testCluster() throws JSONException, Exception { 195 WebResource r = resource(); 196 ClientResponse response = r.path("ws").path("v1").path("cluster") 197 .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class); 198 199 assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType()); 200 JSONObject json = response.getEntity(JSONObject.class); 201 verifyClusterInfo(json); 202 } 203 204 @Test testClusterSlash()205 public void testClusterSlash() throws JSONException, Exception { 206 WebResource r = resource(); 207 // test with trailing "/" to make sure acts same as without slash 208 ClientResponse response = r.path("ws").path("v1").path("cluster/") 209 .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class); 210 211 assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType()); 212 JSONObject json = response.getEntity(JSONObject.class); 213 verifyClusterInfo(json); 214 } 215 216 @Test testClusterDefault()217 public void testClusterDefault() throws JSONException, Exception { 218 WebResource r = resource(); 219 // test with trailing "/" to make sure acts same as without slash 220 ClientResponse response = r.path("ws").path("v1").path("cluster") 221 .get(ClientResponse.class); 222 223 assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType()); 224 JSONObject json = response.getEntity(JSONObject.class); 225 verifyClusterInfo(json); 226 } 227 228 @Test testInfo()229 public void testInfo() throws JSONException, Exception { 230 WebResource r = resource(); 231 ClientResponse response = r.path("ws").path("v1").path("cluster") 232 .path("info").accept(MediaType.APPLICATION_JSON) 233 .get(ClientResponse.class); 234 235 assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType()); 236 JSONObject json = response.getEntity(JSONObject.class); 237 verifyClusterInfo(json); 238 } 239 240 @Test testInfoSlash()241 public void testInfoSlash() throws JSONException, Exception { 242 // test with trailing "/" to make sure acts same as without slash 243 WebResource r = resource(); 244 ClientResponse response = r.path("ws").path("v1").path("cluster") 245 .path("info/").accept(MediaType.APPLICATION_JSON) 246 .get(ClientResponse.class); 247 248 assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType()); 249 JSONObject json = response.getEntity(JSONObject.class); 250 verifyClusterInfo(json); 251 } 252 253 @Test testInfoDefault()254 public void testInfoDefault() throws JSONException, Exception { 255 WebResource r = resource(); 256 ClientResponse response = r.path("ws").path("v1").path("cluster") 257 .path("info").get(ClientResponse.class); 258 259 assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType()); 260 JSONObject json = response.getEntity(JSONObject.class); 261 verifyClusterInfo(json); 262 } 263 verifyClusterInfoXML(String xml)264 public void verifyClusterInfoXML(String xml) throws JSONException, Exception { 265 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 266 DocumentBuilder db = dbf.newDocumentBuilder(); 267 InputSource is = new InputSource(); 268 is.setCharacterStream(new StringReader(xml)); 269 Document dom = db.parse(is); 270 NodeList nodes = dom.getElementsByTagName("clusterInfo"); 271 assertEquals("incorrect number of elements", 1, nodes.getLength()); 272 273 for (int i = 0; i < nodes.getLength(); i++) { 274 Element element = (Element) nodes.item(i); 275 276 verifyClusterGeneric(WebServicesTestUtils.getXmlLong(element, "id"), 277 WebServicesTestUtils.getXmlLong(element, "startedOn"), 278 WebServicesTestUtils.getXmlString(element, "state"), 279 WebServicesTestUtils.getXmlString(element, "haState"), 280 WebServicesTestUtils.getXmlString( 281 element, "haZooKeeperConnectionState"), 282 WebServicesTestUtils.getXmlString(element, "hadoopVersionBuiltOn"), 283 WebServicesTestUtils.getXmlString(element, "hadoopBuildVersion"), 284 WebServicesTestUtils.getXmlString(element, "hadoopVersion"), 285 WebServicesTestUtils.getXmlString(element, 286 "resourceManagerVersionBuiltOn"), 287 WebServicesTestUtils.getXmlString(element, 288 "resourceManagerBuildVersion"), 289 WebServicesTestUtils.getXmlString(element, "resourceManagerVersion")); 290 } 291 } 292 verifyClusterInfo(JSONObject json)293 public void verifyClusterInfo(JSONObject json) throws JSONException, 294 Exception { 295 assertEquals("incorrect number of elements", 1, json.length()); 296 JSONObject info = json.getJSONObject("clusterInfo"); 297 assertEquals("incorrect number of elements", 12, info.length()); 298 verifyClusterGeneric(info.getLong("id"), info.getLong("startedOn"), 299 info.getString("state"), info.getString("haState"), 300 info.getString("haZooKeeperConnectionState"), 301 info.getString("hadoopVersionBuiltOn"), 302 info.getString("hadoopBuildVersion"), info.getString("hadoopVersion"), 303 info.getString("resourceManagerVersionBuiltOn"), 304 info.getString("resourceManagerBuildVersion"), 305 info.getString("resourceManagerVersion")); 306 307 } 308 verifyClusterGeneric(long clusterid, long startedon, String state, String haState, String haZooKeeperConnectionState, String hadoopVersionBuiltOn, String hadoopBuildVersion, String hadoopVersion, String resourceManagerVersionBuiltOn, String resourceManagerBuildVersion, String resourceManagerVersion)309 public void verifyClusterGeneric(long clusterid, long startedon, 310 String state, String haState, String haZooKeeperConnectionState, 311 String hadoopVersionBuiltOn, 312 String hadoopBuildVersion, String hadoopVersion, 313 String resourceManagerVersionBuiltOn, String resourceManagerBuildVersion, 314 String resourceManagerVersion) { 315 316 assertEquals("clusterId doesn't match: ", 317 ResourceManager.getClusterTimeStamp(), clusterid); 318 assertEquals("startedOn doesn't match: ", 319 ResourceManager.getClusterTimeStamp(), startedon); 320 assertTrue("stated doesn't match: " + state, 321 state.matches(STATE.INITED.toString())); 322 assertTrue("HA state doesn't match: " + haState, 323 haState.matches("INITIALIZING")); 324 325 WebServicesTestUtils.checkStringMatch("hadoopVersionBuiltOn", 326 VersionInfo.getDate(), hadoopVersionBuiltOn); 327 WebServicesTestUtils.checkStringEqual("hadoopBuildVersion", 328 VersionInfo.getBuildVersion(), hadoopBuildVersion); 329 WebServicesTestUtils.checkStringMatch("hadoopVersion", 330 VersionInfo.getVersion(), hadoopVersion); 331 332 WebServicesTestUtils.checkStringMatch("resourceManagerVersionBuiltOn", 333 YarnVersionInfo.getDate(), resourceManagerVersionBuiltOn); 334 WebServicesTestUtils.checkStringEqual("resourceManagerBuildVersion", 335 YarnVersionInfo.getBuildVersion(), resourceManagerBuildVersion); 336 WebServicesTestUtils.checkStringMatch("resourceManagerVersion", 337 YarnVersionInfo.getVersion(), resourceManagerVersion); 338 } 339 340 @Test testClusterMetrics()341 public void testClusterMetrics() throws JSONException, Exception { 342 WebResource r = resource(); 343 ClientResponse response = r.path("ws").path("v1").path("cluster") 344 .path("metrics").accept(MediaType.APPLICATION_JSON) 345 .get(ClientResponse.class); 346 347 assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType()); 348 JSONObject json = response.getEntity(JSONObject.class); 349 verifyClusterMetricsJSON(json); 350 } 351 352 @Test testClusterMetricsSlash()353 public void testClusterMetricsSlash() throws JSONException, Exception { 354 WebResource r = resource(); 355 ClientResponse response = r.path("ws").path("v1").path("cluster") 356 .path("metrics/").accept(MediaType.APPLICATION_JSON) 357 .get(ClientResponse.class); 358 359 assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType()); 360 JSONObject json = response.getEntity(JSONObject.class); 361 verifyClusterMetricsJSON(json); 362 } 363 364 @Test testClusterMetricsDefault()365 public void testClusterMetricsDefault() throws JSONException, Exception { 366 WebResource r = resource(); 367 ClientResponse response = r.path("ws").path("v1").path("cluster") 368 .path("metrics").get(ClientResponse.class); 369 370 assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType()); 371 JSONObject json = response.getEntity(JSONObject.class); 372 verifyClusterMetricsJSON(json); 373 } 374 375 @Test testClusterMetricsXML()376 public void testClusterMetricsXML() throws JSONException, Exception { 377 WebResource r = resource(); 378 ClientResponse response = r.path("ws").path("v1").path("cluster") 379 .path("metrics").accept("application/xml").get(ClientResponse.class); 380 assertEquals(MediaType.APPLICATION_XML_TYPE, response.getType()); 381 String xml = response.getEntity(String.class); 382 verifyClusterMetricsXML(xml); 383 } 384 verifyClusterMetricsXML(String xml)385 public void verifyClusterMetricsXML(String xml) throws JSONException, 386 Exception { 387 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 388 DocumentBuilder db = dbf.newDocumentBuilder(); 389 InputSource is = new InputSource(); 390 is.setCharacterStream(new StringReader(xml)); 391 Document dom = db.parse(is); 392 NodeList nodes = dom.getElementsByTagName("clusterMetrics"); 393 assertEquals("incorrect number of elements", 1, nodes.getLength()); 394 395 for (int i = 0; i < nodes.getLength(); i++) { 396 Element element = (Element) nodes.item(i); 397 398 verifyClusterMetrics( 399 WebServicesTestUtils.getXmlInt(element, "appsSubmitted"), 400 WebServicesTestUtils.getXmlInt(element, "appsCompleted"), 401 WebServicesTestUtils.getXmlInt(element, "reservedMB"), 402 WebServicesTestUtils.getXmlInt(element, "availableMB"), 403 WebServicesTestUtils.getXmlInt(element, "allocatedMB"), 404 WebServicesTestUtils.getXmlInt(element, "reservedVirtualCores"), 405 WebServicesTestUtils.getXmlInt(element, "availableVirtualCores"), 406 WebServicesTestUtils.getXmlInt(element, "allocatedVirtualCores"), 407 WebServicesTestUtils.getXmlInt(element, "totalVirtualCores"), 408 WebServicesTestUtils.getXmlInt(element, "containersAllocated"), 409 WebServicesTestUtils.getXmlInt(element, "totalMB"), 410 WebServicesTestUtils.getXmlInt(element, "totalNodes"), 411 WebServicesTestUtils.getXmlInt(element, "lostNodes"), 412 WebServicesTestUtils.getXmlInt(element, "unhealthyNodes"), 413 WebServicesTestUtils.getXmlInt(element, "decommissionedNodes"), 414 WebServicesTestUtils.getXmlInt(element, "rebootedNodes"), 415 WebServicesTestUtils.getXmlInt(element, "activeNodes")); 416 } 417 } 418 verifyClusterMetricsJSON(JSONObject json)419 public void verifyClusterMetricsJSON(JSONObject json) throws JSONException, 420 Exception { 421 assertEquals("incorrect number of elements", 1, json.length()); 422 JSONObject clusterinfo = json.getJSONObject("clusterMetrics"); 423 assertEquals("incorrect number of elements", 23, clusterinfo.length()); 424 verifyClusterMetrics( 425 clusterinfo.getInt("appsSubmitted"), clusterinfo.getInt("appsCompleted"), 426 clusterinfo.getInt("reservedMB"), clusterinfo.getInt("availableMB"), 427 clusterinfo.getInt("allocatedMB"), 428 clusterinfo.getInt("reservedVirtualCores"), clusterinfo.getInt("availableVirtualCores"), 429 clusterinfo.getInt("allocatedVirtualCores"), clusterinfo.getInt("totalVirtualCores"), 430 clusterinfo.getInt("containersAllocated"), 431 clusterinfo.getInt("totalMB"), clusterinfo.getInt("totalNodes"), 432 clusterinfo.getInt("lostNodes"), clusterinfo.getInt("unhealthyNodes"), 433 clusterinfo.getInt("decommissionedNodes"), 434 clusterinfo.getInt("rebootedNodes"),clusterinfo.getInt("activeNodes")); 435 } 436 verifyClusterMetrics(int submittedApps, int completedApps, int reservedMB, int availableMB, int allocMB, int reservedVirtualCores, int availableVirtualCores, int allocVirtualCores, int totalVirtualCores, int containersAlloc, int totalMB, int totalNodes, int lostNodes, int unhealthyNodes, int decommissionedNodes, int rebootedNodes, int activeNodes)437 public void verifyClusterMetrics(int submittedApps, int completedApps, 438 int reservedMB, int availableMB, 439 int allocMB, int reservedVirtualCores, int availableVirtualCores, 440 int allocVirtualCores, int totalVirtualCores, 441 int containersAlloc, int totalMB, int totalNodes, 442 int lostNodes, int unhealthyNodes, int decommissionedNodes, 443 int rebootedNodes, int activeNodes) throws JSONException, Exception { 444 445 ResourceScheduler rs = rm.getResourceScheduler(); 446 QueueMetrics metrics = rs.getRootQueueMetrics(); 447 ClusterMetrics clusterMetrics = ClusterMetrics.getMetrics(); 448 449 long totalMBExpect = 450 metrics.getAvailableMB() + metrics.getAllocatedMB(); 451 long totalVirtualCoresExpect = 452 metrics.getAvailableVirtualCores() + metrics.getAllocatedVirtualCores(); 453 assertEquals("appsSubmitted doesn't match", 454 metrics.getAppsSubmitted(), submittedApps); 455 assertEquals("appsCompleted doesn't match", 456 metrics.getAppsCompleted(), completedApps); 457 assertEquals("reservedMB doesn't match", 458 metrics.getReservedMB(), reservedMB); 459 assertEquals("availableMB doesn't match", 460 metrics.getAvailableMB(), availableMB); 461 assertEquals("allocatedMB doesn't match", 462 metrics.getAllocatedMB(), allocMB); 463 assertEquals("reservedVirtualCores doesn't match", 464 metrics.getReservedVirtualCores(), reservedVirtualCores); 465 assertEquals("availableVirtualCores doesn't match", 466 metrics.getAvailableVirtualCores(), availableVirtualCores); 467 assertEquals("allocatedVirtualCores doesn't match", 468 totalVirtualCoresExpect, allocVirtualCores); 469 assertEquals("containersAllocated doesn't match", 0, containersAlloc); 470 assertEquals("totalMB doesn't match", totalMBExpect, totalMB); 471 assertEquals( 472 "totalNodes doesn't match", 473 clusterMetrics.getNumActiveNMs() + clusterMetrics.getNumLostNMs() 474 + clusterMetrics.getNumDecommisionedNMs() 475 + clusterMetrics.getNumRebootedNMs() 476 + clusterMetrics.getUnhealthyNMs(), totalNodes); 477 assertEquals("lostNodes doesn't match", clusterMetrics.getNumLostNMs(), 478 lostNodes); 479 assertEquals("unhealthyNodes doesn't match", 480 clusterMetrics.getUnhealthyNMs(), unhealthyNodes); 481 assertEquals("decommissionedNodes doesn't match", 482 clusterMetrics.getNumDecommisionedNMs(), decommissionedNodes); 483 assertEquals("rebootedNodes doesn't match", 484 clusterMetrics.getNumRebootedNMs(), rebootedNodes); 485 assertEquals("activeNodes doesn't match", clusterMetrics.getNumActiveNMs(), 486 activeNodes); 487 } 488 489 @Test testClusterSchedulerFifo()490 public void testClusterSchedulerFifo() throws JSONException, Exception { 491 WebResource r = resource(); 492 ClientResponse response = r.path("ws").path("v1").path("cluster") 493 .path("scheduler").accept(MediaType.APPLICATION_JSON) 494 .get(ClientResponse.class); 495 496 assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType()); 497 JSONObject json = response.getEntity(JSONObject.class); 498 verifyClusterSchedulerFifo(json); 499 } 500 501 @Test testClusterSchedulerFifoSlash()502 public void testClusterSchedulerFifoSlash() throws JSONException, Exception { 503 WebResource r = resource(); 504 ClientResponse response = r.path("ws").path("v1").path("cluster") 505 .path("scheduler/").accept(MediaType.APPLICATION_JSON) 506 .get(ClientResponse.class); 507 508 assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType()); 509 JSONObject json = response.getEntity(JSONObject.class); 510 verifyClusterSchedulerFifo(json); 511 } 512 513 @Test testClusterSchedulerFifoDefault()514 public void testClusterSchedulerFifoDefault() throws JSONException, Exception { 515 WebResource r = resource(); 516 ClientResponse response = r.path("ws").path("v1").path("cluster") 517 .path("scheduler").get(ClientResponse.class); 518 519 assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType()); 520 JSONObject json = response.getEntity(JSONObject.class); 521 verifyClusterSchedulerFifo(json); 522 } 523 524 @Test testClusterSchedulerFifoXML()525 public void testClusterSchedulerFifoXML() throws JSONException, Exception { 526 WebResource r = resource(); 527 ClientResponse response = r.path("ws").path("v1").path("cluster") 528 .path("scheduler").accept(MediaType.APPLICATION_XML) 529 .get(ClientResponse.class); 530 531 assertEquals(MediaType.APPLICATION_XML_TYPE, response.getType()); 532 String xml = response.getEntity(String.class); 533 verifySchedulerFifoXML(xml); 534 } 535 verifySchedulerFifoXML(String xml)536 public void verifySchedulerFifoXML(String xml) throws JSONException, 537 Exception { 538 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 539 DocumentBuilder db = dbf.newDocumentBuilder(); 540 InputSource is = new InputSource(); 541 is.setCharacterStream(new StringReader(xml)); 542 Document dom = db.parse(is); 543 NodeList nodesSched = dom.getElementsByTagName("scheduler"); 544 assertEquals("incorrect number of elements", 1, nodesSched.getLength()); 545 NodeList nodes = dom.getElementsByTagName("schedulerInfo"); 546 assertEquals("incorrect number of elements", 1, nodes.getLength()); 547 548 for (int i = 0; i < nodes.getLength(); i++) { 549 Element element = (Element) nodes.item(i); 550 551 verifyClusterSchedulerFifoGeneric( 552 WebServicesTestUtils.getXmlAttrString(element, "xsi:type"), 553 WebServicesTestUtils.getXmlString(element, "qstate"), 554 WebServicesTestUtils.getXmlFloat(element, "capacity"), 555 WebServicesTestUtils.getXmlFloat(element, "usedCapacity"), 556 WebServicesTestUtils.getXmlInt(element, "minQueueMemoryCapacity"), 557 WebServicesTestUtils.getXmlInt(element, "maxQueueMemoryCapacity"), 558 WebServicesTestUtils.getXmlInt(element, "numNodes"), 559 WebServicesTestUtils.getXmlInt(element, "usedNodeCapacity"), 560 WebServicesTestUtils.getXmlInt(element, "availNodeCapacity"), 561 WebServicesTestUtils.getXmlInt(element, "totalNodeCapacity"), 562 WebServicesTestUtils.getXmlInt(element, "numContainers")); 563 } 564 } 565 verifyClusterSchedulerFifo(JSONObject json)566 public void verifyClusterSchedulerFifo(JSONObject json) throws JSONException, 567 Exception { 568 assertEquals("incorrect number of elements", 1, json.length()); 569 JSONObject info = json.getJSONObject("scheduler"); 570 assertEquals("incorrect number of elements", 1, info.length()); 571 info = info.getJSONObject("schedulerInfo"); 572 assertEquals("incorrect number of elements", 11, info.length()); 573 574 verifyClusterSchedulerFifoGeneric(info.getString("type"), 575 info.getString("qstate"), (float) info.getDouble("capacity"), 576 (float) info.getDouble("usedCapacity"), 577 info.getInt("minQueueMemoryCapacity"), 578 info.getInt("maxQueueMemoryCapacity"), info.getInt("numNodes"), 579 info.getInt("usedNodeCapacity"), info.getInt("availNodeCapacity"), 580 info.getInt("totalNodeCapacity"), info.getInt("numContainers")); 581 582 } 583 verifyClusterSchedulerFifoGeneric(String type, String state, float capacity, float usedCapacity, int minQueueCapacity, int maxQueueCapacity, int numNodes, int usedNodeCapacity, int availNodeCapacity, int totalNodeCapacity, int numContainers)584 public void verifyClusterSchedulerFifoGeneric(String type, String state, 585 float capacity, float usedCapacity, int minQueueCapacity, 586 int maxQueueCapacity, int numNodes, int usedNodeCapacity, 587 int availNodeCapacity, int totalNodeCapacity, int numContainers) 588 throws JSONException, Exception { 589 590 assertEquals("type doesn't match", "fifoScheduler", type); 591 assertEquals("qstate doesn't match", QueueState.RUNNING.toString(), state); 592 assertEquals("capacity doesn't match", 1.0, capacity, 0.0); 593 assertEquals("usedCapacity doesn't match", 0.0, usedCapacity, 0.0); 594 assertEquals( 595 "minQueueMemoryCapacity doesn't match", 596 YarnConfiguration.DEFAULT_RM_SCHEDULER_MINIMUM_ALLOCATION_MB, 597 minQueueCapacity); 598 assertEquals("maxQueueMemoryCapacity doesn't match", 599 YarnConfiguration.DEFAULT_RM_SCHEDULER_MAXIMUM_ALLOCATION_MB, 600 maxQueueCapacity); 601 assertEquals("numNodes doesn't match", 0, numNodes); 602 assertEquals("usedNodeCapacity doesn't match", 0, usedNodeCapacity); 603 assertEquals("availNodeCapacity doesn't match", 0, availNodeCapacity); 604 assertEquals("totalNodeCapacity doesn't match", 0, totalNodeCapacity); 605 assertEquals("numContainers doesn't match", 0, numContainers); 606 607 } 608 609 // Test the scenario where the RM removes an app just as we try to 610 // look at it in the apps list 611 @Test testAppsRace()612 public void testAppsRace() throws Exception { 613 // mock up an RM that returns app reports for apps that don't exist 614 // in the RMApps list 615 ApplicationId appId = ApplicationId.newInstance(1, 1); 616 ApplicationReport mockReport = mock(ApplicationReport.class); 617 when(mockReport.getApplicationId()).thenReturn(appId); 618 GetApplicationsResponse mockAppsResponse = 619 mock(GetApplicationsResponse.class); 620 when(mockAppsResponse.getApplicationList()) 621 .thenReturn(Arrays.asList(new ApplicationReport[] { mockReport })); 622 ClientRMService mockClientSvc = mock(ClientRMService.class); 623 when(mockClientSvc.getApplications(isA(GetApplicationsRequest.class), 624 anyBoolean())).thenReturn(mockAppsResponse); 625 ResourceManager mockRM = mock(ResourceManager.class); 626 RMContextImpl rmContext = new RMContextImpl(null, null, null, null, null, 627 null, null, null, null, null); 628 when(mockRM.getRMContext()).thenReturn(rmContext); 629 when(mockRM.getClientRMService()).thenReturn(mockClientSvc); 630 631 RMWebServices webSvc = new RMWebServices(mockRM, new Configuration(), 632 mock(HttpServletResponse.class)); 633 634 final Set<String> emptySet = 635 Collections.unmodifiableSet(Collections.<String>emptySet()); 636 637 // verify we don't get any apps when querying 638 HttpServletRequest mockHsr = mock(HttpServletRequest.class); 639 AppsInfo appsInfo = webSvc.getApps(mockHsr, null, emptySet, null, 640 null, null, null, null, null, null, null, emptySet, emptySet); 641 assertTrue(appsInfo.getApps().isEmpty()); 642 643 // verify we don't get an NPE when specifying a final status query 644 appsInfo = webSvc.getApps(mockHsr, null, emptySet, "FAILED", 645 null, null, null, null, null, null, null, emptySet, emptySet); 646 assertTrue(appsInfo.getApps().isEmpty()); 647 } 648 } 649