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

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


The following commit(s) were added to refs/heads/main by this push:
     new 84b807eeee1 [CKS] Simplify logic for scaling CKS cluster service 
offerings (#11063)
84b807eeee1 is described below

commit 84b807eeee15b8398ebefd1f554f579bb05b14b4
Author: Nicolas Vazquez <[email protected]>
AuthorDate: Wed Jul 16 03:23:33 2025 -0300

    [CKS] Simplify logic for scaling CKS cluster service offerings (#11063)
---
 .../KubernetesClusterScaleWorker.java              | 85 +++++++++++-----------
 1 file changed, 44 insertions(+), 41 deletions(-)

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 bfc553f6afa..3461d5c0634 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
@@ -532,6 +532,8 @@ public class KubernetesClusterScaleWorker extends 
KubernetesClusterResourceModif
         }
         scaleTimeoutTime = System.currentTimeMillis() + 
KubernetesClusterService.KubernetesClusterScaleTimeout.value() * 1000;
         final long originalClusterSize = kubernetesCluster.getNodeCount();
+
+        // DEFAULT node type means only the global service offering has been 
set for the Kubernetes cluster
         boolean scaleClusterDefaultOffering = 
serviceOfferingNodeTypeMap.containsKey(DEFAULT.name());
         if (scaleClusterDefaultOffering) {
             final ServiceOffering existingServiceOffering = 
serviceOfferingDao.findById(kubernetesCluster.getServiceOfferingId());
@@ -546,38 +548,37 @@ public class KubernetesClusterScaleWorker extends 
KubernetesClusterResourceModif
         ServiceOffering defaultServiceOffering = 
serviceOfferingNodeTypeMap.getOrDefault(DEFAULT.name(), null);
 
         for (KubernetesClusterNodeType nodeType : Arrays.asList(CONTROL, ETCD, 
WORKER)) {
-            boolean isWorkerNodeOrAllNodes = WORKER == nodeType;
-            final long newVMRequired = (!isWorkerNodeOrAllNodes || clusterSize 
== null) ? 0 : clusterSize - originalClusterSize;
+            boolean isWorkerNode = WORKER == nodeType;
+            final long newVMRequired = (!isWorkerNode || clusterSize == null) 
? 0 : clusterSize - originalClusterSize;
             if (!scaleClusterDefaultOffering && 
!serviceOfferingNodeTypeMap.containsKey(nodeType.name()) && newVMRequired == 0) 
{
                 continue;
             }
 
-            Long existingNodeTypeOfferingId = 
getKubernetesClusterNodeTypeOfferingId(kubernetesCluster, nodeType);
-            boolean clusterHasExistingOfferingForNodeType = 
existingNodeTypeOfferingId != null;
-            boolean serviceOfferingScalingNeeded = 
isServiceOfferingScalingNeededForNodeType(nodeType, serviceOfferingNodeTypeMap, 
kubernetesCluster);
-            ServiceOffering serviceOffering = 
serviceOfferingNodeTypeMap.getOrDefault(nodeType.name(), 
defaultServiceOffering);
-            boolean updateNodeOffering = 
serviceOfferingNodeTypeMap.containsKey(nodeType.name()) ||
-                    scaleClusterDefaultOffering && 
clusterHasExistingOfferingForNodeType;
-            boolean updateClusterOffering = isWorkerNodeOrAllNodes && 
scaleClusterDefaultOffering;
-            if (isWorkerNodeOrAllNodes && autoscalingChanged) {
+            ServiceOffering existingServiceOffering = 
getExistingServiceOfferingForNodeType(nodeType, kubernetesCluster);
+            ServiceOffering scalingServiceOffering = 
serviceOfferingNodeTypeMap.getOrDefault(nodeType.name(), 
defaultServiceOffering);
+            boolean isNodeOfferingScalingNeeded = 
isServiceOfferingScalingNeededForNodeType(existingServiceOffering, 
scalingServiceOffering);
+            boolean updateNodeOffering = 
serviceOfferingNodeTypeMap.containsKey(nodeType.name()) || 
isNodeOfferingScalingNeeded;
+
+            boolean updateClusterOffering = isWorkerNode && 
scaleClusterDefaultOffering;
+            if (isWorkerNode && autoscalingChanged) {
                 boolean autoScaled = 
autoscaleCluster(this.isAutoscalingEnabled, minSize, maxSize);
-                if (autoScaled && serviceOfferingScalingNeeded) {
-                    scaleKubernetesClusterOffering(nodeType, serviceOffering, 
updateNodeOffering, updateClusterOffering);
+                if (autoScaled && isNodeOfferingScalingNeeded) {
+                    scaleKubernetesClusterOffering(nodeType, 
scalingServiceOffering, updateNodeOffering, updateClusterOffering);
                 }
                 stateTransitTo(kubernetesCluster.getId(), 
KubernetesCluster.Event.OperationSucceeded);
                 return autoScaled;
             }
-            final boolean clusterSizeScalingNeeded = isWorkerNodeOrAllNodes && 
clusterSize != null && clusterSize != originalClusterSize;
-            if (serviceOfferingScalingNeeded && clusterSizeScalingNeeded) {
+            final boolean clusterSizeScalingNeeded = isWorkerNode && 
clusterSize != null && clusterSize != originalClusterSize;
+            if (isNodeOfferingScalingNeeded && clusterSizeScalingNeeded) {
                 if (newVMRequired > 0) {
-                    scaleKubernetesClusterOffering(nodeType, serviceOffering, 
updateNodeOffering, updateClusterOffering);
+                    scaleKubernetesClusterOffering(nodeType, 
scalingServiceOffering, updateNodeOffering, updateClusterOffering);
                     scaleKubernetesClusterSize(nodeType);
                 } else {
                     scaleKubernetesClusterSize(nodeType);
-                    scaleKubernetesClusterOffering(nodeType, serviceOffering, 
updateNodeOffering, updateClusterOffering);
+                    scaleKubernetesClusterOffering(nodeType, 
scalingServiceOffering, updateNodeOffering, updateClusterOffering);
                 }
-            } else if (serviceOfferingScalingNeeded) {
-                scaleKubernetesClusterOffering(nodeType, serviceOffering, 
updateNodeOffering, updateClusterOffering);
+            } else if (isNodeOfferingScalingNeeded) {
+                scaleKubernetesClusterOffering(nodeType, 
scalingServiceOffering, updateNodeOffering, updateClusterOffering);
             } else if (clusterSizeScalingNeeded) {
                 scaleKubernetesClusterSize(nodeType);
             }
@@ -587,43 +588,45 @@ public class KubernetesClusterScaleWorker extends 
KubernetesClusterResourceModif
         return true;
     }
 
-    private Long getKubernetesClusterNodeTypeOfferingId(KubernetesCluster 
kubernetesCluster, KubernetesClusterNodeType nodeType) {
-        if (nodeType == WORKER) {
-            return kubernetesCluster.getWorkerNodeServiceOfferingId();
-        } else if (nodeType == ETCD) {
-            return kubernetesCluster.getEtcdNodeServiceOfferingId();
-        } else if (nodeType == CONTROL) {
-            return kubernetesCluster.getControlNodeServiceOfferingId();
-        }
-        return null;
-    }
-
-    protected boolean 
isServiceOfferingScalingNeededForNodeType(KubernetesClusterNodeType nodeType,
-                                                                Map<String, 
ServiceOffering> map, KubernetesCluster kubernetesCluster) {
-        // DEFAULT node type means only the global service offering has been 
set for the Kubernetes cluster
-        Long existingOfferingId = map.containsKey(DEFAULT.name()) ?
-                kubernetesCluster.getServiceOfferingId() :
-                getExistingOfferingIdForNodeType(nodeType, kubernetesCluster);
+    private ServiceOffering 
getExistingServiceOfferingForNodeType(KubernetesClusterNodeType nodeType, 
KubernetesCluster kubernetesCluster) {
+        Long existingOfferingId = getExistingOfferingIdForNodeType(nodeType, 
kubernetesCluster);
         if (existingOfferingId == null) {
-            logAndThrow(Level.ERROR, String.format("The Kubernetes cluster %s 
does not have a global service offering set", kubernetesCluster.getName()));
+            logAndThrow(Level.ERROR, String.format("The Kubernetes cluster %s 
does not have a service offering set for node type %s",
+                    kubernetesCluster.getName(), nodeType.name()));
         }
         ServiceOffering existingOffering = 
serviceOfferingDao.findById(existingOfferingId);
         if (existingOffering == null) {
-            logAndThrow(Level.ERROR, String.format("Cannot find the global 
service offering with ID %s set on the Kubernetes cluster %s", 
existingOfferingId, kubernetesCluster.getName()));
+            logAndThrow(Level.ERROR, String.format("Cannot find service 
offering with ID %s set on the Kubernetes cluster %s node type %s",
+                    existingOfferingId, kubernetesCluster.getName(), 
nodeType.name()));
+        }
+        return existingOffering;
+    }
+
+    protected void compareExistingToScalingServiceOfferingForNodeType(Long 
existingOfferingId, Long scalingOfferingId,
+                                                                      
KubernetesClusterNodeType nodeType) {
+        if (existingOfferingId.equals(scalingOfferingId)) {
+            String err = String.format("Cannot scale the nodes of type %s as 
the provided offering %s " +
+                    "is the same as the existing offering", nodeType.name(), 
scalingOfferingId);
+            logger.error(err);
+            throw new CloudRuntimeException(err);
         }
-        ServiceOffering newOffering = map.containsKey(DEFAULT.name()) ? 
map.get(DEFAULT.name()) : map.get(nodeType.name());
-        return newOffering != null && newOffering.getId() != 
existingOffering.getId();
+    }
+
+    protected boolean 
isServiceOfferingScalingNeededForNodeType(ServiceOffering 
existingServiceOffering,
+                                                                
ServiceOffering scalingServiceOffering) {
+        return scalingServiceOffering != null && existingServiceOffering != 
null &&
+                scalingServiceOffering.getId() != 
existingServiceOffering.getId();
     }
 
     protected Long getExistingOfferingIdForNodeType(KubernetesClusterNodeType 
nodeType, KubernetesCluster kubernetesCluster) {
         List<KubernetesClusterVmMapVO> clusterVms = 
kubernetesClusterVmMapDao.listByClusterIdAndVmType(kubernetesCluster.getId(), 
nodeType);
         if (CollectionUtils.isEmpty(clusterVms)) {
-            return null;
+            return kubernetesCluster.getServiceOfferingId();
         }
         KubernetesClusterVmMapVO clusterVm = clusterVms.get(0);
         UserVmVO clusterUserVm = userVmDao.findById(clusterVm.getVmId());
         if (clusterUserVm == null) {
-            return null;
+            return kubernetesCluster.getServiceOfferingId();
         }
         return clusterUserVm.getServiceOfferingId();
     }

Reply via email to