From d426047b9435e4b7b975c5a8c8e66ab78aaec0f0 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Tue, 18 Nov 2025 18:42:12 +0530 Subject: [PATCH 1/4] engine-schema: fix systemvm template upgrade for missing or unused hypervisor type Fixes #12077 Signed-off-by: Abhishek Kumar --- .../java/com/cloud/dc/dao/ClusterDao.java | 3 -- .../java/com/cloud/dc/dao/ClusterDaoImpl.java | 17 -------- .../upgrade/SystemVmTemplateRegistration.java | 32 ++++++++++----- .../com/cloud/dc/dao/ClusterDaoImplTest.java | 40 ------------------- .../SystemVmTemplateRegistrationTest.java | 13 +++--- .../com/cloud/storage/StorageManagerImpl.java | 2 +- 6 files changed, 30 insertions(+), 77 deletions(-) diff --git a/engine/schema/src/main/java/com/cloud/dc/dao/ClusterDao.java b/engine/schema/src/main/java/com/cloud/dc/dao/ClusterDao.java index 69b5f0e146e8..46b9b930bc1f 100644 --- a/engine/schema/src/main/java/com/cloud/dc/dao/ClusterDao.java +++ b/engine/schema/src/main/java/com/cloud/dc/dao/ClusterDao.java @@ -22,7 +22,6 @@ import com.cloud.cpu.CPU; import com.cloud.dc.ClusterVO; import com.cloud.hypervisor.Hypervisor.HypervisorType; -import com.cloud.utils.Pair; import com.cloud.utils.db.GenericDao; public interface ClusterDao extends GenericDao { @@ -34,8 +33,6 @@ public interface ClusterDao extends GenericDao { List getAvailableHypervisorInZone(Long zoneId); - List> listDistinctHypervisorsArchAcrossClusters(Long zoneId); - List listByDcHyType(long dcId, String hyType); Map> getPodClusterIdMap(List clusterIds); diff --git a/engine/schema/src/main/java/com/cloud/dc/dao/ClusterDaoImpl.java b/engine/schema/src/main/java/com/cloud/dc/dao/ClusterDaoImpl.java index 59614b547456..ce06b58dd283 100644 --- a/engine/schema/src/main/java/com/cloud/dc/dao/ClusterDaoImpl.java +++ b/engine/schema/src/main/java/com/cloud/dc/dao/ClusterDaoImpl.java @@ -37,7 +37,6 @@ import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.org.Grouping; import com.cloud.org.Managed; -import com.cloud.utils.Pair; import com.cloud.utils.db.GenericDaoBase; import com.cloud.utils.db.GenericSearchBuilder; import com.cloud.utils.db.JoinBuilder; @@ -168,22 +167,6 @@ public List getAvailableHypervisorInZone(Long zoneId) { .collect(Collectors.toList()); } - @Override - public List> listDistinctHypervisorsArchAcrossClusters(Long zoneId) { - SearchBuilder sb = createSearchBuilder(); - sb.select(null, Func.DISTINCT_PAIR, sb.entity().getHypervisorType(), sb.entity().getArch()); - sb.and("zoneId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ); - sb.done(); - SearchCriteria sc = sb.create(); - if (zoneId != null) { - sc.setParameters("zoneId", zoneId); - } - final List clusters = search(sc, null); - return clusters.stream() - .map(c -> new Pair<>(c.getHypervisorType(), c.getArch())) - .collect(Collectors.toList()); - } - @Override public Map> getPodClusterIdMap(List clusterIds) { TransactionLegacy txn = TransactionLegacy.currentTxn(); diff --git a/engine/schema/src/main/java/com/cloud/upgrade/SystemVmTemplateRegistration.java b/engine/schema/src/main/java/com/cloud/upgrade/SystemVmTemplateRegistration.java index 26b033c8d790..9ffb349bd0a9 100644 --- a/engine/schema/src/main/java/com/cloud/upgrade/SystemVmTemplateRegistration.java +++ b/engine/schema/src/main/java/com/cloud/upgrade/SystemVmTemplateRegistration.java @@ -58,10 +58,9 @@ import com.cloud.cpu.CPU; import com.cloud.dc.DataCenterVO; -import com.cloud.dc.dao.ClusterDao; -import com.cloud.dc.dao.ClusterDaoImpl; import com.cloud.dc.dao.DataCenterDao; import com.cloud.dc.dao.DataCenterDaoImpl; +import com.cloud.host.dao.HostDao; import com.cloud.hypervisor.Hypervisor; import com.cloud.storage.DataStoreRole; import com.cloud.storage.GuestOSVO; @@ -108,9 +107,16 @@ public class SystemVmTemplateRegistration { private static Integer LINUX_12_ID = 363; private static final Integer SCRIPT_TIMEOUT = 1800000; private static final Integer LOCK_WAIT_TIMEOUT = 1200; - protected static final List DOWNLOADABLE_TEMPLATE_ARCH_TYPES = Arrays.asList( - CPU.CPUArch.arm64 - ); + protected static final List> BUNDLED_TEMPLATE_HYPERVISOR_ARCH_TYPES = + Arrays.asList( + new Pair<>(Hypervisor.HypervisorType.KVM, CPU.CPUArch.amd64), + new Pair<>(Hypervisor.HypervisorType.VMware, CPU.CPUArch.amd64), + new Pair<>(Hypervisor.HypervisorType.XenServer, CPU.CPUArch.amd64) + ); + protected static final List> DOWNLOADABLE_TEMPLATE_HYPERVISOR_ARCH_TYPES = + Arrays.asList( + new Pair<>(Hypervisor.HypervisorType.KVM, CPU.CPUArch.arm64) + ); public static String CS_MAJOR_VERSION = null; public static String CS_TINY_VERSION = null; @@ -130,7 +136,7 @@ public class SystemVmTemplateRegistration { @Inject ImageStoreDetailsDao imageStoreDetailsDao; @Inject - ClusterDao clusterDao; + HostDao hostDao; @Inject ConfigurationDao configurationDao; @Inject @@ -148,7 +154,6 @@ public SystemVmTemplateRegistration() { vmInstanceDao = new VMInstanceDaoImpl(); imageStoreDao = new ImageStoreDaoImpl(); imageStoreDetailsDao = new ImageStoreDetailsDaoImpl(); - clusterDao = new ClusterDaoImpl(); configurationDao = new ConfigurationDaoImpl(); guestOSDao = new GuestOSDaoImpl(); tempDownloadDir = new File(System.getProperty("java.io.tmpdir")); @@ -857,7 +862,9 @@ protected File getTemplateFile(MetadataTemplateDetails templateDetails) { return templateFile; } LOGGER.debug("{} is not present", templateFile.getAbsolutePath()); - if (DOWNLOADABLE_TEMPLATE_ARCH_TYPES.contains(templateDetails.getArch()) && + Pair templateHypervisorAndArch = + new Pair<>(templateDetails.getHypervisorType(), templateDetails.getArch()); + if (DOWNLOADABLE_TEMPLATE_HYPERVISOR_ARCH_TYPES.contains(templateHypervisorAndArch) && StringUtils.isNotBlank(templateDetails.getUrl())) { LOGGER.debug("Downloading the template file {} for {}", templateDetails.getUrl(), templateDetails.getHypervisorArchLog()); @@ -900,6 +907,11 @@ protected void validateTemplates(List> hypervisorArchList = - clusterDao.listDistinctHypervisorsArchAcrossClusters(zoneId); + hostDao.listDistinctHypervisorArchTypes(zoneId); for (Pair hypervisorArch : hypervisorArchList) { Hypervisor.HypervisorType hypervisorType = hypervisorArch.first(); MetadataTemplateDetails templateDetails = getMetadataTemplateDetails(hypervisorType, @@ -1065,7 +1077,7 @@ public void updateSystemVmTemplates(final Connection conn) { public void doInTransactionWithoutResult(final TransactionStatus status) { List> hypervisorsInUse; try { - hypervisorsInUse = clusterDao.listDistinctHypervisorsArchAcrossClusters(null); + hypervisorsInUse = hostDao.listDistinctHypervisorArchTypes(null); } catch (final Exception e) { throw new CloudRuntimeException("Exception while getting hypervisor types from clusters", e); } diff --git a/engine/schema/src/test/java/com/cloud/dc/dao/ClusterDaoImplTest.java b/engine/schema/src/test/java/com/cloud/dc/dao/ClusterDaoImplTest.java index f8673fa9c9fd..a513809be057 100644 --- a/engine/schema/src/test/java/com/cloud/dc/dao/ClusterDaoImplTest.java +++ b/engine/schema/src/test/java/com/cloud/dc/dao/ClusterDaoImplTest.java @@ -17,7 +17,6 @@ package com.cloud.dc.dao; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.any; import static org.mockito.Mockito.doReturn; @@ -37,13 +36,9 @@ import org.mockito.Spy; import org.mockito.junit.MockitoJUnitRunner; -import com.cloud.cpu.CPU; import com.cloud.dc.ClusterVO; -import com.cloud.hypervisor.Hypervisor; -import com.cloud.utils.Pair; import com.cloud.utils.db.GenericSearchBuilder; import com.cloud.utils.db.SearchBuilder; -import com.cloud.utils.db.SearchCriteria; @RunWith(MockitoJUnitRunner.class) public class ClusterDaoImplTest { @@ -80,39 +75,4 @@ public void testListAllIdsEmptyResult() { verify(clusterDao).customSearch(genericSearchBuilder.create(), null); assertTrue(result.isEmpty()); } - - @Test - public void listDistinctHypervisorsArchAcrossClusters_WithZone() { - Long zoneId = 123L; - ClusterVO cluster1 = mock(ClusterVO.class); - when(cluster1.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.XenServer); - when(cluster1.getArch()).thenReturn(CPU.CPUArch.amd64); - ClusterVO cluster2 = mock(ClusterVO.class); - when(cluster2.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.KVM); - when(cluster2.getArch()).thenReturn(CPU.CPUArch.arm64); - List dummyHosts = Arrays.asList(cluster1, cluster2); - doReturn(dummyHosts).when(clusterDao).search(any(SearchCriteria.class), isNull()); - List> result = clusterDao.listDistinctHypervisorsArchAcrossClusters(zoneId); - assertNotNull(result); - assertEquals(2, result.size()); - assertEquals(Hypervisor.HypervisorType.XenServer, result.get(0).first()); - assertEquals(CPU.CPUArch.amd64, result.get(0).second()); - assertEquals(Hypervisor.HypervisorType.KVM, result.get(1).first()); - assertEquals(CPU.CPUArch.arm64, result.get(1).second()); - } - - @Test - public void listDistinctHypervisorsArchAcrossClusters_WithoutZone() { - Long zoneId = null; - ClusterVO cluster = mock(ClusterVO.class); - when(cluster.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.VMware); - when(cluster.getArch()).thenReturn(CPU.CPUArch.amd64); - List dummyHosts = Collections.singletonList(cluster); - doReturn(dummyHosts).when(clusterDao).search(any(SearchCriteria.class), isNull()); - List> result = clusterDao.listDistinctHypervisorsArchAcrossClusters(zoneId); - assertNotNull(result); - assertEquals(1, result.size()); - assertEquals(Hypervisor.HypervisorType.VMware, result.get(0).first()); - assertEquals(CPU.CPUArch.amd64, result.get(0).second()); - } } diff --git a/engine/schema/src/test/java/com/cloud/upgrade/SystemVmTemplateRegistrationTest.java b/engine/schema/src/test/java/com/cloud/upgrade/SystemVmTemplateRegistrationTest.java index 6573a5565f30..9b6e3b3b64e9 100644 --- a/engine/schema/src/test/java/com/cloud/upgrade/SystemVmTemplateRegistrationTest.java +++ b/engine/schema/src/test/java/com/cloud/upgrade/SystemVmTemplateRegistrationTest.java @@ -53,7 +53,7 @@ import org.mockito.junit.MockitoJUnitRunner; import com.cloud.cpu.CPU; -import com.cloud.dc.dao.ClusterDao; +import com.cloud.host.dao.HostDao; import com.cloud.hypervisor.Hypervisor; import com.cloud.storage.VMTemplateVO; import com.cloud.storage.dao.VMTemplateDao; @@ -67,7 +67,7 @@ public class SystemVmTemplateRegistrationTest { @Mock - ClusterDao clusterDao; + HostDao hostDao; @Mock VMTemplateDao vmTemplateDao; @@ -363,14 +363,15 @@ public void testValidateTemplates_fileFailure() { systemVmTemplateRegistration.validateTemplates(list); } + @Test public void testValidateTemplates_downloadableFileNotFound() { - CPU.CPUArch arch = SystemVmTemplateRegistration.DOWNLOADABLE_TEMPLATE_ARCH_TYPES.get(0); + Pair hypervisorTypeCPUArchPair = SystemVmTemplateRegistration.DOWNLOADABLE_TEMPLATE_HYPERVISOR_ARCH_TYPES.get(0); List> list = new ArrayList<>(); - list.add(new Pair<>(Hypervisor.HypervisorType.KVM, arch)); + list.add(hypervisorTypeCPUArchPair); SystemVmTemplateRegistration.MetadataTemplateDetails details = Mockito.mock(SystemVmTemplateRegistration.MetadataTemplateDetails.class); SystemVmTemplateRegistration.NewTemplateMap.put(SystemVmTemplateRegistration.getHypervisorArchKey( - Hypervisor.HypervisorType.KVM, arch), details); + hypervisorTypeCPUArchPair.first(), hypervisorTypeCPUArchPair.second()), details); doReturn(null).when(systemVmTemplateRegistration).getTemplateFile(details); systemVmTemplateRegistration.validateTemplates(list); } @@ -404,7 +405,7 @@ public void testRegisterTemplatesForZone() { Hypervisor.HypervisorType hypervisorType = Hypervisor.HypervisorType.KVM; CPU.CPUArch arch = CPU.CPUArch.getDefault(); hypervisorArchList.add(new Pair<>(hypervisorType, arch)); - doReturn(hypervisorArchList).when(clusterDao).listDistinctHypervisorsArchAcrossClusters(zoneId); + doReturn(hypervisorArchList).when(hostDao).listDistinctHypervisorArchTypes(zoneId); SystemVmTemplateRegistration.MetadataTemplateDetails details = Mockito.mock(SystemVmTemplateRegistration.MetadataTemplateDetails.class); String name = "existing"; diff --git a/server/src/main/java/com/cloud/storage/StorageManagerImpl.java b/server/src/main/java/com/cloud/storage/StorageManagerImpl.java index 5a66ad502f24..060d05b9c9db 100644 --- a/server/src/main/java/com/cloud/storage/StorageManagerImpl.java +++ b/server/src/main/java/com/cloud/storage/StorageManagerImpl.java @@ -3646,7 +3646,7 @@ public void doInTransactionWithoutResult(final TransactionStatus status) { DataStoreRole.Image, store.getId()); if (CollectionUtils.isEmpty(stores)) { List> hypervisorTypes = - _clusterDao.listDistinctHypervisorsArchAcrossClusters(zoneId); + _hostDao.listDistinctHypervisorArchTypes(zoneId); TransactionLegacy txn = TransactionLegacy.open("AutomaticTemplateRegister"); SystemVmTemplateRegistration systemVmTemplateRegistration = new SystemVmTemplateRegistration(); String filePath = null; From c8159dc928ec5f56e07441e4e22b8896f2b6beb1 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Mon, 24 Nov 2025 11:54:35 +0530 Subject: [PATCH 2/4] fix Signed-off-by: Abhishek Kumar --- .../java/com/cloud/upgrade/SystemVmTemplateRegistration.java | 4 +++- .../src/main/java/com/cloud/storage/StorageManagerImpl.java | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/engine/schema/src/main/java/com/cloud/upgrade/SystemVmTemplateRegistration.java b/engine/schema/src/main/java/com/cloud/upgrade/SystemVmTemplateRegistration.java index 9ffb349bd0a9..4b985a872e26 100644 --- a/engine/schema/src/main/java/com/cloud/upgrade/SystemVmTemplateRegistration.java +++ b/engine/schema/src/main/java/com/cloud/upgrade/SystemVmTemplateRegistration.java @@ -61,6 +61,7 @@ import com.cloud.dc.dao.DataCenterDao; import com.cloud.dc.dao.DataCenterDaoImpl; import com.cloud.host.dao.HostDao; +import com.cloud.host.dao.HostDaoImpl; import com.cloud.hypervisor.Hypervisor; import com.cloud.storage.DataStoreRole; import com.cloud.storage.GuestOSVO; @@ -156,6 +157,7 @@ public SystemVmTemplateRegistration() { imageStoreDetailsDao = new ImageStoreDetailsDaoImpl(); configurationDao = new ConfigurationDaoImpl(); guestOSDao = new GuestOSDaoImpl(); + hostDao = new HostDaoImpl(); tempDownloadDir = new File(System.getProperty("java.io.tmpdir")); } @@ -1079,7 +1081,7 @@ public void doInTransactionWithoutResult(final TransactionStatus status) { try { hypervisorsInUse = hostDao.listDistinctHypervisorArchTypes(null); } catch (final Exception e) { - throw new CloudRuntimeException("Exception while getting hypervisor types from clusters", e); + throw new CloudRuntimeException("Exception while getting hypervisor types from hosts", e); } Collection templateEntries = NewTemplateMap.values(); for (MetadataTemplateDetails templateDetails : templateEntries) { diff --git a/server/src/main/java/com/cloud/storage/StorageManagerImpl.java b/server/src/main/java/com/cloud/storage/StorageManagerImpl.java index 060d05b9c9db..c14f133e82a9 100644 --- a/server/src/main/java/com/cloud/storage/StorageManagerImpl.java +++ b/server/src/main/java/com/cloud/storage/StorageManagerImpl.java @@ -3669,7 +3669,7 @@ public void doInTransactionWithoutResult(final TransactionStatus status) { } } } catch (Exception e) { - logger.error("Failed to register systemVM template(s)"); + logger.error("Failed to register systemVM template(s)", e); } finally { SystemVmTemplateRegistration.unmountStore(filePath); txn.close(); From 2a5768d9420c3ff9d8c1525a107e49fbdd6268e8 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Fri, 6 Feb 2026 15:07:04 +0530 Subject: [PATCH 3/4] changes Signed-off-by: Abhishek Kumar --- .../java/com/cloud/dc/dao/ClusterDao.java | 3 ++ .../java/com/cloud/dc/dao/ClusterDaoImpl.java | 17 ++++++++ .../upgrade/SystemVmTemplateRegistration.java | 39 +++++++++--------- .../com/cloud/dc/dao/ClusterDaoImplTest.java | 40 +++++++++++++++++++ .../SystemVmTemplateRegistrationTest.java | 5 ++- 5 files changed, 84 insertions(+), 20 deletions(-) diff --git a/engine/schema/src/main/java/com/cloud/dc/dao/ClusterDao.java b/engine/schema/src/main/java/com/cloud/dc/dao/ClusterDao.java index 46b9b930bc1f..69b5f0e146e8 100644 --- a/engine/schema/src/main/java/com/cloud/dc/dao/ClusterDao.java +++ b/engine/schema/src/main/java/com/cloud/dc/dao/ClusterDao.java @@ -22,6 +22,7 @@ import com.cloud.cpu.CPU; import com.cloud.dc.ClusterVO; import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.utils.Pair; import com.cloud.utils.db.GenericDao; public interface ClusterDao extends GenericDao { @@ -33,6 +34,8 @@ public interface ClusterDao extends GenericDao { List getAvailableHypervisorInZone(Long zoneId); + List> listDistinctHypervisorsArchAcrossClusters(Long zoneId); + List listByDcHyType(long dcId, String hyType); Map> getPodClusterIdMap(List clusterIds); diff --git a/engine/schema/src/main/java/com/cloud/dc/dao/ClusterDaoImpl.java b/engine/schema/src/main/java/com/cloud/dc/dao/ClusterDaoImpl.java index ce06b58dd283..59614b547456 100644 --- a/engine/schema/src/main/java/com/cloud/dc/dao/ClusterDaoImpl.java +++ b/engine/schema/src/main/java/com/cloud/dc/dao/ClusterDaoImpl.java @@ -37,6 +37,7 @@ import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.org.Grouping; import com.cloud.org.Managed; +import com.cloud.utils.Pair; import com.cloud.utils.db.GenericDaoBase; import com.cloud.utils.db.GenericSearchBuilder; import com.cloud.utils.db.JoinBuilder; @@ -167,6 +168,22 @@ public List getAvailableHypervisorInZone(Long zoneId) { .collect(Collectors.toList()); } + @Override + public List> listDistinctHypervisorsArchAcrossClusters(Long zoneId) { + SearchBuilder sb = createSearchBuilder(); + sb.select(null, Func.DISTINCT_PAIR, sb.entity().getHypervisorType(), sb.entity().getArch()); + sb.and("zoneId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ); + sb.done(); + SearchCriteria sc = sb.create(); + if (zoneId != null) { + sc.setParameters("zoneId", zoneId); + } + final List clusters = search(sc, null); + return clusters.stream() + .map(c -> new Pair<>(c.getHypervisorType(), c.getArch())) + .collect(Collectors.toList()); + } + @Override public Map> getPodClusterIdMap(List clusterIds) { TransactionLegacy txn = TransactionLegacy.currentTxn(); diff --git a/engine/schema/src/main/java/com/cloud/upgrade/SystemVmTemplateRegistration.java b/engine/schema/src/main/java/com/cloud/upgrade/SystemVmTemplateRegistration.java index 4b985a872e26..80e2185bd596 100644 --- a/engine/schema/src/main/java/com/cloud/upgrade/SystemVmTemplateRegistration.java +++ b/engine/schema/src/main/java/com/cloud/upgrade/SystemVmTemplateRegistration.java @@ -58,10 +58,10 @@ import com.cloud.cpu.CPU; import com.cloud.dc.DataCenterVO; +import com.cloud.dc.dao.ClusterDao; +import com.cloud.dc.dao.ClusterDaoImpl; import com.cloud.dc.dao.DataCenterDao; import com.cloud.dc.dao.DataCenterDaoImpl; -import com.cloud.host.dao.HostDao; -import com.cloud.host.dao.HostDaoImpl; import com.cloud.hypervisor.Hypervisor; import com.cloud.storage.DataStoreRole; import com.cloud.storage.GuestOSVO; @@ -108,12 +108,15 @@ public class SystemVmTemplateRegistration { private static Integer LINUX_12_ID = 363; private static final Integer SCRIPT_TIMEOUT = 1800000; private static final Integer LOCK_WAIT_TIMEOUT = 1200; - protected static final List> BUNDLED_TEMPLATE_HYPERVISOR_ARCH_TYPES = - Arrays.asList( - new Pair<>(Hypervisor.HypervisorType.KVM, CPU.CPUArch.amd64), - new Pair<>(Hypervisor.HypervisorType.VMware, CPU.CPUArch.amd64), - new Pair<>(Hypervisor.HypervisorType.XenServer, CPU.CPUArch.amd64) - ); + protected static final List> AVAILABLE_SYSTEM_TEMPLATES_HYPERVISOR_ARCH_LIST = Arrays.asList( + new Pair<>(Hypervisor.HypervisorType.KVM, CPU.CPUArch.amd64), + new Pair<>(Hypervisor.HypervisorType.KVM, CPU.CPUArch.arm64), + new Pair<>(Hypervisor.HypervisorType.VMware, CPU.CPUArch.amd64), + new Pair<>(Hypervisor.HypervisorType.XenServer, CPU.CPUArch.amd64), + new Pair<>(Hypervisor.HypervisorType.Hyperv, CPU.CPUArch.amd64), + new Pair<>(Hypervisor.HypervisorType.LXC, CPU.CPUArch.amd64), + new Pair<>(Hypervisor.HypervisorType.Ovm3, CPU.CPUArch.amd64) + ); protected static final List> DOWNLOADABLE_TEMPLATE_HYPERVISOR_ARCH_TYPES = Arrays.asList( new Pair<>(Hypervisor.HypervisorType.KVM, CPU.CPUArch.arm64) @@ -137,7 +140,7 @@ public class SystemVmTemplateRegistration { @Inject ImageStoreDetailsDao imageStoreDetailsDao; @Inject - HostDao hostDao; + ClusterDao clusterDao; @Inject ConfigurationDao configurationDao; @Inject @@ -157,7 +160,7 @@ public SystemVmTemplateRegistration() { imageStoreDetailsDao = new ImageStoreDetailsDaoImpl(); configurationDao = new ConfigurationDaoImpl(); guestOSDao = new GuestOSDaoImpl(); - hostDao = new HostDaoImpl(); + clusterDao = new ClusterDaoImpl(); tempDownloadDir = new File(System.getProperty("java.io.tmpdir")); } @@ -903,17 +906,17 @@ protected void validateTemplates(List> hypervisorArchList = - hostDao.listDistinctHypervisorArchTypes(zoneId); + clusterDao.listDistinctHypervisorsArchAcrossClusters(zoneId); for (Pair hypervisorArch : hypervisorArchList) { Hypervisor.HypervisorType hypervisorType = hypervisorArch.first(); MetadataTemplateDetails templateDetails = getMetadataTemplateDetails(hypervisorType, @@ -1079,9 +1082,9 @@ public void updateSystemVmTemplates(final Connection conn) { public void doInTransactionWithoutResult(final TransactionStatus status) { List> hypervisorsInUse; try { - hypervisorsInUse = hostDao.listDistinctHypervisorArchTypes(null); + hypervisorsInUse = clusterDao.listDistinctHypervisorsArchAcrossClusters(null); } catch (final Exception e) { - throw new CloudRuntimeException("Exception while getting hypervisor types from hosts", e); + throw new CloudRuntimeException("Exception while getting hypervisor types from clusters", e); } Collection templateEntries = NewTemplateMap.values(); for (MetadataTemplateDetails templateDetails : templateEntries) { diff --git a/engine/schema/src/test/java/com/cloud/dc/dao/ClusterDaoImplTest.java b/engine/schema/src/test/java/com/cloud/dc/dao/ClusterDaoImplTest.java index a513809be057..f8673fa9c9fd 100644 --- a/engine/schema/src/test/java/com/cloud/dc/dao/ClusterDaoImplTest.java +++ b/engine/schema/src/test/java/com/cloud/dc/dao/ClusterDaoImplTest.java @@ -17,6 +17,7 @@ package com.cloud.dc.dao; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.any; import static org.mockito.Mockito.doReturn; @@ -36,9 +37,13 @@ import org.mockito.Spy; import org.mockito.junit.MockitoJUnitRunner; +import com.cloud.cpu.CPU; import com.cloud.dc.ClusterVO; +import com.cloud.hypervisor.Hypervisor; +import com.cloud.utils.Pair; import com.cloud.utils.db.GenericSearchBuilder; import com.cloud.utils.db.SearchBuilder; +import com.cloud.utils.db.SearchCriteria; @RunWith(MockitoJUnitRunner.class) public class ClusterDaoImplTest { @@ -75,4 +80,39 @@ public void testListAllIdsEmptyResult() { verify(clusterDao).customSearch(genericSearchBuilder.create(), null); assertTrue(result.isEmpty()); } + + @Test + public void listDistinctHypervisorsArchAcrossClusters_WithZone() { + Long zoneId = 123L; + ClusterVO cluster1 = mock(ClusterVO.class); + when(cluster1.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.XenServer); + when(cluster1.getArch()).thenReturn(CPU.CPUArch.amd64); + ClusterVO cluster2 = mock(ClusterVO.class); + when(cluster2.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.KVM); + when(cluster2.getArch()).thenReturn(CPU.CPUArch.arm64); + List dummyHosts = Arrays.asList(cluster1, cluster2); + doReturn(dummyHosts).when(clusterDao).search(any(SearchCriteria.class), isNull()); + List> result = clusterDao.listDistinctHypervisorsArchAcrossClusters(zoneId); + assertNotNull(result); + assertEquals(2, result.size()); + assertEquals(Hypervisor.HypervisorType.XenServer, result.get(0).first()); + assertEquals(CPU.CPUArch.amd64, result.get(0).second()); + assertEquals(Hypervisor.HypervisorType.KVM, result.get(1).first()); + assertEquals(CPU.CPUArch.arm64, result.get(1).second()); + } + + @Test + public void listDistinctHypervisorsArchAcrossClusters_WithoutZone() { + Long zoneId = null; + ClusterVO cluster = mock(ClusterVO.class); + when(cluster.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.VMware); + when(cluster.getArch()).thenReturn(CPU.CPUArch.amd64); + List dummyHosts = Collections.singletonList(cluster); + doReturn(dummyHosts).when(clusterDao).search(any(SearchCriteria.class), isNull()); + List> result = clusterDao.listDistinctHypervisorsArchAcrossClusters(zoneId); + assertNotNull(result); + assertEquals(1, result.size()); + assertEquals(Hypervisor.HypervisorType.VMware, result.get(0).first()); + assertEquals(CPU.CPUArch.amd64, result.get(0).second()); + } } diff --git a/engine/schema/src/test/java/com/cloud/upgrade/SystemVmTemplateRegistrationTest.java b/engine/schema/src/test/java/com/cloud/upgrade/SystemVmTemplateRegistrationTest.java index 9b6e3b3b64e9..933c83da47e0 100644 --- a/engine/schema/src/test/java/com/cloud/upgrade/SystemVmTemplateRegistrationTest.java +++ b/engine/schema/src/test/java/com/cloud/upgrade/SystemVmTemplateRegistrationTest.java @@ -53,6 +53,7 @@ import org.mockito.junit.MockitoJUnitRunner; import com.cloud.cpu.CPU; +import com.cloud.dc.dao.ClusterDao; import com.cloud.host.dao.HostDao; import com.cloud.hypervisor.Hypervisor; import com.cloud.storage.VMTemplateVO; @@ -67,7 +68,7 @@ public class SystemVmTemplateRegistrationTest { @Mock - HostDao hostDao; + ClusterDao clusterDao; @Mock VMTemplateDao vmTemplateDao; @@ -405,7 +406,7 @@ public void testRegisterTemplatesForZone() { Hypervisor.HypervisorType hypervisorType = Hypervisor.HypervisorType.KVM; CPU.CPUArch arch = CPU.CPUArch.getDefault(); hypervisorArchList.add(new Pair<>(hypervisorType, arch)); - doReturn(hypervisorArchList).when(hostDao).listDistinctHypervisorArchTypes(zoneId); + doReturn(hypervisorArchList).when(clusterDao).listDistinctHypervisorsArchAcrossClusters(zoneId); SystemVmTemplateRegistration.MetadataTemplateDetails details = Mockito.mock(SystemVmTemplateRegistration.MetadataTemplateDetails.class); String name = "existing"; From 9e387f929755b9931a8b332b333296d5260d6e42 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Fri, 6 Feb 2026 15:16:06 +0530 Subject: [PATCH 4/4] fix Signed-off-by: Abhishek Kumar --- .../com/cloud/upgrade/SystemVmTemplateRegistrationTest.java | 1 - server/src/main/java/com/cloud/storage/StorageManagerImpl.java | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/engine/schema/src/test/java/com/cloud/upgrade/SystemVmTemplateRegistrationTest.java b/engine/schema/src/test/java/com/cloud/upgrade/SystemVmTemplateRegistrationTest.java index 933c83da47e0..bafba32d05e8 100644 --- a/engine/schema/src/test/java/com/cloud/upgrade/SystemVmTemplateRegistrationTest.java +++ b/engine/schema/src/test/java/com/cloud/upgrade/SystemVmTemplateRegistrationTest.java @@ -54,7 +54,6 @@ import com.cloud.cpu.CPU; import com.cloud.dc.dao.ClusterDao; -import com.cloud.host.dao.HostDao; import com.cloud.hypervisor.Hypervisor; import com.cloud.storage.VMTemplateVO; import com.cloud.storage.dao.VMTemplateDao; diff --git a/server/src/main/java/com/cloud/storage/StorageManagerImpl.java b/server/src/main/java/com/cloud/storage/StorageManagerImpl.java index c14f133e82a9..69df612db2fd 100644 --- a/server/src/main/java/com/cloud/storage/StorageManagerImpl.java +++ b/server/src/main/java/com/cloud/storage/StorageManagerImpl.java @@ -3646,7 +3646,7 @@ public void doInTransactionWithoutResult(final TransactionStatus status) { DataStoreRole.Image, store.getId()); if (CollectionUtils.isEmpty(stores)) { List> hypervisorTypes = - _hostDao.listDistinctHypervisorArchTypes(zoneId); + _clusterDao.listDistinctHypervisorsArchAcrossClusters(zoneId); TransactionLegacy txn = TransactionLegacy.open("AutomaticTemplateRegister"); SystemVmTemplateRegistration systemVmTemplateRegistration = new SystemVmTemplateRegistration(); String filePath = null;