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 package org.apache.hadoop.yarn.server.resourcemanager.reservation; 19 20 import static org.mockito.Matchers.any; 21 import static org.mockito.Mockito.mock; 22 import static org.mockito.Mockito.when; 23 24 import java.text.MessageFormat; 25 import java.util.Collections; 26 import java.util.HashMap; 27 import java.util.Map; 28 29 import org.apache.commons.logging.Log; 30 import org.apache.commons.logging.LogFactory; 31 import org.apache.hadoop.yarn.api.protocolrecords.ReservationDeleteRequest; 32 import org.apache.hadoop.yarn.api.protocolrecords.ReservationSubmissionRequest; 33 import org.apache.hadoop.yarn.api.protocolrecords.ReservationUpdateRequest; 34 import org.apache.hadoop.yarn.api.protocolrecords.impl.pb.ReservationDeleteRequestPBImpl; 35 import org.apache.hadoop.yarn.api.protocolrecords.impl.pb.ReservationSubmissionRequestPBImpl; 36 import org.apache.hadoop.yarn.api.protocolrecords.impl.pb.ReservationUpdateRequestPBImpl; 37 import org.apache.hadoop.yarn.api.records.ReservationDefinition; 38 import org.apache.hadoop.yarn.api.records.ReservationId; 39 import org.apache.hadoop.yarn.api.records.ReservationRequest; 40 import org.apache.hadoop.yarn.api.records.ReservationRequestInterpreter; 41 import org.apache.hadoop.yarn.api.records.ReservationRequests; 42 import org.apache.hadoop.yarn.api.records.Resource; 43 import org.apache.hadoop.yarn.api.records.impl.pb.ReservationDefinitionPBImpl; 44 import org.apache.hadoop.yarn.api.records.impl.pb.ReservationRequestsPBImpl; 45 import org.apache.hadoop.yarn.exceptions.YarnException; 46 import org.apache.hadoop.yarn.util.Clock; 47 import org.apache.hadoop.yarn.util.resource.DefaultResourceCalculator; 48 import org.apache.hadoop.yarn.util.resource.ResourceCalculator; 49 import org.junit.After; 50 import org.junit.Assert; 51 import org.junit.Before; 52 import org.junit.Test; 53 54 public class TestReservationInputValidator { 55 56 private static final Log LOG = LogFactory 57 .getLog(TestReservationInputValidator.class); 58 59 private static final String PLAN_NAME = "test-reservation"; 60 61 private Clock clock; 62 private Map<String, Plan> plans = new HashMap<String, Plan>(1); 63 private ReservationSystem rSystem; 64 private Plan plan; 65 66 private ReservationInputValidator rrValidator; 67 68 @Before setUp()69 public void setUp() { 70 clock = mock(Clock.class); 71 plan = mock(Plan.class); 72 rSystem = mock(ReservationSystem.class); 73 plans.put(PLAN_NAME, plan); 74 rrValidator = new ReservationInputValidator(clock); 75 when(clock.getTime()).thenReturn(1L); 76 ResourceCalculator rCalc = new DefaultResourceCalculator(); 77 Resource resource = Resource.newInstance(10240, 10); 78 when(plan.getResourceCalculator()).thenReturn(rCalc); 79 when(plan.getTotalCapacity()).thenReturn(resource); 80 when(rSystem.getQueueForReservation(any(ReservationId.class))).thenReturn( 81 PLAN_NAME); 82 when(rSystem.getPlan(PLAN_NAME)).thenReturn(plan); 83 } 84 85 @After tearDown()86 public void tearDown() { 87 rrValidator = null; 88 clock = null; 89 plan = null; 90 } 91 92 @Test testSubmitReservationNormal()93 public void testSubmitReservationNormal() { 94 ReservationSubmissionRequest request = 95 createSimpleReservationSubmissionRequest(1, 1, 1, 5, 3); 96 Plan plan = null; 97 try { 98 plan = 99 rrValidator.validateReservationSubmissionRequest(rSystem, request, 100 ReservationSystemTestUtil.getNewReservationId()); 101 } catch (YarnException e) { 102 Assert.fail(e.getMessage()); 103 } 104 Assert.assertNotNull(plan); 105 } 106 107 @Test testSubmitReservationDoesnotExist()108 public void testSubmitReservationDoesnotExist() { 109 ReservationSubmissionRequest request = 110 new ReservationSubmissionRequestPBImpl(); 111 Plan plan = null; 112 try { 113 plan = 114 rrValidator.validateReservationSubmissionRequest(rSystem, request, 115 ReservationSystemTestUtil.getNewReservationId()); 116 Assert.fail(); 117 } catch (YarnException e) { 118 Assert.assertNull(plan); 119 String message = e.getMessage(); 120 Assert 121 .assertTrue(message 122 .equals("The queue to submit is not specified. Please try again with a valid reservable queue.")); 123 LOG.info(message); 124 } 125 } 126 127 @Test testSubmitReservationInvalidPlan()128 public void testSubmitReservationInvalidPlan() { 129 ReservationSubmissionRequest request = 130 createSimpleReservationSubmissionRequest(1, 1, 1, 5, 3); 131 when(rSystem.getPlan(PLAN_NAME)).thenReturn(null); 132 Plan plan = null; 133 try { 134 plan = 135 rrValidator.validateReservationSubmissionRequest(rSystem, request, 136 ReservationSystemTestUtil.getNewReservationId()); 137 Assert.fail(); 138 } catch (YarnException e) { 139 Assert.assertNull(plan); 140 String message = e.getMessage(); 141 Assert 142 .assertTrue(message 143 .endsWith(" is not managed by reservation system. Please try again with a valid reservable queue.")); 144 LOG.info(message); 145 } 146 } 147 148 @Test testSubmitReservationNoDefinition()149 public void testSubmitReservationNoDefinition() { 150 ReservationSubmissionRequest request = 151 new ReservationSubmissionRequestPBImpl(); 152 request.setQueue(PLAN_NAME); 153 Plan plan = null; 154 try { 155 plan = 156 rrValidator.validateReservationSubmissionRequest(rSystem, request, 157 ReservationSystemTestUtil.getNewReservationId()); 158 Assert.fail(); 159 } catch (YarnException e) { 160 Assert.assertNull(plan); 161 String message = e.getMessage(); 162 Assert 163 .assertTrue(message 164 .equals("Missing reservation definition. Please try again by specifying a reservation definition.")); 165 LOG.info(message); 166 } 167 } 168 169 @Test testSubmitReservationInvalidDeadline()170 public void testSubmitReservationInvalidDeadline() { 171 ReservationSubmissionRequest request = 172 createSimpleReservationSubmissionRequest(1, 1, 1, 0, 3); 173 Plan plan = null; 174 try { 175 plan = 176 rrValidator.validateReservationSubmissionRequest(rSystem, request, 177 ReservationSystemTestUtil.getNewReservationId()); 178 Assert.fail(); 179 } catch (YarnException e) { 180 Assert.assertNull(plan); 181 String message = e.getMessage(); 182 Assert.assertTrue(message 183 .startsWith("The specified deadline: 0 is the past")); 184 LOG.info(message); 185 } 186 } 187 188 @Test testSubmitReservationInvalidRR()189 public void testSubmitReservationInvalidRR() { 190 ReservationSubmissionRequest request = 191 createSimpleReservationSubmissionRequest(0, 0, 1, 5, 3); 192 Plan plan = null; 193 try { 194 plan = 195 rrValidator.validateReservationSubmissionRequest(rSystem, request, 196 ReservationSystemTestUtil.getNewReservationId()); 197 Assert.fail(); 198 } catch (YarnException e) { 199 Assert.assertNull(plan); 200 String message = e.getMessage(); 201 Assert.assertTrue(message 202 .startsWith("No resources have been specified to reserve")); 203 LOG.info(message); 204 } 205 } 206 207 @Test testSubmitReservationEmptyRR()208 public void testSubmitReservationEmptyRR() { 209 ReservationSubmissionRequest request = 210 createSimpleReservationSubmissionRequest(1, 0, 1, 5, 3); 211 Plan plan = null; 212 try { 213 plan = 214 rrValidator.validateReservationSubmissionRequest(rSystem, request, 215 ReservationSystemTestUtil.getNewReservationId()); 216 Assert.fail(); 217 } catch (YarnException e) { 218 Assert.assertNull(plan); 219 String message = e.getMessage(); 220 Assert.assertTrue(message 221 .startsWith("No resources have been specified to reserve")); 222 LOG.info(message); 223 } 224 } 225 226 @Test testSubmitReservationInvalidDuration()227 public void testSubmitReservationInvalidDuration() { 228 ReservationSubmissionRequest request = 229 createSimpleReservationSubmissionRequest(1, 1, 1, 3, 4); 230 Plan plan = null; 231 try { 232 plan = 233 rrValidator.validateReservationSubmissionRequest(rSystem, request, 234 ReservationSystemTestUtil.getNewReservationId()); 235 Assert.fail(); 236 } catch (YarnException e) { 237 Assert.assertNull(plan); 238 String message = e.getMessage(); 239 Assert.assertTrue(message.startsWith("The time difference")); 240 Assert 241 .assertTrue(message 242 .contains("must be greater or equal to the minimum resource duration")); 243 LOG.info(message); 244 } 245 } 246 247 @Test testSubmitReservationExceedsGangSize()248 public void testSubmitReservationExceedsGangSize() { 249 ReservationSubmissionRequest request = 250 createSimpleReservationSubmissionRequest(1, 1, 1, 5, 4); 251 Resource resource = Resource.newInstance(512, 1); 252 when(plan.getTotalCapacity()).thenReturn(resource); 253 Plan plan = null; 254 try { 255 plan = 256 rrValidator.validateReservationSubmissionRequest(rSystem, request, 257 ReservationSystemTestUtil.getNewReservationId()); 258 Assert.fail(); 259 } catch (YarnException e) { 260 Assert.assertNull(plan); 261 String message = e.getMessage(); 262 Assert 263 .assertTrue(message 264 .startsWith("The size of the largest gang in the reservation refinition")); 265 Assert.assertTrue(message.contains("exceed the capacity available ")); 266 LOG.info(message); 267 } 268 } 269 270 @Test testUpdateReservationNormal()271 public void testUpdateReservationNormal() { 272 ReservationUpdateRequest request = 273 createSimpleReservationUpdateRequest(1, 1, 1, 5, 3); 274 Plan plan = null; 275 try { 276 plan = rrValidator.validateReservationUpdateRequest(rSystem, request); 277 } catch (YarnException e) { 278 Assert.fail(e.getMessage()); 279 } 280 Assert.assertNotNull(plan); 281 } 282 283 @Test testUpdateReservationNoID()284 public void testUpdateReservationNoID() { 285 ReservationUpdateRequest request = new ReservationUpdateRequestPBImpl(); 286 Plan plan = null; 287 try { 288 plan = rrValidator.validateReservationUpdateRequest(rSystem, request); 289 Assert.fail(); 290 } catch (YarnException e) { 291 Assert.assertNull(plan); 292 String message = e.getMessage(); 293 Assert 294 .assertTrue(message 295 .startsWith("Missing reservation id. Please try again by specifying a reservation id.")); 296 LOG.info(message); 297 } 298 } 299 300 @Test testUpdateReservationDoesnotExist()301 public void testUpdateReservationDoesnotExist() { 302 ReservationUpdateRequest request = 303 createSimpleReservationUpdateRequest(1, 1, 1, 5, 4); 304 ReservationId rId = request.getReservationId(); 305 when(rSystem.getQueueForReservation(rId)).thenReturn(null); 306 Plan plan = null; 307 try { 308 plan = rrValidator.validateReservationUpdateRequest(rSystem, request); 309 Assert.fail(); 310 } catch (YarnException e) { 311 Assert.assertNull(plan); 312 String message = e.getMessage(); 313 Assert 314 .assertTrue(message.equals(MessageFormat 315 .format( 316 "The specified reservation with ID: {0} is unknown. Please try again with a valid reservation.", 317 rId))); 318 LOG.info(message); 319 } 320 } 321 322 @Test testUpdateReservationInvalidPlan()323 public void testUpdateReservationInvalidPlan() { 324 ReservationUpdateRequest request = 325 createSimpleReservationUpdateRequest(1, 1, 1, 5, 4); 326 when(rSystem.getPlan(PLAN_NAME)).thenReturn(null); 327 Plan plan = null; 328 try { 329 plan = rrValidator.validateReservationUpdateRequest(rSystem, request); 330 Assert.fail(); 331 } catch (YarnException e) { 332 Assert.assertNull(plan); 333 String message = e.getMessage(); 334 Assert 335 .assertTrue(message 336 .endsWith(" is not associated with any valid plan. Please try again with a valid reservation.")); 337 LOG.info(message); 338 } 339 } 340 341 @Test testUpdateReservationNoDefinition()342 public void testUpdateReservationNoDefinition() { 343 ReservationUpdateRequest request = new ReservationUpdateRequestPBImpl(); 344 request.setReservationId(ReservationSystemTestUtil.getNewReservationId()); 345 Plan plan = null; 346 try { 347 plan = rrValidator.validateReservationUpdateRequest(rSystem, request); 348 Assert.fail(); 349 } catch (YarnException e) { 350 Assert.assertNull(plan); 351 String message = e.getMessage(); 352 Assert 353 .assertTrue(message 354 .startsWith("Missing reservation definition. Please try again by specifying a reservation definition.")); 355 LOG.info(message); 356 } 357 } 358 359 @Test testUpdateReservationInvalidDeadline()360 public void testUpdateReservationInvalidDeadline() { 361 ReservationUpdateRequest request = 362 createSimpleReservationUpdateRequest(1, 1, 1, 0, 3); 363 Plan plan = null; 364 try { 365 plan = rrValidator.validateReservationUpdateRequest(rSystem, request); 366 Assert.fail(); 367 } catch (YarnException e) { 368 Assert.assertNull(plan); 369 String message = e.getMessage(); 370 Assert.assertTrue(message 371 .startsWith("The specified deadline: 0 is the past")); 372 LOG.info(message); 373 } 374 } 375 376 @Test testUpdateReservationInvalidRR()377 public void testUpdateReservationInvalidRR() { 378 ReservationUpdateRequest request = 379 createSimpleReservationUpdateRequest(0, 0, 1, 5, 3); 380 Plan plan = null; 381 try { 382 plan = rrValidator.validateReservationUpdateRequest(rSystem, request); 383 Assert.fail(); 384 } catch (YarnException e) { 385 Assert.assertNull(plan); 386 String message = e.getMessage(); 387 Assert.assertTrue(message 388 .startsWith("No resources have been specified to reserve")); 389 LOG.info(message); 390 } 391 } 392 393 @Test testUpdateReservationEmptyRR()394 public void testUpdateReservationEmptyRR() { 395 ReservationUpdateRequest request = 396 createSimpleReservationUpdateRequest(1, 0, 1, 5, 3); 397 Plan plan = null; 398 try { 399 plan = rrValidator.validateReservationUpdateRequest(rSystem, request); 400 Assert.fail(); 401 } catch (YarnException e) { 402 Assert.assertNull(plan); 403 String message = e.getMessage(); 404 Assert.assertTrue(message 405 .startsWith("No resources have been specified to reserve")); 406 LOG.info(message); 407 } 408 } 409 410 @Test testUpdateReservationInvalidDuration()411 public void testUpdateReservationInvalidDuration() { 412 ReservationUpdateRequest request = 413 createSimpleReservationUpdateRequest(1, 1, 1, 3, 4); 414 Plan plan = null; 415 try { 416 plan = rrValidator.validateReservationUpdateRequest(rSystem, request); 417 Assert.fail(); 418 } catch (YarnException e) { 419 Assert.assertNull(plan); 420 String message = e.getMessage(); 421 Assert 422 .assertTrue(message 423 .contains("must be greater or equal to the minimum resource duration")); 424 LOG.info(message); 425 } 426 } 427 428 @Test testUpdateReservationExceedsGangSize()429 public void testUpdateReservationExceedsGangSize() { 430 ReservationUpdateRequest request = 431 createSimpleReservationUpdateRequest(1, 1, 1, 5, 4); 432 Resource resource = Resource.newInstance(512, 1); 433 when(plan.getTotalCapacity()).thenReturn(resource); 434 Plan plan = null; 435 try { 436 plan = rrValidator.validateReservationUpdateRequest(rSystem, request); 437 Assert.fail(); 438 } catch (YarnException e) { 439 Assert.assertNull(plan); 440 String message = e.getMessage(); 441 Assert 442 .assertTrue(message 443 .startsWith("The size of the largest gang in the reservation refinition")); 444 Assert.assertTrue(message.contains("exceed the capacity available ")); 445 LOG.info(message); 446 } 447 } 448 449 @Test testDeleteReservationNormal()450 public void testDeleteReservationNormal() { 451 ReservationDeleteRequest request = new ReservationDeleteRequestPBImpl(); 452 ReservationId reservationID = 453 ReservationSystemTestUtil.getNewReservationId(); 454 request.setReservationId(reservationID); 455 ReservationAllocation reservation = mock(ReservationAllocation.class); 456 when(plan.getReservationById(reservationID)).thenReturn(reservation); 457 Plan plan = null; 458 try { 459 plan = rrValidator.validateReservationDeleteRequest(rSystem, request); 460 } catch (YarnException e) { 461 Assert.fail(e.getMessage()); 462 } 463 Assert.assertNotNull(plan); 464 } 465 466 @Test testDeleteReservationNoID()467 public void testDeleteReservationNoID() { 468 ReservationDeleteRequest request = new ReservationDeleteRequestPBImpl(); 469 Plan plan = null; 470 try { 471 plan = rrValidator.validateReservationDeleteRequest(rSystem, request); 472 Assert.fail(); 473 } catch (YarnException e) { 474 Assert.assertNull(plan); 475 String message = e.getMessage(); 476 Assert 477 .assertTrue(message 478 .startsWith("Missing reservation id. Please try again by specifying a reservation id.")); 479 LOG.info(message); 480 } 481 } 482 483 @Test testDeleteReservationDoesnotExist()484 public void testDeleteReservationDoesnotExist() { 485 ReservationDeleteRequest request = new ReservationDeleteRequestPBImpl(); 486 ReservationId rId = ReservationSystemTestUtil.getNewReservationId(); 487 request.setReservationId(rId); 488 when(rSystem.getQueueForReservation(rId)).thenReturn(null); 489 Plan plan = null; 490 try { 491 plan = rrValidator.validateReservationDeleteRequest(rSystem, request); 492 Assert.fail(); 493 } catch (YarnException e) { 494 Assert.assertNull(plan); 495 String message = e.getMessage(); 496 Assert 497 .assertTrue(message.equals(MessageFormat 498 .format( 499 "The specified reservation with ID: {0} is unknown. Please try again with a valid reservation.", 500 rId))); 501 LOG.info(message); 502 } 503 } 504 505 @Test testDeleteReservationInvalidPlan()506 public void testDeleteReservationInvalidPlan() { 507 ReservationDeleteRequest request = new ReservationDeleteRequestPBImpl(); 508 ReservationId reservationID = 509 ReservationSystemTestUtil.getNewReservationId(); 510 request.setReservationId(reservationID); 511 when(rSystem.getPlan(PLAN_NAME)).thenReturn(null); 512 Plan plan = null; 513 try { 514 plan = rrValidator.validateReservationDeleteRequest(rSystem, request); 515 Assert.fail(); 516 } catch (YarnException e) { 517 Assert.assertNull(plan); 518 String message = e.getMessage(); 519 Assert 520 .assertTrue(message 521 .endsWith(" is not associated with any valid plan. Please try again with a valid reservation.")); 522 LOG.info(message); 523 } 524 } 525 createSimpleReservationSubmissionRequest( int numRequests, int numContainers, long arrival, long deadline, long duration)526 private ReservationSubmissionRequest createSimpleReservationSubmissionRequest( 527 int numRequests, int numContainers, long arrival, long deadline, 528 long duration) { 529 // create a request with a single atomic ask 530 ReservationSubmissionRequest request = 531 new ReservationSubmissionRequestPBImpl(); 532 ReservationDefinition rDef = new ReservationDefinitionPBImpl(); 533 rDef.setArrival(arrival); 534 rDef.setDeadline(deadline); 535 if (numRequests > 0) { 536 ReservationRequests reqs = new ReservationRequestsPBImpl(); 537 rDef.setReservationRequests(reqs); 538 if (numContainers > 0) { 539 ReservationRequest r = 540 ReservationRequest.newInstance(Resource.newInstance(1024, 1), 541 numContainers, 1, duration); 542 543 reqs.setReservationResources(Collections.singletonList(r)); 544 reqs.setInterpreter(ReservationRequestInterpreter.R_ALL); 545 } 546 } 547 request.setQueue(PLAN_NAME); 548 request.setReservationDefinition(rDef); 549 return request; 550 } 551 createSimpleReservationUpdateRequest( int numRequests, int numContainers, long arrival, long deadline, long duration)552 private ReservationUpdateRequest createSimpleReservationUpdateRequest( 553 int numRequests, int numContainers, long arrival, long deadline, 554 long duration) { 555 // create a request with a single atomic ask 556 ReservationUpdateRequest request = new ReservationUpdateRequestPBImpl(); 557 ReservationDefinition rDef = new ReservationDefinitionPBImpl(); 558 rDef.setArrival(arrival); 559 rDef.setDeadline(deadline); 560 if (numRequests > 0) { 561 ReservationRequests reqs = new ReservationRequestsPBImpl(); 562 rDef.setReservationRequests(reqs); 563 if (numContainers > 0) { 564 ReservationRequest r = 565 ReservationRequest.newInstance(Resource.newInstance(1024, 1), 566 numContainers, 1, duration); 567 568 reqs.setReservationResources(Collections.singletonList(r)); 569 reqs.setInterpreter(ReservationRequestInterpreter.R_ALL); 570 } 571 } 572 request.setReservationDefinition(rDef); 573 request.setReservationId(ReservationSystemTestUtil.getNewReservationId()); 574 return request; 575 } 576 577 } 578