This is an automated email from the ASF dual-hosted git repository.

sureshanaparti pushed a commit to branch 4.22
in repository https://gitbox.apache.org/repos/asf/cloudstack.git


The following commit(s) were added to refs/heads/4.22 by this push:
     new c4c9731f0c8 Fix Cross zone templates registration for Edge Zones 
(#12874)
c4c9731f0c8 is described below

commit c4c9731f0c831298339bebb6778fea6f80c77e7a
Author: Vishesh <[email protected]>
AuthorDate: Mon Oct 26 11:03:17 2026 +0530

    Fix Cross zone templates registration for Edge Zones (#12874)
---
 .../subsystem/api/storage/TemplateService.java     |  2 +-
 .../java/com/cloud/storage/dao/VMTemplateDao.java  |  2 ++
 .../com/cloud/storage/dao/VMTemplateDaoImpl.java   |  8 +++++++
 .../resources/META-INF/db/schema-42210to42220.sql  |  9 +++++++
 .../storage/image/TemplateServiceImpl.java         | 16 ++++++-------
 .../com/cloud/resource/SimulatorDiscoverer.java    | 27 +++++++--------------
 .../configuration/ConfigurationManagerImpl.java    |  9 +++++++
 .../java/com/cloud/storage/StorageManagerImpl.java | 15 ++----------
 .../cloud/storage/download/DownloadListener.java   |  2 +-
 .../configuration/ConfigurationManagerTest.java    |  3 +++
 .../resource/SecondaryStorageDiscoverer.java       | 28 +++++++---------------
 11 files changed, 60 insertions(+), 61 deletions(-)

diff --git 
a/engine/api/src/main/java/org/apache/cloudstack/engine/subsystem/api/storage/TemplateService.java
 
b/engine/api/src/main/java/org/apache/cloudstack/engine/subsystem/api/storage/TemplateService.java
index 269eb4f1c21..5a98f55d731 100644
--- 
a/engine/api/src/main/java/org/apache/cloudstack/engine/subsystem/api/storage/TemplateService.java
+++ 
b/engine/api/src/main/java/org/apache/cloudstack/engine/subsystem/api/storage/TemplateService.java
@@ -73,7 +73,7 @@ public interface TemplateService {
 
     void associateTemplateToZone(long templateId, Long zoneId);
 
-    void associateCrosszoneTemplatesToZone(long dcId);
+    void associateCrossZoneTemplatesToZone(long dcId);
 
     AsyncCallFuture<TemplateApiResult> 
createDatadiskTemplateAsync(TemplateInfo parentTemplate, TemplateInfo 
dataDiskTemplate, String path, String diskId, long fileSize, boolean bootable);
 
diff --git 
a/engine/schema/src/main/java/com/cloud/storage/dao/VMTemplateDao.java 
b/engine/schema/src/main/java/com/cloud/storage/dao/VMTemplateDao.java
index 6785c365329..71f937a1d34 100644
--- a/engine/schema/src/main/java/com/cloud/storage/dao/VMTemplateDao.java
+++ b/engine/schema/src/main/java/com/cloud/storage/dao/VMTemplateDao.java
@@ -62,6 +62,8 @@ public interface VMTemplateDao extends 
GenericDao<VMTemplateVO, Long>, StateDao<
 
     public List<VMTemplateVO> listAllActive();
 
+    List<VMTemplateVO> listAllCrossZoneTemplates();
+
     public List<VMTemplateVO> listByState(VirtualMachineTemplate.State... 
states);
 
     public List<VMTemplateVO> listByHypervisorType(List<HypervisorType> 
hyperTypes);
diff --git 
a/engine/schema/src/main/java/com/cloud/storage/dao/VMTemplateDaoImpl.java 
b/engine/schema/src/main/java/com/cloud/storage/dao/VMTemplateDaoImpl.java
index 4127ce8dc87..2247670d159 100644
--- a/engine/schema/src/main/java/com/cloud/storage/dao/VMTemplateDaoImpl.java
+++ b/engine/schema/src/main/java/com/cloud/storage/dao/VMTemplateDaoImpl.java
@@ -418,6 +418,7 @@ public class VMTemplateDaoImpl extends 
GenericDaoBase<VMTemplateVO, Long> implem
         AllFieldsSearch.and("notDestroyed", 
AllFieldsSearch.entity().getState(), SearchCriteria.Op.NEQ);
         AllFieldsSearch.and("updatedCount", 
AllFieldsSearch.entity().getUpdatedCount(), SearchCriteria.Op.EQ);
         AllFieldsSearch.and("name", AllFieldsSearch.entity().getName(), 
SearchCriteria.Op.EQ);
+        AllFieldsSearch.and("crossZone", 
AllFieldsSearch.entity().isCrossZones(), SearchCriteria.Op.EQ);
         AllFieldsSearch.done();
 
         ParentTemplateIdSearch = createSearchBuilder();
@@ -571,6 +572,13 @@ public class VMTemplateDaoImpl extends 
GenericDaoBase<VMTemplateVO, Long> implem
         return listBy(sc);
     }
 
+    @Override
+    public List<VMTemplateVO> listAllCrossZoneTemplates() {
+        SearchCriteria<VMTemplateVO> sc = AllFieldsSearch.create();
+        sc.setParameters("crossZone", true);
+        return listBy(sc);
+    }
+
     @Override
     public List<VMTemplateVO> listByState(VirtualMachineTemplate.State... 
states) {
         SearchCriteria<VMTemplateVO> sc = ActiveTmpltSearch.create();
diff --git 
a/engine/schema/src/main/resources/META-INF/db/schema-42210to42220.sql 
b/engine/schema/src/main/resources/META-INF/db/schema-42210to42220.sql
index 557c165539d..2fe476dd7bb 100644
--- a/engine/schema/src/main/resources/META-INF/db/schema-42210to42220.sql
+++ b/engine/schema/src/main/resources/META-INF/db/schema-42210to42220.sql
@@ -63,3 +63,12 @@ UPDATE `cloud`.`ip4_guest_subnet_network_map` m
 WHERE m.data_center_id IS NULL;
 
 CALL 
`cloud`.`IDEMPOTENT_ADD_FOREIGN_KEY`('cloud.ip4_guest_subnet_network_map', 
'fk_ip4_guest_subnet_network_map__data_center_id', '(`data_center_id`)', 
'`data_center`(`id`)');
+
+--- Add existing cross zone templates to the missing edge zones
+INSERT INTO cloud.template_zone_ref (zone_id, template_id, created, 
last_updated)
+SELECT dc.id, vt.id, NOW(), NOW()
+FROM cloud.data_center dc
+JOIN cloud.vm_template vt ON vt.cross_zones = 1 AND vt.removed IS NULL
+WHERE dc.type = 'Edge' AND dc.removed IS NULL
+  AND NOT EXISTS (SELECT 1 FROM cloud.template_zone_ref tzr
+                  WHERE tzr.zone_id = dc.id AND tzr.template_id = vt.id AND 
tzr.removed IS NULL);
diff --git 
a/engine/storage/image/src/main/java/org/apache/cloudstack/storage/image/TemplateServiceImpl.java
 
b/engine/storage/image/src/main/java/org/apache/cloudstack/storage/image/TemplateServiceImpl.java
index e29e89cf431..adb612762d2 100644
--- 
a/engine/storage/image/src/main/java/org/apache/cloudstack/storage/image/TemplateServiceImpl.java
+++ 
b/engine/storage/image/src/main/java/org/apache/cloudstack/storage/image/TemplateServiceImpl.java
@@ -881,17 +881,15 @@ public class TemplateServiceImpl implements 
TemplateService {
 
     // update template_zone_ref for cross-zone template for newly added zone
     @Override
-    public void associateCrosszoneTemplatesToZone(long dcId) {
+    public void associateCrossZoneTemplatesToZone(long dcId) {
         VMTemplateZoneVO tmpltZone;
 
-        List<VMTemplateVO> allTemplates = _templateDao.listAll();
-        for (VMTemplateVO vt : allTemplates) {
-            if (vt.isCrossZones()) {
-                tmpltZone = _vmTemplateZoneDao.findByZoneTemplate(dcId, 
vt.getId());
-                if (tmpltZone == null) {
-                    VMTemplateZoneVO vmTemplateZone = new 
VMTemplateZoneVO(dcId, vt.getId(), new Date());
-                    _vmTemplateZoneDao.persist(vmTemplateZone);
-                }
+        List<VMTemplateVO> crossZoneTemplates = 
_templateDao.listAllCrossZoneTemplates();
+        for (VMTemplateVO vt : crossZoneTemplates) {
+            tmpltZone = _vmTemplateZoneDao.findByZoneTemplate(dcId, 
vt.getId());
+            if (tmpltZone == null) {
+                VMTemplateZoneVO vmTemplateZone = new VMTemplateZoneVO(dcId, 
vt.getId(), new Date());
+                _vmTemplateZoneDao.persist(vmTemplateZone);
             }
         }
     }
diff --git 
a/plugins/hypervisors/simulator/src/main/java/com/cloud/resource/SimulatorDiscoverer.java
 
b/plugins/hypervisors/simulator/src/main/java/com/cloud/resource/SimulatorDiscoverer.java
index 12489334ab0..1e94e4d91b5 100644
--- 
a/plugins/hypervisors/simulator/src/main/java/com/cloud/resource/SimulatorDiscoverer.java
+++ 
b/plugins/hypervisors/simulator/src/main/java/com/cloud/resource/SimulatorDiscoverer.java
@@ -18,10 +18,11 @@ package com.cloud.resource;
 
 import java.net.URI;
 import java.net.URLDecoder;
-import java.util.Date;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.UUID;
 
 import javax.inject.Inject;
@@ -46,10 +47,9 @@ import com.cloud.host.HostVO;
 import com.cloud.host.Status;
 import com.cloud.host.dao.HostDao;
 import com.cloud.hypervisor.Hypervisor.HypervisorType;
-import com.cloud.storage.VMTemplateVO;
-import com.cloud.storage.VMTemplateZoneVO;
 import com.cloud.storage.dao.VMTemplateDao;
 import com.cloud.storage.dao.VMTemplateZoneDao;
+import org.apache.cloudstack.engine.subsystem.api.storage.TemplateService;
 
 public class SimulatorDiscoverer extends DiscovererBase implements Discoverer, 
Listener, ResourceStateAdapter {
 
@@ -64,6 +64,8 @@ public class SimulatorDiscoverer extends DiscovererBase 
implements Discoverer, L
     @Inject
     MockAgentManager _mockAgentMgr = null;
     @Inject
+    TemplateService templateService;
+    @Inject
     MockStorageManager _mockStorageMgr = null;
 
     /**
@@ -194,23 +196,12 @@ public class SimulatorDiscoverer extends DiscovererBase 
implements Discoverer, L
     @Override
     public void postDiscovery(List<HostVO> hosts, long msId) {
 
+        Set<Long> dcIds = new HashSet<>();
         for (HostVO h : hosts) {
-            associateTemplatesToZone(h.getId(), h.getDataCenterId());
+            dcIds.add(h.getDataCenterId());
         }
-    }
-
-    private void associateTemplatesToZone(long hostId, long dcId) {
-        VMTemplateZoneVO tmpltZone;
-
-        List<VMTemplateVO> allTemplates = _vmTemplateDao.listAll();
-        for (VMTemplateVO vt : allTemplates) {
-            if (vt.isCrossZones()) {
-                tmpltZone = _vmTemplateZoneDao.findByZoneTemplate(dcId, 
vt.getId());
-                if (tmpltZone == null) {
-                    VMTemplateZoneVO vmTemplateZone = new 
VMTemplateZoneVO(dcId, vt.getId(), new Date());
-                    _vmTemplateZoneDao.persist(vmTemplateZone);
-                }
-            }
+        for (Long dcId : dcIds) {
+            templateService.associateCrossZoneTemplatesToZone(dcId);
         }
     }
 
diff --git 
a/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java 
b/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java
index 986825d6416..6044b0cf040 100644
--- a/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java
+++ b/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java
@@ -98,6 +98,7 @@ import org.apache.cloudstack.config.Configuration;
 import org.apache.cloudstack.context.CallContext;
 import 
org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
 import 
org.apache.cloudstack.engine.orchestration.service.VolumeOrchestrationService;
+import org.apache.cloudstack.engine.subsystem.api.storage.TemplateService;
 import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope;
 import org.apache.cloudstack.framework.config.ConfigDepot;
 import org.apache.cloudstack.framework.config.ConfigKey;
@@ -458,6 +459,8 @@ public class ConfigurationManagerImpl extends ManagerBase 
implements Configurati
     @Inject
     StorageManager _storageManager;
     @Inject
+    TemplateService _templateService;
+    @Inject
     ImageStoreDao _imageStoreDao;
     @Inject
     ImageStoreDetailsDao _imageStoreDetailsDao;
@@ -3163,6 +3166,12 @@ public class ConfigurationManagerImpl extends 
ManagerBase implements Configurati
                 // Create default system networks
                 createDefaultSystemNetworks(zone.getId());
 
+                // Associate cross zone templates with the Edge Zones here 
because they don't have SSVMs
+                // For Core zones, this happens when the SSVM starts up.
+                if (isEdge) {
+                    
_templateService.associateCrossZoneTemplatesToZone(zone.getId());
+                }
+
                 return zone;
             }
         });
diff --git a/server/src/main/java/com/cloud/storage/StorageManagerImpl.java 
b/server/src/main/java/com/cloud/storage/StorageManagerImpl.java
index 587a5269cba..d71e5f06451 100644
--- a/server/src/main/java/com/cloud/storage/StorageManagerImpl.java
+++ b/server/src/main/java/com/cloud/storage/StorageManagerImpl.java
@@ -4257,9 +4257,6 @@ public class StorageManagerImpl extends ManagerBase 
implements StorageManager, C
     }
 
     private void associateCrosszoneTemplatesToZone(Long zoneId) {
-        VMTemplateZoneVO tmpltZone;
-
-        List<VMTemplateVO> allTemplates = _vmTemplateDao.listAll();
         List<Long> dcIds = new ArrayList<>();
         if (zoneId != null) {
             dcIds.add(zoneId);
@@ -4272,16 +4269,8 @@ public class StorageManagerImpl extends ManagerBase 
implements StorageManager, C
             }
         }
 
-        for (VMTemplateVO vt : allTemplates) {
-            if (vt.isCrossZones()) {
-                for (Long dcId : dcIds) {
-                    tmpltZone = _vmTemplateZoneDao.findByZoneTemplate(dcId, 
vt.getId());
-                    if (tmpltZone == null) {
-                        VMTemplateZoneVO vmTemplateZone = new 
VMTemplateZoneVO(dcId, vt.getId(), new Date());
-                        _vmTemplateZoneDao.persist(vmTemplateZone);
-                    }
-                }
-            }
+        for (Long dcId : dcIds) {
+            _imageSrv.associateCrossZoneTemplatesToZone(dcId);
         }
     }
 
diff --git 
a/server/src/main/java/com/cloud/storage/download/DownloadListener.java 
b/server/src/main/java/com/cloud/storage/download/DownloadListener.java
index a35f4391b0a..e4668d15c27 100644
--- a/server/src/main/java/com/cloud/storage/download/DownloadListener.java
+++ b/server/src/main/java/com/cloud/storage/download/DownloadListener.java
@@ -378,7 +378,7 @@ public class DownloadListener implements Listener {
             }
             _imageSrv.handleSysTemplateDownload(hostHyper, 
agent.getDataCenterId());
             // update template_zone_ref for cross-zone templates
-            
_imageSrv.associateCrosszoneTemplatesToZone(agent.getDataCenterId());
+            
_imageSrv.associateCrossZoneTemplatesToZone(agent.getDataCenterId());
 
         }
         /* This can be removed
diff --git 
a/server/src/test/java/com/cloud/configuration/ConfigurationManagerTest.java 
b/server/src/test/java/com/cloud/configuration/ConfigurationManagerTest.java
index 8873d58de60..24616435645 100644
--- a/server/src/test/java/com/cloud/configuration/ConfigurationManagerTest.java
+++ b/server/src/test/java/com/cloud/configuration/ConfigurationManagerTest.java
@@ -95,6 +95,7 @@ import 
org.apache.cloudstack.api.command.admin.zone.UpdateZoneCmd;
 import org.apache.cloudstack.api.command.user.network.ListNetworkOfferingsCmd;
 import org.apache.cloudstack.context.CallContext;
 import 
org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
+import org.apache.cloudstack.engine.subsystem.api.storage.TemplateService;
 import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope;
 import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
 import org.apache.cloudstack.framework.messagebus.MessageBusBase;
@@ -223,6 +224,8 @@ public class ConfigurationManagerTest {
     Ipv6GuestPrefixSubnetNetworkMapDao ipv6GuestPrefixSubnetNetworkMapDao;
     @Mock
     MessageBusBase messageBus;
+    @Mock
+    TemplateService _templateService;
 
     VlanVO vlan = new VlanVO(Vlan.VlanType.VirtualNetwork, "vlantag", 
"vlangateway", "vlannetmask", 1L, "iprange", 1L, 1L, null, null, null);
 
diff --git 
a/services/secondary-storage/server/src/main/java/org/apache/cloudstack/storage/resource/SecondaryStorageDiscoverer.java
 
b/services/secondary-storage/server/src/main/java/org/apache/cloudstack/storage/resource/SecondaryStorageDiscoverer.java
index 5b328c33c86..73e2282b920 100644
--- 
a/services/secondary-storage/server/src/main/java/org/apache/cloudstack/storage/resource/SecondaryStorageDiscoverer.java
+++ 
b/services/secondary-storage/server/src/main/java/org/apache/cloudstack/storage/resource/SecondaryStorageDiscoverer.java
@@ -20,11 +20,12 @@ import java.io.File;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.InvocationTargetException;
 import java.net.URI;
-import java.util.Date;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Random;
+import java.util.Set;
 
 import javax.inject.Inject;
 import javax.naming.ConfigurationException;
@@ -37,14 +38,13 @@ import com.cloud.hypervisor.Hypervisor;
 import com.cloud.resource.Discoverer;
 import com.cloud.resource.DiscovererBase;
 import com.cloud.resource.ServerResource;
-import com.cloud.storage.VMTemplateVO;
-import com.cloud.storage.VMTemplateZoneVO;
 import com.cloud.storage.dao.VMTemplateDao;
 import com.cloud.storage.dao.VMTemplateZoneDao;
 import com.cloud.storage.resource.DummySecondaryStorageResource;
 import com.cloud.utils.component.ComponentContext;
 import com.cloud.utils.net.NfsUtils;
 import com.cloud.utils.script.Script;
+import org.apache.cloudstack.engine.subsystem.api.storage.TemplateService;
 
 /**
  * SecondaryStorageDiscoverer is used to discover secondary
@@ -65,6 +65,8 @@ public class SecondaryStorageDiscoverer extends 
DiscovererBase implements Discov
     @Inject
     protected VMTemplateDao _vmTemplateDao = null;
     @Inject
+    protected TemplateService templateService;
+    @Inject
     protected AgentManager _agentMgr = null;
 
     protected SecondaryStorageDiscoverer() {
@@ -285,24 +287,12 @@ public class SecondaryStorageDiscoverer extends 
DiscovererBase implements Discov
                 _agentMgr.agentStatusTransitTo(h, Event.AgentDisconnected, 
msId);
             }
         }
+        Set<Long> dcIds = new HashSet<>();
         for (HostVO h : hosts) {
-            associateTemplatesToZone(h.getId(), h.getDataCenterId());
+            dcIds.add(h.getDataCenterId());
         }
-
-    }
-
-    private void associateTemplatesToZone(long hostId, long dcId) {
-        VMTemplateZoneVO tmpltZone;
-
-        List<VMTemplateVO> allTemplates = _vmTemplateDao.listAll();
-        for (VMTemplateVO vt : allTemplates) {
-            if (vt.isCrossZones()) {
-                tmpltZone = _vmTemplateZoneDao.findByZoneTemplate(dcId, 
vt.getId());
-                if (tmpltZone == null) {
-                    VMTemplateZoneVO vmTemplateZone = new 
VMTemplateZoneVO(dcId, vt.getId(), new Date());
-                    _vmTemplateZoneDao.persist(vmTemplateZone);
-                }
-            }
+        for (Long dcId : dcIds) {
+            templateService.associateCrossZoneTemplatesToZone(dcId);
         }
     }
 }

Reply via email to