@@ -2357,6 +2357,7 @@ public boolean addNodesToKubernetesCluster(AddNodesToKubernetesClusterCmd cmd) {
23572357 if (validNodeIds .isEmpty ()) {
23582358 throw new CloudRuntimeException ("No valid nodes found to be added to the Kubernetes cluster" );
23592359 }
2360+ validateNodeAffinityGroups (validNodeIds , kubernetesCluster );
23602361 KubernetesClusterAddWorker addWorker = new KubernetesClusterAddWorker (kubernetesCluster , KubernetesClusterManagerImpl .this );
23612362 addWorker = ComponentContext .inject (addWorker );
23622363 return addWorker .addNodesToCluster (validNodeIds , cmd .isMountCksIsoOnVr (), cmd .isManualUpgrade ());
@@ -2416,6 +2417,83 @@ private List<Long> validateNodes(List<Long> nodeIds, Long networkId, String netw
24162417 return validNodeIds ;
24172418 }
24182419
2420+ protected void validateNodeAffinityGroups (List <Long > nodeIds , KubernetesCluster cluster ) {
2421+ List <Long > workerAffinityGroupIds = kubernetesClusterAffinityGroupMapDao .listAffinityGroupIdsByClusterIdAndNodeType (
2422+ cluster .getId (), WORKER .name ());
2423+ if (CollectionUtils .isEmpty (workerAffinityGroupIds )) {
2424+ return ;
2425+ }
2426+
2427+ List <KubernetesClusterVmMapVO > existingWorkerVms = kubernetesClusterVmMapDao .listByClusterIdAndVmType (cluster .getId (), WORKER );
2428+ Set <Long > existingWorkerHostIds = new HashSet <>();
2429+ for (KubernetesClusterVmMapVO workerVmMap : existingWorkerVms ) {
2430+ VMInstanceVO workerVm = vmInstanceDao .findById (workerVmMap .getVmId ());
2431+ if (workerVm != null && workerVm .getHostId () != null ) {
2432+ existingWorkerHostIds .add (workerVm .getHostId ());
2433+ }
2434+ }
2435+
2436+ for (Long affinityGroupId : workerAffinityGroupIds ) {
2437+ AffinityGroupVO affinityGroup = affinityGroupDao .findById (affinityGroupId );
2438+ if (affinityGroup == null ) {
2439+ continue ;
2440+ }
2441+ String affinityGroupType = affinityGroup .getType ();
2442+
2443+ for (Long nodeId : nodeIds ) {
2444+ VMInstanceVO node = vmInstanceDao .findById (nodeId );
2445+ if (node == null || node .getHostId () == null ) {
2446+ continue ;
2447+ }
2448+ Long nodeHostId = node .getHostId ();
2449+ HostVO nodeHost = hostDao .findById (nodeHostId );
2450+ String nodeHostName = nodeHost != null ? nodeHost .getName () : String .valueOf (nodeHostId );
2451+
2452+ if ("host anti-affinity" .equalsIgnoreCase (affinityGroupType )) {
2453+ if (existingWorkerHostIds .contains (nodeHostId )) {
2454+ throw new InvalidParameterValueException (String .format (
2455+ "Cannot add VM %s to cluster %s. VM is running on host %s which violates the cluster's " +
2456+ "host anti-affinity rule (affinity group: %s). Existing worker VMs are already running on this host." ,
2457+ node .getInstanceName (), cluster .getName (), nodeHostName , affinityGroup .getName ()));
2458+ }
2459+ } else if ("host affinity" .equalsIgnoreCase (affinityGroupType )) {
2460+ if (!existingWorkerHostIds .isEmpty () && !existingWorkerHostIds .contains (nodeHostId )) {
2461+ List <String > existingHostNames = new ArrayList <>();
2462+ for (Long hostId : existingWorkerHostIds ) {
2463+ HostVO host = hostDao .findById (hostId );
2464+ existingHostNames .add (host != null ? host .getName () : String .valueOf (hostId ));
2465+ }
2466+ throw new InvalidParameterValueException (String .format (
2467+ "Cannot add VM %s to cluster %s. VM is running on host %s which violates the cluster's " +
2468+ "host affinity rule (affinity group: %s). All worker VMs must run on the same host. " +
2469+ "Existing workers are on host(s): %s." ,
2470+ node .getInstanceName (), cluster .getName (), nodeHostName , affinityGroup .getName (),
2471+ String .join (", " , existingHostNames )));
2472+ }
2473+ }
2474+ }
2475+
2476+ if ("host anti-affinity" .equalsIgnoreCase (affinityGroupType )) {
2477+ Set <Long > newNodeHostIds = new HashSet <>();
2478+ for (Long nodeId : nodeIds ) {
2479+ VMInstanceVO node = vmInstanceDao .findById (nodeId );
2480+ if (node != null && node .getHostId () != null ) {
2481+ Long nodeHostId = node .getHostId ();
2482+ if (newNodeHostIds .contains (nodeHostId )) {
2483+ HostVO nodeHost = hostDao .findById (nodeHostId );
2484+ String nodeHostName = nodeHost != null ? nodeHost .getName () : String .valueOf (nodeHostId );
2485+ throw new InvalidParameterValueException (String .format (
2486+ "Cannot add VM %s to cluster %s. Multiple VMs being added are running on the same host %s, " +
2487+ "which violates the cluster's host anti-affinity rule (affinity group: %s)." ,
2488+ node .getInstanceName (), cluster .getName (), nodeHostName , affinityGroup .getName ()));
2489+ }
2490+ newNodeHostIds .add (nodeHostId );
2491+ }
2492+ }
2493+ }
2494+ }
2495+ }
2496+
24192497 @ Override
24202498 public List <RemoveVirtualMachinesFromKubernetesClusterResponse > removeVmsFromCluster (RemoveVirtualMachinesFromKubernetesClusterCmd cmd ) {
24212499 if (!KubernetesServiceEnabled .value ()) {
0 commit comments