From 231a9eae2eb606def265af54c4eaa8fb8c7fc526 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Fri, 8 Dec 2023 21:38:35 +0530 Subject: [PATCH 1/4] ui: add action to declare/cancel host as degraded (#8327) --- ui/public/locales/en.json | 2 ++ ui/src/config/section/infra/hosts.js | 20 ++++++++++++++++++++ ui/src/core/lazy_lib/icons_use.js | 4 ++++ 3 files changed, 26 insertions(+) diff --git a/ui/public/locales/en.json b/ui/public/locales/en.json index 69a794079b5..67351fd21b7 100644 --- a/ui/public/locales/en.json +++ b/ui/public/locales/en.json @@ -404,6 +404,7 @@ "label.cachemode": "Write-cache type", "label.cancel": "Cancel", "label.cancelmaintenance": "Cancel maintenance", +"label.cancel.host.as.degraded": "Cancel host as degraded", "label.capacity": "Capacity", "label.capacitybytes": "Capacity bytes", "label.capacityiops": "IOPS total", @@ -570,6 +571,7 @@ "label.db.usage.metrics": "DB/Usage server", "label.dbislocal": "The db runs locally", "label.dc.name": "DC name", +"label.declare.host.as.degraded": "Declare host as degraded", "label.decline.invitation": "Decline invitation", "label.dedicate": "Dedicate", "label.dedicate.cluster": "Dedicate cluster", diff --git a/ui/src/config/section/infra/hosts.js b/ui/src/config/section/infra/hosts.js index 9f2c6292052..cb0de90b26c 100644 --- a/ui/src/config/section/infra/hosts.js +++ b/ui/src/config/section/infra/hosts.js @@ -290,6 +290,26 @@ export default { } } }, + { + api: 'declareHostAsDegraded', + icon: 'exception-outlined', + label: 'label.declare.host.as.degraded', + message: 'label.declare.host.as.degraded', + dataView: true, + show: (record) => { + return record.resourcestate !== 'Degraded' && (record.state === 'Alert' || record.state === 'Disconnected') + } + }, + { + api: 'cancelHostAsDegraded', + icon: 'file-done-outlined', + label: 'label.cancel.host.as.degraded', + message: 'label.cancel.host.as.degraded', + dataView: true, + show: (record) => { + return record.resourcestate === 'Degraded' + } + }, { api: 'deleteHost', icon: 'delete-outlined', diff --git a/ui/src/core/lazy_lib/icons_use.js b/ui/src/core/lazy_lib/icons_use.js index ec2d67deaf9..bbda90e3bef 100644 --- a/ui/src/core/lazy_lib/icons_use.js +++ b/ui/src/core/lazy_lib/icons_use.js @@ -72,10 +72,12 @@ import { DragOutlined, EditOutlined, EnvironmentOutlined, + ExceptionOutlined, ExclamationCircleOutlined, EyeInvisibleOutlined, EyeOutlined, FieldTimeOutlined, + FileDoneOutlined, FileProtectOutlined, FilterOutlined, FilterTwoTone, @@ -226,10 +228,12 @@ export default { app.component('DragOutlined', DragOutlined) app.component('EditOutlined', EditOutlined) app.component('EnvironmentOutlined', EnvironmentOutlined) + app.component('ExceptionOutlined', ExceptionOutlined) app.component('ExclamationCircleOutlined', ExclamationCircleOutlined) app.component('EyeInvisibleOutlined', EyeInvisibleOutlined) app.component('EyeOutlined', EyeOutlined) app.component('FieldTimeOutlined', FieldTimeOutlined) + app.component('FileDoneOutlined', FileDoneOutlined) app.component('FileProtectOutlined', FileProtectOutlined) app.component('FilterOutlined', FilterOutlined) app.component('FilterTwoTone', FilterTwoTone) From fc44df7c95e50ceefb89cc18b1af088d1142fd3c Mon Sep 17 00:00:00 2001 From: Wei Zhou Date: Sat, 9 Dec 2023 07:03:05 +0100 Subject: [PATCH 2/4] CKS: create HA cluster with 3 control VMs instead 2 (#8297) This PR fixes the test failures with CKS HA-cluster upgrade. In production, the CKS HA cluster should have at least 3 control VMs as well. The etcd cluster requires 3 members to achieve reliable HA. The etcd daemon in control VMs uses RAFT protocol to determine the roles of nodes. During upgrade of CKS with HA, the etcd become unreliable if there are only 2 control VMs. --- .../actionworkers/KubernetesClusterUpgradeWorker.java | 2 +- .../src/main/resources/script/upgrade-kubernetes.sh | 2 +- test/integration/smoke/test_kubernetes_clusters.py | 10 +++++----- ui/src/views/compute/CreateKubernetesCluster.vue | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) 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 9b7b6ca47c2..14f5760d5ae 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 @@ -91,7 +91,7 @@ public class KubernetesClusterUpgradeWorker extends KubernetesClusterActionWorke } try { result = SshHelper.sshExecute(publicIpAddress, sshPort, getControlNodeLoginUser(), sshKeyFile, null, - String.format("sudo /opt/bin/kubectl drain %s --ignore-daemonsets --delete-local-data", hostName), + String.format("sudo /opt/bin/kubectl drain %s --ignore-daemonsets --delete-emptydir-data", hostName), 10000, 10000, 60000); } catch (Exception e) { logTransitStateDetachIsoAndThrow(Level.ERROR, String.format("Failed to upgrade Kubernetes cluster : %s, unable to drain Kubernetes node on VM : %s", kubernetesCluster.getName(), vm.getDisplayName()), kubernetesCluster, clusterVMs, KubernetesCluster.Event.OperationFailed, e); diff --git a/plugins/integrations/kubernetes-service/src/main/resources/script/upgrade-kubernetes.sh b/plugins/integrations/kubernetes-service/src/main/resources/script/upgrade-kubernetes.sh index 84f764de93e..c092f53359d 100755 --- a/plugins/integrations/kubernetes-service/src/main/resources/script/upgrade-kubernetes.sh +++ b/plugins/integrations/kubernetes-service/src/main/resources/script/upgrade-kubernetes.sh @@ -137,7 +137,7 @@ if [ -d "$BINARIES_DIR" ]; then systemctl stop kubelet cp -a ${BINARIES_DIR}/k8s/{kubelet,kubectl} /opt/bin - chmod +x {kubelet,kubectl} + chmod +x /opt/bin/{kubelet,kubectl} systemctl daemon-reload systemctl restart containerd diff --git a/test/integration/smoke/test_kubernetes_clusters.py b/test/integration/smoke/test_kubernetes_clusters.py index e53f71871d8..dc8d42f444c 100644 --- a/test/integration/smoke/test_kubernetes_clusters.py +++ b/test/integration/smoke/test_kubernetes_clusters.py @@ -526,7 +526,7 @@ class TestKubernetesCluster(cloudstackTestCase): @attr(tags=["advanced", "smoke"], required_hardware="true") @skipTestIf("hypervisorNotSupported") def test_07_deploy_kubernetes_ha_cluster(self): - """Test to deploy a new Kubernetes cluster + """Test to deploy a new HA Kubernetes cluster # Validate the following: # 1. createKubernetesCluster should return valid info for new cluster @@ -537,14 +537,14 @@ class TestKubernetesCluster(cloudstackTestCase): if self.default_network: self.skipTest("HA cluster on shared network requires external ip address, skipping it") global k8s_cluster - k8s_cluster = self.getValidKubernetesCluster(1, 2) + k8s_cluster = self.getValidKubernetesCluster(1, 3) self.debug("HA Kubernetes cluster with ID: %s successfully deployed" % k8s_cluster.id) return @attr(tags=["advanced", "smoke"], required_hardware="true") @skipTestIf("hypervisorNotSupported") def test_08_upgrade_kubernetes_ha_cluster(self): - """Test to upgrade a Kubernetes cluster to newer version + """Test to upgrade a HA Kubernetes cluster to newer version # Validate the following: # 1. upgradeKubernetesCluster should return valid info for the cluster @@ -554,7 +554,7 @@ class TestKubernetesCluster(cloudstackTestCase): if self.default_network: self.skipTest("HA cluster on shared network requires external ip address, skipping it") global k8s_cluster - k8s_cluster = self.getValidKubernetesCluster(1, 2, version=self.kubernetes_version_v1) + k8s_cluster = self.getValidKubernetesCluster(1, 3, version=self.kubernetes_version_v1) time.sleep(self.services["sleep"]) self.debug("Upgrading HA Kubernetes cluster with ID: %s" % k8s_cluster.id) @@ -581,7 +581,7 @@ class TestKubernetesCluster(cloudstackTestCase): if self.default_network: self.skipTest("HA cluster on shared network requires external ip address, skipping it") global k8s_cluster - k8s_cluster = self.getValidKubernetesCluster(1, 2) + k8s_cluster = self.getValidKubernetesCluster(1, 3) self.debug("Deleting Kubernetes cluster with ID: %s" % k8s_cluster.id) return diff --git a/ui/src/views/compute/CreateKubernetesCluster.vue b/ui/src/views/compute/CreateKubernetesCluster.vue index 1c70dece6e1..908fc58013e 100644 --- a/ui/src/views/compute/CreateKubernetesCluster.vue +++ b/ui/src/views/compute/CreateKubernetesCluster.vue @@ -278,7 +278,7 @@ export default { initForm () { this.formRef = ref() this.form = reactive({ - controlnodes: 2, + controlnodes: 3, size: 1, noderootdisksize: 8 }) From ea569ffaadcc7eaf38c7998d1fa8b7da0b6e3580 Mon Sep 17 00:00:00 2001 From: dahn Date: Sat, 9 Dec 2023 07:03:55 +0100 Subject: [PATCH 3/4] expand tags in csv (#8258) Fixes: #8256 --- ui/src/views/network/AclListRulesTab.vue | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/ui/src/views/network/AclListRulesTab.vue b/ui/src/views/network/AclListRulesTab.vue index c8b6689fb59..124d91ce399 100644 --- a/ui/src/views/network/AclListRulesTab.vue +++ b/ui/src/views/network/AclListRulesTab.vue @@ -334,7 +334,17 @@ export default { result += columnDelimiter } - result += typeof item[key] === 'string' && item[key].includes(columnDelimiter) ? `"${item[key]}"` : item[key] + if (key === 'tags') { + var tags = '"' + if (item[key].length > 0) { + item[key].forEach(tag => { + tags += '(' + tag.key + ',' + tag.value + ')' + }) + } + result += tags + '"' + } else { + result += typeof item[key] === 'string' && item[key].includes(columnDelimiter) ? `"${item[key]}"` : item[key] + } ctr++ }) result += lineDelimiter From a11fc43788e873f09031d0b03cdbf6477d8305da Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Sat, 9 Dec 2023 11:43:52 +0530 Subject: [PATCH 4/4] server: fix diskoffering details in vm response (#8135) Fixes #8120 --- .../org/apache/cloudstack/api/response/UserVmResponse.java | 4 ++-- .../java/com/cloud/api/query/dao/UserVmJoinDaoImpl.java | 7 +++++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/api/src/main/java/org/apache/cloudstack/api/response/UserVmResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/UserVmResponse.java index 114403da7bc..4c67d24ae83 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/UserVmResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/UserVmResponse.java @@ -159,11 +159,11 @@ public class UserVmResponse extends BaseResponseWithTagInformation implements Co private String serviceOfferingName; @SerializedName(ApiConstants.DISK_OFFERING_ID) - @Param(description = "the ID of the disk offering of the virtual machine", since = "4.4") + @Param(description = "the ID of the disk offering of the virtual machine. This parameter should not be used for retrieving disk offering details of DATA volumes. Use listVolumes API instead", since = "4.4") private String diskOfferingId; @SerializedName("diskofferingname") - @Param(description = "the name of the disk offering of the virtual machine", since = "4.4") + @Param(description = "the name of the disk offering of the virtual machine. This parameter should not be used for retrieving disk offering details of DATA volumes. Use listVolumes API instead", since = "4.4") private String diskOfferingName; @SerializedName(ApiConstants.BACKUP_OFFERING_ID) diff --git a/server/src/main/java/com/cloud/api/query/dao/UserVmJoinDaoImpl.java b/server/src/main/java/com/cloud/api/query/dao/UserVmJoinDaoImpl.java index 49489c2bfeb..7f376b16f02 100644 --- a/server/src/main/java/com/cloud/api/query/dao/UserVmJoinDaoImpl.java +++ b/server/src/main/java/com/cloud/api/query/dao/UserVmJoinDaoImpl.java @@ -27,6 +27,7 @@ import java.util.stream.Collectors; import javax.inject.Inject; +import com.cloud.storage.Volume; import org.apache.cloudstack.affinity.AffinityGroupResponse; import org.apache.cloudstack.annotation.AnnotationService; import org.apache.cloudstack.annotation.dao.AnnotationDao; @@ -42,6 +43,7 @@ import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.framework.config.dao.ConfigurationDao; import org.apache.cloudstack.query.QueryService; import org.apache.commons.lang3.BooleanUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.log4j.Logger; import org.springframework.stereotype.Component; @@ -550,6 +552,11 @@ public class UserVmJoinDaoImpl extends GenericDaoBaseWithTagInformation