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

Pearl1594 pushed a commit to branch fix-cks-scale-etcd
in repository https://gitbox.apache.org/repos/asf/cloudstack.git

commit 21b76ea7e7640355d474b4871723fc8a55eefd6c
Author: Pearl1594 <[email protected]>
AuthorDate: Thu Sep 10 15:56:51 2026 -0400

    CCKS: fix scaling failures for clusters without a default service offering
---
 .../cluster/KubernetesClusterManagerImpl.java      | 33 ++++++++++++++++------
 .../KubernetesClusterScaleWorker.java              | 26 +++++++----------
 2 files changed, 34 insertions(+), 25 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 061f6264d66..e352a690ca6 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
@@ -1398,6 +1398,16 @@ public class KubernetesClusterManagerImpl extends 
ManagerBase implements Kuberne
         }
     }
 
+    public static long getNodeCountForType(KubernetesClusterNodeType nodeType, 
KubernetesCluster kubernetesCluster) {
+        if (WORKER == nodeType) {
+            return kubernetesCluster.getNodeCount();
+        } else if (CONTROL == nodeType) {
+            return kubernetesCluster.getControlNodeCount();
+        } else if (ETCD == nodeType) {
+            return kubernetesCluster.getEtcdNodeCount();
+        }
+        return kubernetesCluster.getTotalNodeCount();
+    }
 
     protected void validateServiceOfferingsForNodeTypesScale(Map<String, Long> 
map, Long defaultServiceOfferingId, KubernetesClusterVO kubernetesCluster, 
KubernetesSupportedVersion clusterVersion) {
         for (String key : CLUSTER_NODES_TYPES_LIST) {
@@ -1410,6 +1420,9 @@ public class KubernetesClusterManagerImpl extends 
ManagerBase implements Kuberne
                 checkServiceOfferingForNodesScale(serviceOffering, 
kubernetesCluster, clusterVersion);
                 Long nodeTypeOfferingId = 
getExistingServiceOfferingIdForNodeType(key, kubernetesCluster);
                 if (nodeTypeOfferingId == null) {
+                    if 
(getNodeCountForType(KubernetesClusterNodeType.valueOf(key), kubernetesCluster) 
<=0) {
+                        continue;
+                    }
                     nodeTypeOfferingId = 
kubernetesCluster.getServiceOfferingId();
                 }
                 final ServiceOffering existingServiceOffering = 
serviceOfferingDao.findById(nodeTypeOfferingId);
@@ -2196,18 +2209,20 @@ public class KubernetesClusterManagerImpl extends 
ManagerBase implements Kuberne
     protected Map<String, ServiceOffering> 
createNodeTypeToServiceOfferingMap(Map<String, Long> idsMapping,
                                                                               
Long serviceOfferingId, KubernetesClusterVO kubernetesCluster) {
         Map<String, ServiceOffering> map = new HashMap<>();
-        if (MapUtils.isEmpty(idsMapping)) {
-            ServiceOfferingVO offering = serviceOfferingId != null ?
-                    serviceOfferingDao.findById(serviceOfferingId) :
-                    
serviceOfferingDao.findById(kubernetesCluster.getServiceOfferingId());
-            map.put(DEFAULT.name(), offering);
+        if (MapUtils.isNotEmpty(idsMapping)) {
+            for (String key : CLUSTER_NODES_TYPES_LIST) {
+                if (idsMapping.containsKey(key)) {
+                    map.put(key, 
serviceOfferingDao.findById(idsMapping.get(key)));
+                }
+            }
             return map;
         }
-        for (String key : CLUSTER_NODES_TYPES_LIST) {
-            if (!idsMapping.containsKey(key)) {
-                continue;
+        Long defaultOfferingId = serviceOfferingId != null ? serviceOfferingId 
: kubernetesCluster.getServiceOfferingId();
+        if (defaultOfferingId != null) {
+            ServiceOfferingVO offering = 
serviceOfferingDao.findById(defaultOfferingId);
+            if (offering != null) {
+                map.put(DEFAULT.name(), offering);
             }
-            map.put(key, serviceOfferingDao.findById(idsMapping.get(key)));
         }
         return map;
     }
diff --git 
a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterScaleWorker.java
 
b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterScaleWorker.java
index 0ca27c29d8d..5a91831b6c5 100644
--- 
a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterScaleWorker.java
+++ 
b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterScaleWorker.java
@@ -225,7 +225,7 @@ public class KubernetesClusterScaleWorker extends 
KubernetesClusterResourceModif
             cores = serviceOffering.getCpu() * totalClusterSize;
             memory = serviceOffering.getRamSize() * totalClusterSize;
         } else {
-            long nodeCount = getNodeCountForType(nodeType, kubernetesCluster);
+            long nodeCount = 
KubernetesClusterManagerImpl.getNodeCountForType(nodeType, kubernetesCluster);
             Long existingOfferingId = 
getExistingOfferingIdForNodeType(nodeType, kubernetesCluster);
             if (existingOfferingId == null) {
                 existingOfferingId = serviceOffering.getId();
@@ -243,17 +243,6 @@ public class KubernetesClusterScaleWorker extends 
KubernetesClusterResourceModif
         return new Pair<>(cores, memory);
     }
 
-    private long getNodeCountForType(KubernetesClusterNodeType nodeType, 
KubernetesCluster kubernetesCluster) {
-        if (WORKER == nodeType) {
-            return kubernetesCluster.getNodeCount();
-        } else if (CONTROL == nodeType) {
-            return kubernetesCluster.getControlNodeCount();
-        } else if (ETCD == nodeType) {
-            return kubernetesCluster.getEtcdNodeCount();
-        }
-        return kubernetesCluster.getTotalNodeCount();
-    }
-
     protected Pair<Long, Long> calculateClusterNewCapacity(KubernetesCluster 
kubernetesCluster,
                                                            Pair<Long, Long> 
previousNodeTypeCapacity,
                                                            Pair<Long, Long> 
newNodeTypeCapacity) {
@@ -337,7 +326,9 @@ public class KubernetesClusterScaleWorker extends 
KubernetesClusterResourceModif
         // Check capacity and transition state
         final long newVmRequiredCount = clusterSize - originalClusterSize;
         final ServiceOffering clusterServiceOffering = 
serviceOfferingDao.findById(kubernetesCluster.getServiceOfferingId());
-        if (clusterServiceOffering == null) {
+        final ServiceOffering existingWorkerOffering = 
serviceOfferingDao.findById(kubernetesCluster.getWorkerNodeServiceOfferingId());
+        final ServiceOffering effectiveOffering = existingWorkerOffering != 
null ? existingWorkerOffering : clusterServiceOffering;
+        if (effectiveOffering == null) {
             logTransitStateToFailedIfNeededAndThrow(Level.WARN, 
String.format("Scaling failed for Kubernetes cluster : %s, cluster service 
offering not found", kubernetesCluster.getName()));
         }
         if (newVmRequiredCount > 0) {
@@ -345,9 +336,9 @@ public class KubernetesClusterScaleWorker extends 
KubernetesClusterResourceModif
             VMTemplateVO clusterTemplate = 
templateDao.findById(kubernetesCluster.getTemplateId());
             try {
                 if (originalState.equals(KubernetesCluster.State.Running)) {
-                    plan(newVmRequiredCount, zone, clusterServiceOffering, 
kubernetesCluster.getDomainId(), kubernetesCluster.getAccountId(), 
clusterTemplate.getHypervisorType(), clusterTemplate.getArch());
+                    plan(newVmRequiredCount, zone, effectiveOffering, 
kubernetesCluster.getDomainId(), kubernetesCluster.getAccountId(), 
clusterTemplate.getHypervisorType(), clusterTemplate.getArch());
                 } else {
-                    plan(kubernetesCluster.getTotalNodeCount() + 
newVmRequiredCount, zone, clusterServiceOffering, 
kubernetesCluster.getDomainId(), kubernetesCluster.getAccountId(), 
clusterTemplate.getHypervisorType(), clusterTemplate.getArch());
+                    plan(kubernetesCluster.getTotalNodeCount() + 
newVmRequiredCount, zone, effectiveOffering, kubernetesCluster.getDomainId(), 
kubernetesCluster.getAccountId(), clusterTemplate.getHypervisorType(), 
clusterTemplate.getArch());
                 }
             } catch (InsufficientCapacityException e) {
                 logTransitStateToFailedIfNeededAndThrow(Level.WARN, 
String.format("Scaling failed for Kubernetes cluster : %s in zone : %s, 
insufficient capacity", kubernetesCluster.getName(), zone.getName()));
@@ -370,7 +361,7 @@ public class KubernetesClusterScaleWorker extends 
KubernetesClusterResourceModif
             kubernetesCluster = updateKubernetesClusterEntryForNodeType(null, 
nodeType, serviceOffering, updateNodeOffering, updateClusterOffering);
             return;
         }
-        final long size = getNodeCountForType(nodeType, kubernetesCluster);
+        final long size = 
KubernetesClusterManagerImpl.getNodeCountForType(nodeType, kubernetesCluster);
         List<KubernetesClusterVmMapVO> vmList = 
kubernetesClusterVmMapDao.listByClusterIdAndVmType(kubernetesCluster.getId(), 
nodeType);
         final long tobeScaledVMCount =  Math.min(vmList.size(), size);
         for (long i = 0; i < tobeScaledVMCount; i++) {
@@ -610,6 +601,9 @@ public class KubernetesClusterScaleWorker extends 
KubernetesClusterResourceModif
     private ServiceOffering 
getExistingServiceOfferingForNodeType(KubernetesClusterNodeType nodeType, 
KubernetesCluster kubernetesCluster) {
         Long existingOfferingId = getExistingOfferingIdForNodeType(nodeType, 
kubernetesCluster);
         if (existingOfferingId == null) {
+            if (KubernetesClusterManagerImpl.getNodeCountForType(nodeType, 
kubernetesCluster) <= 0) {
+                return null;
+            }
             logAndThrow(Level.ERROR, String.format("The Kubernetes cluster %s 
does not have a service offering set for node type %s",
                     kubernetesCluster.getName(), nodeType.name()));
         }

Reply via email to