From 4da3bcec83c55d084e1840104e2e9d4ff0757b3f Mon Sep 17 00:00:00 2001 From: Daman Arora Date: Tue, 6 Jan 2026 12:38:23 -0500 Subject: [PATCH] Update affinity group handling to support multiple IDs in KubernetesServiceHelper and related classes --- .../cluster/KubernetesServiceHelper.java | 2 +- .../cluster/KubernetesClusterManagerImpl.java | 8 +-- .../cluster/KubernetesServiceHelperImpl.java | 58 +++++++++++++------ .../cluster/CreateKubernetesClusterCmd.java | 2 +- 4 files changed, 46 insertions(+), 24 deletions(-) diff --git a/api/src/main/java/com/cloud/kubernetes/cluster/KubernetesServiceHelper.java b/api/src/main/java/com/cloud/kubernetes/cluster/KubernetesServiceHelper.java index a9f76c174b5..1bda7019d1d 100644 --- a/api/src/main/java/com/cloud/kubernetes/cluster/KubernetesServiceHelper.java +++ b/api/src/main/java/com/cloud/kubernetes/cluster/KubernetesServiceHelper.java @@ -36,6 +36,6 @@ public interface KubernetesServiceHelper extends Adapter { boolean isValidNodeType(String nodeType); Map getServiceOfferingNodeTypeMap(Map> serviceOfferingNodeTypeMap); Map getTemplateNodeTypeMap(Map> templateNodeTypeMap); - Map getAffinityGroupNodeTypeMap(Map> affinityGroupNodeTypeMap); + Map getAffinityGroupNodeTypeMap(Map> affinityGroupNodeTypeMap); void cleanupForAccount(Account account); } 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 66b491f2c31..8699eeb3547 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 @@ -1627,7 +1627,7 @@ public class KubernetesClusterManagerImpl extends ManagerBase implements Kuberne } Map templateNodeTypeMap = cmd.getTemplateNodeTypeMap(); - Map affinityGroupNodeTypeMap = cmd.getAffinityGroupNodeTypeMap(); + Map affinityGroupNodeTypeMap = cmd.getAffinityGroupNodeTypeMap(); final VMTemplateVO finalTemplate = getKubernetesServiceTemplate(zone, hypervisorType, templateNodeTypeMap, DEFAULT, clusterKubernetesVersion); final VMTemplateVO controlNodeTemplate = getKubernetesServiceTemplate(zone, hypervisorType, templateNodeTypeMap, CONTROL, clusterKubernetesVersion); final VMTemplateVO workerNodeTemplate = getKubernetesServiceTemplate(zone, hypervisorType, templateNodeTypeMap, WORKER, clusterKubernetesVersion); @@ -1669,13 +1669,13 @@ public class KubernetesClusterManagerImpl extends ManagerBase implements Kuberne newCluster.setWorkerNodeTemplateId(workerNodeTemplate.getId()); newCluster.setControlNodeTemplateId(controlNodeTemplate.getId()); if (affinityGroupNodeTypeMap.containsKey(WORKER.name())) { - newCluster.setWorkerNodeAffinityGroupId(affinityGroupNodeTypeMap.get(WORKER.name())); + newCluster.setWorkerNodeAffinityGroupIds(affinityGroupNodeTypeMap.get(WORKER.name())); } if (affinityGroupNodeTypeMap.containsKey(CONTROL.name())) { - newCluster.setControlNodeAffinityGroupId(affinityGroupNodeTypeMap.get(CONTROL.name())); + newCluster.setControlNodeAffinityGroupIds(affinityGroupNodeTypeMap.get(CONTROL.name())); } if (etcdNodes > 0 && affinityGroupNodeTypeMap.containsKey(ETCD.name())) { - newCluster.setEtcdNodeAffinityGroupId(affinityGroupNodeTypeMap.get(ETCD.name())); + newCluster.setEtcdNodeAffinityGroupIds(affinityGroupNodeTypeMap.get(ETCD.name())); } if (zone.isSecurityGroupEnabled()) { newCluster.setSecurityGroupId(finalSecurityGroup.getId()); diff --git a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/KubernetesServiceHelperImpl.java b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/KubernetesServiceHelperImpl.java index 62e190b35bd..85a4191ed20 100644 --- a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/KubernetesServiceHelperImpl.java +++ b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/KubernetesServiceHelperImpl.java @@ -248,8 +248,8 @@ public class KubernetesServiceHelperImpl extends AdapterBase implements Kubernet return mapping; } - protected void checkNodeTypeAffinityGroupEntryCompleteness(String nodeTypeStr, String affinityGroupUuid) { - if (StringUtils.isAnyBlank(nodeTypeStr, affinityGroupUuid)) { + protected void checkNodeTypeAffinityGroupEntryCompleteness(String nodeTypeStr, String affinityGroupUuids) { + if (StringUtils.isAnyBlank(nodeTypeStr, affinityGroupUuids)) { String error = String.format("Any Node Type to Affinity Group entry should have a valid '%s' and '%s' values", VmDetailConstants.CKS_NODE_TYPE, VmDetailConstants.AFFINITY_GROUP); logger.error(error); @@ -257,12 +257,21 @@ public class KubernetesServiceHelperImpl extends AdapterBase implements Kubernet } } - protected void checkNodeTypeAffinityGroupEntryValues(String nodeTypeStr, AffinityGroup affinityGroup, String affinityGroupUuid) { + protected void checkNodeTypeAffinityGroupEntryNodeType(String nodeTypeStr) { if (!isValidNodeType(nodeTypeStr)) { String error = String.format("The provided value '%s' for Node Type is invalid", nodeTypeStr); logger.error(error); - throw new InvalidParameterValueException(String.format(error)); + throw new InvalidParameterValueException(error); } + } + + protected void validateAffinityGroupUuid(String affinityGroupUuid) { + if (StringUtils.isBlank(affinityGroupUuid)) { + String error = "Empty affinity group UUID provided"; + logger.error(error); + throw new InvalidParameterValueException(error); + } + AffinityGroup affinityGroup = affinityGroupDao.findByUuid(affinityGroupUuid); if (affinityGroup == null) { String error = String.format("Cannot find an affinity group with ID %s", affinityGroupUuid); logger.error(error); @@ -270,31 +279,44 @@ public class KubernetesServiceHelperImpl extends AdapterBase implements Kubernet } } - protected void addNodeTypeAffinityGroupEntry(String nodeTypeStr, String affinityGroupUuid, AffinityGroup affinityGroup, Map mapping) { - if (logger.isDebugEnabled()) { - logger.debug(String.format("Node Type: '%s' should use affinity group ID: '%s'", nodeTypeStr, affinityGroupUuid)); + protected String validateAndNormalizeAffinityGroupUuids(String affinityGroupUuids) { + String[] uuids = affinityGroupUuids.split(","); + StringBuilder normalizedUuids = new StringBuilder(); + for (int i = 0; i < uuids.length; i++) { + String uuid = uuids[i].trim(); + validateAffinityGroupUuid(uuid); + if (i > 0) { + normalizedUuids.append(","); + } + normalizedUuids.append(uuid); } - KubernetesClusterNodeType nodeType = KubernetesClusterNodeType.valueOf(nodeTypeStr.toUpperCase()); - mapping.put(nodeType.name(), affinityGroup.getId()); + return normalizedUuids.toString(); } - protected void processNodeTypeAffinityGroupEntryAndAddToMappingIfValid(Map entry, Map mapping) { + protected void addNodeTypeAffinityGroupEntry(String nodeTypeStr, String validatedAffinityGroupUuids, Map mapping) { + if (logger.isDebugEnabled()) { + logger.debug(String.format("Node Type: '%s' should use affinity group IDs: '%s'", nodeTypeStr, validatedAffinityGroupUuids)); + } + KubernetesClusterNodeType nodeType = KubernetesClusterNodeType.valueOf(nodeTypeStr.toUpperCase()); + mapping.put(nodeType.name(), validatedAffinityGroupUuids); + } + + protected void processNodeTypeAffinityGroupEntryAndAddToMappingIfValid(Map entry, Map mapping) { if (MapUtils.isEmpty(entry)) { return; } String nodeTypeStr = entry.get(VmDetailConstants.CKS_NODE_TYPE); - String affinityGroupUuid = entry.get(VmDetailConstants.AFFINITY_GROUP); - checkNodeTypeAffinityGroupEntryCompleteness(nodeTypeStr, affinityGroupUuid); + String affinityGroupUuids = entry.get(VmDetailConstants.AFFINITY_GROUP); + checkNodeTypeAffinityGroupEntryCompleteness(nodeTypeStr, affinityGroupUuids); + checkNodeTypeAffinityGroupEntryNodeType(nodeTypeStr); - AffinityGroup affinityGroup = affinityGroupDao.findByUuid(affinityGroupUuid); - checkNodeTypeAffinityGroupEntryValues(nodeTypeStr, affinityGroup, affinityGroupUuid); - - addNodeTypeAffinityGroupEntry(nodeTypeStr, affinityGroupUuid, affinityGroup, mapping); + String validatedUuids = validateAndNormalizeAffinityGroupUuids(affinityGroupUuids); + addNodeTypeAffinityGroupEntry(nodeTypeStr, validatedUuids, mapping); } @Override - public Map getAffinityGroupNodeTypeMap(Map> affinityGroupNodeTypeMap) { - Map mapping = new HashMap<>(); + public Map getAffinityGroupNodeTypeMap(Map> affinityGroupNodeTypeMap) { + Map mapping = new HashMap<>(); if (MapUtils.isNotEmpty(affinityGroupNodeTypeMap)) { for (Map entry : affinityGroupNodeTypeMap.values()) { processNodeTypeAffinityGroupEntryAndAddToMappingIfValid(entry, mapping); diff --git a/plugins/integrations/kubernetes-service/src/main/java/org/apache/cloudstack/api/command/user/kubernetes/cluster/CreateKubernetesClusterCmd.java b/plugins/integrations/kubernetes-service/src/main/java/org/apache/cloudstack/api/command/user/kubernetes/cluster/CreateKubernetesClusterCmd.java index 4e458bbe6d7..1ab88cb1372 100644 --- a/plugins/integrations/kubernetes-service/src/main/java/org/apache/cloudstack/api/command/user/kubernetes/cluster/CreateKubernetesClusterCmd.java +++ b/plugins/integrations/kubernetes-service/src/main/java/org/apache/cloudstack/api/command/user/kubernetes/cluster/CreateKubernetesClusterCmd.java @@ -327,7 +327,7 @@ public class CreateKubernetesClusterCmd extends BaseAsyncCreateCmd { return kubernetesServiceHelper.getTemplateNodeTypeMap(templateNodeTypeMap); } - public Map getAffinityGroupNodeTypeMap() { + public Map getAffinityGroupNodeTypeMap() { return kubernetesServiceHelper.getAffinityGroupNodeTypeMap(affinityGroupNodeTypeMap); }