From f103c43f0984e4e89c21cc751061f3fc3979889e Mon Sep 17 00:00:00 2001 From: Nicolas Vazquez Date: Thu, 2 May 2024 08:41:28 -0300 Subject: [PATCH] CKS Mark Nodes for Manual Upgrade and Filter Nodes to add to CKS cluster from the same network --- .../apache/cloudstack/api/ApiConstants.java | 1 + .../META-INF/db/schema-41810to41900.sql | 1 + .../cluster/KubernetesClusterManagerImpl.java | 8 +- .../cluster/KubernetesClusterVmMapVO.java | 11 +++ .../KubernetesClusterActionWorker.java | 4 +- .../KubernetesClusterAddWorker.java | 8 +- ...esClusterResourceModifierActionWorker.java | 2 +- .../KubernetesClusterStartWorker.java | 4 +- .../KubernetesClusterUpgradeWorker.java | 15 +++- .../AddNodesToKubernetesClusterCmd.java | 11 ++- .../KubernetesClusterUpgradeWorkerTest.java | 83 +++++++++++++++++++ ui/public/locales/en.json | 3 +- ui/src/views/compute/KubernetesAddNodes.vue | 11 ++- 13 files changed, 149 insertions(+), 13 deletions(-) create mode 100644 plugins/integrations/kubernetes-service/src/test/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterUpgradeWorkerTest.java diff --git a/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java b/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java index 72b2d466dd3..c31160ead84 100644 --- a/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java +++ b/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java @@ -295,6 +295,7 @@ public class ApiConstants { public static final String LBID = "lbruleid"; public static final String LB_PROVIDER = "lbprovider"; public static final String MAC_ADDRESS = "macaddress"; + public static final String MANUAL_UPGRADE = "manualupgrade"; public static final String MAX = "max"; public static final String MAX_SNAPS = "maxsnaps"; public static final String MAX_CPU_NUMBER = "maxcpunumber"; diff --git a/engine/schema/src/main/resources/META-INF/db/schema-41810to41900.sql b/engine/schema/src/main/resources/META-INF/db/schema-41810to41900.sql index c1eff3f8a2d..59e3d8c9e39 100644 --- a/engine/schema/src/main/resources/META-INF/db/schema-41810to41900.sql +++ b/engine/schema/src/main/resources/META-INF/db/schema-41810to41900.sql @@ -337,6 +337,7 @@ CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.kubernetes_cluster','worker_template CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.kubernetes_cluster','etcd_template_id', 'bigint unsigned COMMENT "template id to be used for etcd Nodes"'); CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.kubernetes_cluster_vm_map','etcd_node', 'tinyint(1) unsigned NOT NULL DEFAULT 0 COMMENT "indicates if the VM is an etcd node"'); CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.kubernetes_cluster_vm_map','external_node', 'tinyint(1) unsigned NOT NULL DEFAULT 0 COMMENT "indicates if the node was imported into the Kubernetes cluster"'); +CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.kubernetes_cluster_vm_map','manual_upgrade', 'tinyint(1) unsigned NOT NULL DEFAULT 0 COMMENT "indicates if the node is marked for manual upgrade and excluded from the Kubernetes cluster upgrade operation"'); ALTER TABLE `cloud`.`kubernetes_cluster` ADD CONSTRAINT `fk_cluster__control_service_offering_id` FOREIGN KEY `fk_cluster__control_service_offering_id`(`control_service_offering_id`) REFERENCES `service_offering`(`id`) ON DELETE CASCADE; ALTER TABLE `cloud`.`kubernetes_cluster` ADD CONSTRAINT `fk_cluster__worker_service_offering_id` FOREIGN KEY `fk_cluster__worker_service_offering_id`(`worker_service_offering_id`) REFERENCES `service_offering`(`id`) ON DELETE CASCADE; 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 53a6a3670e5..db49ba27252 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 @@ -1855,6 +1855,9 @@ public class KubernetesClusterManagerImpl extends ManagerBase implements Kuberne @Override public boolean addNodesToKubernetesCluster(AddNodesToKubernetesClusterCmd cmd) { + if (!KubernetesServiceEnabled.value()) { + logAndThrow(Level.ERROR, "Kubernetes Service plugin is disabled"); + } KubernetesClusterVO kubernetesCluster = validateCluster(cmd.getClusterId()); long networkId = kubernetesCluster.getNetworkId(); NetworkVO networkVO = networkDao.findById(networkId); @@ -1864,11 +1867,14 @@ public class KubernetesClusterManagerImpl extends ManagerBase implements Kuberne } KubernetesClusterAddWorker addWorker = new KubernetesClusterAddWorker(kubernetesCluster, KubernetesClusterManagerImpl.this); addWorker = ComponentContext.inject(addWorker); - return addWorker.addNodesToCluster(validNodeIds, cmd.isMountCksIsoOnVr()); + return addWorker.addNodesToCluster(validNodeIds, cmd.isMountCksIsoOnVr(), cmd.isManualUpgrade()); } @Override public boolean removeNodesFromKubernetesCluster(RemoveNodesFromKubernetesClusterCmd cmd) throws Exception { + if (!KubernetesServiceEnabled.value()) { + logAndThrow(Level.ERROR, "Kubernetes Service plugin is disabled"); + } KubernetesClusterVO kubernetesCluster = validateCluster(cmd.getClusterId()); List validNodeIds = validateNodes(cmd.getNodeIds(), null, null, kubernetesCluster, true); if (validNodeIds.isEmpty()) { diff --git a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/KubernetesClusterVmMapVO.java b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/KubernetesClusterVmMapVO.java index 804d5b016f8..eace7254081 100644 --- a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/KubernetesClusterVmMapVO.java +++ b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/KubernetesClusterVmMapVO.java @@ -48,6 +48,9 @@ public class KubernetesClusterVmMapVO implements KubernetesClusterVmMap { @Column(name = "external_node") boolean externalNode; + @Column(name = "manual_upgrade") + boolean manualUpgrade; + public KubernetesClusterVmMapVO() { } @@ -105,4 +108,12 @@ public class KubernetesClusterVmMapVO implements KubernetesClusterVmMap { public void setExternalNode(boolean externalNode) { this.externalNode = externalNode; } + + public boolean isManualUpgrade() { + return manualUpgrade; + } + + public void setManualUpgrade(boolean manualUpgrade) { + this.manualUpgrade = manualUpgrade; + } } 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 df3e7675ce8..553245b9075 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 @@ -354,12 +354,14 @@ public class KubernetesClusterActionWorker { return new File(keyFile); } - protected KubernetesClusterVmMapVO addKubernetesClusterVm(final long kubernetesClusterId, final long vmId, boolean isControlNode, boolean isExternalNode) { + protected KubernetesClusterVmMapVO addKubernetesClusterVm(final long kubernetesClusterId, final long vmId, boolean isControlNode, + boolean isExternalNode, boolean markForManualUpgrade) { return Transaction.execute(new TransactionCallback() { @Override public KubernetesClusterVmMapVO doInTransaction(TransactionStatus status) { KubernetesClusterVmMapVO newClusterVmMap = new KubernetesClusterVmMapVO(kubernetesClusterId, vmId, isControlNode); newClusterVmMap.setExternalNode(isExternalNode); + newClusterVmMap.setManualUpgrade(markForManualUpgrade); kubernetesClusterVmMapDao.persist(newClusterVmMap); return newClusterVmMap; } diff --git a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterAddWorker.java b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterAddWorker.java index 935d206e489..8abfc66e23e 100644 --- a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterAddWorker.java +++ b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterAddWorker.java @@ -70,7 +70,7 @@ public class KubernetesClusterAddWorker extends KubernetesClusterActionWorker { super(kubernetesCluster, clusterManager); } - public boolean addNodesToCluster(List nodeIds, boolean mountCksIsoOnVr) throws CloudRuntimeException { + public boolean addNodesToCluster(List nodeIds, boolean mountCksIsoOnVr, boolean manualUpgrade) throws CloudRuntimeException { try { init(); addNodeTimeoutTime = System.currentTimeMillis() + KubernetesClusterService.KubernetesClusterAddNodeTimeout.value() * 1000; @@ -90,7 +90,7 @@ public class KubernetesClusterAddWorker extends KubernetesClusterActionWorker { stateTransitTo(kubernetesCluster.getId(), KubernetesCluster.Event.AddNodeRequested); Ternary nodesAddedAndMemory = importNodeToCluster(nodeIds, network, publicIp, mountCksIsoOnVr); int nodesAdded = nodesAddedAndMemory.first(); - updateKubernetesCluster(kubernetesCluster.getId(), nodesAddedAndMemory); + updateKubernetesCluster(kubernetesCluster.getId(), nodesAddedAndMemory, manualUpgrade); if (nodeIds.size() != nodesAdded) { String msg = String.format("Not every node was added to the CKS cluster %s, nodes added: %s out of %s", kubernetesCluster.getUuid(), nodesAdded, nodeIds.size()); logger.info(msg); @@ -255,7 +255,7 @@ public class KubernetesClusterAddWorker extends KubernetesClusterActionWorker { return new Pair<>(true, ++nodeIndex); } - private void updateKubernetesCluster(long clusterId, Ternary additionalNodesDetails) { + private void updateKubernetesCluster(long clusterId, Ternary additionalNodesDetails, boolean manualUpgrade) { int additionalNodeCount = additionalNodesDetails.first(); KubernetesClusterVO kubernetesClusterVO = kubernetesClusterDao.findById(clusterId); kubernetesClusterVO.setNodeCount(kubernetesClusterVO.getNodeCount() + additionalNodeCount); @@ -264,7 +264,7 @@ public class KubernetesClusterAddWorker extends KubernetesClusterActionWorker { kubernetesClusterDao.update(clusterId, kubernetesClusterVO); kubernetesCluster = kubernetesClusterVO; - finalNodeIds.forEach(id -> addKubernetesClusterVm(clusterId, id, false, true)); + finalNodeIds.forEach(id -> addKubernetesClusterVm(clusterId, id, false, true, manualUpgrade)); } 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 df5a58f7bdf..b4a2bd363b5 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 @@ -363,7 +363,7 @@ public class KubernetesClusterResourceModifierActionWorker extends KubernetesClu List nodes = new ArrayList<>(); for (int i = offset + 1; i <= nodeCount; i++) { UserVm vm = createKubernetesNode(publicIpAddress); - addKubernetesClusterVm(kubernetesCluster.getId(), vm.getId(), false, false); + addKubernetesClusterVm(kubernetesCluster.getId(), vm.getId(), false, false, false); if (kubernetesCluster.getNodeRootDiskSize() > 0) { resizeNodeVolume(vm); } diff --git a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterStartWorker.java b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterStartWorker.java index 8a4685251d2..160d8869adb 100644 --- a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterStartWorker.java +++ b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterStartWorker.java @@ -331,7 +331,7 @@ public class KubernetesClusterStartWorker extends KubernetesClusterResourceModif ManagementServerException, InsufficientCapacityException, ResourceUnavailableException { UserVm k8sControlVM = null; k8sControlVM = createKubernetesControlNode(network, publicIpAddress); - addKubernetesClusterVm(kubernetesCluster.getId(), k8sControlVM.getId(), true, false); + addKubernetesClusterVm(kubernetesCluster.getId(), k8sControlVM.getId(), true, false, false); if (kubernetesCluster.getNodeRootDiskSize() > 0) { resizeNodeVolume(k8sControlVM); } @@ -353,7 +353,7 @@ public class KubernetesClusterStartWorker extends KubernetesClusterResourceModif for (int i = 1; i < kubernetesCluster.getControlNodeCount(); i++) { UserVm vm = null; vm = createKubernetesAdditionalControlNode(publicIpAddress, i); - addKubernetesClusterVm(kubernetesCluster.getId(), vm.getId(), true, false); + addKubernetesClusterVm(kubernetesCluster.getId(), vm.getId(), true, false, false); if (kubernetesCluster.getNodeRootDiskSize() > 0) { resizeNodeVolume(vm); } diff --git a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterUpgradeWorker.java b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterUpgradeWorker.java index 4fefa54a6d9..f80a5f0a16d 100644 --- a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterUpgradeWorker.java +++ b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterUpgradeWorker.java @@ -20,7 +20,9 @@ package com.cloud.kubernetes.cluster.actionworkers; import java.io.File; import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; +import com.cloud.kubernetes.cluster.KubernetesClusterVmMapVO; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.Level; @@ -40,7 +42,7 @@ import com.cloud.utils.ssh.SshHelper; public class KubernetesClusterUpgradeWorker extends KubernetesClusterActionWorker { - private List clusterVMs = new ArrayList<>(); + protected List clusterVMs = new ArrayList<>(); private KubernetesSupportedVersion upgradeVersion; private final String upgradeScriptFilename = "upgrade-kubernetes.sh"; private File upgradeScriptFile; @@ -171,6 +173,7 @@ public class KubernetesClusterUpgradeWorker extends KubernetesClusterActionWorke if (CollectionUtils.isEmpty(clusterVMs)) { logAndThrow(Level.ERROR, String.format("Upgrade failed for Kubernetes cluster : %s, unable to retrieve VMs for cluster", kubernetesCluster.getName())); } + filterOutManualUpgradeNodesFromClusterUpgrade(); retrieveScriptFiles(); stateTransitTo(kubernetesCluster.getId(), KubernetesCluster.Event.UpgradeRequested); attachIsoKubernetesVMs(clusterVMs, upgradeVersion); @@ -186,4 +189,14 @@ public class KubernetesClusterUpgradeWorker extends KubernetesClusterActionWorke } return updated; } + + protected void filterOutManualUpgradeNodesFromClusterUpgrade() { + if (CollectionUtils.isEmpty(clusterVMs)) { + return; + } + clusterVMs = clusterVMs.stream().filter(x -> { + KubernetesClusterVmMapVO mapVO = kubernetesClusterVmMapDao.getClusterMapFromVmId(x.getId()); + return mapVO != null && !mapVO.isManualUpgrade(); + }).collect(Collectors.toList()); + } } diff --git a/plugins/integrations/kubernetes-service/src/main/java/org/apache/cloudstack/api/command/user/kubernetes/cluster/AddNodesToKubernetesClusterCmd.java b/plugins/integrations/kubernetes-service/src/main/java/org/apache/cloudstack/api/command/user/kubernetes/cluster/AddNodesToKubernetesClusterCmd.java index 3392928d225..f8bea80e67b 100644 --- a/plugins/integrations/kubernetes-service/src/main/java/org/apache/cloudstack/api/command/user/kubernetes/cluster/AddNodesToKubernetesClusterCmd.java +++ b/plugins/integrations/kubernetes-service/src/main/java/org/apache/cloudstack/api/command/user/kubernetes/cluster/AddNodesToKubernetesClusterCmd.java @@ -31,6 +31,7 @@ import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.response.KubernetesClusterResponse; import org.apache.cloudstack.api.response.UserVmResponse; import org.apache.cloudstack.context.CallContext; +import org.apache.commons.lang3.BooleanUtils; import org.apache.log4j.Logger; import javax.inject.Inject; @@ -69,6 +70,10 @@ public class AddNodesToKubernetesClusterCmd extends BaseAsyncCmd { since = "4.20.0") private Boolean mountCksIsoOnVr; + @Parameter(name = ApiConstants.MANUAL_UPGRADE, type = CommandType.BOOLEAN, + description = "(optional) indicates if the node is marked for manual upgrade and excluded from the Kubernetes cluster upgrade operation", + since = "4.20.0") + private Boolean manualUpgrade; ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// @@ -83,7 +88,11 @@ public class AddNodesToKubernetesClusterCmd extends BaseAsyncCmd { } public boolean isMountCksIsoOnVr() { - return mountCksIsoOnVr != null && mountCksIsoOnVr; + return BooleanUtils.isTrue(mountCksIsoOnVr); + } + + public boolean isManualUpgrade() { + return BooleanUtils.isTrue(manualUpgrade); } ///////////////////////////////////////////////////// diff --git a/plugins/integrations/kubernetes-service/src/test/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterUpgradeWorkerTest.java b/plugins/integrations/kubernetes-service/src/test/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterUpgradeWorkerTest.java new file mode 100644 index 00000000000..ff8f875d06e --- /dev/null +++ b/plugins/integrations/kubernetes-service/src/test/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterUpgradeWorkerTest.java @@ -0,0 +1,83 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package com.cloud.kubernetes.cluster.actionworkers; + +import com.cloud.kubernetes.cluster.KubernetesCluster; +import com.cloud.kubernetes.cluster.KubernetesClusterManagerImpl; +import com.cloud.kubernetes.cluster.KubernetesClusterVmMapVO; +import com.cloud.kubernetes.cluster.dao.KubernetesClusterVmMapDao; +import com.cloud.kubernetes.version.KubernetesSupportedVersion; +import com.cloud.uservm.UserVm; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +@RunWith(MockitoJUnitRunner.class) +public class KubernetesClusterUpgradeWorkerTest { + + @Mock + private KubernetesCluster kubernetesCluster; + @Mock + private KubernetesSupportedVersion kubernetesSupportedVersion; + @Mock + private KubernetesClusterManagerImpl clusterManager; + @Mock + private KubernetesClusterVmMapDao kubernetesClusterVmMapDao; + + private KubernetesClusterUpgradeWorker worker; + + @Before + public void setUp() { + String[] keys = {}; + worker = new KubernetesClusterUpgradeWorker(kubernetesCluster, kubernetesSupportedVersion, clusterManager, keys); + worker.kubernetesClusterVmMapDao = kubernetesClusterVmMapDao; + } + + @Test + public void testFilterOutManualUpgradeNodesFromClusterUpgrade() { + long controlNodeId = 1L; + long workerNode1Id = 2L; + long workerNode2Id = 3L; + UserVm controlNode = Mockito.mock(UserVm.class); + Mockito.when(controlNode.getId()).thenReturn(controlNodeId); + UserVm workerNode1 = Mockito.mock(UserVm.class); + Mockito.when(workerNode1.getId()).thenReturn(workerNode1Id); + UserVm workerNode2 = Mockito.mock(UserVm.class); + Mockito.when(workerNode2.getId()).thenReturn(workerNode2Id); + KubernetesClusterVmMapVO controlNodeMap = Mockito.mock(KubernetesClusterVmMapVO.class); + KubernetesClusterVmMapVO workerNode1Map = Mockito.mock(KubernetesClusterVmMapVO.class); + KubernetesClusterVmMapVO workerNode2Map = Mockito.mock(KubernetesClusterVmMapVO.class); + Mockito.when(workerNode2Map.isManualUpgrade()).thenReturn(true); + Mockito.when(kubernetesClusterVmMapDao.getClusterMapFromVmId(controlNodeId)).thenReturn(controlNodeMap); + Mockito.when(kubernetesClusterVmMapDao.getClusterMapFromVmId(workerNode1Id)).thenReturn(workerNode1Map); + Mockito.when(kubernetesClusterVmMapDao.getClusterMapFromVmId(workerNode2Id)).thenReturn(workerNode2Map); + worker.clusterVMs = Arrays.asList(controlNode, workerNode1, workerNode2); + worker.filterOutManualUpgradeNodesFromClusterUpgrade(); + Assert.assertEquals(2, worker.clusterVMs.size()); + List ids = worker.clusterVMs.stream().map(UserVm::getId).collect(Collectors.toList()); + Assert.assertTrue(ids.contains(controlNodeId) && ids.contains(workerNode1Id)); + Assert.assertFalse(ids.contains(workerNode2Id)); + } +} diff --git a/ui/public/locales/en.json b/ui/public/locales/en.json index 7e52486aa3d..65b44209b38 100644 --- a/ui/public/locales/en.json +++ b/ui/public/locales/en.json @@ -469,6 +469,7 @@ "label.cks.cluster.etcd.nodes.templateid": "Template for etcd Nodes", "label.cks.cluster.maxsize": "Maximum cluster size (Worker nodes)", "label.cks.cluster.minsize": "Minimum cluster size (Worker nodes)", +"label.cks.cluster.node.manual.upgrade": "Mark nodes for manual upgrade", "label.cks.cluster.size": "Cluster size (Worker nodes)", "label.cks.cluster.worker.nodes.offeringid": "Service Offering for Worker Nodes", "label.cks.cluster.worker.nodes.templateid": "Template for Worker Nodes", @@ -1380,7 +1381,7 @@ "label.monitor.url": "URL Path", "label.monthly": "Monthly", "label.more.access.dashboard.ui": "More about accessing dashboard UI", -"label.mount.cks.iso.on.vr": "Mount and serve CKS ISO on the CKS cluster's network Virtual Router", +"label.mount.cks.iso.on.vr": "Use CKS packages from Virtual Router", "label.move.down.row": "Move down one row", "label.move.to.bottom": "Move to bottom", "label.move.to.top": "Move to top", diff --git a/ui/src/views/compute/KubernetesAddNodes.vue b/ui/src/views/compute/KubernetesAddNodes.vue index d6d8dc72731..dddcc90be25 100644 --- a/ui/src/views/compute/KubernetesAddNodes.vue +++ b/ui/src/views/compute/KubernetesAddNodes.vue @@ -48,6 +48,11 @@ {{ $t('label.mount.cks.iso.on.vr') }} + + + {{ $t('label.cks.cluster.node.manual.upgrade') }} + +

@@ -111,7 +116,8 @@ export default { accountId: accountId, domainId: domainId, details: 'min', - listall: 'true' + listall: 'true', + networkid: this.resource.networkid }).then(json => { const vms = json.listvirtualmachinesresponse.virtualmachine || [] resolve(vms) @@ -135,6 +141,9 @@ export default { if (values.mountcksiso) { params.mountcksisoonvr = values.mountcksiso } + if (values.manualupgrade) { + params.manualupgrade = values.manualupgrade + } this.loading = true try { const jobId = await this.addNodesToKubernetesCluster(params)