Skip to content

Commit a7ed2a8

Browse files
committed
Delete template from storage pool instantly if no volume is using it.
1 parent c631d6a commit a7ed2a8

File tree

7 files changed

+83
-16
lines changed

7 files changed

+83
-16
lines changed

engine/components-api/src/main/java/com/cloud/template/TemplateManager.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,13 @@ public interface TemplateManager {
5656
+ "will validate if the provided URL is resolvable during the register of templates/ISOs before persisting them in the database.",
5757
true);
5858

59+
ConfigKey<Boolean> TemplateDeleteFromPrimaryStorage = new ConfigKey<Boolean>("Advanced",
60+
Boolean.class,
61+
"template.delete.from.primary.storage", "true",
62+
"Template when deleted will be instantly deleted from the Primary Storage",
63+
true,
64+
ConfigKey.Scope.Global);
65+
5966
static final String VMWARE_TOOLS_ISO = "vmware-tools.iso";
6067
static final String XS_TOOLS_ISO = "xs-tools.iso";
6168

@@ -103,6 +110,8 @@ public interface TemplateManager {
103110
*/
104111
List<VMTemplateStoragePoolVO> getUnusedTemplatesInPool(StoragePoolVO pool);
105112

113+
void evictTemplateFromStoragePoolsForZones(Long templateId, List<Long> zoneId);
114+
106115
/**
107116
* Deletes a template in the specified storage pool.
108117
*

engine/schema/src/main/java/com/cloud/storage/dao/VMTemplatePoolDao.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ public interface VMTemplatePoolDao extends GenericDao<VMTemplateStoragePoolVO, L
3535

3636
List<VMTemplateStoragePoolVO> listByPoolIdAndState(long poolId, ObjectInDataStoreStateMachine.State state);
3737

38+
List<VMTemplateStoragePoolVO> listByPoolIdsAndTemplate(List<Long> poolIds, Long templateId);
39+
3840
List<VMTemplateStoragePoolVO> listByTemplateStatus(long templateId, VMTemplateStoragePoolVO.Status downloadState);
3941

4042
List<VMTemplateStoragePoolVO> listByTemplateStatus(long templateId, VMTemplateStoragePoolVO.Status downloadState, long poolId);

engine/schema/src/main/java/com/cloud/storage/dao/VMTemplatePoolDaoImpl.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,16 @@ public VMTemplateStoragePoolVO findByPoolTemplate(long poolId, long templateId,
150150
return findOneIncludingRemovedBy(sc);
151151
}
152152

153+
@Override
154+
public List<VMTemplateStoragePoolVO> listByPoolIdsAndTemplate(List<Long> poolIds, Long templateId) {
155+
SearchCriteria<VMTemplateStoragePoolVO> sc = PoolTemplateSearch.create();
156+
if (poolIds != null && !poolIds.isEmpty()) {
157+
sc.setParameters("pool_id", poolIds.toArray());
158+
}
159+
sc.setParameters("template_id", templateId);
160+
return listBy(sc);
161+
}
162+
153163
@Override
154164
public List<VMTemplateStoragePoolVO> listByTemplateStatus(long templateId, VMTemplateStoragePoolVO.Status downloadState) {
155165
SearchCriteria<VMTemplateStoragePoolVO> sc = TemplateStatusSearch.create();

engine/schema/src/main/java/org/apache/cloudstack/storage/datastore/db/PrimaryDataStoreDao.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,4 +154,6 @@ Pair<List<Long>, Integer> searchForIdsAndCount(Long storagePoolId, String storag
154154
String keyword, Filter searchFilter);
155155

156156
List<StoragePoolVO> listByIds(List<Long> ids);
157+
158+
List<StoragePoolVO> listByDataCenterIds(List<Long> dataCenterIds);
157159
}

engine/schema/src/main/java/org/apache/cloudstack/storage/datastore/db/PrimaryDataStoreDaoImpl.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ public class PrimaryDataStoreDaoImpl extends GenericDaoBase<StoragePoolVO, Long>
6363
private final GenericSearchBuilder<StoragePoolVO, Long> StatusCountSearch;
6464
private final SearchBuilder<StoragePoolVO> ClustersSearch;
6565
private final SearchBuilder<StoragePoolVO> IdsSearch;
66+
private final SearchBuilder<StoragePoolVO> DcsSearch;
6667

6768
@Inject
6869
private StoragePoolDetailsDao _detailsDao;
@@ -155,6 +156,9 @@ public PrimaryDataStoreDaoImpl() {
155156
IdsSearch.and("ids", IdsSearch.entity().getId(), SearchCriteria.Op.IN);
156157
IdsSearch.done();
157158

159+
DcsSearch = createSearchBuilder();
160+
DcsSearch.and("dataCenterId", DcsSearch.entity().getDataCenterId(), SearchCriteria.Op.IN);
161+
DcsSearch.done();
158162
}
159163

160164
@Override
@@ -733,6 +737,16 @@ public List<StoragePoolVO> listByIds(List<Long> ids) {
733737
return listBy(sc);
734738
}
735739

740+
@Override
741+
public List<StoragePoolVO> listByDataCenterIds(List<Long> dataCenterIds) {
742+
if (CollectionUtils.isEmpty(dataCenterIds)) {
743+
return Collections.emptyList();
744+
}
745+
SearchCriteria<StoragePoolVO> sc = DcsSearch.create();
746+
sc.setParameters("dataCenterId", dataCenterIds.toArray());
747+
return listBy(sc);
748+
}
749+
736750
private SearchCriteria<StoragePoolVO> createStoragePoolSearchCriteria(Long storagePoolId, String storagePoolName,
737751
Long zoneId, String path, Long podId, Long clusterId, String address, ScopeType scopeType,
738752
StoragePoolStatus status, String keyword) {

server/src/main/java/com/cloud/template/HypervisorTemplateAdapter.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -693,6 +693,9 @@ public boolean delete(TemplateProfile profile) {
693693
if (success) {
694694
if ((imageStores != null && imageStores.size() > 1) && (profile.getZoneIdList() != null)) {
695695
//if template is stored in more than one image stores, and the zone id is not null, then don't delete other templates.
696+
if (templateMgr.TemplateDeleteFromPrimaryStorage.value()) {
697+
templateMgr.evictTemplateFromStoragePoolsForZones(template.getId(), profile.getZoneIdList());
698+
}
696699
return cleanupTemplate(template, success);
697700
}
698701

@@ -726,6 +729,10 @@ public boolean delete(TemplateProfile profile) {
726729

727730
}
728731

732+
if (templateMgr.TemplateDeleteFromPrimaryStorage.value()) {
733+
templateMgr.evictTemplateFromStoragePoolsForZones(template.getId(), profile.getZoneIdList());
734+
}
735+
729736
// remove its related ACL permission
730737
Pair<Class<?>, Long> templateClassForId = new Pair<>(VirtualMachineTemplate.class, template.getId());
731738
_messageBus.publish(_name, EntityManager.MESSAGE_REMOVE_ENTITY_EVENT, PublishScope.LOCAL, templateClassForId);

server/src/main/java/com/cloud/template/TemplateManagerImpl.java

Lines changed: 39 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1024,33 +1024,53 @@ public boolean delete(long userId, long templateId, Long zoneId) {
10241024
return adapter.delete(new TemplateProfile(userId, template, zoneId));
10251025
}
10261026

1027+
private Boolean templateIsUnusedInPool(VMTemplateStoragePoolVO templatePoolVO) {
1028+
VMTemplateVO template = _tmpltDao.findByIdIncludingRemoved(templatePoolVO.getTemplateId());
1029+
1030+
// If this is a routing template, consider it in use
1031+
if (template.getTemplateType() == TemplateType.SYSTEM) {
1032+
return false;
1033+
}
1034+
1035+
// If the template is not yet downloaded to the pool, consider it in use
1036+
if (templatePoolVO.getDownloadState() != Status.DOWNLOADED) {
1037+
return false;
1038+
}
1039+
1040+
if (template.getFormat() == ImageFormat.ISO || _volumeDao.isAnyVolumeActivelyUsingTemplateOnPool(template.getId(), templatePoolVO.getPoolId())) {
1041+
return false;
1042+
}
1043+
return true;
1044+
}
1045+
10271046
@Override
10281047
public List<VMTemplateStoragePoolVO> getUnusedTemplatesInPool(StoragePoolVO pool) {
10291048
List<VMTemplateStoragePoolVO> unusedTemplatesInPool = new ArrayList<VMTemplateStoragePoolVO>();
10301049
List<VMTemplateStoragePoolVO> allTemplatesInPool = _tmpltPoolDao.listByPoolId(pool.getId());
10311050

10321051
for (VMTemplateStoragePoolVO templatePoolVO : allTemplatesInPool) {
1033-
VMTemplateVO template = _tmpltDao.findByIdIncludingRemoved(templatePoolVO.getTemplateId());
1034-
1035-
// If this is a routing template, consider it in use
1036-
if (template.getTemplateType() == TemplateType.SYSTEM) {
1037-
continue;
1038-
}
1039-
1040-
// If the template is not yet downloaded to the pool, consider it in
1041-
// use
1042-
if (templatePoolVO.getDownloadState() != Status.DOWNLOADED) {
1043-
continue;
1044-
}
1045-
1046-
if (template.getFormat() != ImageFormat.ISO && !_volumeDao.isAnyVolumeActivelyUsingTemplateOnPool(template.getId(), pool.getId())) {
1052+
if (templateIsUnusedInPool(templatePoolVO)) {
10471053
unusedTemplatesInPool.add(templatePoolVO);
10481054
}
10491055
}
1050-
10511056
return unusedTemplatesInPool;
10521057
}
10531058

1059+
@Override
1060+
public void evictTemplateFromStoragePoolsForZones(Long templateId, List<Long> zoneIds) {
1061+
List<Long> poolIds = new ArrayList<>();
1062+
if (zoneIds != null && !zoneIds.isEmpty()) {
1063+
List<StoragePoolVO> pools = _poolDao.listByDataCenterIds(zoneIds);
1064+
poolIds = pools.stream().map(StoragePoolVO::getId).collect(Collectors.toList());
1065+
}
1066+
List<VMTemplateStoragePoolVO> templateStoragePoolVOS = _tmpltPoolDao.listByPoolIdsAndTemplate(poolIds, templateId);
1067+
for (VMTemplateStoragePoolVO templateStoragePoolVO: templateStoragePoolVOS) {
1068+
if (templateIsUnusedInPool(templateStoragePoolVO)) {
1069+
evictTemplateFromStoragePool(templateStoragePoolVO);
1070+
}
1071+
}
1072+
}
1073+
10541074
@Override
10551075
@DB
10561076
public void evictTemplateFromStoragePool(VMTemplateStoragePoolVO templatePoolVO) {
@@ -2368,7 +2388,10 @@ public String getConfigComponentName() {
23682388

23692389
@Override
23702390
public ConfigKey<?>[] getConfigKeys() {
2371-
return new ConfigKey<?>[] {AllowPublicUserTemplates, TemplatePreloaderPoolSize, ValidateUrlIsResolvableBeforeRegisteringTemplate};
2391+
return new ConfigKey<?>[] {AllowPublicUserTemplates,
2392+
TemplatePreloaderPoolSize,
2393+
ValidateUrlIsResolvableBeforeRegisteringTemplate,
2394+
TemplateDeleteFromPrimaryStorage};
23722395
}
23732396

23742397
public List<TemplateAdapter> getTemplateAdapters() {

0 commit comments

Comments
 (0)