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

DaanHoogland 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 f493d993dbf sharedfs: skip hypervisors without system templates 
(#13830)
f493d993dbf is described below

commit f493d993dbf786a06f13222ff37ecce69a6cc8e5
Author: Brad <[email protected]>
AuthorDate: Tue Sep 8 13:12:26 2026 +0100

    sharedfs: skip hypervisors without system templates (#13830)
---
 .../lifecycle/StorageVmSharedFSLifeCycle.java      |  5 ++-
 .../lifecycle/StorageVmSharedFSLifeCycleTest.java  | 41 ++++++++++++++++++++++
 2 files changed, 45 insertions(+), 1 deletion(-)

diff --git 
a/plugins/storage/sharedfs/storagevm/src/main/java/org/apache/cloudstack/storage/sharedfs/lifecycle/StorageVmSharedFSLifeCycle.java
 
b/plugins/storage/sharedfs/storagevm/src/main/java/org/apache/cloudstack/storage/sharedfs/lifecycle/StorageVmSharedFSLifeCycle.java
index ac8d6a58f0c..15c45226e00 100644
--- 
a/plugins/storage/sharedfs/storagevm/src/main/java/org/apache/cloudstack/storage/sharedfs/lifecycle/StorageVmSharedFSLifeCycle.java
+++ 
b/plugins/storage/sharedfs/storagevm/src/main/java/org/apache/cloudstack/storage/sharedfs/lifecycle/StorageVmSharedFSLifeCycle.java
@@ -180,7 +180,10 @@ public class StorageVmSharedFSLifeCycle implements 
SharedFSLifeCycle {
         for (final Iterator<Hypervisor.HypervisorType> iter = 
hypervisors.iterator(); iter.hasNext();) {
             final Hypervisor.HypervisorType hypervisor = iter.next();
             VMTemplateVO template = 
templateDao.findSystemVMReadyTemplate(zoneId, hypervisor, 
preferredArchitecture);
-            if (template == null && !iter.hasNext()) {
+            if (template == null) {
+                if (iter.hasNext()) {
+                    continue;
+                }
                 throw new CloudRuntimeException(String.format("Unable to find 
the systemvm template for %s or it was not downloaded in %s.", 
hypervisor.toString(), zone.toString()));
             }
 
diff --git 
a/plugins/storage/sharedfs/storagevm/src/test/java/org/apache/cloudstack/storage/sharedfs/lifecycle/StorageVmSharedFSLifeCycleTest.java
 
b/plugins/storage/sharedfs/storagevm/src/test/java/org/apache/cloudstack/storage/sharedfs/lifecycle/StorageVmSharedFSLifeCycleTest.java
index c64e8c05c99..dd7f873998e 100644
--- 
a/plugins/storage/sharedfs/storagevm/src/test/java/org/apache/cloudstack/storage/sharedfs/lifecycle/StorageVmSharedFSLifeCycleTest.java
+++ 
b/plugins/storage/sharedfs/storagevm/src/test/java/org/apache/cloudstack/storage/sharedfs/lifecycle/StorageVmSharedFSLifeCycleTest.java
@@ -53,6 +53,7 @@ import com.cloud.vm.VirtualMachineManager;
 import com.cloud.vm.dao.NicDao;
 import com.cloud.vm.dao.UserVmDao;
 import java.io.IOException;
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Optional;
 import org.apache.cloudstack.api.ApiCommandResourceType;
@@ -273,6 +274,46 @@ public class StorageVmSharedFSLifeCycleTest {
          Assert.assertEquals(Optional.ofNullable(result.second()), 
Optional.ofNullable(s_vmId));
     }
 
+    @Test
+    public void 
testDeploySharedFSContinuesWhenTemplateIsMissingForNonLastHypervisor() throws 
ResourceUnavailableException, InsufficientCapacityException, 
ResourceAllocationException, IOException, OperationTimedoutException {
+        SharedFS sharedFS = prepareDeploySharedFS();
+        when(resourceMgr.getSupportedHypervisorTypes(s_zoneId, false, 
null)).thenReturn(new ArrayList<>(List.of(Hypervisor.HypervisorType.External, 
Hypervisor.HypervisorType.KVM)) {
+            @Override
+            public Hypervisor.HypervisorType set(int index, 
Hypervisor.HypervisorType element) {
+                // Keep the test order stable while exercising the production 
shuffle call.
+                return get(index);
+            }
+        });
+        when(templateDao.findSystemVMReadyTemplate(s_zoneId, 
Hypervisor.HypervisorType.External, 
ResourceManager.SystemVmPreferredArchitecture.defaultValue())).thenReturn(null);
+
+        Account owner = mock(Account.class);
+        when(owner.getId()).thenReturn(s_ownerId);
+        when(accountMgr.getActiveAccountById(s_ownerId)).thenReturn(owner);
+
+        UserVm vm = mock(UserVm.class);
+        when(vm.getId()).thenReturn(s_vmId);
+        when(userVmService.createAdvancedVirtualMachine(
+                any(DataCenter.class), any(ServiceOffering.class), 
any(VirtualMachineTemplate.class), anyList(), any(Account.class), anyString(),
+                anyString(), anyLong(), anyLong(), any(), isNull(), 
any(Hypervisor.HypervisorType.class), any(BaseCmd.HTTPMethod.class), 
anyString(),
+                isNull(), isNull(), anyList(), isNull(), 
any(Network.IpAddresses.class), isNull(), isNull(), isNull(),
+                anyMap(), isNull(), isNull(), isNull(), isNull(),
+                anyBoolean(), anyString(), isNull(), isNull(), 
isNull())).thenReturn(vm);
+
+        VolumeVO rootVol = mock(VolumeVO.class);
+        when(rootVol.getVolumeType()).thenReturn(Volume.Type.ROOT);
+        when(rootVol.getName()).thenReturn("ROOT-1");
+        VolumeVO dataVol = mock(VolumeVO.class);
+        when(dataVol.getId()).thenReturn(s_volumeId);
+        when(dataVol.getName()).thenReturn("DATA-1");
+        when(dataVol.getVolumeType()).thenReturn(Volume.Type.DATADISK);
+        when(volumeDao.findByInstance(s_vmId)).thenReturn(List.of(rootVol, 
dataVol));
+
+        Pair<Long, Long> result = lifeCycle.deploySharedFS(sharedFS, 
s_networkId, s_diskOfferingId, s_size, s_minIops, s_maxIops);
+
+        Assert.assertEquals(Optional.ofNullable(result.first()), 
Optional.ofNullable(s_volumeId));
+        Assert.assertEquals(Optional.ofNullable(result.second()), 
Optional.ofNullable(s_vmId));
+    }
+
     @Test(expected = CloudRuntimeException.class)
     public void testDeploySharedFSHypervisorNotFound() throws 
ResourceUnavailableException, InsufficientCapacityException, 
ResourceAllocationException, IOException, OperationTimedoutException {
         SharedFS sharedFS = mock(SharedFS.class);

Reply via email to