This is an automated email from the ASF dual-hosted git repository. weizhou pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/cloudstack.git
commit 93406f5582bbccfa39b7b2cbe7d38aaef98195da Merge: 3291a62fc12 bda49ab08ff Author: Wei Zhou <[email protected]> AuthorDate: Tue Feb 13 10:38:21 2024 +0100 Merge remote-tracking branch 'apache/4.19' api/src/main/java/com/cloud/storage/Storage.java | 20 ++- .../cloudstack/cluster/ClusterDrsAlgorithm.java | 192 +++++++++++++++------ .../cloudstack/cluster/ClusterDrsService.java | 23 +++ .../test/java/com/cloud/storage/StorageTest.java | 4 +- .../cluster/ClusterDrsAlgorithmTest.java | 97 +++++++++++ debian/cloudstack-management.install | 1 + debian/rules | 4 + packaging/centos7/cloud.spec | 4 + packaging/centos8/cloud.spec | 4 + .../org/apache/cloudstack/cluster/Balanced.java | 76 ++++---- .../apache/cloudstack/cluster/BalancedTest.java | 53 ++---- .../org/apache/cloudstack/cluster/Condensed.java | 79 ++++----- .../apache/cloudstack/cluster/CondensedTest.java | 46 ++--- .../hypervisor/kvm/resource/LibvirtVMDef.java | 4 +- .../cloudstack/metrics/MetricsServiceImpl.java | 23 ++- .../response/ClusterMetricsResponse.java | 12 ++ .../kvm/storage/LinstorStorageAdaptor.java | 73 +------- .../hypervisor/kvm/storage/LinstorStoragePool.java | 132 +++++++++++++- .../driver/LinstorPrimaryDataStoreDriverImpl.java | 2 +- .../datastore/provider/LinstorHostListener.java | 32 ++++ .../LinstorPrimaryDatastoreProviderImpl.java | 2 +- .../storage/datastore/util/LinstorUtil.java | 27 +-- .../configuration/ConfigurationManagerImpl.java | 1 + .../VpcVirtualNetworkApplianceManagerImpl.java | 19 +- .../cloudstack/backup/BackupManagerImpl.java | 4 - .../cloudstack/cluster/ClusterDrsServiceImpl.java | 28 +-- .../cluster/ClusterDrsServiceImplTest.java | 6 +- systemvm/debian/opt/cloud/bin/cs/CsAddress.py | 7 +- systemvm/debian/opt/cloud/bin/cs/CsDatabag.py | 6 + ui/public/locales/en.json | 8 +- ui/src/components/view/ListView.vue | 3 + ui/src/components/view/SearchView.vue | 51 +++--- ui/src/config/section/infra/clusters.js | 4 +- ui/src/views/infra/ClusterDRSTab.vue | 18 +- ui/src/views/infra/zone/ZoneWizardLaunchZone.vue | 3 + .../zone/ZoneWizardPhysicalNetworkSetupStep.vue | 70 ++++++-- 36 files changed, 753 insertions(+), 385 deletions(-) diff --cc api/src/main/java/com/cloud/storage/Storage.java index 2ef424adcb0,1163fcc892f..c997f5e1dbf --- a/api/src/main/java/com/cloud/storage/Storage.java +++ b/api/src/main/java/com/cloud/storage/Storage.java @@@ -139,72 -135,37 +139,72 @@@ public class Storage ISODISK /* Template corresponding to a iso (non root disk) present in an OVA */ } - public static enum StoragePoolType { - Filesystem(false, true, true), // local directory - NetworkFilesystem(true, true, true), // NFS - IscsiLUN(true, false, false), // shared LUN, with a clusterfs overlay - Iscsi(true, false, false), // for e.g., ZFS Comstar - ISO(false, false, false), // for iso image - LVM(false, false, false), // XenServer local LVM SR - CLVM(true, false, false), - RBD(true, true, false), // http://libvirt.org/storage.html#StorageBackendRBD - SharedMountPoint(true, true, true), - VMFS(true, true, false), // VMware VMFS storage - PreSetup(true, true, false), // for XenServer, Storage Pool is set up by customers. - EXT(false, true, false), // XenServer local EXT SR - OCFS2(true, false, false), - SMB(true, false, false), - Gluster(true, false, false), - PowerFlex(true, true, true), // Dell EMC PowerFlex/ScaleIO (formerly VxFlexOS) - ManagedNFS(true, false, false), - Linstor(true, true, false), - DatastoreCluster(true, true, false), // for VMware, to abstract pool of clusters - StorPool(true, true, true), - FiberChannel(true, true, false); // Fiber Channel Pool for KVM hypervisors is used to find the volume by WWN value (/dev/disk/by-id/wwn-<wwnvalue>) - + /** + * StoragePoolTypes carry some details about the format and capabilities of a storage pool. While not necessarily a + * 1:1 with PrimaryDataStoreDriver (and for KVM agent, KVMStoragePool and StorageAdaptor) implementations, it is + * often used to decide which storage plugin or storage command to call, so it may be necessary for new storage + * plugins to add a StoragePoolType. This can be done by adding it below, or by creating a new public static final + * instance of StoragePoolType in the plugin itself, which registers it with the map. + * + * Note that if the StoragePoolType is for KVM and defined in plugin code rather than below, care must be taken to + * ensure this is available on the agent side as well. This is best done by defining the StoragePoolType in a common + * package available on both management server and agent plugin jars. + */ + public static class StoragePoolType { + private static final Map<String, StoragePoolType> map = new LinkedHashMap<>(); + + public static final StoragePoolType Filesystem = new StoragePoolType("Filesystem", false, true, true); + public static final StoragePoolType NetworkFilesystem = new StoragePoolType("NetworkFilesystem", true, true, true); + public static final StoragePoolType IscsiLUN = new StoragePoolType("IscsiLUN", true, false, false); + public static final StoragePoolType Iscsi = new StoragePoolType("Iscsi", true, false, false); + public static final StoragePoolType ISO = new StoragePoolType("ISO", false, false, false); + public static final StoragePoolType LVM = new StoragePoolType("LVM", false, false, false); + public static final StoragePoolType CLVM = new StoragePoolType("CLVM", true, false, false); + public static final StoragePoolType RBD = new StoragePoolType("RBD", true, true, false); - public static final StoragePoolType SharedMountPoint = new StoragePoolType("SharedMountPoint", true, false, true); ++ public static final StoragePoolType SharedMountPoint = new StoragePoolType("SharedMountPoint", true, true, true); + public static final StoragePoolType VMFS = new StoragePoolType("VMFS", true, true, false); + public static final StoragePoolType PreSetup = new StoragePoolType("PreSetup", true, true, false); + public static final StoragePoolType EXT = new StoragePoolType("EXT", false, true, false); + public static final StoragePoolType OCFS2 = new StoragePoolType("OCFS2", true, false, false); + public static final StoragePoolType SMB = new StoragePoolType("SMB", true, false, false); + public static final StoragePoolType Gluster = new StoragePoolType("Gluster", true, false, false); + public static final StoragePoolType PowerFlex = new StoragePoolType("PowerFlex", true, true, true); + public static final StoragePoolType ManagedNFS = new StoragePoolType("ManagedNFS", true, false, false); + public static final StoragePoolType Linstor = new StoragePoolType("Linstor", true, true, false); + public static final StoragePoolType DatastoreCluster = new StoragePoolType("DatastoreCluster", true, true, false); + public static final StoragePoolType StorPool = new StoragePoolType("StorPool", true,true,true); + public static final StoragePoolType FiberChannel = new StoragePoolType("FiberChannel", true,true,false); + + + private final String name; private final boolean shared; - private final boolean overprovisioning; + private final boolean overProvisioning; private final boolean encryption; - StoragePoolType(boolean shared, boolean overProvisioning, boolean encryption) { + /** + * New StoragePoolType, set the name to check with it in Dao (Note: Do not register it into the map of pool types). + * @param name name of the StoragePoolType. + */ + public StoragePoolType(String name) { + this.name = name; + this.shared = false; - this.overprovisioning = false; ++ this.overProvisioning = false; + this.encryption = false; + } + + /** + * Define a new StoragePoolType, and register it into the map of pool types known to the management server. + * @param name Simple unique name of the StoragePoolType. + * @param shared Storage pool is shared/accessible to multiple hypervisors - * @param overprovisioning Storage pool supports overprovisioning ++ * @param overProvisioning Storage pool supports overProvisioning + * @param encryption Storage pool supports encrypted volumes + */ - public StoragePoolType(String name, boolean shared, boolean overprovisioning, boolean encryption) { ++ public StoragePoolType(String name, boolean shared, boolean overProvisioning, boolean encryption) { + this.name = name; this.shared = shared; - this.overprovisioning = overprovisioning; + this.overProvisioning = overProvisioning; this.encryption = encryption; + addStoragePoolType(this); } public boolean isShared() { @@@ -212,52 -173,12 +212,54 @@@ } public boolean supportsOverProvisioning() { - return overprovisioning; + return overProvisioning; } - public boolean supportsEncryption() { return encryption; } + public boolean supportsEncryption() { + return encryption; + } + + private static void addStoragePoolType(StoragePoolType storagePoolType) { + map.putIfAbsent(storagePoolType.name, storagePoolType); + } + + public static StoragePoolType[] values() { + return map.values().toArray(StoragePoolType[]::new).clone(); + } + + public static StoragePoolType valueOf(String name) { + if (StringUtils.isBlank(name)) { + return null; + } + + StoragePoolType storage = map.get(name); + if (storage == null) { + throw new IllegalArgumentException("StoragePoolType '" + name + "' not found"); + } + return storage; + } + + @Override + public String toString() { + return name; + } + + public String name() { + return name; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + StoragePoolType that = (StoragePoolType) o; + return Objects.equals(name, that.name); + } + + @Override + public int hashCode() { + return Objects.hash(name); + } } public static List<StoragePoolType> getNonSharedStoragePoolTypes() { diff --cc plugins/storage/volume/linstor/src/main/java/com/cloud/hypervisor/kvm/storage/LinstorStorageAdaptor.java index de231f3b594,101e8d3597e..f3a70b079be --- 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 @@@ -32,12 -30,9 +30,10 @@@ import org.apache.cloudstack.storage.da import org.apache.cloudstack.utils.qemu.QemuImg; import org.apache.cloudstack.utils.qemu.QemuImgException; import org.apache.cloudstack.utils.qemu.QemuImgFile; -import org.apache.log4j.Logger; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.LogManager; import org.libvirt.LibvirtException; - import com.cloud.storage.Storage; - import com.cloud.utils.exception.CloudRuntimeException; import com.linbit.linstor.api.ApiClient; import com.linbit.linstor.api.ApiException; import com.linbit.linstor.api.Configuration; @@@ -75,35 -65,13 +70,13 @@@ public class LinstorStorageAdaptor impl return LinstorUtil.RSC_PREFIX + name; } - private String getHostname() { - // either there is already some function for that in the agent or a better way. - ProcessBuilder pb = new ProcessBuilder("/usr/bin/hostname"); - try - { - String result; - Process p = pb.start(); - final BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream())); - - StringJoiner sj = new StringJoiner(System.getProperty("line.separator")); - reader.lines().iterator().forEachRemaining(sj::add); - result = sj.toString(); - - p.waitFor(); - p.destroy(); - return result.trim(); - } catch (IOException | InterruptedException exc) { - Thread.currentThread().interrupt(); - throw new CloudRuntimeException("Unable to run '/usr/bin/hostname' command."); - } - } - private void logLinstorAnswer(@Nonnull ApiCallRc answer) { if (answer.isError()) { - s_logger.error(answer.getMessage()); + logger.error(answer.getMessage()); } else if (answer.isWarning()) { - s_logger.warn(answer.getMessage()); + logger.warn(answer.getMessage()); } else if (answer.isInfo()) { - s_logger.info(answer.getMessage()); + logger.info(answer.getMessage()); } } diff --cc plugins/storage/volume/linstor/src/main/java/org/apache/cloudstack/storage/datastore/util/LinstorUtil.java index c0c55a9ceae,e953c94db22..a8635b404b3 --- 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 @@@ -146,13 -144,13 +145,13 @@@ public class LinstorUtil null, null); - if (rscGrps.isEmpty()) { - final String errMsg = String.format("Linstor: Resource group '%s' not found", rscGroupName); - LOGGER.error(errMsg); - throw new CloudRuntimeException(errMsg); - } + if (rscGrps.isEmpty()) { + final String errMsg = String.format("Linstor: Resource group '%s' not found", rscGroupName); - s_logger.error(errMsg); ++ LOGGER.error(errMsg); + throw new CloudRuntimeException(errMsg); + } - List<StoragePool> storagePools = linstorApi.viewStoragePools( + return api.viewStoragePools( Collections.emptyList(), rscGrps.get(0).getSelectFilter().getStoragePoolList(), null, diff --cc server/src/main/java/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImpl.java index 048dc356ff5,aebeb5c9398..a46c2fd81ea --- a/server/src/main/java/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImpl.java +++ b/server/src/main/java/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImpl.java @@@ -27,6 -27,8 +27,7 @@@ import java.util.Map import javax.inject.Inject; import javax.naming.ConfigurationException; + import org.apache.commons.collections.CollectionUtils; -import org.apache.log4j.Logger; import org.springframework.stereotype.Component; import com.cloud.agent.api.Answer;
