diff --git a/api/src/main/java/com/cloud/storage/ScopeType.java b/api/src/main/java/com/cloud/storage/ScopeType.java index e20f525c5f8..a944ebae10c 100644 --- a/api/src/main/java/com/cloud/storage/ScopeType.java +++ b/api/src/main/java/com/cloud/storage/ScopeType.java @@ -18,6 +18,21 @@ */ package com.cloud.storage; +import com.cloud.exception.InvalidParameterValueException; +import org.apache.commons.lang3.EnumUtils; + public enum ScopeType { HOST, CLUSTER, ZONE, REGION, GLOBAL; + + public static ScopeType validateAndGetScopeType(String value) { + if (value == null) { + return null; + } else { + ScopeType scopeType = EnumUtils.getEnumIgnoreCase(ScopeType.class, value); + if (scopeType == null) { + throw new InvalidParameterValueException("Invalid scope type: " + value); + } + return scopeType; + } + } } diff --git a/api/src/main/java/com/cloud/storage/StoragePoolStatus.java b/api/src/main/java/com/cloud/storage/StoragePoolStatus.java index 778d3881e3e..3bfd829d2f7 100644 --- a/api/src/main/java/com/cloud/storage/StoragePoolStatus.java +++ b/api/src/main/java/com/cloud/storage/StoragePoolStatus.java @@ -16,6 +16,21 @@ // under the License. package com.cloud.storage; +import com.cloud.exception.InvalidParameterValueException; +import org.apache.commons.lang3.EnumUtils; + public enum StoragePoolStatus { Initial, Initialized, Creating, Attaching, Up, PrepareForMaintenance, ErrorInMaintenance, CancelMaintenance, Maintenance, Disabled, Removed; + + public static StoragePoolStatus validateAndGetStatus(String value) { + if (value == null) { + return null; + } else { + StoragePoolStatus status = EnumUtils.getEnumIgnoreCase(StoragePoolStatus.class, value); + if (status == null) { + throw new InvalidParameterValueException("Invalid status: " + value); + } + return status; + } + } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/ListStoragePoolsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/ListStoragePoolsCmd.java index ce1164000fc..209aaac279c 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/ListStoragePoolsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/ListStoragePoolsCmd.java @@ -66,6 +66,9 @@ public class ListStoragePoolsCmd extends BaseListCmd { @Parameter(name = ApiConstants.SCOPE, type = CommandType.STRING, entityType = StoragePoolResponse.class, description = "the ID of the storage pool") private String scope; + @Parameter(name = ApiConstants.STATUS, type = CommandType.STRING, description = "the status of the storage pool") + private String status; + ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// @@ -94,6 +97,10 @@ public class ListStoragePoolsCmd extends BaseListCmd { return zoneId; } + public String getStatus() { + return status; + } + public Long getId() { return id; } @@ -101,7 +108,7 @@ public class ListStoragePoolsCmd extends BaseListCmd { public void setId(Long id) { this.id = id; } -///////////////////////////////////////////////////// + ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// diff --git a/server/src/main/java/com/cloud/api/query/QueryManagerImpl.java b/server/src/main/java/com/cloud/api/query/QueryManagerImpl.java index d6c166e7ed7..ce5b9db574d 100644 --- a/server/src/main/java/com/cloud/api/query/QueryManagerImpl.java +++ b/server/src/main/java/com/cloud/api/query/QueryManagerImpl.java @@ -231,6 +231,7 @@ import com.cloud.storage.ScopeType; import com.cloud.storage.Storage; import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.Storage.TemplateType; +import com.cloud.storage.StoragePoolStatus; import com.cloud.storage.StoragePoolTagVO; import com.cloud.storage.VMTemplateVO; import com.cloud.storage.Volume; @@ -2620,89 +2621,26 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q } private Pair, Integer> searchForStoragePoolsInternal(ListStoragePoolsCmd cmd) { - ScopeType scopeType = null; - if (cmd.getScope() != null) { - try { - scopeType = Enum.valueOf(ScopeType.class, cmd.getScope().toUpperCase()); - } catch (Exception e) { - throw new InvalidParameterValueException("Invalid scope type: " + cmd.getScope()); - } - } + ScopeType scopeType = ScopeType.validateAndGetScopeType(cmd.getScope()); + StoragePoolStatus status = StoragePoolStatus.validateAndGetStatus(cmd.getStatus()); Long zoneId = _accountMgr.checkAccessAndSpecifyAuthority(CallContext.current().getCallingAccount(), cmd.getZoneId()); - Object id = cmd.getId(); - Object name = cmd.getStoragePoolName(); - Object path = cmd.getPath(); - Object pod = cmd.getPodId(); - Object cluster = cmd.getClusterId(); - Object address = cmd.getIpAddress(); - Object keyword = cmd.getKeyword(); + Long id = cmd.getId(); + String name = cmd.getStoragePoolName(); + String path = cmd.getPath(); + Long pod = cmd.getPodId(); + Long cluster = cmd.getClusterId(); + String address = cmd.getIpAddress(); + String keyword = cmd.getKeyword(); Long startIndex = cmd.getStartIndex(); Long pageSize = cmd.getPageSizeVal(); Filter searchFilter = new Filter(StoragePoolJoinVO.class, "id", Boolean.TRUE, startIndex, pageSize); - SearchBuilder sb = _poolJoinDao.createSearchBuilder(); - sb.select(null, Func.DISTINCT, sb.entity().getId()); // select distinct - // ids - sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ); - sb.and("name", sb.entity().getName(), SearchCriteria.Op.EQ); - sb.and("path", sb.entity().getPath(), SearchCriteria.Op.EQ); - sb.and("dataCenterId", sb.entity().getZoneId(), SearchCriteria.Op.EQ); - sb.and("podId", sb.entity().getPodId(), SearchCriteria.Op.EQ); - sb.and("clusterId", sb.entity().getClusterId(), SearchCriteria.Op.EQ); - sb.and("hostAddress", sb.entity().getHostAddress(), SearchCriteria.Op.EQ); - sb.and("scope", sb.entity().getScope(), SearchCriteria.Op.EQ); - sb.and("parent", sb.entity().getParent(), Op.EQ); + // search & count Pool details by ids + Pair, Integer> uniquePoolPair = _poolJoinDao.searchAndCount(id, name, zoneId, path, pod, + cluster, address, scopeType, status, keyword, searchFilter); - SearchCriteria sc = sb.create(); - - if (keyword != null) { - SearchCriteria ssc = _poolJoinDao.createSearchCriteria(); - ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%"); - ssc.addOr("poolType", SearchCriteria.Op.LIKE, "%" + keyword + "%"); - - sc.addAnd("name", SearchCriteria.Op.SC, ssc); - } - - if (id != null) { - sc.setParameters("id", id); - } - - if (name != null) { - sc.setParameters("name", name); - } - - if (path != null) { - sc.setParameters("path", path); - } - if (zoneId != null) { - sc.setParameters("dataCenterId", zoneId); - } - if (pod != null) { - SearchCriteria ssc = _poolJoinDao.createSearchCriteria(); - ssc.addOr("podId", Op.EQ, pod); - ssc.addOr("podId", Op.NULL); - - sc.addAnd("podId", SearchCriteria.Op.SC, ssc); - } - if (address != null) { - sc.setParameters("hostAddress", address); - } - if (cluster != null) { - SearchCriteria ssc = _poolJoinDao.createSearchCriteria(); - ssc.addOr("clusterId", Op.EQ, cluster); - ssc.addOr("clusterId", Op.NULL); - - sc.addAnd("clusterId", SearchCriteria.Op.SC, ssc); - } - if (scopeType != null) { - sc.setParameters("scope", scopeType.toString()); - } - sc.setParameters("parent", 0); - - // search Pool details by ids - Pair, Integer> uniquePoolPair = _poolJoinDao.searchAndCount(sc, searchFilter); Integer count = uniquePoolPair.second(); if (count.intValue() == 0) { // empty result diff --git a/server/src/main/java/com/cloud/api/query/dao/StoragePoolJoinDao.java b/server/src/main/java/com/cloud/api/query/dao/StoragePoolJoinDao.java index 55c028044f7..87659210ad7 100644 --- a/server/src/main/java/com/cloud/api/query/dao/StoragePoolJoinDao.java +++ b/server/src/main/java/com/cloud/api/query/dao/StoragePoolJoinDao.java @@ -18,6 +18,10 @@ package com.cloud.api.query.dao; import java.util.List; +import com.cloud.storage.ScopeType; +import com.cloud.storage.StoragePoolStatus; +import com.cloud.utils.Pair; +import com.cloud.utils.db.Filter; import org.apache.cloudstack.api.response.StoragePoolResponse; import com.cloud.api.query.vo.StoragePoolJoinVO; @@ -38,4 +42,6 @@ public interface StoragePoolJoinDao extends GenericDao List searchByIds(Long... spIds); + Pair, Integer> searchAndCount(Long storagePoolId, String storagePoolName, Long zoneId, String path, Long podId, Long clusterId, String address, ScopeType scopeType, StoragePoolStatus status, String keyword, Filter searchFilter); + } diff --git a/server/src/main/java/com/cloud/api/query/dao/StoragePoolJoinDaoImpl.java b/server/src/main/java/com/cloud/api/query/dao/StoragePoolJoinDaoImpl.java index 28ba1f63fc6..527cc949ed1 100644 --- a/server/src/main/java/com/cloud/api/query/dao/StoragePoolJoinDaoImpl.java +++ b/server/src/main/java/com/cloud/api/query/dao/StoragePoolJoinDaoImpl.java @@ -20,11 +20,15 @@ import com.cloud.api.ApiDBUtils; import com.cloud.api.query.vo.StoragePoolJoinVO; import com.cloud.capacity.CapacityManager; import com.cloud.storage.DataStoreRole; +import com.cloud.storage.ScopeType; import com.cloud.storage.Storage; import com.cloud.storage.StoragePool; +import com.cloud.storage.StoragePoolStatus; import com.cloud.storage.StorageStats; import com.cloud.user.AccountManager; +import com.cloud.utils.Pair; import com.cloud.utils.StringUtils; +import com.cloud.utils.db.Filter; import com.cloud.utils.db.GenericDaoBase; import com.cloud.utils.db.SearchBuilder; import com.cloud.utils.db.SearchCriteria; @@ -291,4 +295,75 @@ public class StoragePoolJoinDaoImpl extends GenericDaoBase, Integer> searchAndCount(Long storagePoolId, String storagePoolName, Long zoneId, String path, Long podId, Long clusterId, String address, ScopeType scopeType, StoragePoolStatus status, String keyword, Filter searchFilter) { + SearchCriteria sc = createStoragePoolSearchCriteria(storagePoolId, storagePoolName, zoneId, path, podId, clusterId, address, scopeType, status, keyword); + return searchAndCount(sc, searchFilter); + } + + private SearchCriteria createStoragePoolSearchCriteria(Long storagePoolId, String storagePoolName, Long zoneId, String path, Long podId, Long clusterId, String address, ScopeType scopeType, StoragePoolStatus status, String keyword) { + SearchBuilder sb = createSearchBuilder(); + sb.select(null, SearchCriteria.Func.DISTINCT, sb.entity().getId()); // select distinct + // ids + sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ); + sb.and("name", sb.entity().getName(), SearchCriteria.Op.EQ); + sb.and("path", sb.entity().getPath(), SearchCriteria.Op.EQ); + sb.and("dataCenterId", sb.entity().getZoneId(), SearchCriteria.Op.EQ); + sb.and("podId", sb.entity().getPodId(), SearchCriteria.Op.EQ); + sb.and("clusterId", sb.entity().getClusterId(), SearchCriteria.Op.EQ); + sb.and("hostAddress", sb.entity().getHostAddress(), SearchCriteria.Op.EQ); + sb.and("scope", sb.entity().getScope(), SearchCriteria.Op.EQ); + sb.and("status", sb.entity().getStatus(), SearchCriteria.Op.EQ); + sb.and("parent", sb.entity().getParent(), SearchCriteria.Op.EQ); + + SearchCriteria sc = sb.create(); + + if (keyword != null) { + SearchCriteria ssc = createSearchCriteria(); + ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%"); + ssc.addOr("poolType", SearchCriteria.Op.LIKE, "%" + keyword + "%"); + + sc.addAnd("name", SearchCriteria.Op.SC, ssc); + } + + if (storagePoolId != null) { + sc.setParameters("id", storagePoolId); + } + + if (storagePoolName != null) { + sc.setParameters("name", storagePoolName); + } + + if (path != null) { + sc.setParameters("path", path); + } + if (zoneId != null) { + sc.setParameters("dataCenterId", zoneId); + } + if (podId != null) { + SearchCriteria ssc = createSearchCriteria(); + ssc.addOr("podId", SearchCriteria.Op.EQ, podId); + ssc.addOr("podId", SearchCriteria.Op.NULL); + + sc.addAnd("podId", SearchCriteria.Op.SC, ssc); + } + if (address != null) { + sc.setParameters("hostAddress", address); + } + if (clusterId != null) { + SearchCriteria ssc = createSearchCriteria(); + ssc.addOr("clusterId", SearchCriteria.Op.EQ, clusterId); + ssc.addOr("clusterId", SearchCriteria.Op.NULL); + + sc.addAnd("clusterId", SearchCriteria.Op.SC, ssc); + } + if (scopeType != null) { + sc.setParameters("scope", scopeType.toString()); + } + if (status != null) { + sc.setParameters("status", status.toString()); + } + sc.setParameters("parent", 0); + return sc; + } } diff --git a/server/src/main/java/com/cloud/network/NetworkServiceImpl.java b/server/src/main/java/com/cloud/network/NetworkServiceImpl.java index 746e4365e1b..f3109c04095 100644 --- a/server/src/main/java/com/cloud/network/NetworkServiceImpl.java +++ b/server/src/main/java/com/cloud/network/NetworkServiceImpl.java @@ -4411,12 +4411,14 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C } vlanOwnerId = vlanOwner.getAccountId(); - // Verify physical network isolation type is VLAN + // Verify physical network isolation methods contain VLAN or VXLAN PhysicalNetworkVO physicalNetwork = _physicalNetworkDao.findById(physicalNetworkId); if (physicalNetwork == null) { throw new InvalidParameterValueException("Unable to find physical network by id " + physicalNetworkId); - } else if (!physicalNetwork.getIsolationMethods().isEmpty() && !physicalNetwork.getIsolationMethods().contains("VLAN")) { - throw new InvalidParameterValueException("Cannot dedicate guest vlan range. " + "Physical isolation type of network " + physicalNetworkId + " is not VLAN"); + } else if (!physicalNetwork.getIsolationMethods().isEmpty() && + !physicalNetwork.getIsolationMethods().contains("VLAN") && + !physicalNetwork.getIsolationMethods().contains("VXLAN")) { + throw new InvalidParameterValueException("Cannot dedicate guest vlan range. " + "Physical isolation type of network " + physicalNetworkId + " is not VLAN nor VXLAN"); } // Get the start and end vlan diff --git a/ui/public/locales/en.json b/ui/public/locales/en.json index d66f936f2c0..dfa813238be 100644 --- a/ui/public/locales/en.json +++ b/ui/public/locales/en.json @@ -342,6 +342,7 @@ "label.associatednetworkid": "Associated network ID", "label.associatednetworkname": "Network name", "label.asyncbackup": "Async backup", +"label.attaching": "Attaching", "label.authentication.method": "Authentication Method", "label.authentication.sshkey": "System SSH Key", "label.autoscale": "AutoScale", @@ -404,6 +405,7 @@ "label.cachemode": "Write-cache type", "label.cancel": "Cancel", "label.cancel.shutdown": "Cancel Shutdown", +"label.cancelmaintenance": "Cancel maintenance", "label.capacity": "Capacity", "label.capacitybytes": "Capacity bytes", "label.capacityiops": "IOPS total", @@ -549,6 +551,7 @@ "label.create.user": "Create user", "label.create.vpn.connection": "Create VPN connection", "label.created": "Created", +"label.creating": "Creating", "label.creating.iprange": "Creating IP ranges", "label.credit": "Credit", "label.crosszones": "Cross zones", @@ -657,6 +660,7 @@ "label.destnetworkuuid": "Network", "label.destport": "Destination Ports", "label.destroy": "Destroy", +"label.destroyed": "Destroyed", "label.destroy.router": "Destroy router", "label.deststartport": "Destination Start Port", "label.desttaguuid": "Destination Tag", @@ -726,6 +730,7 @@ "label.domainrouter": "Virtual Router", "label.domains": "Domains", "label.done": "Done", +"label.down": "Down", "label.download": "Download", "label.download.kubeconfig.cluster": "Download kubeconfig for the cluster

