diff --git a/api/src/main/java/org/apache/cloudstack/acl/RoleService.java b/api/src/main/java/org/apache/cloudstack/acl/RoleService.java index dfc5cb1cafe..578c13ef6fd 100644 --- a/api/src/main/java/org/apache/cloudstack/acl/RoleService.java +++ b/api/src/main/java/org/apache/cloudstack/acl/RoleService.java @@ -80,7 +80,7 @@ public interface RoleService { */ List findRolesByName(String name); - Pair, Integer> findRolesByName(String name, Long startIndex, Long limit); + Pair, Integer> findRolesByName(String name, String keyword, Long startIndex, Long limit); /** * Find all roles by {@link RoleType}. If the role type is {@link RoleType#Admin}, the calling account must be a root admin, otherwise we return an empty list. diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/acl/ListRolesCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/acl/ListRolesCmd.java index dfe401596f4..b55dc80e705 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/acl/ListRolesCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/acl/ListRolesCmd.java @@ -105,8 +105,8 @@ public class ListRolesCmd extends BaseListCmd { Pair, Integer> roles; if (getId() != null && getId() > 0L) { roles = new Pair, Integer>(Collections.singletonList(roleService.findRole(getId())), 1); - } else if (StringUtils.isNotBlank(getName())) { - roles = roleService.findRolesByName(getName(), getStartIndex(), getPageSizeVal()); + } else if (StringUtils.isNotBlank(getName()) || StringUtils.isNotBlank(getKeyword())) { + roles = roleService.findRolesByName(getName(), getKeyword(), getStartIndex(), getPageSizeVal()); } else if (getRoleType() != null) { roles = roleService.findRolesByType(getRoleType(), getStartIndex(), getPageSizeVal()); } else { diff --git a/engine/components-api/src/main/java/com/cloud/storage/StorageManager.java b/engine/components-api/src/main/java/com/cloud/storage/StorageManager.java index 8437b56f2e0..28e7c89419a 100644 --- a/engine/components-api/src/main/java/com/cloud/storage/StorageManager.java +++ b/engine/components-api/src/main/java/com/cloud/storage/StorageManager.java @@ -356,4 +356,6 @@ public interface StorageManager extends StorageService { void syncDatastoreClusterStoragePool(long datastoreClusterPoolId, List childDatastoreAnswerList, long hostId); + void validateChildDatastoresToBeAddedInUpState(StoragePoolVO datastoreClusterPool, List childDatastoreAnswerList); + } diff --git a/engine/schema/src/main/java/org/apache/cloudstack/acl/dao/RoleDao.java b/engine/schema/src/main/java/org/apache/cloudstack/acl/dao/RoleDao.java index ec1051bfae9..36833d5e790 100644 --- a/engine/schema/src/main/java/org/apache/cloudstack/acl/dao/RoleDao.java +++ b/engine/schema/src/main/java/org/apache/cloudstack/acl/dao/RoleDao.java @@ -28,7 +28,7 @@ import java.util.List; public interface RoleDao extends GenericDao { List findAllByName(String roleName); - Pair, Integer> findAllByName(final String roleName, Long offset, Long limit); + Pair, Integer> findAllByName(final String roleName, String keyword, Long offset, Long limit); List findAllByRoleType(RoleType type); List findByName(String roleName); diff --git a/engine/schema/src/main/java/org/apache/cloudstack/acl/dao/RoleDaoImpl.java b/engine/schema/src/main/java/org/apache/cloudstack/acl/dao/RoleDaoImpl.java index dda836a9706..b4938a1e833 100644 --- a/engine/schema/src/main/java/org/apache/cloudstack/acl/dao/RoleDaoImpl.java +++ b/engine/schema/src/main/java/org/apache/cloudstack/acl/dao/RoleDaoImpl.java @@ -25,6 +25,7 @@ import com.cloud.utils.db.SearchCriteria; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.acl.RoleVO; +import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Component; import java.util.List; @@ -54,13 +55,19 @@ public class RoleDaoImpl extends GenericDaoBase implements RoleDao @Override public List findAllByName(final String roleName) { - return findAllByName(roleName, null, null).first(); + return findAllByName(roleName, null, null, null).first(); } @Override - public Pair, Integer> findAllByName(final String roleName, Long offset, Long limit) { + public Pair, Integer> findAllByName(final String roleName, String keyword, Long offset, Long limit) { SearchCriteria sc = RoleByNameSearch.create(); - sc.setParameters("roleName", "%" + roleName + "%"); + if (StringUtils.isNotEmpty(roleName)) { + sc.setParameters("roleName", roleName); + } + if (StringUtils.isNotEmpty(keyword)) { + sc.setParameters("roleName", "%" + keyword + "%"); + } + return searchAndCount(sc, new Filter(RoleVO.class, "id", true, offset, limit)); } diff --git a/engine/storage/src/main/java/org/apache/cloudstack/storage/image/db/TemplateDataStoreDaoImpl.java b/engine/storage/src/main/java/org/apache/cloudstack/storage/image/db/TemplateDataStoreDaoImpl.java index bac01ada5d7..ef3d20a8ea0 100644 --- a/engine/storage/src/main/java/org/apache/cloudstack/storage/image/db/TemplateDataStoreDaoImpl.java +++ b/engine/storage/src/main/java/org/apache/cloudstack/storage/image/db/TemplateDataStoreDaoImpl.java @@ -22,6 +22,7 @@ import java.util.Collections; import java.util.Date; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; import javax.inject.Inject; import javax.naming.ConfigurationException; @@ -593,6 +594,23 @@ public class TemplateDataStoreDaoImpl extends GenericDaoBase list, long templateId) { + if (CollectionUtils.isEmpty(list)) { + return null; + } + List filteredList = list.stream() + .filter(x -> x.getSize() > 0L && + x.getTemplateId() == templateId && x.getDownloadState() == Status.BYPASSED && + x.getState() == State.Ready) + .sorted((x,y) -> Long.compare(y.getSize(), x.getSize())) + .collect(Collectors.toList()); + return CollectionUtils.isNotEmpty(filteredList) ? filteredList.get(0) : null; + } + @Override public TemplateDataStoreVO getReadyBypassedTemplate(long templateId) { SearchCriteria sc = directDownloadTemplateSeach.create(); @@ -600,10 +618,7 @@ public class TemplateDataStoreDaoImpl extends GenericDaoBase list = search(sc, null); - if (CollectionUtils.isEmpty(list) || list.size() > 1) { - return null; - } - return list.get(0); + return getValidGreaterSizeBypassedTemplate(list, templateId); } @Override diff --git a/engine/storage/src/test/java/org/apache/cloudstack/storage/image/db/TemplateDataStoreDaoImplTest.java b/engine/storage/src/test/java/org/apache/cloudstack/storage/image/db/TemplateDataStoreDaoImplTest.java new file mode 100644 index 00000000000..0949dd97dc3 --- /dev/null +++ b/engine/storage/src/test/java/org/apache/cloudstack/storage/image/db/TemplateDataStoreDaoImplTest.java @@ -0,0 +1,77 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.storage.image.db; + +import com.cloud.storage.VMTemplateStorageResourceAssoc; +import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine; +import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO; +import org.junit.Assert; +import org.junit.Test; + +import java.util.Arrays; +import java.util.List; + +public class TemplateDataStoreDaoImplTest { + + private final TemplateDataStoreDaoImpl dao = new TemplateDataStoreDaoImpl(); + + private static final long templateId = 1; + private static final long templateSize = 9999; + + @Test + public void testGetValidGreaterSizeBypassedTemplateEmptyList() { + TemplateDataStoreVO ref = dao.getValidGreaterSizeBypassedTemplate(null, templateId); + Assert.assertNull(ref); + } + + private TemplateDataStoreVO createNewTestReferenceRecord() { + TemplateDataStoreVO ref = new TemplateDataStoreVO(); + ref.setTemplateId(templateId); + ref.setState(ObjectInDataStoreStateMachine.State.Ready); + ref.setDownloadState(VMTemplateStorageResourceAssoc.Status.BYPASSED); + ref.setSize(templateSize); + return ref; + } + + @Test + public void testGetValidGreaterSizeBypassedTemplateMultipleRecords() { + TemplateDataStoreVO ref1 = createNewTestReferenceRecord(); + TemplateDataStoreVO ref2 = createNewTestReferenceRecord(); + TemplateDataStoreVO ref3 = createNewTestReferenceRecord(); + ref1.setSize(1111L); + ref3.setSize(2L); + TemplateDataStoreVO ref = dao.getValidGreaterSizeBypassedTemplate(Arrays.asList(ref1, ref2, ref3), templateId); + Assert.assertNotNull(ref); + Assert.assertEquals(templateSize, ref.getSize()); + } + + @Test + public void testGetValidGreaterSizeBypassedTemplateOneRecord() { + TemplateDataStoreVO ref1 = createNewTestReferenceRecord(); + TemplateDataStoreVO ref = dao.getValidGreaterSizeBypassedTemplate(List.of(ref1), templateId); + Assert.assertNotNull(ref); + Assert.assertEquals(templateSize, ref.getSize()); + } + + @Test + public void testGetValidGreaterSizeBypassedTemplateOneRecordInvalidState() { + TemplateDataStoreVO ref1 = createNewTestReferenceRecord(); + ref1.setDownloadState(VMTemplateStorageResourceAssoc.Status.DOWNLOADED); + TemplateDataStoreVO ref = dao.getValidGreaterSizeBypassedTemplate(List.of(ref1), templateId); + Assert.assertNull(ref); + } +} diff --git a/engine/storage/volume/src/main/java/org/apache/cloudstack/storage/datastore/provider/DefaultHostListener.java b/engine/storage/volume/src/main/java/org/apache/cloudstack/storage/datastore/provider/DefaultHostListener.java index c3d3cf5c65c..e344a87831d 100644 --- a/engine/storage/volume/src/main/java/org/apache/cloudstack/storage/datastore/provider/DefaultHostListener.java +++ b/engine/storage/volume/src/main/java/org/apache/cloudstack/storage/datastore/provider/DefaultHostListener.java @@ -152,6 +152,7 @@ public class DefaultHostListener implements HypervisorHostListener { updateStoragePoolHostVOAndDetails(poolVO, hostId, mspAnswer); if (pool.getPoolType() == Storage.StoragePoolType.DatastoreCluster) { + storageManager.validateChildDatastoresToBeAddedInUpState(poolVO, mspAnswer.getDatastoreClusterChildren()); storageManager.syncDatastoreClusterStoragePool(poolId, ((ModifyStoragePoolAnswer) answer).getDatastoreClusterChildren(), hostId); } diff --git a/plugins/metrics/src/main/java/org/apache/cloudstack/metrics/MetricsServiceImpl.java b/plugins/metrics/src/main/java/org/apache/cloudstack/metrics/MetricsServiceImpl.java index 7d1f74ed924..979e4aacbe7 100644 --- a/plugins/metrics/src/main/java/org/apache/cloudstack/metrics/MetricsServiceImpl.java +++ b/plugins/metrics/src/main/java/org/apache/cloudstack/metrics/MetricsServiceImpl.java @@ -287,7 +287,7 @@ public class MetricsServiceImpl extends MutualExclusiveIdsManagerBase implements SearchBuilder sb = vmInstanceDao.createSearchBuilder(); sb.and("idIN", sb.entity().getId(), SearchCriteria.Op.IN); - sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE); + sb.and("name", sb.entity().getName(), SearchCriteria.Op.EQ); sb.and("state", sb.entity().getState(), SearchCriteria.Op.EQ); sb.and("type", sb.entity().getType(), SearchCriteria.Op.NEQ); @@ -340,7 +340,7 @@ public class MetricsServiceImpl extends MutualExclusiveIdsManagerBase implements SearchBuilder sb = volumeDao.createSearchBuilder(); sb.and("idIN", sb.entity().getId(), SearchCriteria.Op.IN); - sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE); + sb.and("name", sb.entity().getName(), SearchCriteria.Op.EQ); sb.and("state", sb.entity().getState(), SearchCriteria.Op.EQ); SearchCriteria sc = sb.create(); diff --git a/server/src/main/java/com/cloud/network/vpc/VpcManagerImpl.java b/server/src/main/java/com/cloud/network/vpc/VpcManagerImpl.java index 9222520602f..f5682665895 100644 --- a/server/src/main/java/com/cloud/network/vpc/VpcManagerImpl.java +++ b/server/src/main/java/com/cloud/network/vpc/VpcManagerImpl.java @@ -1391,7 +1391,7 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis final SearchBuilder sb = vpcDao.createSearchBuilder(); _accountMgr.buildACLSearchBuilder(sb, domainId, isRecursive, permittedAccounts, listProjectResourcesCriteria); - sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE); + sb.and("name", sb.entity().getName(), SearchCriteria.Op.EQ); sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ); sb.and("displayText", sb.entity().getDisplayText(), SearchCriteria.Op.LIKE); sb.and("vpcOfferingId", sb.entity().getVpcOfferingId(), SearchCriteria.Op.EQ); diff --git a/server/src/main/java/com/cloud/server/ManagementServerImpl.java b/server/src/main/java/com/cloud/server/ManagementServerImpl.java index 4b6782659ba..964cca71f1c 100644 --- a/server/src/main/java/com/cloud/server/ManagementServerImpl.java +++ b/server/src/main/java/com/cloud/server/ManagementServerImpl.java @@ -4580,7 +4580,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ); sb.and("name", sb.entity().getName(), SearchCriteria.Op.EQ); - sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE); + sb.and("name", sb.entity().getName(), SearchCriteria.Op.EQ); final SearchCriteria sc = sb.create(); _accountMgr.buildACLSearchCriteria(sc, domainId, isRecursive, permittedAccounts, listProjectResourcesCriteria); diff --git a/server/src/main/java/com/cloud/storage/StorageManagerImpl.java b/server/src/main/java/com/cloud/storage/StorageManagerImpl.java index 93a805a9afd..c1d17cc8f70 100644 --- a/server/src/main/java/com/cloud/storage/StorageManagerImpl.java +++ b/server/src/main/java/com/cloud/storage/StorageManagerImpl.java @@ -1889,7 +1889,7 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C return _storagePoolDao.findByUuid(uuid); } - private void validateChildDatastoresToBeAddedInUpState(StoragePoolVO datastoreClusterPool, List childDatastoreAnswerList) { + public void validateChildDatastoresToBeAddedInUpState(StoragePoolVO datastoreClusterPool, List childDatastoreAnswerList) { for (ModifyStoragePoolAnswer childDataStoreAnswer : childDatastoreAnswerList) { StoragePoolInfo childStoragePoolInfo = childDataStoreAnswer.getPoolInfo(); StoragePoolVO dataStoreVO = _storagePoolDao.findPoolByUUID(childStoragePoolInfo.getUuid()); @@ -1904,8 +1904,8 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C } } if (dataStoreVO != null && !dataStoreVO.getStatus().equals(StoragePoolStatus.Up)) { - String msg = String.format("Cannot synchronise datastore cluster %s because primary storage with id %s is not ready for syncing, " + - "as the status is %s", datastoreClusterPool.getUuid(), dataStoreVO.getUuid(), dataStoreVO.getStatus().toString()); + String msg = String.format("Cannot synchronise datastore cluster %s because primary storage with id %s is not in Up state, " + + "current state is %s", datastoreClusterPool.getUuid(), dataStoreVO.getUuid(), dataStoreVO.getStatus().toString()); throw new CloudRuntimeException(msg); } } diff --git a/server/src/main/java/org/apache/cloudstack/acl/RoleManagerImpl.java b/server/src/main/java/org/apache/cloudstack/acl/RoleManagerImpl.java index fc2a7e86160..f2f4a6fe06a 100644 --- a/server/src/main/java/org/apache/cloudstack/acl/RoleManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/acl/RoleManagerImpl.java @@ -357,13 +357,13 @@ public class RoleManagerImpl extends ManagerBase implements RoleService, Configu @Override public List findRolesByName(String name) { - return findRolesByName(name, null, null).first(); + return findRolesByName(name, null, null, null).first(); } @Override - public Pair, Integer> findRolesByName(String name, Long startIndex, Long limit) { - if (StringUtils.isNotBlank(name)) { - Pair, Integer> data = roleDao.findAllByName(name, startIndex, limit); + public Pair, Integer> findRolesByName(String name, String keyword, Long startIndex, Long limit) { + if (StringUtils.isNotBlank(name) || StringUtils.isNotBlank(keyword)) { + Pair, Integer> data = roleDao.findAllByName(name, keyword, startIndex, limit); int removed = removeRootAdminRolesIfNeeded(data.first()); return new Pair,Integer>(ListUtils.toListOfInterface(data.first()), Integer.valueOf(data.second() - removed)); } diff --git a/server/src/main/java/org/apache/cloudstack/backup/BackupManagerImpl.java b/server/src/main/java/org/apache/cloudstack/backup/BackupManagerImpl.java index 4b972dc1ebe..5da3514b848 100644 --- a/server/src/main/java/org/apache/cloudstack/backup/BackupManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/backup/BackupManagerImpl.java @@ -233,7 +233,7 @@ public class BackupManagerImpl extends ManagerBase implements BackupManager { final Filter searchFilter = new Filter(BackupOfferingVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal()); SearchBuilder sb = backupOfferingDao.createSearchBuilder(); sb.and("zone_id", sb.entity().getZoneId(), SearchCriteria.Op.EQ); - sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE); + sb.and("name", sb.entity().getName(), SearchCriteria.Op.EQ); final SearchCriteria sc = sb.create(); diff --git a/server/src/test/java/org/apache/cloudstack/acl/RoleManagerImplTest.java b/server/src/test/java/org/apache/cloudstack/acl/RoleManagerImplTest.java index a1be4541541..049bc17e0b6 100644 --- a/server/src/test/java/org/apache/cloudstack/acl/RoleManagerImplTest.java +++ b/server/src/test/java/org/apache/cloudstack/acl/RoleManagerImplTest.java @@ -166,7 +166,7 @@ public class RoleManagerImplTest { String roleName = "roleName"; List roles = new ArrayList<>(); Pair, Integer> toBeReturned = new Pair(roles, 0); - Mockito.doReturn(toBeReturned).when(roleDaoMock).findAllByName(roleName, null, null); + Mockito.doReturn(toBeReturned).when(roleDaoMock).findAllByName(roleName, null, null, null); roleManagerImpl.findRolesByName(roleName); Mockito.verify(roleManagerImpl).removeRootAdminRolesIfNeeded(roles); diff --git a/ui/src/views/AutogenView.vue b/ui/src/views/AutogenView.vue index e71e6dd8fa8..1b66467cb4d 100644 --- a/ui/src/views/AutogenView.vue +++ b/ui/src/views/AutogenView.vue @@ -1433,13 +1433,13 @@ export default { continue } if (input === undefined || input === null || - (input === '' && !['updateStoragePool', 'updateHost', 'updatePhysicalNetwork', 'updateDiskOffering', 'updateNetworkOffering', 'updateServiceOffering', 'updateAccount'].includes(action.api))) { + (input === '' && !['updateStoragePool', 'updateHost', 'updatePhysicalNetwork', 'updateDiskOffering', 'updateNetworkOffering', 'updateServiceOffering', 'updateZone', 'updateAccount'].includes(action.api))) { if (param.type === 'boolean') { params[key] = false } break } - if (input === '' && !['tags', 'hosttags', 'storagetags', 'networkdomain'].includes(key)) { + if (input === '' && !['tags', 'hosttags', 'storagetags', 'dns2', 'ip6dns1', 'ip6dns2', 'internaldns2', 'networkdomain'].includes(key)) { break } if (action.mapping && key in action.mapping && action.mapping[key].options) { @@ -1636,9 +1636,7 @@ export default { if ('searchQuery' in opts) { const value = opts.searchQuery if (value && value.length > 0) { - if (this.$route.name === 'role') { - query.name = value - } else if (this.$route.name === 'quotaemailtemplate') { + if (this.$route.name === 'quotaemailtemplate') { query.templatetype = value } else if (this.$route.name === 'globalsetting') { query.name = value diff --git a/ui/tests/unit/views/AutogenView.spec.js b/ui/tests/unit/views/AutogenView.spec.js index 048a71d78d6..daac26da0d4 100644 --- a/ui/tests/unit/views/AutogenView.spec.js +++ b/ui/tests/unit/views/AutogenView.spec.js @@ -926,7 +926,7 @@ describe('Views > AutogenView.vue', () => { await flushPromises() expect(router.currentRoute.value.path).toEqual('/role') - expect(router.currentRoute.value.query).toEqual({ name: 'test-value', q: 'test-value', page: '1', pagesize: '20' }) + expect(router.currentRoute.value.query).toEqual({ keyword: 'test-value', q: 'test-value', page: '1', pagesize: '20' }) done() })