diff --git a/server/src/main/java/com/cloud/template/HypervisorTemplateAdapter.java b/server/src/main/java/com/cloud/template/HypervisorTemplateAdapter.java index 1ca9ca73036..2204e5a78b0 100644 --- a/server/src/main/java/com/cloud/template/HypervisorTemplateAdapter.java +++ b/server/src/main/java/com/cloud/template/HypervisorTemplateAdapter.java @@ -177,7 +177,10 @@ public class HypervisorTemplateAdapter extends TemplateAdapterBase { return ans.getTemplateSize(); } - private void checkZoneImageStores(final List zoneIdList) { + protected void checkZoneImageStores(final VMTemplateVO template, final List zoneIdList) { + if (template.isDirectDownload()) { + return; + } if (zoneIdList != null && CollectionUtils.isEmpty(storeMgr.getImageStoresByScope(new ZoneScope(zoneIdList.get(0))))) { throw new InvalidParameterValueException("Failed to find a secondary storage in the specified zone."); } @@ -677,14 +680,14 @@ public class HypervisorTemplateAdapter extends TemplateAdapterBase { if (template.getTemplateType() == TemplateType.SYSTEM) { throw new InvalidParameterValueException("The DomR template cannot be deleted."); } - checkZoneImageStores(profile.getZoneIdList()); + checkZoneImageStores(profile.getTemplate(), profile.getZoneIdList()); return profile; } @Override public TemplateProfile prepareDelete(DeleteIsoCmd cmd) { TemplateProfile profile = super.prepareDelete(cmd); - checkZoneImageStores(profile.getZoneIdList()); + checkZoneImageStores(profile.getTemplate(), profile.getZoneIdList()); return profile; } } diff --git a/server/src/test/java/com/cloud/template/HypervisorTemplateAdapterTest.java b/server/src/test/java/com/cloud/template/HypervisorTemplateAdapterTest.java index d8ff3bc354e..c50ca655d37 100644 --- a/server/src/test/java/com/cloud/template/HypervisorTemplateAdapterTest.java +++ b/server/src/test/java/com/cloud/template/HypervisorTemplateAdapterTest.java @@ -18,6 +18,13 @@ package com.cloud.template; +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.anyLong; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; @@ -29,6 +36,7 @@ import java.util.Map; import java.util.concurrent.ExecutionException; import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; import org.apache.cloudstack.engine.subsystem.api.storage.TemplateDataFactory; import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo; import org.apache.cloudstack.engine.subsystem.api.storage.TemplateService; @@ -44,7 +52,7 @@ import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO; import org.apache.cloudstack.storage.image.datastore.ImageStoreEntity; import org.junit.Assert; import org.junit.Before; -//import org.junit.Test; +import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InjectMocks; import org.mockito.Mock; @@ -61,23 +69,17 @@ import com.cloud.event.EventTypes; import com.cloud.event.UsageEventUtils; import com.cloud.event.UsageEventVO; import com.cloud.event.dao.UsageEventDao; +import com.cloud.exception.InvalidParameterValueException; import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.TemplateProfile; import com.cloud.storage.VMTemplateStorageResourceAssoc.Status; -import com.cloud.storage.dao.VMTemplateZoneDao; import com.cloud.storage.VMTemplateVO; +import com.cloud.storage.dao.VMTemplateZoneDao; import com.cloud.user.AccountVO; import com.cloud.user.ResourceLimitService; import com.cloud.user.dao.AccountDao; import com.cloud.utils.component.ComponentContext; -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.anyLong; -import static org.mockito.Mockito.when; -import static org.mockito.Mockito.eq; -import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.mock; - @RunWith(PowerMockRunner.class) @PrepareForTest(ComponentContext.class) public class HypervisorTemplateAdapterTest { @@ -118,6 +120,9 @@ public class HypervisorTemplateAdapterTest { @Mock ConfigurationDao _configDao; + @Mock + DataStoreManager storeMgr; + @InjectMocks HypervisorTemplateAdapter _adapter; @@ -282,4 +287,27 @@ public class HypervisorTemplateAdapterTest { cleanupUsageUtils(); } + + @Test + public void testCheckZoneImageStoresDirectDownloadTemplate() { + VMTemplateVO templateVO = Mockito.mock(VMTemplateVO.class); + Mockito.when(templateVO.isDirectDownload()).thenReturn(true); + _adapter.checkZoneImageStores(templateVO, List.of(1L)); + } + + @Test + public void testCheckZoneImageStoresRegularTemplateWithStore() { + VMTemplateVO templateVO = Mockito.mock(VMTemplateVO.class); + Mockito.when(templateVO.isDirectDownload()).thenReturn(false); + Mockito.when(storeMgr.getImageStoresByScope(Mockito.any())).thenReturn(List.of(Mockito.mock(DataStore.class))); + _adapter.checkZoneImageStores(templateVO, List.of(1L)); + } + + @Test(expected = InvalidParameterValueException.class) + public void testCheckZoneImageStoresRegularTemplateNoStore() { + VMTemplateVO templateVO = Mockito.mock(VMTemplateVO.class); + Mockito.when(templateVO.isDirectDownload()).thenReturn(false); + Mockito.when(storeMgr.getImageStoresByScope(Mockito.any())).thenReturn(new ArrayList<>()); + _adapter.checkZoneImageStores(templateVO, List.of(1L)); + } }