3232import java .util .ArrayList ;
3333import java .util .Collections ;
3434import java .util .HashMap ;
35- import java .util .HashSet ;
3635import java .util .List ;
3736import java .util .Map ;
38- import java .util .Set ;
3937import java .util .concurrent .ExecutionException ;
4038
4139import org .apache .cloudstack .engine .subsystem .api .storage .DataStore ;
@@ -371,11 +369,11 @@ public void createTemplateWithinZonesTestZoneWithHeuristicRuleShouldCallValidate
371369
372370 Mockito .when (templateProfileMock .getZoneIdList ()).thenReturn (zoneIds );
373371 Mockito .doReturn (dataStoreMock ).when (_templateMgr ).verifyHeuristicRulesForZone (Mockito .any (VMTemplateVO .class ), Mockito .anyLong ());
374- Mockito .doNothing ().when (_adapter ).validateSecondaryStorageAndCreateTemplate (Mockito .any (List .class ), Mockito .any (VMTemplateVO .class ), Mockito .isNull ());
372+ Mockito .doNothing ().when (_adapter ).validateSecondaryStorageAndCreateTemplate (Mockito .any (List .class ), Mockito .any (VMTemplateVO .class ), Mockito .any ( Map . class ), Mockito . anyInt ());
375373
376374 _adapter .createTemplateWithinZones (templateProfileMock , vmTemplateVOMock );
377375
378- Mockito .verify (_adapter , Mockito .times (1 )).validateSecondaryStorageAndCreateTemplate (Mockito .any (List .class ), Mockito .any (VMTemplateVO .class ), Mockito .isNull ());
376+ Mockito .verify (_adapter , Mockito .times (1 )).validateSecondaryStorageAndCreateTemplate (Mockito .any (List .class ), Mockito .any (VMTemplateVO .class ), Mockito .any ( Map . class ), Mockito . anyInt ());
379377 }
380378
381379 @ Test (expected = CloudRuntimeException .class )
@@ -411,11 +409,8 @@ public void getImageStoresThrowsExceptionIfNotFoundTestNonEmptyImageStoreShouldN
411409 @ Test
412410 public void isZoneAndImageStoreAvailableTestZoneIdIsNullShouldReturnFalse () {
413411 DataStore dataStoreMock = Mockito .mock (DataStore .class );
414- Long zoneId = null ;
415- Set <Long > zoneSet = null ;
416- boolean isTemplatePrivate = false ;
417412
418- boolean result = _adapter .isZoneAndImageStoreAvailable (dataStoreMock , zoneId , zoneSet , isTemplatePrivate );
413+ boolean result = _adapter .isZoneAndImageStoreAvailable (dataStoreMock , null , new HashMap <>(), 0 );
419414
420415 Mockito .verify (loggerMock , Mockito .times (1 )).warn (String .format ("Zone ID is null, cannot allocate ISO/template in image store [%s]." , dataStoreMock ));
421416 Assert .assertFalse (result );
@@ -425,13 +420,10 @@ public void isZoneAndImageStoreAvailableTestZoneIdIsNullShouldReturnFalse() {
425420 public void isZoneAndImageStoreAvailableTestZoneIsNullShouldReturnFalse () {
426421 DataStore dataStoreMock = Mockito .mock (DataStore .class );
427422 Long zoneId = 1L ;
428- Set <Long > zoneSet = null ;
429- boolean isTemplatePrivate = false ;
430- DataCenterVO dataCenterVOMock = null ;
431423
432- Mockito .when (_dcDao .findById (Mockito .anyLong ())).thenReturn (dataCenterVOMock );
424+ Mockito .when (_dcDao .findById (Mockito .anyLong ())).thenReturn (null );
433425
434- boolean result = _adapter .isZoneAndImageStoreAvailable (dataStoreMock , zoneId , zoneSet , isTemplatePrivate );
426+ boolean result = _adapter .isZoneAndImageStoreAvailable (dataStoreMock , zoneId , new HashMap <>(), 0 );
435427
436428 Mockito .verify (loggerMock , Mockito .times (1 )).warn ("Unable to find zone by id [{}], so skip downloading template to its image store [{}]." ,
437429 zoneId , dataStoreMock );
@@ -442,14 +434,12 @@ public void isZoneAndImageStoreAvailableTestZoneIsNullShouldReturnFalse() {
442434 public void isZoneAndImageStoreAvailableTestZoneIsDisabledShouldReturnFalse () {
443435 DataStore dataStoreMock = Mockito .mock (DataStore .class );
444436 Long zoneId = 1L ;
445- Set <Long > zoneSet = null ;
446- boolean isTemplatePrivate = false ;
447437 DataCenterVO dataCenterVOMock = Mockito .mock (DataCenterVO .class );
448438
449439 Mockito .when (_dcDao .findById (Mockito .anyLong ())).thenReturn (dataCenterVOMock );
450440 Mockito .when (dataCenterVOMock .getAllocationState ()).thenReturn (Grouping .AllocationState .Disabled );
451441
452- boolean result = _adapter .isZoneAndImageStoreAvailable (dataStoreMock , zoneId , zoneSet , isTemplatePrivate );
442+ boolean result = _adapter .isZoneAndImageStoreAvailable (dataStoreMock , zoneId , new HashMap <>(), 0 );
453443
454444 Mockito .verify (loggerMock , Mockito .times (1 )).info ("Zone [{}] is disabled. Skip downloading template to its image store [{}]." , dataCenterVOMock , dataStoreMock );
455445 Assert .assertFalse (result );
@@ -459,76 +449,86 @@ public void isZoneAndImageStoreAvailableTestZoneIsDisabledShouldReturnFalse() {
459449 public void isZoneAndImageStoreAvailableTestImageStoreDoesNotHaveEnoughCapacityShouldReturnFalse () {
460450 DataStore dataStoreMock = Mockito .mock (DataStore .class );
461451 Long zoneId = 1L ;
462- Set <Long > zoneSet = null ;
463- boolean isTemplatePrivate = false ;
464452 DataCenterVO dataCenterVOMock = Mockito .mock (DataCenterVO .class );
465453
466454 Mockito .when (_dcDao .findById (Mockito .anyLong ())).thenReturn (dataCenterVOMock );
467455 Mockito .when (dataCenterVOMock .getAllocationState ()).thenReturn (Grouping .AllocationState .Enabled );
468456 Mockito .when (statsCollectorMock .imageStoreHasEnoughCapacity (any (DataStore .class ))).thenReturn (false );
469457
470- boolean result = _adapter .isZoneAndImageStoreAvailable (dataStoreMock , zoneId , zoneSet , isTemplatePrivate );
458+ boolean result = _adapter .isZoneAndImageStoreAvailable (dataStoreMock , zoneId , new HashMap <>(), 0 );
471459
472460 Mockito .verify (loggerMock , times (1 )).info ("Image store doesn't have enough capacity. Skip downloading template to this image store [{}]." ,
473461 dataStoreMock );
474462 Assert .assertFalse (result );
475463 }
476464
477465 @ Test
478- public void isZoneAndImageStoreAvailableTestImageStoreHasEnoughCapacityAndZoneSetIsNullShouldReturnTrue () {
466+ public void isZoneAndImageStoreAvailableTestReplicaLimitZeroShouldCopyToAllStores () {
479467 DataStore dataStoreMock = Mockito .mock (DataStore .class );
480468 Long zoneId = 1L ;
481- Set <Long > zoneSet = null ;
482- boolean isTemplatePrivate = false ;
483469 DataCenterVO dataCenterVOMock = Mockito .mock (DataCenterVO .class );
470+ Map <Long , Integer > zoneCopyCount = new HashMap <>();
471+ zoneCopyCount .put (zoneId , 999 );
484472
485473 Mockito .when (_dcDao .findById (Mockito .anyLong ())).thenReturn (dataCenterVOMock );
486474 Mockito .when (dataCenterVOMock .getAllocationState ()).thenReturn (Grouping .AllocationState .Enabled );
487475 Mockito .when (statsCollectorMock .imageStoreHasEnoughCapacity (any (DataStore .class ))).thenReturn (true );
488476
489- boolean result = _adapter .isZoneAndImageStoreAvailable (dataStoreMock , zoneId , zoneSet , isTemplatePrivate );
477+ boolean result = _adapter .isZoneAndImageStoreAvailable (dataStoreMock , zoneId , zoneCopyCount , 0 );
490478
491- Mockito .verify (loggerMock , times (1 )).info (String .format ("Zone set is null; therefore, the ISO/template should be allocated in every secondary storage " +
492- "of zone [%s]." , dataCenterVOMock ));
493479 Assert .assertTrue (result );
480+ Assert .assertEquals (1000 , (int ) zoneCopyCount .get (zoneId ));
494481 }
495482
496483 @ Test
497- public void isZoneAndImageStoreAvailableTestTemplateIsPrivateAndItIsAlreadyAllocatedToTheSameZoneShouldReturnFalse () {
484+ public void isZoneAndImageStoreAvailableTestReplicaLimitReachedShouldReturnFalse () {
498485 DataStore dataStoreMock = Mockito .mock (DataStore .class );
499486 Long zoneId = 1L ;
500- Set <Long > zoneSet = Set .of (1L );
501- boolean isTemplatePrivate = true ;
502487 DataCenterVO dataCenterVOMock = Mockito .mock (DataCenterVO .class );
488+ Map <Long , Integer > zoneCopyCount = new HashMap <>();
489+ zoneCopyCount .put (zoneId , 1 );
503490
504491 Mockito .when (_dcDao .findById (Mockito .anyLong ())).thenReturn (dataCenterVOMock );
505492 Mockito .when (dataCenterVOMock .getAllocationState ()).thenReturn (Grouping .AllocationState .Enabled );
506493 Mockito .when (statsCollectorMock .imageStoreHasEnoughCapacity (any (DataStore .class ))).thenReturn (true );
507494
508- boolean result = _adapter .isZoneAndImageStoreAvailable (dataStoreMock , zoneId , zoneSet , isTemplatePrivate );
495+ boolean result = _adapter .isZoneAndImageStoreAvailable (dataStoreMock , zoneId , zoneCopyCount , 1 );
509496
510- Mockito .verify (loggerMock , times (1 )).info (String .format ("The template is private and it is already allocated in a secondary storage in zone [%s]; " +
511- "therefore, image store [%s] will be skipped." , dataCenterVOMock , dataStoreMock ));
497+ Mockito .verify (loggerMock , times (1 )).info ("Replica limit of {} reached for zone [{}]; skipping image store [{}]." , 1 , dataCenterVOMock , dataStoreMock );
512498 Assert .assertFalse (result );
513499 }
514500
515501 @ Test
516- public void isZoneAndImageStoreAvailableTestTemplateIsPrivateAndItIsNotAlreadyAllocatedToTheSameZoneShouldReturnTrue () {
502+ public void isZoneAndImageStoreAvailableTestReplicaLimitNotYetReachedShouldReturnTrueAndIncrementCount () {
517503 DataStore dataStoreMock = Mockito .mock (DataStore .class );
518504 Long zoneId = 1L ;
519- Set <Long > zoneSet = new HashSet <>();
520- boolean isTemplatePrivate = true ;
521505 DataCenterVO dataCenterVOMock = Mockito .mock (DataCenterVO .class );
506+ Map <Long , Integer > zoneCopyCount = new HashMap <>();
522507
523508 Mockito .when (_dcDao .findById (Mockito .anyLong ())).thenReturn (dataCenterVOMock );
524509 Mockito .when (dataCenterVOMock .getAllocationState ()).thenReturn (Grouping .AllocationState .Enabled );
525510 Mockito .when (statsCollectorMock .imageStoreHasEnoughCapacity (any (DataStore .class ))).thenReturn (true );
526511
527- boolean result = _adapter .isZoneAndImageStoreAvailable (dataStoreMock , zoneId , zoneSet , isTemplatePrivate );
512+ boolean result = _adapter .isZoneAndImageStoreAvailable (dataStoreMock , zoneId , zoneCopyCount , 2 );
528513
529- Mockito .verify (loggerMock , times (1 )).info (String .format ("Private template will be allocated in image store [%s] in zone [%s]." ,
530- dataStoreMock , dataCenterVOMock ));
531514 Assert .assertTrue (result );
515+ Assert .assertEquals (1 , (int ) zoneCopyCount .get (zoneId ));
516+ }
517+
518+ @ Test
519+ public void isZoneAndImageStoreAvailableTestReplicaLimitOfTwoShouldCopyToExactlyTwoStores () {
520+ Long zoneId = 1L ;
521+ DataCenterVO dataCenterVOMock = Mockito .mock (DataCenterVO .class );
522+ Map <Long , Integer > zoneCopyCount = new HashMap <>();
523+
524+ Mockito .when (_dcDao .findById (Mockito .anyLong ())).thenReturn (dataCenterVOMock );
525+ Mockito .when (dataCenterVOMock .getAllocationState ()).thenReturn (Grouping .AllocationState .Enabled );
526+ Mockito .when (statsCollectorMock .imageStoreHasEnoughCapacity (any (DataStore .class ))).thenReturn (true );
527+
528+ Assert .assertTrue (_adapter .isZoneAndImageStoreAvailable (Mockito .mock (DataStore .class ), zoneId , zoneCopyCount , 2 ));
529+ Assert .assertTrue (_adapter .isZoneAndImageStoreAvailable (Mockito .mock (DataStore .class ), zoneId , zoneCopyCount , 2 ));
530+ Assert .assertFalse (_adapter .isZoneAndImageStoreAvailable (Mockito .mock (DataStore .class ), zoneId , zoneCopyCount , 2 ));
531+ Assert .assertEquals (2 , (int ) zoneCopyCount .get (zoneId ));
532532 }
533533
534534 @ Test
0 commit comments