|
37 | 37 | import com.cloud.vm.VMInstanceVO; |
38 | 38 | import com.cloud.vm.VirtualMachine; |
39 | 39 | import com.cloud.vm.dao.VMInstanceDao; |
| 40 | +import org.apache.cloudstack.framework.config.ConfigKey; |
| 41 | +import org.apache.cloudstack.framework.config.impl.ConfigDepotImpl; |
40 | 42 | import org.apache.cloudstack.framework.jobs.AsyncJobDispatcher; |
41 | 43 | import org.apache.cloudstack.framework.jobs.AsyncJobManager; |
42 | 44 | import org.apache.cloudstack.framework.jobs.dao.AsyncJobDao; |
@@ -374,6 +376,38 @@ public void getScopedConfigValueTestFallsBackToGlobalDefaultWhenNoScopeOverrideC |
374 | 376 | Assert.assertEquals(Integer.valueOf(3), result); |
375 | 377 | } |
376 | 378 |
|
| 379 | + private Integer getScopedMaxFailuresWith(String accountValue, String domainValue, String zoneValue) { |
| 380 | + doReturn(1L).when(volumeVoMock).getAccountId(); |
| 381 | + doReturn(3L).when(volumeVoMock).getDataCenterId(); |
| 382 | + doReturn(2L).when(accountVoMock).getDomainId(); |
| 383 | + String name = SnapshotManager.SnapshotRecurringMaxFailures.key(); |
| 384 | + ConfigDepotImpl configDepotMock = mock(ConfigDepotImpl.class); |
| 385 | + doReturn(accountValue).when(configDepotMock).getConfigStringValue(name, ConfigKey.Scope.Account, 1L); |
| 386 | + doReturn(domainValue).when(configDepotMock).getConfigStringValue(name, ConfigKey.Scope.Domain, 2L); |
| 387 | + doReturn(zoneValue).when(configDepotMock).getConfigStringValue(name, ConfigKey.Scope.Zone, 3L); |
| 388 | + ConfigKey.init(configDepotMock); |
| 389 | + try { |
| 390 | + return snapshotSchedulerImplSpy.getScopedConfigValue(SnapshotManager.SnapshotRecurringMaxFailures, volumeVoMock, accountVoMock); |
| 391 | + } finally { |
| 392 | + ConfigKey.init(null); |
| 393 | + } |
| 394 | + } |
| 395 | + |
| 396 | + @Test |
| 397 | + public void getScopedConfigValueTestZoneOverrideIsUsedWhenAccountAndDomainAreNotSet() { |
| 398 | + Assert.assertEquals(Integer.valueOf(7), getScopedMaxFailuresWith(null, null, "7")); |
| 399 | + } |
| 400 | + |
| 401 | + @Test |
| 402 | + public void getScopedConfigValueTestDomainOverrideWinsOverZone() { |
| 403 | + Assert.assertEquals(Integer.valueOf(5), getScopedMaxFailuresWith(null, "5", "7")); |
| 404 | + } |
| 405 | + |
| 406 | + @Test |
| 407 | + public void getScopedConfigValueTestAccountOverrideWinsOverDomainAndZone() { |
| 408 | + Assert.assertEquals(Integer.valueOf(1), getScopedMaxFailuresWith("1", "5", "7")); |
| 409 | + } |
| 410 | + |
377 | 411 | // --- handleFailedSnapshotDispatch (#13454) --- |
378 | 412 |
|
379 | 413 | private void stubVolumeAndAccount() { |
@@ -470,29 +504,36 @@ public void recordSnapshotAttemptOutcomeTestSucceededLogsInfoEventAndReturns() { |
470 | 504 | // --- dispatchSnapshotCreateJob (#13454) --- |
471 | 505 |
|
472 | 506 | @Test |
473 | | - public void dispatchSnapshotCreateJobTestBuildsAsyncJobAndReturnsScheduledEventId() throws Exception { |
| 507 | + public void createScheduledSnapshotEventTestReturnsScheduledEventIdForVolume() { |
| 508 | + doReturn(2L).when(volumeVoMock).getId(); |
| 509 | + doReturn(1L).when(volumeVoMock).getAccountId(); |
| 510 | + doReturn("volume-uuid").when(volumeVoMock).getUuid(); |
| 511 | + |
| 512 | + try (MockedStatic<ActionEventUtils> actionEventUtilsMocked = Mockito.mockStatic(ActionEventUtils.class)) { |
| 513 | + actionEventUtilsMocked.when(() -> ActionEventUtils.onScheduledActionEvent( |
| 514 | + Mockito.anyLong(), Mockito.anyLong(), Mockito.eq(EventTypes.EVENT_SNAPSHOT_CREATE), Mockito.anyString(), Mockito.eq(2L), Mockito.eq("Volume"), Mockito.anyBoolean(), Mockito.anyLong()) |
| 515 | + ).thenReturn(42L); |
| 516 | + |
| 517 | + Assert.assertEquals(Long.valueOf(42L), snapshotSchedulerImplSpy.createScheduledSnapshotEvent(volumeVoMock)); |
| 518 | + } |
| 519 | + } |
| 520 | + |
| 521 | + @Test |
| 522 | + public void dispatchSnapshotCreateJobTestBuildsAsyncJob() throws Exception { |
474 | 523 | doReturn(1L).when(snapshotScheduleVoMock).getId(); |
475 | 524 | doReturn(1L).when(snapshotScheduleVoMock).getPolicyId(); |
476 | 525 | doReturn(2L).when(snapshotScheduleVoMock).getVolumeId(); |
477 | 526 | doReturn(new Date()).when(snapshotScheduleVoMock).getScheduledTimestamp(); |
478 | 527 |
|
479 | 528 | doReturn(1L).when(volumeVoMock).getAccountId(); |
480 | | - doReturn("volume-uuid").when(volumeVoMock).getUuid(); |
481 | 529 |
|
482 | 530 | doReturn(Collections.emptyList()).when(taggedResourceServiceMock).listByResourceTypeAndId(Mockito.any(), Mockito.anyLong()); |
483 | 531 | doReturn(7L).when(asyncJobManagerMock).submitAsyncJob(Mockito.any(AsyncJobVO.class)); |
484 | 532 | doReturn("SnapshotDispatcher").when(asyncJobDispatcherMock).getName(); |
485 | 533 | snapshotSchedulerImplSpy.setAsyncJobDispatcher(asyncJobDispatcherMock); |
486 | 534 |
|
487 | | - try (MockedStatic<ActionEventUtils> actionEventUtilsMocked = Mockito.mockStatic(ActionEventUtils.class); |
488 | | - MockedStatic<com.cloud.utils.component.ComponentContext> componentContextMocked = Mockito.mockStatic(com.cloud.utils.component.ComponentContext.class)) { |
489 | | - actionEventUtilsMocked.when(() -> ActionEventUtils.onScheduledActionEvent( |
490 | | - Mockito.anyLong(), Mockito.anyLong(), Mockito.anyString(), Mockito.anyString(), Mockito.anyLong(), Mockito.anyString(), Mockito.anyBoolean(), Mockito.anyLong()) |
491 | | - ).thenReturn(42L); |
492 | | - |
493 | | - Long eventId = snapshotSchedulerImplSpy.dispatchSnapshotCreateJob(snapshotScheduleVoMock, volumeVoMock, snapshotScheduleVoMock); |
494 | | - |
495 | | - Assert.assertEquals(Long.valueOf(42L), eventId); |
| 535 | + try (MockedStatic<com.cloud.utils.component.ComponentContext> componentContextMocked = Mockito.mockStatic(com.cloud.utils.component.ComponentContext.class)) { |
| 536 | + snapshotSchedulerImplSpy.dispatchSnapshotCreateJob(snapshotScheduleVoMock, volumeVoMock, snapshotScheduleVoMock, 42L); |
496 | 537 | } |
497 | 538 |
|
498 | 539 | verify(snapshotScheduleVoMock).setAsyncJobId(7L); |
@@ -544,23 +585,24 @@ public void scheduleSnapshotsTestSkippedScheduleIsNeverLockedOrDispatched() thro |
544 | 585 | snapshotSchedulerImplSpy.scheduleSnapshots(); |
545 | 586 |
|
546 | 587 | verify(snapshotScheduleDaoMock, never()).acquireInLockTable(Mockito.anyLong()); |
547 | | - verify(snapshotSchedulerImplSpy, never()).dispatchSnapshotCreateJob(Mockito.any(), Mockito.any(), Mockito.any()); |
| 588 | + verify(snapshotSchedulerImplSpy, never()).dispatchSnapshotCreateJob(Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any()); |
548 | 589 | } |
549 | 590 |
|
550 | 591 | @Test |
551 | | - public void scheduleSnapshotsTestDispatchFailureIsHandledAndLockIsReleased() throws Exception { |
| 592 | + public void scheduleSnapshotsTestDispatchFailureCompletesScheduledEventAndLockIsReleased() throws Exception { |
552 | 593 | ReflectionTestUtils.setField(snapshotSchedulerImplSpy, "_currentTimestamp", new Date()); |
553 | 594 | doReturn(1L).when(snapshotScheduleVoMock).getId(); |
554 | 595 | doReturn(List.of(snapshotScheduleVoMock)).when(snapshotScheduleDaoMock).getSchedulesToExecute(Mockito.any(Date.class)); |
555 | 596 | doReturn(volumeVoMock).when(volumeDaoMock).findByIdIncludingRemoved(Mockito.anyLong()); |
556 | 597 | doReturn(false).when(snapshotSchedulerImplSpy).shouldSkipSchedule(Mockito.any(), Mockito.any()); |
557 | 598 | doReturn(snapshotScheduleVoMock).when(snapshotScheduleDaoMock).acquireInLockTable(1L); |
558 | | - doThrow(new RuntimeException("dispatch boom")).when(snapshotSchedulerImplSpy).dispatchSnapshotCreateJob(Mockito.any(), Mockito.any(), Mockito.any()); |
| 599 | + doReturn(42L).when(snapshotSchedulerImplSpy).createScheduledSnapshotEvent(volumeVoMock); |
| 600 | + doThrow(new RuntimeException("dispatch boom")).when(snapshotSchedulerImplSpy).dispatchSnapshotCreateJob(Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any()); |
559 | 601 | doNothing().when(snapshotSchedulerImplSpy).handleFailedSnapshotDispatch(Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any()); |
560 | 602 |
|
561 | 603 | snapshotSchedulerImplSpy.scheduleSnapshots(); |
562 | 604 |
|
563 | | - verify(snapshotSchedulerImplSpy).handleFailedSnapshotDispatch(Mockito.eq(snapshotScheduleVoMock), Mockito.eq(volumeVoMock), Mockito.eq(snapshotScheduleVoMock), Mockito.isNull(), Mockito.any(Exception.class)); |
| 605 | + verify(snapshotSchedulerImplSpy).handleFailedSnapshotDispatch(Mockito.eq(snapshotScheduleVoMock), Mockito.eq(volumeVoMock), Mockito.eq(snapshotScheduleVoMock), Mockito.eq(42L), Mockito.any(Exception.class)); |
564 | 606 | verify(snapshotScheduleDaoMock).releaseFromLockTable(1L); |
565 | 607 | } |
566 | 608 |
|
|
0 commit comments