The kubectl command-line tool uses kubeconfig files to find the information it needs to choose a cluster and communicate with the API server of a cluster.", "label.download.kubectl": "Download kubectl tool for cluster's Kubernetes version", @@ -766,6 +771,7 @@ "label.egressdefaultpolicy": "Default egress policy", "label.elastic": "Elastic", "label.email": "Email", +"label.enabled": "Enabled", "label.enable.autoscale.vmgroup": "Enable AutoScale VM Group", "label.enable.host": "Enable Host", "label.enable.network.offering": "Enable network offering", @@ -773,6 +779,7 @@ "label.enable.storage": "Enable storage pool", "label.enable.vpc.offering": "Enable VPC offering", "label.enable.vpn": "Enable remote access VPN", +"label.enabled": "Enabled", "label.encrypt": "Encrypt", "label.encryptroot": "Encrypt Root Disk", "label.end": "End", @@ -800,6 +807,7 @@ "label.error.setting": "Error setting", "label.error.something.went.wrong.please.correct.the.following": "Something went wrong; please correct the following", "label.error.upper": "ERROR", +"label.errorinmaintenance": "Error in maintenance", "label.espencryption": "ESP encryption", "label.esphash": "ESP hash", "label.esplifetime": "ESP lifetime (second)", @@ -959,6 +967,8 @@ "label.infrastructure": "Infrastructure", "label.ingress": "Ingress", "label.ingress.rule": "Ingress Rule", +"label.initial": "Inital", +"label.initialized": "Initalized", "label.insideportprofile": "Inside port profile", "label.installwizard.addzoneintro.title": "Let's add a zone", "label.installwizard.subtitle": "This guide will aid you in setting up your CloudStack™ installation", @@ -1149,6 +1159,7 @@ "label.local.storage.enabled.system.vms": "Enable local storage for system VMs", "label.localstorageenabled": "Enable local storage for user VMs", "label.localstorageenabledforsystemvm": "Enable local storage for system VMs", +"label.locked": "Locked", "label.login": "Login", "label.loginfo": "Log file information", "label.login.portal": "Portal login", @@ -1162,6 +1173,7 @@ "label.macaddresschanges": "MAC address changes", "label.maclearning": "MAC learning", "label.macos": "MacOS", +"label.maintenance": "Maintenance", "label.majorsequence": "Major Sequence", "label.make": "Make", "label.make.project.owner": "Make account project owner", @@ -1449,6 +1461,7 @@ "label.prefix": "Prefix", "label.prefix.type": "Prefix type", "label.prepare.for.shutdown": "Prepare for Shutdown", +"label.prepareformaintenance": "Prepare for Maintenance", "label.presetup": "PreSetup", "label.prev": "Prev", "label.previous": "Previous", @@ -1594,6 +1607,7 @@ "label.remove.vmware.datacenter": "Remove VMware Datacenter", "label.remove.vpc": "Remove VPC", "label.remove.vpc.offering": "Remove VPC offering", +"label.removed": "Removed", "label.removing": "Removing", "label.replace.acl": "Replace ACL", "label.replace.acl.list": "Replace ACL list", @@ -1661,7 +1675,8 @@ "label.rules.file.import.description": "Click or drag rule definitions CSV file to import.", "label.rules.file.to.import": "Rule definitions CSV file to import", "label.run.proxy.locally": "Run proxy locally", -"label.running": "Running VMs", +"label.running": "Running", +"label.running.vms": "Running VMs", "label.s2scustomergatewayid": "Site to site customer gateway ID", "label.s2svpngatewayid": "Site to site VPN gateway ID", "label.s3.access.key": "Access key", @@ -1757,6 +1772,7 @@ "label.sharewith": "Share with", "label.showing": "Showing", "label.shrinkok": "Shrink OK", +"label.shutdown": "Shutdown", "label.shutdown.provider": "Shutdown provider", "label.simplified.chinese.keyboard": "Simplified Chinese keyboard", "label.site.to.site.vpn": "Site-to-site VPN", @@ -1825,6 +1841,7 @@ "label.start.rolling.maintenance": "Start rolling maintenance", "label.start.vm": "Start VM", "label.startdate": "By date (start)", +"label.starting": "Starting", "label.startip": "Start IP", "label.startipv4": "IPv4 start IP", "label.startipv6": "IPv6 start IP", @@ -1852,7 +1869,9 @@ "label.sticky.request-learn": "Request learn", "label.sticky.tablesize": "Table size", "label.stop": "Stop", -"label.stopped": "Stopped VMs", +"label.stopped": "Stopped", +"label.stopped.vms": "Stopped VMs", +"label.stopping": "Stopping", "label.storage": "Storage", "label.storage.migration.required": "Storage migration required", "label.storage.tags": "Storage tags", @@ -2009,6 +2028,7 @@ "label.unmanaged.instance": "Unmanaged instance", "label.unmanaged.instances": "Unmanaged instances", "label.untagged": "Untagged", +"label.up": "Up", "label.updateinsequence": "Update in sequence", "label.update.autoscale.vmgroup": "Update AutoScale VM group", "label.update.condition": "Update condition", diff --git a/ui/src/config/section/account.js b/ui/src/config/section/account.js index 4e69da72b92..3141b966190 100644 --- a/ui/src/config/section/account.js +++ b/ui/src/config/section/account.js @@ -31,6 +31,10 @@ export default { title: 'label.users', param: 'account' }], + filters: () => { + const filters = ['enabled', 'disabled', 'locked'] + return filters + }, tabs: [ { name: 'details', diff --git a/ui/src/config/section/infra/clusters.js b/ui/src/config/section/infra/clusters.js index 8aa0bc6ecc7..ca6dde7ec9b 100644 --- a/ui/src/config/section/infra/clusters.js +++ b/ui/src/config/section/infra/clusters.js @@ -41,6 +41,10 @@ export default { param: 'clusterid' }], resourceType: 'Cluster', + filters: () => { + const filters = ['enabled', 'disabled'] + return filters + }, tabs: [{ name: 'details', component: shallowRef(defineAsyncComponent(() => import('@/components/view/DetailsTab.vue'))) diff --git a/ui/src/config/section/infra/hosts.js b/ui/src/config/section/infra/hosts.js index 1e2d1ca6c2f..60f30e3f3e0 100644 --- a/ui/src/config/section/infra/hosts.js +++ b/ui/src/config/section/infra/hosts.js @@ -25,6 +25,10 @@ export default { docHelp: 'conceptsandterminology/concepts.html#about-hosts', permission: ['listHostsMetrics'], resourceType: 'Host', + filters: () => { + const filters = ['enabled', 'disabled', 'maintenance', 'up', 'down', 'alert'] + return filters + }, params: { type: 'routing' }, columns: () => { const fields = ['name', 'state', 'resourcestate', 'ipaddress', 'hypervisor', 'instances', 'powerstate'] diff --git a/ui/src/config/section/infra/pods.js b/ui/src/config/section/infra/pods.js index f8daf98588e..eff62e0a4a2 100644 --- a/ui/src/config/section/infra/pods.js +++ b/ui/src/config/section/infra/pods.js @@ -36,6 +36,10 @@ export default { param: 'podid' }], resourceType: 'Pod', + filters: () => { + const filters = ['enabled', 'disabled'] + return filters + }, tabs: [{ name: 'details', component: shallowRef(defineAsyncComponent(() => import('@/components/view/DetailsTab.vue'))) diff --git a/ui/src/config/section/infra/primaryStorages.js b/ui/src/config/section/infra/primaryStorages.js index ff5bb41be65..4537b993a06 100644 --- a/ui/src/config/section/infra/primaryStorages.js +++ b/ui/src/config/section/infra/primaryStorages.js @@ -41,6 +41,10 @@ export default { param: 'storageid' }], resourceType: 'PrimaryStorage', + filters: () => { + const filters = ['initial', 'initialized', 'creating', 'attaching', 'up', 'prepareformaintenance', 'errorinmaintenance', 'cancelmaintenance', 'maintenance', 'disabled', 'removed'] + return filters + }, tabs: [{ name: 'details', component: shallowRef(defineAsyncComponent(() => import('@/components/view/DetailsTab.vue'))) diff --git a/ui/src/config/section/infra/routers.js b/ui/src/config/section/infra/routers.js index 6f24d6b7d82..9e45cb73246 100644 --- a/ui/src/config/section/infra/routers.js +++ b/ui/src/config/section/infra/routers.js @@ -33,6 +33,10 @@ export default { searchFilters: ['name', 'zoneid', 'podid', 'clusterid'], details: ['name', 'id', 'version', 'softwareversion', 'requiresupgrade', 'guestnetworkname', 'vpcname', 'publicip', 'guestipaddress', 'linklocalip', 'serviceofferingname', 'networkdomain', 'isredundantrouter', 'redundantstate', 'hostname', 'account', 'zonename', 'created', 'hostcontrolstate'], resourceType: 'VirtualRouter', + filters: () => { + const filters = ['starting', 'running', 'stopping', 'stopped', 'destroyed', 'expunging', 'migrating', 'error', 'unknown', 'shutdown'] + return filters + }, tabs: [{ name: 'details', component: shallowRef(defineAsyncComponent(() => import('@/components/view/DetailsTab.vue'))) diff --git a/ui/src/config/section/infra/systemVms.js b/ui/src/config/section/infra/systemVms.js index a649ef1c11a..e48b19cb5d4 100644 --- a/ui/src/config/section/infra/systemVms.js +++ b/ui/src/config/section/infra/systemVms.js @@ -27,6 +27,10 @@ export default { columns: ['name', 'state', 'agentstate', 'systemvmtype', 'publicip', 'privateip', 'linklocalip', 'hostname', 'zonename'], details: ['name', 'id', 'agentstate', 'systemvmtype', 'publicip', 'privateip', 'linklocalip', 'gateway', 'hostname', 'zonename', 'created', 'activeviewersessions', 'isdynamicallyscalable', 'hostcontrolstate'], resourceType: 'SystemVm', + filters: () => { + const filters = ['starting', 'running', 'stopping', 'stopped', 'destroyed', 'expunging', 'migrating', 'error', 'unknown', 'shutdown'] + return filters + }, tabs: [ { name: 'details', diff --git a/ui/src/views/AutogenView.vue b/ui/src/views/AutogenView.vue index 1b66467cb4d..fd241fee163 100644 --- a/ui/src/views/AutogenView.vue +++ b/ui/src/views/AutogenView.vue @@ -63,7 +63,9 @@ }" > {{ $t('label.all') }} @@ -673,7 +675,7 @@ export default { return this.$route.query.filter } const routeName = this.$route.name - if ((this.projectView && routeName === 'vm') || (['Admin', 'DomainAdmin'].includes(this.$store.getters.userInfo.roletype) && ['vm', 'iso', 'template'].includes(routeName)) || ['guestnetwork', 'guestvlans'].includes(routeName)) { + if ((this.projectView && routeName === 'vm') || (['Admin', 'DomainAdmin'].includes(this.$store.getters.userInfo.roletype) && ['vm', 'iso', 'template', 'pod', 'cluster', 'host', 'systemvm', 'router', 'storagepool'].includes(routeName)) || ['account', 'guestnetwork', 'guestvlans'].includes(routeName)) { return 'all' } if (['publicip'].includes(routeName)) { @@ -1592,8 +1594,33 @@ export default { } else { query.networkfilter = filter } - } else if (this.$route.name === 'publicip') { - query.state = filter + } else if (['account', 'publicip', 'systemvm', 'router'].includes(this.$route.name)) { + if (filter !== 'all') { + query.state = filter + } + } else if (this.$route.name === 'storagepool') { + if (filter === 'all') { + delete query.status + } else { + query.status = filter + } + } else if (['pod', 'cluster'].includes(this.$route.name)) { + if (filter === 'all') { + delete query.allocationstate + } else { + query.allocationstate = filter + } + } else if (['host'].includes(this.$route.name)) { + if (filter === 'all') { + delete query.resourcestate + delete query.state + } else if (['up', 'down', 'alert'].includes(filter)) { + delete query.resourcestate + query.state = filter + } else { + delete query.state + query.resourcestate = filter + } } else if (this.$route.name === 'vm') { if (filter === 'self') { query.account = this.$store.getters.userInfo.account diff --git a/ui/src/views/dashboard/UsageDashboard.vue b/ui/src/views/dashboard/UsageDashboard.vue index 77eb16ef496..4264a90f925 100644 --- a/ui/src/views/dashboard/UsageDashboard.vue +++ b/ui/src/views/dashboard/UsageDashboard.vue @@ -175,7 +175,7 @@ export default { count = json.listvirtualmachinesresponse.count } var tileColor = this.$config.theme['@dashboard-tile-runningvms-bg'] || '#dfe9cc' - this.stats.splice(0, 1, { name: this.$t('label.running'), count: count, icon: 'desktop-outlined', bgcolor: tileColor, path: '/vm', query: { state: 'running', filter: 'running' } }) + this.stats.splice(0, 1, { name: this.$t('label.running.vms'), count: count, icon: 'desktop-outlined', bgcolor: tileColor, path: '/vm', query: { state: 'running', filter: 'running' } }) }) api('listVirtualMachines', { state: 'Stopped', listall: true }).then(json => { var count = 0 @@ -183,7 +183,7 @@ export default { count = json.listvirtualmachinesresponse.count } var tileColor = this.$config.theme['@dashboard-tile-stoppedvms-bg'] || '#edcbce' - this.stats.splice(1, 1, { name: this.$t('label.stopped'), count: count, icon: 'poweroff-outlined', bgcolor: tileColor, path: '/vm', query: { state: 'stopped', filter: 'stopped' } }) + this.stats.splice(1, 1, { name: this.$t('label.stopped.vms'), count: count, icon: 'poweroff-outlined', bgcolor: tileColor, path: '/vm', query: { state: 'stopped', filter: 'stopped' } }) }) api('listVirtualMachines', { listall: true }).then(json => { var count = 0