diff --git a/api/src/main/java/org/apache/cloudstack/api/response/NetworkResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/NetworkResponse.java index db811ffbe2d..a1ffda72234 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/NetworkResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/NetworkResponse.java @@ -28,12 +28,11 @@ import org.apache.cloudstack.api.BaseResponseWithAssociatedNetwork; import org.apache.cloudstack.api.EntityReference; import com.cloud.network.Network; -import com.cloud.projects.ProjectAccount; import com.cloud.serializer.Param; import com.google.gson.annotations.SerializedName; @SuppressWarnings("unused") -@EntityReference(value = {Network.class, ProjectAccount.class}) +@EntityReference(value = {Network.class}) public class NetworkResponse extends BaseResponseWithAssociatedNetwork implements ControlledEntityResponse, SetResourceIconResponse { @SerializedName(ApiConstants.ID) diff --git a/engine/storage/volume/src/main/java/org/apache/cloudstack/storage/datastore/lifecycle/BasePrimaryDataStoreLifeCycleImpl.java b/engine/storage/volume/src/main/java/org/apache/cloudstack/storage/datastore/lifecycle/BasePrimaryDataStoreLifeCycleImpl.java index de3be809a05..959d63ed2b5 100644 --- a/engine/storage/volume/src/main/java/org/apache/cloudstack/storage/datastore/lifecycle/BasePrimaryDataStoreLifeCycleImpl.java +++ b/engine/storage/volume/src/main/java/org/apache/cloudstack/storage/datastore/lifecycle/BasePrimaryDataStoreLifeCycleImpl.java @@ -22,14 +22,16 @@ import java.util.List; import javax.inject.Inject; -import com.cloud.dc.dao.DataCenterDao; import org.apache.cloudstack.engine.subsystem.api.storage.ClusterScope; import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; +import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; +import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; import org.apache.cloudstack.storage.volume.datastore.PrimaryDataStoreHelper; import com.cloud.agent.AgentManager; import com.cloud.agent.api.Answer; import com.cloud.agent.api.DeleteStoragePoolCommand; +import com.cloud.dc.dao.DataCenterDao; import com.cloud.host.HostVO; import com.cloud.host.dao.HostDao; import com.cloud.hypervisor.Hypervisor.HypervisorType; @@ -37,8 +39,12 @@ import com.cloud.resource.ResourceManager; import com.cloud.storage.StorageManager; import com.cloud.storage.StoragePool; import com.cloud.storage.StoragePoolHostVO; +import com.cloud.storage.VMTemplateStoragePoolVO; +import com.cloud.storage.VMTemplateStorageResourceAssoc; import com.cloud.storage.dao.StoragePoolHostDao; +import com.cloud.template.TemplateManager; import com.cloud.utils.Pair; + import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -59,6 +65,10 @@ public class BasePrimaryDataStoreLifeCycleImpl { protected DataCenterDao zoneDao; @Inject protected StoragePoolHostDao storagePoolHostDao; + @Inject + private PrimaryDataStoreDao primaryDataStoreDao; + @Inject + private TemplateManager templateMgr; private List getPoolHostsList(ClusterScope clusterScope, HypervisorType hypervisorType) { List hosts; @@ -81,7 +91,7 @@ public class BasePrimaryDataStoreLifeCycleImpl { try { storageMgr.connectHostToSharedPool(host, store.getId()); } catch (Exception e) { - logger.warn("Unable to establish a connection between " + host + " and " + store, e); + logger.warn("Unable to establish a connection between {} and {}", host, store, e); } } } @@ -99,7 +109,7 @@ public class BasePrimaryDataStoreLifeCycleImpl { if (answer != null) { if (!answer.getResult()) { - logger.debug("Failed to delete storage pool: " + answer.getResult()); + logger.debug("Failed to delete storage pool: {}", answer.getResult()); } else if (HypervisorType.KVM != hypervisorType) { break; } @@ -108,4 +118,42 @@ public class BasePrimaryDataStoreLifeCycleImpl { } dataStoreHelper.switchToCluster(store, clusterScope); } + + private void evictTemplates(StoragePoolVO storagePoolVO) { + List unusedTemplatesInPool = templateMgr.getUnusedTemplatesInPool(storagePoolVO); + for (VMTemplateStoragePoolVO templatePoolVO : unusedTemplatesInPool) { + if (templatePoolVO.getDownloadState() == VMTemplateStorageResourceAssoc.Status.DOWNLOADED) { + templateMgr.evictTemplateFromStoragePool(templatePoolVO); + } + } + } + + private void deleteAgentStoragePools(StoragePool storagePool) { + List poolHostVOs = storagePoolHostDao.listByPoolId(storagePool.getId()); + for (StoragePoolHostVO poolHostVO : poolHostVOs) { + DeleteStoragePoolCommand deleteStoragePoolCommand = new DeleteStoragePoolCommand(storagePool); + final Answer answer = agentMgr.easySend(poolHostVO.getHostId(), deleteStoragePoolCommand); + if (answer != null && answer.getResult()) { + logger.info("Successfully deleted storage pool: {} from host: {}", storagePool.getId(), poolHostVO.getHostId()); + } else { + if (answer != null) { + logger.error("Failed to delete storage pool: {} from host: {} , result: {}", storagePool.getId(), poolHostVO.getHostId(), answer.getResult()); + } else { + logger.error("Failed to delete storage pool: {} from host: {}", storagePool.getId(), poolHostVO.getHostId()); + } + } + } + } + + protected boolean cleanupDatastore(DataStore store) { + StoragePool storagePool = (StoragePool)store; + StoragePoolVO storagePoolVO = primaryDataStoreDao.findById(storagePool.getId()); + if (storagePoolVO == null) { + return false; + } + + evictTemplates(storagePoolVO); + deleteAgentStoragePools(storagePool); + return true; + } } diff --git a/plugins/storage/volume/linstor/CHANGELOG.md b/plugins/storage/volume/linstor/CHANGELOG.md index e27e521bcd8..7e9d754b9f6 100644 --- a/plugins/storage/volume/linstor/CHANGELOG.md +++ b/plugins/storage/volume/linstor/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to Linstor CloudStack plugin will be documented in this file The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [2025-03-13] + +### Fixed + +- Implemented missing delete datastore, to correctly cleanup on datastore removal + ## [2025-02-21] ### Fixed diff --git a/plugins/storage/volume/linstor/src/main/java/org/apache/cloudstack/storage/datastore/lifecycle/LinstorPrimaryDataStoreLifeCycleImpl.java b/plugins/storage/volume/linstor/src/main/java/org/apache/cloudstack/storage/datastore/lifecycle/LinstorPrimaryDataStoreLifeCycleImpl.java index b45953989b5..e36eacf24c2 100644 --- a/plugins/storage/volume/linstor/src/main/java/org/apache/cloudstack/storage/datastore/lifecycle/LinstorPrimaryDataStoreLifeCycleImpl.java +++ b/plugins/storage/volume/linstor/src/main/java/org/apache/cloudstack/storage/datastore/lifecycle/LinstorPrimaryDataStoreLifeCycleImpl.java @@ -286,7 +286,10 @@ public class LinstorPrimaryDataStoreLifeCycleImpl extends BasePrimaryDataStoreLi @Override public boolean deleteDataStore(DataStore store) { - return dataStoreHelper.deletePrimaryDataStore(store); + if (cleanupDatastore(store)) { + return dataStoreHelper.deletePrimaryDataStore(store); + } + return false; } /* (non-Javadoc) diff --git a/plugins/storage/volume/scaleio/src/main/java/org/apache/cloudstack/storage/datastore/lifecycle/ScaleIOPrimaryDataStoreLifeCycle.java b/plugins/storage/volume/scaleio/src/main/java/org/apache/cloudstack/storage/datastore/lifecycle/ScaleIOPrimaryDataStoreLifeCycle.java index 5104787fd9a..350751394d8 100644 --- a/plugins/storage/volume/scaleio/src/main/java/org/apache/cloudstack/storage/datastore/lifecycle/ScaleIOPrimaryDataStoreLifeCycle.java +++ b/plugins/storage/volume/scaleio/src/main/java/org/apache/cloudstack/storage/datastore/lifecycle/ScaleIOPrimaryDataStoreLifeCycle.java @@ -18,7 +18,6 @@ */ package org.apache.cloudstack.storage.datastore.lifecycle; -import java.io.UnsupportedEncodingException; import java.net.URI; import java.net.URISyntaxException; import java.net.URLDecoder; @@ -30,6 +29,7 @@ import java.util.UUID; import javax.inject.Inject; +import com.cloud.utils.StringUtils; import org.apache.cloudstack.engine.subsystem.api.storage.ClusterScope; import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; import org.apache.cloudstack.engine.subsystem.api.storage.HostScope; @@ -48,8 +48,6 @@ import org.apache.cloudstack.storage.volume.datastore.PrimaryDataStoreHelper; import org.apache.commons.collections.CollectionUtils; import com.cloud.agent.AgentManager; -import com.cloud.agent.api.Answer; -import com.cloud.agent.api.DeleteStoragePoolCommand; import com.cloud.agent.api.StoragePoolInfo; import com.cloud.capacity.CapacityManager; import com.cloud.dc.ClusterVO; @@ -63,9 +61,6 @@ import com.cloud.storage.Storage; import com.cloud.storage.StorageManager; import com.cloud.storage.StoragePool; import com.cloud.storage.StoragePoolAutomation; -import com.cloud.storage.StoragePoolHostVO; -import com.cloud.storage.VMTemplateStoragePoolVO; -import com.cloud.storage.VMTemplateStorageResourceAssoc; import com.cloud.storage.dao.StoragePoolHostDao; import com.cloud.template.TemplateManager; import com.cloud.utils.UriUtils; @@ -111,7 +106,7 @@ public class ScaleIOPrimaryDataStoreLifeCycle extends BasePrimaryDataStoreLifeCy List storagePools = client.listStoragePools(); for (org.apache.cloudstack.storage.datastore.api.StoragePool pool : storagePools) { if (pool.getName().equals(storagePoolName)) { - logger.info("Found PowerFlex storage pool: " + storagePoolName); + logger.info("Found PowerFlex storage pool: {}", storagePoolName); final org.apache.cloudstack.storage.datastore.api.StoragePoolStatistics poolStatistics = client.getStoragePoolStatistics(pool.getId()); pool.setStatistics(poolStatistics); @@ -164,7 +159,7 @@ public class ScaleIOPrimaryDataStoreLifeCycle extends BasePrimaryDataStoreLifeCy throw new CloudRuntimeException("Cluster Id must also be specified when the Pod Id is specified for Cluster-wide primary storage."); } - URI uri = null; + URI uri; try { uri = new URI(UriUtils.encodeURIComponent(url)); if (uri.getScheme() == null || !uri.getScheme().equalsIgnoreCase("powerflex")) { @@ -174,12 +169,8 @@ public class ScaleIOPrimaryDataStoreLifeCycle extends BasePrimaryDataStoreLifeCy throw new InvalidParameterValueException(url + " is not a valid uri"); } - String storagePoolName = null; - try { - storagePoolName = URLDecoder.decode(uri.getPath(), "UTF-8"); - } catch (UnsupportedEncodingException e) { - logger.error("[ignored] we are on a platform not supporting \"UTF-8\"!?!", e); - } + String storagePoolName; + storagePoolName = URLDecoder.decode(uri.getPath(), StringUtils.getPreferredCharset()); if (storagePoolName == null) { // if decoding fails, use getPath() anyway storagePoolName = uri.getPath(); } @@ -187,7 +178,7 @@ public class ScaleIOPrimaryDataStoreLifeCycle extends BasePrimaryDataStoreLifeCy final String storageHost = uri.getHost(); final int port = uri.getPort(); - String gatewayApiURL = null; + String gatewayApiURL; if (port == -1) { gatewayApiURL = String.format("https://%s/api", storageHost); } else { @@ -321,37 +312,11 @@ public class ScaleIOPrimaryDataStoreLifeCycle extends BasePrimaryDataStoreLifeCy @Override public boolean deleteDataStore(DataStore dataStore) { - StoragePool storagePool = (StoragePool)dataStore; - StoragePoolVO storagePoolVO = primaryDataStoreDao.findById(storagePool.getId()); - if (storagePoolVO == null) { - return false; + if (cleanupDatastore(dataStore)) { + ScaleIOGatewayClientConnectionPool.getInstance().removeClient(dataStore); + return dataStoreHelper.deletePrimaryDataStore(dataStore); } - - List unusedTemplatesInPool = templateMgr.getUnusedTemplatesInPool(storagePoolVO); - for (VMTemplateStoragePoolVO templatePoolVO : unusedTemplatesInPool) { - if (templatePoolVO.getDownloadState() == VMTemplateStorageResourceAssoc.Status.DOWNLOADED) { - templateMgr.evictTemplateFromStoragePool(templatePoolVO); - } - } - - List poolHostVOs = storagePoolHostDao.listByPoolId(dataStore.getId()); - for (StoragePoolHostVO poolHostVO : poolHostVOs) { - DeleteStoragePoolCommand deleteStoragePoolCommand = new DeleteStoragePoolCommand(storagePool); - final Answer answer = agentMgr.easySend(poolHostVO.getHostId(), deleteStoragePoolCommand); - if (answer != null && answer.getResult()) { - logger.info("Successfully deleted storage pool: {} from host: {}", storagePool, poolHostVO.getHostId()); - } else { - if (answer != null) { - logger.error("Failed to delete storage pool: {} from host: {} , result: {}", storagePool, poolHostVO.getHostId(), answer.getResult()); - } else { - logger.error("Failed to delete storage pool: {} from host: {}", storagePool, poolHostVO.getHostId()); - } - } - } - - ScaleIOGatewayClientConnectionPool.getInstance().removeClient(dataStore); - - return dataStoreHelper.deletePrimaryDataStore(dataStore); + return false; } @Override diff --git a/scripts/storage/secondary/setup-sysvm-tmplt b/scripts/storage/secondary/setup-sysvm-tmplt index 8b656621891..06f0586fe34 100755 --- a/scripts/storage/secondary/setup-sysvm-tmplt +++ b/scripts/storage/secondary/setup-sysvm-tmplt @@ -99,7 +99,7 @@ if [[ -f $destdir/template.properties ]]; then failed 2 "Data already exists at destination $destdir" fi -destfiles=$(find $destdir -name \*.$ext) +destfiles=$(sudo find $destdir -name \*.$ext) if [[ "$destfiles" != "" ]]; then failed 2 "Data already exists at destination $destdir" fi @@ -108,12 +108,12 @@ tmpfolder=/tmp/cloud/templates/ mkdir -p $tmpfolder tmplfile=$tmpfolder/$localfile -sudo touch $tmplfile +touch $tmplfile if [[ $? -ne 0 ]]; then failed 2 "Failed to create temporary file in directory $tmpfolder -- is it read-only or full?\n" fi -destcap=$(df -P $destdir | awk '{print $4}' | tail -1 ) +destcap=$(sudo df -P $destdir | awk '{print $4}' | tail -1 ) [ $destcap -lt $DISKSPACE ] && echo "Insufficient free disk space for target folder $destdir: avail=${destcap}k req=${DISKSPACE}k" && failed 4 localcap=$(df -P $tmpfolder | awk '{print $4}' | tail -1 ) @@ -146,9 +146,9 @@ fi tmpltfile=$destdir/$localfile -tmpltsize=$(ls -l $tmpltfile | awk -F" " '{print $5}') +tmpltsize=$(sudo ls -l $tmpltfile | awk -F" " '{print $5}') if [[ "$ext" == "qcow2" ]]; then - vrtmpltsize=$($qemuimgcmd info $tmpltfile | grep -i 'virtual size' | sed -ne 's/.*(\([0-9]*\).*/\1/p' | xargs) + vrtmpltsize=$(sudo $qemuimgcmd info $tmpltfile | grep -i 'virtual size' | sed -ne 's/.*(\([0-9]*\).*/\1/p' | xargs) else vrtmpltsize=$tmpltsize fi diff --git a/server/conf/cloudstack-sudoers.in b/server/conf/cloudstack-sudoers.in index 5c879f3303f..710241022f5 100644 --- a/server/conf/cloudstack-sudoers.in +++ b/server/conf/cloudstack-sudoers.in @@ -18,7 +18,7 @@ # The CloudStack management server needs sudo permissions # without a password. -Cmnd_Alias CLOUDSTACK = /bin/mkdir, /bin/mount, /bin/umount, /bin/cp, /bin/chmod, /usr/bin/keytool, /bin/keytool, /bin/touch +Cmnd_Alias CLOUDSTACK = /bin/mkdir, /bin/mount, /bin/umount, /bin/cp, /bin/chmod, /usr/bin/keytool, /bin/keytool, /bin/touch, /bin/find, /bin/df, /bin/ls, /bin/qemu-img Defaults:@MSUSER@ !requiretty diff --git a/server/src/main/java/com/cloud/network/router/NetworkHelperImpl.java b/server/src/main/java/com/cloud/network/router/NetworkHelperImpl.java index f33a6c2f632..7072fe6aa9a 100644 --- a/server/src/main/java/com/cloud/network/router/NetworkHelperImpl.java +++ b/server/src/main/java/com/cloud/network/router/NetworkHelperImpl.java @@ -446,7 +446,9 @@ public class NetworkHelperImpl implements NetworkHelper { final int retryIndex = 5; final ExcludeList[] avoids = new ExcludeList[5]; avoids[0] = new ExcludeList(); - avoids[0].addPod(routerToBeAvoid.getPodIdToDeployIn()); + if (routerToBeAvoid.getPodIdToDeployIn() != null) { + avoids[0].addPod(routerToBeAvoid.getPodIdToDeployIn()); + } avoids[1] = new ExcludeList(); avoids[1].addCluster(_hostDao.findById(routerToBeAvoid.getHostId()).getClusterId()); avoids[2] = new ExcludeList(); diff --git a/server/src/main/java/com/cloud/resource/ResourceManagerImpl.java b/server/src/main/java/com/cloud/resource/ResourceManagerImpl.java index 7428475231d..3414ed6651e 100755 --- a/server/src/main/java/com/cloud/resource/ResourceManagerImpl.java +++ b/server/src/main/java/com/cloud/resource/ResourceManagerImpl.java @@ -60,9 +60,10 @@ import org.apache.cloudstack.framework.config.dao.ConfigurationDao; import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; import org.apache.cloudstack.utils.identity.ManagementServerNode; + import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.ObjectUtils; -import org.apache.commons.lang3.StringUtils; + import org.springframework.stereotype.Component; import com.cloud.agent.AgentManager; @@ -92,7 +93,6 @@ import com.cloud.capacity.CapacityVO; import com.cloud.capacity.dao.CapacityDao; import com.cloud.cluster.ClusterManager; import com.cloud.configuration.Config; -import com.cloud.configuration.ConfigurationManager; import com.cloud.cpu.CPU; import com.cloud.dc.ClusterDetailsDao; import com.cloud.dc.ClusterDetailsVO; @@ -125,7 +125,6 @@ import com.cloud.exception.DiscoveryException; import com.cloud.exception.InsufficientServerCapacityException; import com.cloud.exception.InvalidParameterValueException; import com.cloud.exception.PermissionDeniedException; -import com.cloud.exception.ResourceInUseException; import com.cloud.exception.ResourceUnavailableException; import com.cloud.exception.StorageConflictException; import com.cloud.exception.StorageUnavailableException; @@ -170,7 +169,6 @@ import com.cloud.storage.StorageService; import com.cloud.storage.VMTemplateVO; import com.cloud.storage.Volume; import com.cloud.storage.VolumeVO; -import com.cloud.storage.dao.DiskOfferingDao; import com.cloud.storage.dao.GuestOSCategoryDao; import com.cloud.storage.dao.StoragePoolHostDao; import com.cloud.storage.dao.VMTemplateDao; @@ -203,6 +201,7 @@ import com.cloud.utils.net.NetUtils; import com.cloud.utils.ssh.SSHCmdHelper; import com.cloud.utils.ssh.SshException; import com.cloud.vm.UserVmManager; +import com.cloud.utils.StringUtils; import com.cloud.vm.VMInstanceVO; import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachine.State; @@ -236,8 +235,6 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, @Inject private CapacityDao _capacityDao; @Inject - private DiskOfferingDao diskOfferingDao; - @Inject private ServiceOfferingDao serviceOfferingDao; @Inject private HostDao _hostDao; @@ -296,8 +293,6 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, @Inject private VMTemplateDao _templateDao; @Inject - private ConfigurationManager _configMgr; - @Inject private ClusterVSMMapDao _clusterVSMMapDao; @Inject private UserVmDetailsDao userVmDetailsDao; @@ -312,9 +307,9 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, private final long _nodeId = ManagementServerNode.getManagementServerId(); - private final HashMap _resourceStateAdapters = new HashMap(); + private final HashMap _resourceStateAdapters = new HashMap<>(); - private final HashMap> _lifeCycleListeners = new HashMap>(); + private final HashMap> _lifeCycleListeners = new HashMap<>(); private HypervisorType _defaultSystemVMHypervisor; private static final int ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_COOPERATION = 30; // seconds @@ -324,11 +319,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, private SearchBuilder _gpuAvailability; private void insertListener(final Integer event, final ResourceListener listener) { - List lst = _lifeCycleListeners.get(event); - if (lst == null) { - lst = new ArrayList(); - _lifeCycleListeners.put(event, lst); - } + List lst = _lifeCycleListeners.computeIfAbsent(event, k -> new ArrayList<>()); if (lst.contains(listener)) { throw new CloudRuntimeException("Duplicate resource lisener:" + listener.getClass().getSimpleName()); @@ -370,9 +361,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, @Override public void unregisterResourceEvent(final ResourceListener listener) { synchronized (_lifeCycleListeners) { - final Iterator it = _lifeCycleListeners.entrySet().iterator(); - while (it.hasNext()) { - final Map.Entry> items = (Map.Entry>)it.next(); + for (Map.Entry> items : _lifeCycleListeners.entrySet()) { final List lst = items.getValue(); lst.remove(listener); } @@ -381,7 +370,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, protected void processResourceEvent(final Integer event, final Object... params) { final List lst = _lifeCycleListeners.get(event); - if (lst == null || lst.size() == 0) { + if (lst == null || lst.isEmpty()) { return; } @@ -422,7 +411,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, @DB @Override - public List discoverCluster(final AddClusterCmd cmd) throws IllegalArgumentException, DiscoveryException, ResourceInUseException { + public List discoverCluster(final AddClusterCmd cmd) throws IllegalArgumentException, DiscoveryException { final long dcId = cmd.getZoneId(); final long podId = cmd.getPodId(); final String clusterName = cmd.getClusterName(); @@ -432,10 +421,10 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, CPU.CPUArch arch = cmd.getArch(); if (url != null) { - url = URLDecoder.decode(url); + url = URLDecoder.decode(url, com.cloud.utils.StringUtils.getPreferredCharset()); } - URI uri = null; + URI uri; // Check if the zone exists in the system final DataCenterVO zone = _dcDao.findById(dcId); @@ -519,7 +508,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, discoverer.putParam(allParams); } - final List result = new ArrayList(); + final List result = new ArrayList<>(); ClusterVO cluster = new ClusterVO(dcId, podId, clusterName); cluster.setHypervisorType(hypervisorType.toString()); @@ -540,7 +529,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, result.add(cluster); if (clusterType == Cluster.ClusterType.CloudManaged) { - final Map details = new HashMap(); + final Map details = new HashMap<>(); // should do this nicer perhaps ? if (hypervisorType == HypervisorType.Ovm3) { final Map allParams = cmd.getFullUrlParams(); @@ -578,8 +567,8 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, throw new InvalidParameterValueException(url + " is not a valid uri"); } - final List hosts = new ArrayList(); - Map> resources = null; + final List hosts = new ArrayList<>(); + Map> resources; resources = discoverer.find(dcId, podId, cluster.getId(), uri, username, password, null); if (resources != null) { @@ -670,7 +659,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, private List discoverHostsFull(final Long dcId, final Long podId, Long clusterId, final String clusterName, String url, String username, String password, final String hypervisorType, final List hostTags, final Map params, final boolean deferAgentCreation) throws IllegalArgumentException, DiscoveryException, InvalidParameterValueException { - URI uri = null; + URI uri; // Check if the zone exists in the system final DataCenterVO zone = _dcDao.findById(dcId); @@ -810,7 +799,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, throw new InvalidParameterValueException(url + " is not a valid uri"); } - final List hosts = new ArrayList(); + final List hosts = new ArrayList<>(); logger.info("Trying to add a new host at {} in data center {}", url, zone); boolean isHypervisorTypeSupported = false; for (final Discoverer discoverer : _discoverers) { @@ -872,7 +861,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, return null; } - HostVO host = null; + HostVO host; if (deferAgentCreation) { host = (HostVO)createHostAndAgentDeferred(resource, entry.getValue(), true, hostTags, false); } else { @@ -1099,7 +1088,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, // don't allow to remove the cluster if it has non-removed storage // pools final List storagePools = _storagePoolDao.listPoolsByCluster(cmd.getId()); - if (storagePools.size() > 0) { + if (!storagePools.isEmpty()) { logger.debug("{} still has storage pools, can't remove", cluster); throw new CloudRuntimeException(String.format("Cluster: %s cannot be removed. Cluster still has storage pools", cluster)); } @@ -1166,7 +1155,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, } } - Cluster.ClusterType newClusterType = null; + Cluster.ClusterType newClusterType; if (clusterType != null && !clusterType.isEmpty()) { try { newClusterType = Cluster.ClusterType.valueOf(clusterType); @@ -1182,7 +1171,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, } } - Grouping.AllocationState newAllocationState = null; + Grouping.AllocationState newAllocationState; if (allocationState != null && !allocationState.isEmpty()) { try { newAllocationState = Grouping.AllocationState.valueOf(allocationState); @@ -1244,12 +1233,13 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, } } final int retry = 40; - boolean lsuccess = true; + boolean lsuccess; for (int i = 0; i < retry; i++) { lsuccess = true; try { - Thread.sleep(5 * 1000); - } catch (final Exception e) { + Thread.currentThread().wait(5 * 1000); + } catch (final InterruptedException e) { + logger.debug("thread unexpectedly interrupted during wait, while updating cluster"); } hosts = listAllUpAndEnabledHosts(Host.Type.Routing, cluster.getId(), cluster.getPodId(), cluster.getDataCenterId()); for (final HostVO host : hosts) { @@ -1258,12 +1248,12 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, break; } } - if (lsuccess == true) { + if (lsuccess) { success = true; break; } } - if (success == false) { + if (!success) { throw new CloudRuntimeException("PrepareUnmanaged Failed due to some hosts are still in UP status after 5 Minutes, please try later "); } } finally { @@ -1384,7 +1374,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, /* TODO: move below to listener */ if (host.getType() == Host.Type.Routing) { - if (vms.size() == 0) { + if (vms.isEmpty()) { return true; } @@ -1412,7 +1402,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, String logMessage = String.format( "Unsupported host.maintenance.local.storage.strategy: %s. Please set a strategy according to the global settings description: " + "'Error', 'Migration', or 'ForceStop'.", - HOST_MAINTENANCE_LOCAL_STRATEGY.value().toString()); + HOST_MAINTENANCE_LOCAL_STRATEGY.value()); logger.error(logMessage); throw new CloudRuntimeException("There are active VMs using the host's local storage pool. Please stop all VMs on this host that use local storage."); } @@ -1469,14 +1459,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, ServiceOfferingVO offeringVO = serviceOfferingDao.findById(vm.getServiceOfferingId()); final VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm, null, offeringVO, null, null); plan.setMigrationPlan(true); - DeployDestination dest = null; - DeploymentPlanner.ExcludeList avoids = new DeploymentPlanner.ExcludeList(); - avoids.addHost(host.getId()); - try { - dest = deploymentManager.planDeployment(profile, plan, avoids, null); - } catch (InsufficientServerCapacityException e) { - throw new CloudRuntimeException(String.format("Maintenance failed, could not find deployment destination for VM: %s.", vm), e); - } + DeployDestination dest = getDeployDestination(vm, profile, plan, host); Host destHost = dest.getHost(); try { @@ -1487,6 +1470,22 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, } } + private DeployDestination getDeployDestination(VMInstanceVO vm, VirtualMachineProfile profile, DataCenterDeployment plan, HostVO hostToAvoid) { + DeployDestination dest; + DeploymentPlanner.ExcludeList avoids = new DeploymentPlanner.ExcludeList(); + avoids.addHost(hostToAvoid.getId()); + try { + dest = deploymentManager.planDeployment(profile, plan, avoids, null); + } catch (InsufficientServerCapacityException e) { + throw new CloudRuntimeException(String.format("Maintenance failed, could not find deployment destination for VM [id=%s, name=%s].", vm.getId(), vm.getInstanceName()), + e); + } + if (dest == null) { + throw new CloudRuntimeException(String.format("Maintenance failed, could not find deployment destination for VM [id=%s, name=%s], using plan: %s.", vm.getId(), vm.getInstanceName(), plan)); + } + return dest; + } + @Override public boolean maintain(final long hostId) throws AgentUnavailableException { final Boolean result = propagateResourceEvent(hostId, ResourceState.Event.AdminAskMaintenance); @@ -1535,15 +1534,15 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, List migratingInVMs = _vmDao.findByHostInStates(hostId, State.Migrating); - if (migratingInVMs.size() > 0) { + if (!migratingInVMs.isEmpty()) { throw new CloudRuntimeException("Host contains incoming VMs migrating. Please wait for them to complete before putting to maintenance."); } - if (_vmDao.findByHostInStates(hostId, State.Starting, State.Stopping).size() > 0) { + if (!_vmDao.findByHostInStates(hostId, State.Starting, State.Stopping).isEmpty()) { throw new CloudRuntimeException("Host contains VMs in starting/stopping state. Please wait for them to complete before putting to maintenance."); } - if (_vmDao.findByHostInStates(hostId, State.Error, State.Unknown).size() > 0) { + if (!_vmDao.findByHostInStates(hostId, State.Error, State.Unknown).isEmpty()) { throw new CloudRuntimeException("Host contains VMs in error/unknown/shutdown state. Please fix errors to proceed."); } @@ -1564,25 +1563,22 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, if(StringUtils.isBlank(HOST_MAINTENANCE_LOCAL_STRATEGY.value())) { return false; } - return HOST_MAINTENANCE_LOCAL_STRATEGY.value().toLowerCase().equals(WorkType.Migration.toString().toLowerCase()); + return HOST_MAINTENANCE_LOCAL_STRATEGY.value().equalsIgnoreCase(WorkType.Migration.toString()); } protected boolean isMaintenanceLocalStrategyForceStop() { if(StringUtils.isBlank(HOST_MAINTENANCE_LOCAL_STRATEGY.value())) { return false; } - return HOST_MAINTENANCE_LOCAL_STRATEGY.value().toLowerCase().equals(WorkType.ForceStop.toString().toLowerCase()); + return HOST_MAINTENANCE_LOCAL_STRATEGY.value().equalsIgnoreCase(WorkType.ForceStop.toString()); } /** * Returns true if the host.maintenance.local.storage.strategy is the Default: "Error", blank, empty, or null. */ protected boolean isMaintenanceLocalStrategyDefault() { - if (StringUtils.isBlank(HOST_MAINTENANCE_LOCAL_STRATEGY.value().toString()) - || HOST_MAINTENANCE_LOCAL_STRATEGY.value().toLowerCase().equals(State.Error.toString().toLowerCase())) { - return true; - } - return false; + return StringUtils.isBlank(HOST_MAINTENANCE_LOCAL_STRATEGY.value()) + || HOST_MAINTENANCE_LOCAL_STRATEGY.value().equalsIgnoreCase(State.Error.toString()); } /** @@ -1733,7 +1729,6 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, * Return true if host goes into Maintenance mode. There are various possibilities for VMs' states * on a host. We need to track the various VM states on each run and accordingly transit to the * appropriate state. - * * We change states as follows - * 1. If there are no VMs in running, migrating, starting, stopping, error, unknown states we can move * to maintenance state. Note that there cannot be incoming migrations as the API Call prepare for @@ -1907,7 +1902,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, guestOSDetail.setValue(String.valueOf(guestOSCategory.getId())); _hostDetailsDao.update(guestOSDetail.getId(), guestOSDetail); } else { - final Map detail = new HashMap(); + final Map detail = new HashMap<>(); detail.put("guest.os.category.id", String.valueOf(guestOSCategory.getId())); _hostDetailsDao.persist(hostId, detail); } @@ -2057,9 +2052,9 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, @Override public List getSupportedHypervisorTypes(final long zoneId, final boolean forVirtualRouter, final Long podId) { - final List hypervisorTypes = new ArrayList(); + final List hypervisorTypes = new ArrayList<>(); - List clustersForZone = new ArrayList(); + List clustersForZone; if (podId != null) { clustersForZone = _clusterDao.listByPodId(podId); } else { @@ -2068,7 +2063,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, for (final ClusterVO cluster : clustersForZone) { final HypervisorType hType = cluster.getHypervisorType(); - if (!forVirtualRouter || forVirtualRouter && hType != HypervisorType.BareMetal && hType != HypervisorType.Ovm) { + if (!forVirtualRouter || (hType != HypervisorType.BareMetal && hType != HypervisorType.Ovm)) { hypervisorTypes.add(hType); } } @@ -2104,7 +2099,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, if (isValid) { final List clusters = _clusterDao.listByDcHyType(zoneId, defaultHyper.toString()); - if (clusters.size() <= 0) { + if (clusters.isEmpty()) { isValid = false; } } @@ -2121,7 +2116,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, HypervisorType defaultHype = getDefaultHypervisor(zoneId); if (defaultHype == HypervisorType.None) { final List supportedHypes = getSupportedHypervisorTypes(zoneId, false, null); - if (supportedHypes.size() > 0) { + if (!supportedHypes.isEmpty()) { Collections.shuffle(supportedHypes); defaultHype = supportedHypes.get(0); } @@ -2245,10 +2240,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, final String cidrNetmask = NetUtils.getCidrSubNet("255.255.255.255", cidrSize); final long cidrNetmaskNumeric = NetUtils.ip2Long(cidrNetmask); final long serverNetmaskNumeric = NetUtils.ip2Long(serverPrivateNetmask); - if (serverNetmaskNumeric > cidrNetmaskNumeric) { - return false; - } - return true; + return serverNetmaskNumeric <= cidrNetmaskNumeric; } private HostVO getNewHost(StartupCommand[] startupCommands) { @@ -2262,11 +2254,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, host = findHostByGuid(startupCommand.getGuidWithoutResource()); - if (host != null) { - return host; - } - - return null; + return host; // even when host == null! } protected HostVO createHostVO(final StartupCommand[] cmds, final ServerResource resource, final Map details, List hostTags, @@ -2297,11 +2285,11 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, } } - long dcId = -1; + long dcId; DataCenterVO dc = _dcDao.findByName(dataCenter); if (dc == null) { try { - dcId = Long.parseLong(dataCenter); + dcId = Long.parseLong(dataCenter != null ? dataCenter : "-1"); dc = _dcDao.findById(dcId); } catch (final NumberFormatException e) { logger.debug("Cannot parse " + dataCenter + " into Long."); @@ -2315,7 +2303,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, HostPodVO p = _podDao.findByName(pod, dcId); if (p == null) { try { - final long podId = Long.parseLong(pod); + final long podId = Long.parseLong(pod != null ? pod : "-1"); p = _podDao.findById(podId); } catch (final NumberFormatException e) { logger.debug("Cannot parse " + pod + " into Long."); @@ -2334,9 +2322,9 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, clusterId = Long.valueOf(cluster); } catch (final NumberFormatException e) { if (podId != null) { - ClusterVO c = _clusterDao.findBy(cluster, podId.longValue()); + ClusterVO c = _clusterDao.findBy(cluster, podId); if (c == null) { - c = new ClusterVO(dcId, podId.longValue(), cluster); + c = new ClusterVO(dcId, podId, cluster); c = _clusterDao.persist(c); } clusterId = c.getId(); @@ -2439,7 +2427,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, for (Long hostId : hostIds) { DetailVO hostDetailVO = _hostDetailsDao.findDetail(hostId, name); - if (hostDetailVO == null || Boolean.parseBoolean(hostDetailVO.getValue()) == false) { + if (hostDetailVO == null || !Boolean.parseBoolean(hostDetailVO.getValue())) { clusterSupportsResigning = false; break; @@ -2527,7 +2515,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, } if (logger.isDebugEnabled()) { - new Request(-1l, -1l, cmds, true, false).logD("Startup request from directly connected host: ", true); + new Request(-1L, -1L, cmds, true, false).logD("Startup request from directly connected host: ", true); } if (old) { @@ -2597,7 +2585,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, } if (logger.isDebugEnabled()) { - new Request(-1l, -1l, cmds, true, false).logD("Startup request from directly connected host: ", true); + new Request(-1L, -1L, cmds, true, false).logD("Startup request from directly connected host: ", true); } if (old) { @@ -2682,8 +2670,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, @Override public Host createHostAndAgent(final Long hostId, final ServerResource resource, final Map details, final boolean old, final List hostTags, final boolean forRebalance) { - final Host host = createHostAndAgent(resource, details, old, hostTags, forRebalance); - return host; + return createHostAndAgent(resource, details, old, hostTags, forRebalance); } @Override @@ -2693,8 +2680,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, throw new InvalidParameterValueException("Can't find zone with id " + zoneId); } - final Map details = hostDetails; - final String guid = details.get("guid"); + final String guid = hostDetails.get("guid"); final List currentHosts = listAllUpAndEnabledHostsInOneZoneByType(hostType, zoneId); for (final HostVO currentHost : currentHosts) { if (currentHost.getGuid().equals(guid)) { @@ -2710,7 +2696,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, return createHostVO(cmds, null, null, null, ResourceStateAdapter.Event.CREATE_HOST_VO_FOR_CONNECTED); } - private void checkIPConflicts(final HostPodVO pod, final DataCenterVO dc, final String serverPrivateIP, final String serverPrivateNetmask, final String serverPublicIP, final String serverPublicNetmask) { + private void checkIPConflicts(final HostPodVO pod, final DataCenterVO dc, final String serverPrivateIP, final String serverPublicIP) { // If the server's private IP is the same as is public IP, this host has // a host-only private network. Don't check for conflicts with the // private IP address table. @@ -2739,7 +2725,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, // If the server's public IP address is already in the database, // return false final List existingPublicIPs = _publicIPAddressDao.listByDcIdIpAddress(dc.getId(), serverPublicIP); - if (existingPublicIPs.size() > 0) { + if (!existingPublicIPs.isEmpty()) { throw new IllegalArgumentException("The public ip address of the server (" + serverPublicIP + ") is already in use in zone: " + dc.getName()); } } @@ -2776,7 +2762,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, final HostPodVO pod = _podDao.findById(host.getPodId()); final DataCenterVO dc = _dcDao.findById(host.getDataCenterId()); - checkIPConflicts(pod, dc, ssCmd.getPrivateIpAddress(), ssCmd.getPublicIpAddress(), ssCmd.getPublicIpAddress(), ssCmd.getPublicNetmask()); + checkIPConflicts(pod, dc, ssCmd.getPrivateIpAddress(), ssCmd.getPublicIpAddress()); host.setType(com.cloud.host.Host.Type.Routing); host.setDetails(details); host.setCaps(ssCmd.getCapabilities()); @@ -2814,8 +2800,8 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, throw new UnableDeleteHostException("Failed to set primary storage into maintenance mode"); } } catch (final Exception e) { - logger.debug("Failed to set primary storage into maintenance mode, due to: " + e.toString()); - throw new UnableDeleteHostException("Failed to set primary storage into maintenance mode, due to: " + e.toString()); + logger.debug("Failed to set primary storage into maintenance mode", e); + throw new UnableDeleteHostException("Failed to set primary storage into maintenance mode, due to: " + e); } } @@ -2959,7 +2945,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, if (result.getReturnCode() != 0) { throw new CloudRuntimeException(String.format("Could not restart agent on %s due to: %s", host, result.getStdErr())); } - logger.debug("cloudstack-agent restart result: " + result.toString()); + logger.debug("cloudstack-agent restart result: {}", result); } catch (final SshException e) { throw new CloudRuntimeException("SSH to agent is enabled, but agent restart failed", e); } @@ -2980,7 +2966,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, } @Override - public boolean executeUserRequest(final long hostId, final ResourceState.Event event) throws AgentUnavailableException { + public boolean executeUserRequest(final long hostId, final ResourceState.Event event) { if (event == ResourceState.Event.AdminAskMaintenance) { return doMaintain(hostId); } else if (event == ResourceState.Event.AdminCancelMaintenance) { @@ -3306,7 +3292,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, public HostStats getHostStatistics(final Host host) { final Answer answer = _agentMgr.easySend(host.getId(), new GetHostStatsCommand(host.getGuid(), host.getName(), host.getId())); - if (answer != null && answer instanceof UnsupportedAnswer) { + if (answer instanceof UnsupportedAnswer) { return null; } @@ -3342,20 +3328,16 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, @Override public String getHostTags(final long hostId) { final List hostTags = _hostTagsDao.getHostTags(hostId).parallelStream().map(HostTagVO::getTag).collect(Collectors.toList()); - if (hostTags == null) { - return null; - } else { - return com.cloud.utils.StringUtils.listToCsvTags(hostTags); - } + return StringUtils.listToCsvTags(hostTags); } @Override public List listByDataCenter(final long dcId) { final List pods = _podDao.listByDataCenterId(dcId); - final ArrayList pcs = new ArrayList(); + final ArrayList pcs = new ArrayList<>(); for (final HostPodVO pod : pods) { final List clusters = _clusterDao.listByPodId(pod.getId()); - if (clusters.size() == 0) { + if (clusters.isEmpty()) { pcs.add(new PodCluster(pod, null)); } else { for (final ClusterVO cluster : clusters) { @@ -3400,7 +3382,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, public boolean isHostGpuEnabled(final long hostId) { final SearchCriteria sc = _gpuAvailability.create(); sc.setParameters("hostId", hostId); - return _hostGpuGroupsDao.customSearch(sc, null).size() > 0 ? true : false; + return !_hostGpuGroupsDao.customSearch(sc, null).isEmpty(); } @Override @@ -3465,7 +3447,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, // Update GPU group capacity final TransactionLegacy txn = TransactionLegacy.currentTxn(); txn.start(); - _hostGpuGroupsDao.persist(hostId, new ArrayList(groupDetails.keySet())); + _hostGpuGroupsDao.persist(hostId, new ArrayList<>(groupDetails.keySet())); _vgpuTypesDao.persist(hostId, groupDetails); txn.commit(); } @@ -3473,7 +3455,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, @Override public HashMap> getGPUStatistics(final HostVO host) { final Answer answer = _agentMgr.easySend(host.getId(), new GetGPUStatsCommand(host.getGuid(), host.getName())); - if (answer != null && answer instanceof UnsupportedAnswer) { + if (answer instanceof UnsupportedAnswer) { return null; } if (answer == null || !answer.getResult()) { @@ -3514,7 +3496,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, @ActionEvent(eventType = EventTypes.EVENT_HOST_RESERVATION_RELEASE, eventDescription = "releasing host reservation", async = true) public boolean releaseHostReservation(final Long hostId) { try { - return Transaction.execute(new TransactionCallback() { + return Transaction.execute(new TransactionCallback<>() { @Override public Boolean doInTransaction(final TransactionStatus status) { final PlannerHostReservationVO reservationEntry = _plannerHostReserveDao.findByHostId(hostId); diff --git a/ui/src/config/section/compute.js b/ui/src/config/section/compute.js index 803f8eb0c70..6bbcf38e9b5 100644 --- a/ui/src/config/section/compute.js +++ b/ui/src/config/section/compute.js @@ -123,7 +123,7 @@ export default { dataView: true, groupAction: true, popup: true, - groupMap: (selection, values) => { return selection.map(x => { return { id: x, considerlasthost: values.considerlasthost } }) }, + groupMap: (selection, values) => { return selection.map(x => { return { id: x, considerlasthost: values.considerlasthost === true } }) }, args: (record, store) => { if (['Admin'].includes(store.userInfo.roletype)) { return ['considerlasthost'] diff --git a/ui/src/config/section/infra/hosts.js b/ui/src/config/section/infra/hosts.js index c83fba48c2d..2dba77fa4df 100644 --- a/ui/src/config/section/infra/hosts.js +++ b/ui/src/config/section/infra/hosts.js @@ -115,9 +115,14 @@ export default { label: 'label.disable.host', message: 'message.confirm.disable.host', dataView: true, - show: (record) => { return record.resourcestate === 'Enabled' }, + show: (record) => record.resourcestate === 'Enabled', popup: true, - component: shallowRef(defineAsyncComponent(() => import('@/views/infra/HostEnableDisable'))) + component: shallowRef(defineAsyncComponent(() => import('@/views/infra/HostEnableDisable'))), + events: { + 'refresh-data': () => { + store.dispatch('refreshCurrentPage') + } + } }, { api: 'updateHost', @@ -125,9 +130,14 @@ export default { label: 'label.enable.host', message: 'message.confirm.enable.host', dataView: true, - show: (record) => { return record.resourcestate === 'Disabled' }, + show: (record) => record.resourcestate === 'Disabled', popup: true, - component: shallowRef(defineAsyncComponent(() => import('@/views/infra/HostEnableDisable'))) + component: shallowRef(defineAsyncComponent(() => import('@/views/infra/HostEnableDisable'))), + events: { + 'refresh-data': () => { + store.dispatch('refreshCurrentPage') + } + } }, { api: 'prepareHostForMaintenance', diff --git a/ui/src/views/compute/StartVirtualMachine.vue b/ui/src/views/compute/StartVirtualMachine.vue index f229cb44f67..4e1a63b82df 100644 --- a/ui/src/views/compute/StartVirtualMachine.vue +++ b/ui/src/views/compute/StartVirtualMachine.vue @@ -243,7 +243,7 @@ export default { id: this.resource.id } for (const key in values) { - if (values[key]) { + if (values[key] || values[key] === false) { params[key] = values[key] } } diff --git a/ui/src/views/infra/HostEnableDisable.vue b/ui/src/views/infra/HostEnableDisable.vue index 84310a0051f..0eb960cf848 100644 --- a/ui/src/views/infra/HostEnableDisable.vue +++ b/ui/src/views/infra/HostEnableDisable.vue @@ -18,7 +18,7 @@