From 81c6f5ac19df68460b1aac14cf22c6d07e403162 Mon Sep 17 00:00:00 2001 From: nvazquez Date: Mon, 2 Jun 2025 14:17:23 -0300 Subject: [PATCH 1/9] Find system VM templates for CKS cluster honouring the preferred architecture --- .../java/com/cloud/storage/dao/VMTemplateDao.java | 2 +- .../java/com/cloud/storage/dao/VMTemplateDaoImpl.java | 11 ++++++++++- .../cluster/KubernetesClusterManagerImpl.java | 3 ++- .../lifecycle/StorageVmSharedFSLifeCycle.java | 4 +++- .../lifecycle/StorageVmSharedFSLifeCycleTest.java | 4 ++-- 5 files changed, 18 insertions(+), 6 deletions(-) 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 0b40366a8665..c751f81f9273 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 @@ -72,7 +72,7 @@ public interface VMTemplateDao extends GenericDao, StateDao< VMTemplateVO findSystemVMTemplate(long zoneId); - VMTemplateVO findSystemVMReadyTemplate(long zoneId, HypervisorType hypervisorType); + VMTemplateVO findSystemVMReadyTemplate(long zoneId, HypervisorType hypervisorType, String preferredArch); List findSystemVMReadyTemplates(long zoneId, HypervisorType hypervisorType, String preferredArch); 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 12c00a3209ae..42bef095a97e 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 @@ -23,6 +23,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; import javax.inject.Inject; import javax.naming.ConfigurationException; @@ -578,11 +579,19 @@ public List listAllReadySystemVMTemplates(Long zoneId) { } @Override - public VMTemplateVO findSystemVMReadyTemplate(long zoneId, HypervisorType hypervisorType) { + public VMTemplateVO findSystemVMReadyTemplate(long zoneId, HypervisorType hypervisorType, String preferredArch) { List templates = listAllReadySystemVMTemplates(zoneId); if (CollectionUtils.isEmpty(templates)) { return null; } + if (StringUtils.isNotBlank(preferredArch)) { + templates = templates.stream() + .filter(x -> x.getArch().getType().equalsIgnoreCase(preferredArch)) + .collect(Collectors.toList()); + if (CollectionUtils.isEmpty(templates)) { + return null; + } + } if (hypervisorType == HypervisorType.Any) { return templates.get(0); } diff --git a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/KubernetesClusterManagerImpl.java b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/KubernetesClusterManagerImpl.java index 411e6af883e3..a741b961ab7b 100644 --- a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/KubernetesClusterManagerImpl.java +++ b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/KubernetesClusterManagerImpl.java @@ -434,7 +434,8 @@ private IpAddress getSourceNatIp(Network network) { } public VMTemplateVO getKubernetesServiceTemplate(DataCenter dataCenter, Hypervisor.HypervisorType hypervisorType) { - VMTemplateVO template = templateDao.findSystemVMReadyTemplate(dataCenter.getId(), hypervisorType); + ConfigKey preferredArchitecture = ResourceManager.SystemVmPreferredArchitecture; + VMTemplateVO template = templateDao.findSystemVMReadyTemplate(dataCenter.getId(), hypervisorType, preferredArchitecture.value()); if (DataCenter.Type.Edge.equals(dataCenter.getType()) && template != null && !template.isDirectDownload()) { logger.debug(String.format("Template %s can not be used for edge zone %s", template, dataCenter)); template = templateDao.findRoutingTemplate(hypervisorType, networkHelper.getHypervisorRouterTemplateConfigMap().get(hypervisorType).valueIn(dataCenter.getId())); 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 31159e7d3d95..9d76995211bb 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 @@ -61,6 +61,7 @@ import org.apache.cloudstack.api.ApiCommandResourceType; import org.apache.cloudstack.api.BaseCmd; import org.apache.cloudstack.context.CallContext; +import org.apache.cloudstack.framework.config.ConfigKey; import org.apache.cloudstack.storage.sharedfs.SharedFS; import org.apache.cloudstack.storage.sharedfs.SharedFSLifeCycle; import org.apache.commons.codec.binary.Base64; @@ -174,10 +175,11 @@ private UserVm deploySharedFSVM(Long zoneId, Account owner, List networkId customParameterMap.put("maxIopsDo", maxIops.toString()); } List keypairs = new ArrayList(); + ConfigKey preferredArchitecture = ResourceManager.SystemVmPreferredArchitecture; for (final Iterator iter = hypervisors.iterator(); iter.hasNext();) { final Hypervisor.HypervisorType hypervisor = iter.next(); - VMTemplateVO template = templateDao.findSystemVMReadyTemplate(zoneId, hypervisor); + VMTemplateVO template = templateDao.findSystemVMReadyTemplate(zoneId, hypervisor, preferredArchitecture.value()); if (template == null && !iter.hasNext()) { 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 4393b0565f89..a880657797b2 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 @@ -236,7 +236,7 @@ private SharedFS prepareDeploySharedFS() throws ResourceUnavailableException, In when(serviceOfferingDao.findById(s_serviceOfferingId)).thenReturn(serviceOffering); VMTemplateVO template = mock(VMTemplateVO.class); - when(templateDao.findSystemVMReadyTemplate(s_zoneId, Hypervisor.HypervisorType.KVM)).thenReturn(template); + when(templateDao.findSystemVMReadyTemplate(s_zoneId, Hypervisor.HypervisorType.KVM, null)).thenReturn(template); when(template.getId()).thenReturn(s_templateId); return sharedFS; @@ -298,7 +298,7 @@ public void testDeploySharedFSTemplateNotFound() throws ResourceUnavailableExcep when(dataCenterDao.findById(s_zoneId)).thenReturn(zone); when(resourceMgr.getSupportedHypervisorTypes(s_zoneId, false, null)).thenReturn(List.of(Hypervisor.HypervisorType.KVM)); - when(templateDao.findSystemVMReadyTemplate(s_zoneId, Hypervisor.HypervisorType.KVM)).thenReturn(null); + when(templateDao.findSystemVMReadyTemplate(s_zoneId, Hypervisor.HypervisorType.KVM, null)).thenReturn(null); lifeCycle.deploySharedFS(sharedFS, s_networkId, s_diskOfferingId, s_size, s_minIops, s_maxIops); } From 778ccc1ba84cacb97abc4695959f2c6ac073b2d2 Mon Sep 17 00:00:00 2001 From: nvazquez Date: Mon, 2 Jun 2025 14:26:25 -0300 Subject: [PATCH 2/9] Fix unit tests --- .../sharedfs/lifecycle/StorageVmSharedFSLifeCycleTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 a880657797b2..a1610d924eac 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 @@ -46,6 +46,7 @@ import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.MockedStatic; +import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import org.mockito.Spy; import org.mockito.junit.MockitoJUnitRunner; @@ -236,7 +237,7 @@ private SharedFS prepareDeploySharedFS() throws ResourceUnavailableException, In when(serviceOfferingDao.findById(s_serviceOfferingId)).thenReturn(serviceOffering); VMTemplateVO template = mock(VMTemplateVO.class); - when(templateDao.findSystemVMReadyTemplate(s_zoneId, Hypervisor.HypervisorType.KVM, null)).thenReturn(template); + when(templateDao.findSystemVMReadyTemplate(s_zoneId, Hypervisor.HypervisorType.KVM, ResourceManager.SystemVmPreferredArchitecture.defaultValue())).thenReturn(template); when(template.getId()).thenReturn(s_templateId); return sharedFS; @@ -298,7 +299,6 @@ public void testDeploySharedFSTemplateNotFound() throws ResourceUnavailableExcep when(dataCenterDao.findById(s_zoneId)).thenReturn(zone); when(resourceMgr.getSupportedHypervisorTypes(s_zoneId, false, null)).thenReturn(List.of(Hypervisor.HypervisorType.KVM)); - when(templateDao.findSystemVMReadyTemplate(s_zoneId, Hypervisor.HypervisorType.KVM, null)).thenReturn(null); lifeCycle.deploySharedFS(sharedFS, s_networkId, s_diskOfferingId, s_size, s_minIops, s_maxIops); } From 02de12f88251fc4c39589162d6d3f988cd4faf1b Mon Sep 17 00:00:00 2001 From: nvazquez Date: Mon, 2 Jun 2025 14:31:26 -0300 Subject: [PATCH 3/9] Fix checkstyle --- .../sharedfs/lifecycle/StorageVmSharedFSLifeCycleTest.java | 1 - 1 file changed, 1 deletion(-) 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 a1610d924eac..1e5c8774b261 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 @@ -46,7 +46,6 @@ import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.MockedStatic; -import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import org.mockito.Spy; import org.mockito.junit.MockitoJUnitRunner; From 70f4e26ef7eb5e5b997e0ccba096063e29174d6c Mon Sep 17 00:00:00 2001 From: nvazquez Date: Mon, 2 Jun 2025 14:49:59 -0300 Subject: [PATCH 4/9] Sort instead of filtering by preferred arch --- .../cloud/storage/dao/VMTemplateDaoImpl.java | 8 +++---- .../storage/dao/VMTemplateDaoImplTest.java | 23 +++++++++++++++++++ 2 files changed, 27 insertions(+), 4 deletions(-) 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 42bef095a97e..b6796cf8f9d1 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 @@ -585,12 +585,12 @@ public VMTemplateVO findSystemVMReadyTemplate(long zoneId, HypervisorType hyperv return null; } if (StringUtils.isNotBlank(preferredArch)) { + // Sort the templates by preferred architecture first templates = templates.stream() - .filter(x -> x.getArch().getType().equalsIgnoreCase(preferredArch)) + .sorted(Comparator.comparing( + x -> !x.getArch().getType().equalsIgnoreCase(preferredArch) + )) .collect(Collectors.toList()); - if (CollectionUtils.isEmpty(templates)) { - return null; - } } if (hypervisorType == HypervisorType.Any) { return templates.get(0); diff --git a/engine/schema/src/test/java/com/cloud/storage/dao/VMTemplateDaoImplTest.java b/engine/schema/src/test/java/com/cloud/storage/dao/VMTemplateDaoImplTest.java index df0b36ebdbf6..a0c42e7e376c 100644 --- a/engine/schema/src/test/java/com/cloud/storage/dao/VMTemplateDaoImplTest.java +++ b/engine/schema/src/test/java/com/cloud/storage/dao/VMTemplateDaoImplTest.java @@ -31,6 +31,7 @@ import java.util.List; import java.util.Map; +import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InjectMocks; @@ -186,4 +187,26 @@ public void testFindLatestTemplateByTypeAndHypervisorAndArch_NotFound() { VMTemplateVO result = templateDao.findLatestTemplateByTypeAndHypervisorAndArch(hypervisorType, arch, type); assertNull(result); } + + @Test + public void testFindSystemVMReadyTemplate() { + Long zoneId = 1L; + VMTemplateVO systemVmTemplate1 = mock(VMTemplateVO.class); + Mockito.when(systemVmTemplate1.getArch()).thenReturn(CPU.CPUArch.x86); + Mockito.when(systemVmTemplate1.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.KVM); + VMTemplateVO systemVmTemplate2 = mock(VMTemplateVO.class); + Mockito.when(systemVmTemplate2.getArch()).thenReturn(CPU.CPUArch.x86); + Mockito.when(systemVmTemplate2.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.KVM); + VMTemplateVO systemVmTemplate3 = mock(VMTemplateVO.class); + Mockito.when(systemVmTemplate3.getArch()).thenReturn(CPU.CPUArch.arm64); + Mockito.when(systemVmTemplate3.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.KVM); + List templates = Arrays.asList(systemVmTemplate1, systemVmTemplate2, systemVmTemplate3); + Mockito.when(hostDao.listDistinctHypervisorTypes(zoneId)).thenReturn(Arrays.asList(Hypervisor.HypervisorType.KVM)); + SearchBuilder sb = mock(SearchBuilder.class); + templateDao.readySystemTemplateSearch = sb; + when(sb.create()).thenReturn(mock(SearchCriteria.class)); + doReturn(templates).when(templateDao).listBy(any(SearchCriteria.class), any(Filter.class)); + VMTemplateVO readyTemplate = templateDao.findSystemVMReadyTemplate(zoneId, Hypervisor.HypervisorType.KVM, CPU.CPUArch.arm64.getType()); + Assert.assertEquals(CPU.CPUArch.arm64, readyTemplate.getArch()); + } } From efa3bdcb7dff6799206dc1d1469d37c2756ba4ea Mon Sep 17 00:00:00 2001 From: nvazquez Date: Mon, 2 Jun 2025 16:01:39 -0300 Subject: [PATCH 5/9] Remove unnecesary stubs --- .java-version | 2 +- .../test/java/com/cloud/storage/dao/VMTemplateDaoImplTest.java | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/.java-version b/.java-version index 2dbc24b32d3c..6215fcb0c2f9 100644 --- a/.java-version +++ b/.java-version @@ -1 +1 @@ -11.0 +17.0.13 diff --git a/engine/schema/src/test/java/com/cloud/storage/dao/VMTemplateDaoImplTest.java b/engine/schema/src/test/java/com/cloud/storage/dao/VMTemplateDaoImplTest.java index a0c42e7e376c..e97a887cc471 100644 --- a/engine/schema/src/test/java/com/cloud/storage/dao/VMTemplateDaoImplTest.java +++ b/engine/schema/src/test/java/com/cloud/storage/dao/VMTemplateDaoImplTest.java @@ -193,10 +193,8 @@ public void testFindSystemVMReadyTemplate() { Long zoneId = 1L; VMTemplateVO systemVmTemplate1 = mock(VMTemplateVO.class); Mockito.when(systemVmTemplate1.getArch()).thenReturn(CPU.CPUArch.x86); - Mockito.when(systemVmTemplate1.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.KVM); VMTemplateVO systemVmTemplate2 = mock(VMTemplateVO.class); Mockito.when(systemVmTemplate2.getArch()).thenReturn(CPU.CPUArch.x86); - Mockito.when(systemVmTemplate2.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.KVM); VMTemplateVO systemVmTemplate3 = mock(VMTemplateVO.class); Mockito.when(systemVmTemplate3.getArch()).thenReturn(CPU.CPUArch.arm64); Mockito.when(systemVmTemplate3.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.KVM); From dabd83340074b78173ce4847739260c52bca3381 Mon Sep 17 00:00:00 2001 From: nvazquez Date: Mon, 2 Jun 2025 16:08:51 -0300 Subject: [PATCH 6/9] Restore java version --- .java-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.java-version b/.java-version index 6215fcb0c2f9..2dbc24b32d3c 100644 --- a/.java-version +++ b/.java-version @@ -1 +1 @@ -17.0.13 +11.0 From a44dde0d5a96f388b570db7d06dcb5490c6ffb1a Mon Sep 17 00:00:00 2001 From: nvazquez Date: Tue, 17 Jun 2025 08:25:00 -0300 Subject: [PATCH 7/9] Address review comments --- .../kubernetes/cluster/KubernetesClusterManagerImpl.java | 4 ++-- .../KubernetesClusterResourceModifierActionWorker.java | 2 +- .../sharedfs/lifecycle/StorageVmSharedFSLifeCycle.java | 5 ++--- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/KubernetesClusterManagerImpl.java b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/KubernetesClusterManagerImpl.java index a741b961ab7b..fc7f52f2750d 100644 --- a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/KubernetesClusterManagerImpl.java +++ b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/KubernetesClusterManagerImpl.java @@ -434,8 +434,8 @@ private IpAddress getSourceNatIp(Network network) { } public VMTemplateVO getKubernetesServiceTemplate(DataCenter dataCenter, Hypervisor.HypervisorType hypervisorType) { - ConfigKey preferredArchitecture = ResourceManager.SystemVmPreferredArchitecture; - VMTemplateVO template = templateDao.findSystemVMReadyTemplate(dataCenter.getId(), hypervisorType, preferredArchitecture.value()); + String preferredArchitecture = ResourceManager.SystemVmPreferredArchitecture.valueIn(dataCenter.getId()); + VMTemplateVO template = templateDao.findSystemVMReadyTemplate(dataCenter.getId(), hypervisorType, preferredArchitecture); if (DataCenter.Type.Edge.equals(dataCenter.getType()) && template != null && !template.isDirectDownload()) { logger.debug(String.format("Template %s can not be used for edge zone %s", template, dataCenter)); template = templateDao.findRoutingTemplate(hypervisorType, networkHelper.getHypervisorRouterTemplateConfigMap().get(hypervisorType).valueIn(dataCenter.getId())); diff --git a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterResourceModifierActionWorker.java b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterResourceModifierActionWorker.java index 8c983149d02d..04c63bb54838 100644 --- a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterResourceModifierActionWorker.java +++ b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterResourceModifierActionWorker.java @@ -248,7 +248,7 @@ protected DeployDestination plan(final long nodesCount, final DataCenter zone, f for (Map.Entry> hostEntry : hosts_with_resevered_capacity.entrySet()) { Pair hp = hostEntry.getValue(); HostVO h = hp.first(); - if (!h.getHypervisorType().equals(clusterTemplate.getHypervisorType())) { + if (!h.getHypervisorType().equals(clusterTemplate.getHypervisorType()) || !h.getArch().equals(clusterTemplate.getArch())) { continue; } hostDao.loadHostTags(h); 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 9d76995211bb..3f018c1c9b3c 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 @@ -61,7 +61,6 @@ import org.apache.cloudstack.api.ApiCommandResourceType; import org.apache.cloudstack.api.BaseCmd; import org.apache.cloudstack.context.CallContext; -import org.apache.cloudstack.framework.config.ConfigKey; import org.apache.cloudstack.storage.sharedfs.SharedFS; import org.apache.cloudstack.storage.sharedfs.SharedFSLifeCycle; import org.apache.commons.codec.binary.Base64; @@ -175,11 +174,11 @@ private UserVm deploySharedFSVM(Long zoneId, Account owner, List networkId customParameterMap.put("maxIopsDo", maxIops.toString()); } List keypairs = new ArrayList(); - ConfigKey preferredArchitecture = ResourceManager.SystemVmPreferredArchitecture; + String preferredArchitecture = ResourceManager.SystemVmPreferredArchitecture.valueIn(zoneId); for (final Iterator iter = hypervisors.iterator(); iter.hasNext();) { final Hypervisor.HypervisorType hypervisor = iter.next(); - VMTemplateVO template = templateDao.findSystemVMReadyTemplate(zoneId, hypervisor, preferredArchitecture.value()); + VMTemplateVO template = templateDao.findSystemVMReadyTemplate(zoneId, hypervisor, preferredArchitecture); if (template == null && !iter.hasNext()) { throw new CloudRuntimeException(String.format("Unable to find the systemvm template for %s or it was not downloaded in %s.", hypervisor.toString(), zone.toString())); } From 337b0eedb683d882e2fc8a403b33f186412e1ae3 Mon Sep 17 00:00:00 2001 From: nvazquez Date: Wed, 18 Jun 2025 11:13:25 -0300 Subject: [PATCH 8/9] Fail and display error message in case the CKS ISO arch doesnt match the selected template arch --- .../cluster/KubernetesClusterManagerImpl.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/KubernetesClusterManagerImpl.java b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/KubernetesClusterManagerImpl.java index fc7f52f2750d..b1c1c2cd81d9 100644 --- a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/KubernetesClusterManagerImpl.java +++ b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/KubernetesClusterManagerImpl.java @@ -1304,6 +1304,9 @@ public KubernetesCluster createManagedKubernetesCluster(CreateKubernetesClusterC final Network defaultNetwork = getKubernetesClusterNetworkIfMissing(cmd.getName(), zone, owner, (int)controlNodeCount, (int)clusterSize, cmd.getExternalLoadBalancerIpAddress(), cmd.getNetworkId()); final VMTemplateVO finalTemplate = getKubernetesServiceTemplate(zone, deployDestination.getCluster().getHypervisorType()); + + compareKubernetesIsoArchToSelectedTemplateArch(clusterKubernetesVersion, finalTemplate); + final long cores = serviceOffering.getCpu() * (controlNodeCount + clusterSize); final long memory = serviceOffering.getRamSize() * (controlNodeCount + clusterSize); @@ -1332,6 +1335,21 @@ public KubernetesClusterVO doInTransaction(TransactionStatus status) { return cluster; } + private void compareKubernetesIsoArchToSelectedTemplateArch(KubernetesSupportedVersion clusterKubernetesVersion, VMTemplateVO finalTemplate) { + VMTemplateVO cksIso = templateDao.findById(clusterKubernetesVersion.getIsoId()); + if (cksIso == null) { + String err = String.format("Cannot find Kubernetes ISO associated to the Kubernetes version %s (id=%s)", + clusterKubernetesVersion.getName(), clusterKubernetesVersion.getUuid()); + throw new CloudRuntimeException(err); + } + if (!cksIso.getArch().equals(finalTemplate.getArch())) { + String err = String.format("The selected Kubernetes ISO %s arch (%s) doesn't match the template %s arch (%s) " + + "to deploy the Kubernetes cluster", + clusterKubernetesVersion.getName(), cksIso.getArch(), finalTemplate.getName(), finalTemplate.getArch()); + throw new CloudRuntimeException(err); + } + } + private SecurityGroup getOrCreateSecurityGroupForAccount(Account owner) { String securityGroupName = String.format("%s-%s", KubernetesClusterActionWorker.CKS_CLUSTER_SECURITY_GROUP_NAME, owner.getUuid()); String securityGroupDesc = String.format("%s and account %s", KubernetesClusterActionWorker.CKS_SECURITY_GROUP_DESCRIPTION, owner.getName()); From c3b83a45aed6083372878a013fc74bef7173f8da Mon Sep 17 00:00:00 2001 From: nvazquez Date: Wed, 30 Jul 2025 16:38:43 -0300 Subject: [PATCH 9/9] Prefer CKS ISO arch instead of the system VM setting --- .../cluster/KubernetesClusterManagerImpl.java | 19 ++++++++++++++++--- .../KubernetesClusterActionWorker.java | 4 +++- .../KubernetesClusterManagerImplTest.java | 19 +++++++++++++++++++ 3 files changed, 38 insertions(+), 4 deletions(-) diff --git a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/KubernetesClusterManagerImpl.java b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/KubernetesClusterManagerImpl.java index b1c1c2cd81d9..d1babb547f85 100644 --- a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/KubernetesClusterManagerImpl.java +++ b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/KubernetesClusterManagerImpl.java @@ -433,8 +433,13 @@ private IpAddress getSourceNatIp(Network network) { return null; } - public VMTemplateVO getKubernetesServiceTemplate(DataCenter dataCenter, Hypervisor.HypervisorType hypervisorType) { - String preferredArchitecture = ResourceManager.SystemVmPreferredArchitecture.valueIn(dataCenter.getId()); + public VMTemplateVO getKubernetesServiceTemplate(DataCenter dataCenter, Hypervisor.HypervisorType hypervisorType, + KubernetesSupportedVersion clusterKubernetesVersion) { + String systemVMPreferredArchitecture = ResourceManager.SystemVmPreferredArchitecture.valueIn(dataCenter.getId()); + VMTemplateVO cksIso = clusterKubernetesVersion != null ? + templateDao.findById(clusterKubernetesVersion.getIsoId()) : + null; + String preferredArchitecture = getCksClusterPreferredArch(systemVMPreferredArchitecture, cksIso); VMTemplateVO template = templateDao.findSystemVMReadyTemplate(dataCenter.getId(), hypervisorType, preferredArchitecture); if (DataCenter.Type.Edge.equals(dataCenter.getType()) && template != null && !template.isDirectDownload()) { logger.debug(String.format("Template %s can not be used for edge zone %s", template, dataCenter)); @@ -446,6 +451,14 @@ public VMTemplateVO getKubernetesServiceTemplate(DataCenter dataCenter, Hypervis return template; } + protected String getCksClusterPreferredArch(String systemVMPreferredArchitecture, VMTemplateVO cksIso) { + if (cksIso == null) { + return systemVMPreferredArchitecture; + } + String cksIsoArchName = cksIso.getArch().name(); + return cksIsoArchName.equals(systemVMPreferredArchitecture) ? systemVMPreferredArchitecture : cksIsoArchName; + } + protected void validateIsolatedNetworkIpRules(long ipId, FirewallRule.Purpose purpose, Network network, int clusterTotalNodeCount) { List rules = firewallRulesDao.listByIpAndPurposeAndNotRevoked(ipId, purpose); for (FirewallRuleVO rule : rules) { @@ -1303,7 +1316,7 @@ public KubernetesCluster createManagedKubernetesCluster(CreateKubernetesClusterC } final Network defaultNetwork = getKubernetesClusterNetworkIfMissing(cmd.getName(), zone, owner, (int)controlNodeCount, (int)clusterSize, cmd.getExternalLoadBalancerIpAddress(), cmd.getNetworkId()); - final VMTemplateVO finalTemplate = getKubernetesServiceTemplate(zone, deployDestination.getCluster().getHypervisorType()); + final VMTemplateVO finalTemplate = getKubernetesServiceTemplate(zone, deployDestination.getCluster().getHypervisorType(), clusterKubernetesVersion); compareKubernetesIsoArchToSelectedTemplateArch(clusterKubernetesVersion, finalTemplate); diff --git a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterActionWorker.java b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterActionWorker.java index 29ecde477a44..99c4d4c9c96c 100644 --- a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterActionWorker.java +++ b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterActionWorker.java @@ -29,6 +29,7 @@ import javax.inject.Inject; +import com.cloud.kubernetes.version.KubernetesSupportedVersionVO; import org.apache.logging.log4j.Level; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.LogManager; @@ -194,7 +195,8 @@ protected void init() { DataCenterVO dataCenterVO = dataCenterDao.findById(zoneId); VMTemplateVO template = templateDao.findById(templateId); Hypervisor.HypervisorType type = template.getHypervisorType(); - this.clusterTemplate = manager.getKubernetesServiceTemplate(dataCenterVO, type); + KubernetesSupportedVersionVO kubernetesSupportedVersion = kubernetesSupportedVersionDao.findById(this.kubernetesCluster.getKubernetesVersionId()); + this.clusterTemplate = manager.getKubernetesServiceTemplate(dataCenterVO, type, kubernetesSupportedVersion); this.sshKeyFile = getManagementServerSshPublicKeyFile(); } diff --git a/plugins/integrations/kubernetes-service/src/test/java/com/cloud/kubernetes/cluster/KubernetesClusterManagerImplTest.java b/plugins/integrations/kubernetes-service/src/test/java/com/cloud/kubernetes/cluster/KubernetesClusterManagerImplTest.java index a6d46ffc9aa1..287e045a18e0 100644 --- a/plugins/integrations/kubernetes-service/src/test/java/com/cloud/kubernetes/cluster/KubernetesClusterManagerImplTest.java +++ b/plugins/integrations/kubernetes-service/src/test/java/com/cloud/kubernetes/cluster/KubernetesClusterManagerImplTest.java @@ -21,6 +21,7 @@ import com.cloud.api.query.dao.TemplateJoinDao; import com.cloud.api.query.vo.TemplateJoinVO; +import com.cloud.cpu.CPU; import com.cloud.dc.DataCenter; import com.cloud.exception.InvalidParameterValueException; import com.cloud.exception.PermissionDeniedException; @@ -292,4 +293,22 @@ public void removeVmsFromCluster() { Mockito.when(kubernetesClusterDao.findById(Mockito.anyLong())).thenReturn(cluster); Assert.assertTrue(kubernetesClusterManager.removeVmsFromCluster(cmd).size() > 0); } + + @Test + public void testGetCksClusterPreferredArchDifferentArchsPreferCKSIsoArch() { + String systemVMArch = "x86_64"; + VMTemplateVO cksIso = Mockito.mock(VMTemplateVO.class); + Mockito.when(cksIso.getArch()).thenReturn(CPU.CPUArch.arm64); + String cksClusterPreferredArch = kubernetesClusterManager.getCksClusterPreferredArch(systemVMArch, cksIso); + Assert.assertEquals(CPU.CPUArch.arm64.name(), cksClusterPreferredArch); + } + + @Test + public void testGetCksClusterPreferredArchSameArch() { + String systemVMArch = "x86_64"; + VMTemplateVO cksIso = Mockito.mock(VMTemplateVO.class); + Mockito.when(cksIso.getArch()).thenReturn(CPU.CPUArch.amd64); + String cksClusterPreferredArch = kubernetesClusterManager.getCksClusterPreferredArch(systemVMArch, cksIso); + Assert.assertEquals(CPU.CPUArch.amd64.name(), cksClusterPreferredArch); + } }