From 7ea068c4dcfa0c33ec5f258a2a89db52bef09b71 Mon Sep 17 00:00:00 2001 From: Wei Zhou Date: Thu, 7 Dec 2023 09:10:11 +0100 Subject: [PATCH 1/4] kvm: fix error 'Failed to find passphrase for keystore: cloud.jks' when enable SSL for kvm agent (#7923) --- .../java/com/cloud/agent/properties/AgentProperties.java | 9 +++++++++ .../kvm/resource/LibvirtComputingResource.java | 6 +++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/agent/src/main/java/com/cloud/agent/properties/AgentProperties.java b/agent/src/main/java/com/cloud/agent/properties/AgentProperties.java index 5c7f4ed4b23..84a66d70761 100644 --- a/agent/src/main/java/com/cloud/agent/properties/AgentProperties.java +++ b/agent/src/main/java/com/cloud/agent/properties/AgentProperties.java @@ -14,6 +14,8 @@ */ package com.cloud.agent.properties; +import org.apache.cloudstack.utils.security.KeyStoreUtils; + /** * Class of constant agent's properties available to configure on * "agent.properties". @@ -728,6 +730,13 @@ public class AgentProperties{ */ public static final Property CONTROL_CIDR = new Property<>("control.cidr", "169.254.0.0/16"); + /** + * Keystore passphrase + * Data type: String.
+ * Default value: null + */ + public static final Property KEYSTORE_PASSPHRASE = new Property<>(KeyStoreUtils.KS_PASSPHRASE_PROPERTY, null, String.class); + public static class Property { private String name; private T defaultValue; diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java index a34edba7fd0..b7611cd07bb 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java @@ -1012,7 +1012,7 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv } } - enableSSLForKvmAgent(params); + enableSSLForKvmAgent(); configureLocalStorage(); /* Directory to use for Qemu sockets like for the Qemu Guest Agent */ @@ -1319,13 +1319,13 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv } } - private void enableSSLForKvmAgent(final Map params) { + private void enableSSLForKvmAgent() { final File keyStoreFile = PropertiesUtil.findConfigFile(KeyStoreUtils.KS_FILENAME); if (keyStoreFile == null) { s_logger.info("Failed to find keystore file: " + KeyStoreUtils.KS_FILENAME); return; } - String keystorePass = (String)params.get(KeyStoreUtils.KS_PASSPHRASE_PROPERTY); + String keystorePass = AgentPropertiesFileHandler.getPropertyValue(AgentProperties.KEYSTORE_PASSPHRASE); if (StringUtils.isBlank(keystorePass)) { s_logger.info("Failed to find passphrase for keystore: " + KeyStoreUtils.KS_FILENAME); return; From 7eb36367c905848d290c9a1871df8bfe400628fe Mon Sep 17 00:00:00 2001 From: Harikrishna Date: Fri, 8 Dec 2023 13:21:16 +0530 Subject: [PATCH 2/4] Add lock mechanism considering template id, pool id, host id in PowerFlex Storage (#8233) Observed a failure to start new virtual machine with PowerFlex storage. Traced it to concurrent VM starts using the same template and the same host to copy. Second mapping attempt failed. While creating the volume clone from the seeded template in primary storage, adding a lock with the string containing IDs of template, storage pool and destination host avoids the situation of concurrent mapping attempts with the same host. --- .../storage/volume/VolumeServiceImpl.java | 30 +++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/engine/storage/volume/src/main/java/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java b/engine/storage/volume/src/main/java/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java index ffc12b98c84..47577cc52b2 100644 --- a/engine/storage/volume/src/main/java/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java +++ b/engine/storage/volume/src/main/java/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java @@ -1478,8 +1478,8 @@ public class VolumeServiceImpl implements VolumeService { createManagedVolumeCloneTemplateAsync(volumeInfo, templateOnPrimary, destPrimaryDataStore, future); } else { // We have a template on PowerFlex primary storage. Create new volume and copy to it. - s_logger.debug("Copying the template to the volume on primary storage"); - createManagedVolumeCopyManagedTemplateAsync(volumeInfo, destPrimaryDataStore, templateOnPrimary, destHost, future); + createManagedVolumeCopyManagedTemplateAsyncWithLock(volumeInfo, destPrimaryDataStore, templateOnPrimary, + destHost, future, destDataStoreId, srcTemplateInfo.getId()); } } else { s_logger.debug("Primary storage does not support cloning or no support for UUID resigning on the host side; copying the template normally"); @@ -1490,6 +1490,32 @@ public class VolumeServiceImpl implements VolumeService { return future; } + private void createManagedVolumeCopyManagedTemplateAsyncWithLock(VolumeInfo volumeInfo, PrimaryDataStore destPrimaryDataStore, TemplateInfo templateOnPrimary, + Host destHost, AsyncCallFuture future, long destDataStoreId, long srcTemplateId) { + GlobalLock lock = null; + try { + String tmplIdManagedPoolIdDestinationHostLockString = "tmplId:" + srcTemplateId + "managedPoolId:" + destDataStoreId + "destinationHostId:" + destHost.getId(); + lock = GlobalLock.getInternLock(tmplIdManagedPoolIdDestinationHostLockString); + if (lock == null) { + throw new CloudRuntimeException("Unable to create volume from template, couldn't get global lock on " + tmplIdManagedPoolIdDestinationHostLockString); + } + + int storagePoolMaxWaitSeconds = NumbersUtil.parseInt(configDao.getValue(Config.StoragePoolMaxWaitSeconds.key()), 3600); + if (!lock.lock(storagePoolMaxWaitSeconds)) { + s_logger.debug("Unable to create volume from template, couldn't lock on " + tmplIdManagedPoolIdDestinationHostLockString); + throw new CloudRuntimeException("Unable to create volume from template, couldn't lock on " + tmplIdManagedPoolIdDestinationHostLockString); + } + + s_logger.debug("Copying the template to the volume on primary storage"); + createManagedVolumeCopyManagedTemplateAsync(volumeInfo, destPrimaryDataStore, templateOnPrimary, destHost, future); + } finally { + if (lock != null) { + lock.unlock(); + lock.releaseRef(); + } + } + } + private boolean computeSupportsVolumeClone(long zoneId, HypervisorType hypervisorType) { if (HypervisorType.VMware.equals(hypervisorType) || HypervisorType.KVM.equals(hypervisorType)) { return true; From bba554bcc4735009e7552e4116bcad8b1cda7b14 Mon Sep 17 00:00:00 2001 From: Peinthor Rene Date: Fri, 8 Dec 2023 12:32:18 +0100 Subject: [PATCH 3/4] linstor: Fix possible NPE if Linstor storage-pool data missing (#8319) If Linstor doesn't return storage pool info, certain values are null. Now we assume the values are 0 if we get null values. --- .../kvm/storage/LinstorStorageAdaptor.java | 40 +++---------------- .../storage/datastore/util/LinstorUtil.java | 3 +- 2 files changed, 8 insertions(+), 35 deletions(-) diff --git a/plugins/storage/volume/linstor/src/main/java/com/cloud/hypervisor/kvm/storage/LinstorStorageAdaptor.java b/plugins/storage/volume/linstor/src/main/java/com/cloud/hypervisor/kvm/storage/LinstorStorageAdaptor.java index 2847484e30e..3a703cdb426 100644 --- a/plugins/storage/volume/linstor/src/main/java/com/cloud/hypervisor/kvm/storage/LinstorStorageAdaptor.java +++ b/plugins/storage/volume/linstor/src/main/java/com/cloud/hypervisor/kvm/storage/LinstorStorageAdaptor.java @@ -28,6 +28,7 @@ import java.util.StringJoiner; import javax.annotation.Nonnull; +import org.apache.cloudstack.storage.datastore.util.LinstorUtil; import org.apache.cloudstack.utils.qemu.QemuImg; import org.apache.cloudstack.utils.qemu.QemuImgException; import org.apache.cloudstack.utils.qemu.QemuImgFile; @@ -489,39 +490,8 @@ public class LinstorStorageAdaptor implements StorageAdaptor { } public long getCapacity(LinstorStoragePool pool) { - DevelopersApi linstorApi = getLinstorAPI(pool); final String rscGroupName = pool.getResourceGroup(); - try { - List rscGrps = linstorApi.resourceGroupList( - Collections.singletonList(rscGroupName), - null, - null, - null); - - if (rscGrps.isEmpty()) { - final String errMsg = String.format("Linstor: Resource group '%s' not found", rscGroupName); - s_logger.error(errMsg); - throw new CloudRuntimeException(errMsg); - } - - List storagePools = linstorApi.viewStoragePools( - Collections.emptyList(), - rscGrps.get(0).getSelectFilter().getStoragePoolList(), - null, - null, - null - ); - - final long capacity = storagePools.stream() - .filter(sp -> sp.getProviderKind() != ProviderKind.DISKLESS) - .mapToLong(sp -> sp.getTotalCapacity() != null ? sp.getTotalCapacity() : 0) - .sum() * 1024; // linstor uses kiB - s_logger.debug("Linstor: GetCapacity() -> " + capacity); - return capacity; - } catch (ApiException apiEx) { - s_logger.error(apiEx.getMessage()); - throw new CloudRuntimeException(apiEx.getBestMessage(), apiEx); - } + return LinstorUtil.getCapacityBytes(pool.getSourceHost(), rscGroupName); } public long getAvailable(LinstorStoragePool pool) { @@ -550,7 +520,7 @@ public class LinstorStorageAdaptor implements StorageAdaptor { final long free = storagePools.stream() .filter(sp -> sp.getProviderKind() != ProviderKind.DISKLESS) - .mapToLong(StoragePool::getFreeCapacity).sum() * 1024; // linstor uses KiB + .mapToLong(sp -> sp.getFreeCapacity() != null ? sp.getFreeCapacity() : 0L).sum() * 1024; // linstor uses KiB s_logger.debug("Linstor: getAvailable() -> " + free); return free; @@ -586,7 +556,9 @@ public class LinstorStorageAdaptor implements StorageAdaptor { final long used = storagePools.stream() .filter(sp -> sp.getProviderKind() != ProviderKind.DISKLESS) - .mapToLong(sp -> sp.getTotalCapacity() - sp.getFreeCapacity()).sum() * 1024; // linstor uses Kib + .mapToLong(sp -> sp.getTotalCapacity() != null && sp.getFreeCapacity() != null ? + sp.getTotalCapacity() - sp.getFreeCapacity() : 0L) + .sum() * 1024; // linstor uses Kib s_logger.debug("Linstor: getUsed() -> " + used); return used; } catch (ApiException apiEx) { diff --git a/plugins/storage/volume/linstor/src/main/java/org/apache/cloudstack/storage/datastore/util/LinstorUtil.java b/plugins/storage/volume/linstor/src/main/java/org/apache/cloudstack/storage/datastore/util/LinstorUtil.java index f1760a003ab..ddd15a5984a 100644 --- a/plugins/storage/volume/linstor/src/main/java/org/apache/cloudstack/storage/datastore/util/LinstorUtil.java +++ b/plugins/storage/volume/linstor/src/main/java/org/apache/cloudstack/storage/datastore/util/LinstorUtil.java @@ -72,7 +72,8 @@ public class LinstorUtil { return storagePools.stream() .filter(sp -> sp.getProviderKind() != ProviderKind.DISKLESS) - .mapToLong(StoragePool::getTotalCapacity).sum() * 1024; // linstor uses kiB + .mapToLong(sp -> sp.getTotalCapacity() != null ? sp.getTotalCapacity() : 0L) + .sum() * 1024; // linstor uses kiB } catch (ApiException apiEx) { s_logger.error(apiEx.getMessage()); throw new CloudRuntimeException(apiEx); From f42feb1568d38375aa79da074cb07fb171208b7b Mon Sep 17 00:00:00 2001 From: Wei Zhou Date: Fri, 8 Dec 2023 12:35:09 +0100 Subject: [PATCH 4/4] CKS: update imagePullPolicy to IfNotPresent in yaml files (#8296) The kubernetes dashboard yaml file has the following setting image: kubernetesui/dashboard:v2.7.0 imagePullPolicy: Always see https://raw.githubusercontent.com/kubernetes/dashboard/v2.7.0/aio/deploy/recommended.yaml The similar config can be found at https://raw.githubusercontent.com/weaveworks/weave/master/prog/weave-kube/weave-daemonset-k8s-1.11.yaml Due to it, CKS does not work in the following cases reach the dockerhub rate limitations (see https://docs.docker.com/docker-hub/download-rate-limit/) The VMs do not have internet connection Since the CKS ISO contains the image, it is not necessary to pull the images again. --- scripts/util/create-kubernetes-binaries-iso.sh | 3 +++ tools/marvin/marvin/config/test_data.py | 18 +++++++++++++++--- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/scripts/util/create-kubernetes-binaries-iso.sh b/scripts/util/create-kubernetes-binaries-iso.sh index e7981d6ac0b..d5fb014f220 100755 --- a/scripts/util/create-kubernetes-binaries-iso.sh +++ b/scripts/util/create-kubernetes-binaries-iso.sh @@ -145,6 +145,9 @@ if [ -z "${kubeadm_file_permissions}" ]; then fi chmod ${kubeadm_file_permissions} "${working_dir}/k8s/kubeadm" +echo "Updating imagePullPolicy to IfNotPresent in yaml files..." +sed -i "s/imagePullPolicy:.*/imagePullPolicy: IfNotPresent/g" ${working_dir}/*.yaml + mkisofs -o "${output_dir}/${build_name}" -J -R -l "${iso_dir}" rm -rf "${iso_dir}" diff --git a/tools/marvin/marvin/config/test_data.py b/tools/marvin/marvin/config/test_data.py index c4ac6008b1f..ef9bfd774f7 100644 --- a/tools/marvin/marvin/config/test_data.py +++ b/tools/marvin/marvin/config/test_data.py @@ -2260,11 +2260,23 @@ test_data = { "url": "http://download.cloudstack.org/cks/setup-1.26.0.iso", "mincpunumber": 2, "minmemory": 2048 + }, + "1.27.8": { + "semanticversion": "1.27.8", + "url": "http://download.cloudstack.org/cks/setup-1.27.8.iso", + "mincpunumber": 2, + "minmemory": 2048 + }, + "1.28.4": { + "semanticversion": "1.28.4", + "url": "http://download.cloudstack.org/cks/setup-1.28.4.iso", + "mincpunumber": 2, + "minmemory": 2048 } }, - "cks_kubernetes_version": "1.26.0", - "cks_kubernetes_version_upgrade_from": "1.25.0", - "cks_kubernetes_version_upgrade_to": "1.26.0", + "cks_kubernetes_version": "1.28.4", + "cks_kubernetes_version_upgrade_from": "1.27.8", + "cks_kubernetes_version_upgrade_to": "1.28.4", "cks_service_offering": { "name": "CKS-Instance", "displaytext": "CKS Instance",