From d87172997073e11b52a7df3e3242a794fdfdf09a Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Tue, 11 Apr 2023 17:02:15 +0530 Subject: [PATCH 1/4] ui: allow clearing dns during zone update (#7276) * ui: allow clearing dns during zone update Fixes #7273 Signed-off-by: Abhishek Kumar * allow internal dns2 clearing Signed-off-by: Abhishek Kumar --------- Signed-off-by: Abhishek Kumar --- ui/src/views/AutogenView.vue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/src/views/AutogenView.vue b/ui/src/views/AutogenView.vue index 842df0fcc6a..e2dadee44fb 100644 --- a/ui/src/views/AutogenView.vue +++ b/ui/src/views/AutogenView.vue @@ -1367,13 +1367,13 @@ export default { continue } if (input === undefined || input === null || - (input === '' && !['updateStoragePool', 'updateHost', 'updatePhysicalNetwork', 'updateDiskOffering', 'updateNetworkOffering', 'updateServiceOffering'].includes(action.api))) { + (input === '' && !['updateStoragePool', 'updateHost', 'updatePhysicalNetwork', 'updateDiskOffering', 'updateNetworkOffering', 'updateServiceOffering', 'updateZone'].includes(action.api))) { if (param.type === 'boolean') { params[key] = false } break } - if (input === '' && !['tags', 'hosttags', 'storagetags'].includes(key)) { + if (input === '' && !['tags', 'hosttags', 'storagetags', 'dns2', 'ip6dns1', 'ip6dns2', 'internaldns2'].includes(key)) { break } if (action.mapping && key in action.mapping && action.mapping[key].options) { From b774ee5d117ff3d0ffa2ea0e3973c733262b2617 Mon Sep 17 00:00:00 2001 From: Harikrishna Date: Tue, 11 Apr 2023 22:23:12 +0530 Subject: [PATCH 2/4] vmware: Datastore cluster synchronization should check if the child datastores are in UP state or not (#7385) This fix ensures when datastore cluster in VMware is added as a primary storage pool in CloudStack then all the child datastores (which already exists in CS) should be in Up state. For example: 1. Datastore Cluster DS has two child datastores A and B in vCenter. (B is already added as a storage pool in CloudStack) 2. Now try to add datastore cluster DS into CloudStack as a primary storage pool 3. CloudStack tries to add child datastores A and B in CloudStack, since B is already there in CloudStack, it will reuse the existing storagepool entry and will keep under parent Storage pool DS. During Step 3 we are now checking if B is Up state or not. --- .../src/main/java/com/cloud/storage/StorageManager.java | 2 ++ .../storage/datastore/provider/DefaultHostListener.java | 1 + .../src/main/java/com/cloud/storage/StorageManagerImpl.java | 6 +++--- 3 files changed, 6 insertions(+), 3 deletions(-) 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/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/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); } } From 65512af779c7808614e37a1801ca2a705af4921b Mon Sep 17 00:00:00 2001 From: Harikrishna Date: Tue, 11 Apr 2023 22:24:29 +0530 Subject: [PATCH 3/4] server: Roles search by keyword (#7384) This PR fixes #7362 and also other search criteria to use the name as an exact search where keyword is also there. Made UI changes for roles search to make use of keyword instead of name. --- .../java/org/apache/cloudstack/acl/RoleService.java | 2 +- .../api/command/admin/acl/ListRolesCmd.java | 4 ++-- .../java/org/apache/cloudstack/acl/dao/RoleDao.java | 2 +- .../org/apache/cloudstack/acl/dao/RoleDaoImpl.java | 13 ++++++++++--- .../cloudstack/metrics/MetricsServiceImpl.java | 4 ++-- .../java/com/cloud/network/vpc/VpcManagerImpl.java | 2 +- .../java/com/cloud/server/ManagementServerImpl.java | 2 +- .../org/apache/cloudstack/acl/RoleManagerImpl.java | 8 ++++---- .../apache/cloudstack/backup/BackupManagerImpl.java | 2 +- .../apache/cloudstack/acl/RoleManagerImplTest.java | 2 +- ui/src/views/AutogenView.vue | 4 +--- ui/tests/unit/views/AutogenView.spec.js | 2 +- 12 files changed, 26 insertions(+), 21 deletions(-) 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/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/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/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 314d263f75d..4e18caa684b 100644 --- a/server/src/main/java/org/apache/cloudstack/backup/BackupManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/backup/BackupManagerImpl.java @@ -223,7 +223,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 95bed406d58..16cf14e04cb 100644 --- a/ui/src/views/AutogenView.vue +++ b/ui/src/views/AutogenView.vue @@ -1609,9 +1609,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 18872107d77..ec3130c6fb3 100644 --- a/ui/tests/unit/views/AutogenView.spec.js +++ b/ui/tests/unit/views/AutogenView.spec.js @@ -920,7 +920,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() }) From 2dc016adde759bd13caa349fad6d4d85b19d7f78 Mon Sep 17 00:00:00 2001 From: Nicolas Vazquez Date: Thu, 13 Apr 2023 04:18:29 -0300 Subject: [PATCH 4/4] Fix for direct download templates with multiple bypassed references (#7400) This PR fixes an issue observed on multiple zones and direct download templates on KVM, in which a template gets multiple records on the template_store_ref table. When this happens, the template cannot be used as direct download. In case of a system VM template using direct download, system VM deployments fail --- .../image/db/TemplateDataStoreDaoImpl.java | 23 +++++- .../db/TemplateDataStoreDaoImplTest.java | 77 +++++++++++++++++++ 2 files changed, 96 insertions(+), 4 deletions(-) create mode 100644 engine/storage/src/test/java/org/apache/cloudstack/storage/image/db/TemplateDataStoreDaoImplTest.java 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); + } +}