Skip to content

Commit 735b6de

Browse files
raveningRakesh Venkatesh
andauthored
Cleanup download urls when SSVM destroyed (#4078)
Co-authored-by: Rakesh Venkatesh <r.venkatesh@global.leaseweb.com>
1 parent acee15a commit 735b6de

12 files changed

Lines changed: 125 additions & 16 deletions

File tree

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,6 @@ public interface ImageStoreDao extends GenericDao<ImageStoreVO, Long> {
4040
List<ImageStoreVO> listImageStores();
4141

4242
List<ImageStoreVO> listImageCacheStores();
43+
44+
List<ImageStoreVO> listStoresByZoneId(long zoneId);
4345
}

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,4 +134,10 @@ public List<ImageStoreVO> listImageCacheStores() {
134134
return listBy(sc);
135135
}
136136

137+
@Override
138+
public List<ImageStoreVO> listStoresByZoneId(long zoneId) {
139+
SearchCriteria<ImageStoreVO> sc = createSearchCriteria();
140+
sc.addAnd("dcId", SearchCriteria.Op.EQ, zoneId);
141+
return listBy(sc);
142+
}
137143
}

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,4 +91,6 @@ public interface TemplateDataStoreDao extends GenericDao<TemplateDataStoreVO, Lo
9191
TemplateDataStoreVO getReadyBypassedTemplate(long templateId);
9292

9393
boolean isTemplateMarkedForDirectDownload(long templateId);
94+
95+
List<TemplateDataStoreVO> listTemplateDownloadUrlsByStoreId(long storeId);
9496
}

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,4 +53,6 @@ public interface VolumeDataStoreDao extends GenericDao<VolumeDataStoreVO, Long>,
5353
List<VolumeDataStoreVO> listByVolumeState(Volume.State... states);
5454

5555
boolean updateVolumeId(long srcVolId, long destVolId);
56+
57+
List<VolumeDataStoreVO> listVolumeDownloadUrlsByZoneId(long zoneId);
5658
}

engine/storage/src/main/java/org/apache/cloudstack/storage/image/db/TemplateDataStoreDaoImpl.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ public boolean configure(String name, Map<String, Object> params) throws Configu
144144
downloadTemplateSearch.and("download_url", downloadTemplateSearch.entity().getExtractUrl(), Op.NNULL);
145145
downloadTemplateSearch.and("download_url_created", downloadTemplateSearch.entity().getExtractUrlCreated(), Op.NNULL);
146146
downloadTemplateSearch.and("destroyed", downloadTemplateSearch.entity().getDestroyed(), SearchCriteria.Op.EQ);
147+
downloadTemplateSearch.and("store_id", downloadTemplateSearch.entity().getDataStoreId(), Op.EQ);
147148
downloadTemplateSearch.done();
148149

149150
directDownloadTemplateSeach = createSearchBuilder();
@@ -543,6 +544,14 @@ public List<TemplateDataStoreVO> listTemplateDownloadUrls() {
543544
return listBy(sc);
544545
}
545546

547+
@Override
548+
public List<TemplateDataStoreVO> listTemplateDownloadUrlsByStoreId(long storeId) {
549+
SearchCriteria<TemplateDataStoreVO> sc = downloadTemplateSearch.create();
550+
sc.setParameters("destroyed", false);
551+
sc.setParameters("store_id", storeId);
552+
return listBy(sc);
553+
}
554+
546555
@Override
547556
public void expireDnldUrlsForZone(Long dcId){
548557
TransactionLegacy txn = TransactionLegacy.currentTxn();

engine/storage/src/main/java/org/apache/cloudstack/storage/image/db/VolumeDataStoreDaoImpl.java

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import javax.inject.Inject;
2626
import javax.naming.ConfigurationException;
2727

28+
import com.cloud.utils.db.Filter;
2829
import com.cloud.utils.exception.CloudRuntimeException;
2930
import org.apache.log4j.Logger;
3031
import org.springframework.stereotype.Component;
@@ -103,6 +104,7 @@ public boolean configure(String name, Map<String, Object> params) throws Configu
103104
downloadVolumeSearch.and("download_url", downloadVolumeSearch.entity().getExtractUrl(), Op.NNULL);
104105
downloadVolumeSearch.and("download_url_created", downloadVolumeSearch.entity().getExtractUrlCreated(), Op.NNULL);
105106
downloadVolumeSearch.and("destroyed", downloadVolumeSearch.entity().getDestroyed(), SearchCriteria.Op.EQ);
107+
downloadVolumeSearch.and("zone_id", downloadVolumeSearch.entity().getZoneId(), Op.EQ);
106108
downloadVolumeSearch.done();
107109

108110
uploadVolumeSearch = createSearchBuilder();
@@ -213,7 +215,13 @@ public VolumeDataStoreVO findByVolume(long volumeId) {
213215
SearchCriteria<VolumeDataStoreVO> sc = volumeSearch.create();
214216
sc.setParameters("volume_id", volumeId);
215217
sc.setParameters("destroyed", false);
216-
return findOneBy(sc);
218+
return findVolumeby(sc);
219+
}
220+
221+
private VolumeDataStoreVO findVolumeby(SearchCriteria<VolumeDataStoreVO> sc) {
222+
Filter filter = new Filter(VolumeDataStoreVO.class, "created", false, 0L, 1L);
223+
List<VolumeDataStoreVO> results = searchIncludingRemoved(sc, filter, null, false);
224+
return results.size() == 0 ? null : results.get(0);
217225
}
218226

219227
@Override
@@ -316,6 +324,14 @@ public List<VolumeDataStoreVO> listVolumeDownloadUrls() {
316324
return listBy(sc);
317325
}
318326

327+
@Override
328+
public List<VolumeDataStoreVO> listVolumeDownloadUrlsByZoneId(long zoneId) {
329+
SearchCriteria<VolumeDataStoreVO> sc = downloadVolumeSearch.create();
330+
sc.setParameters("destroyed", false);
331+
sc.setParameters("zone_id", zoneId);
332+
return listBy(sc);
333+
}
334+
319335
@Override
320336
public List<VolumeDataStoreVO> listUploadedVolumesByStoreId(long id) {
321337
SearchCriteria<VolumeDataStoreVO> sc = uploadVolumeSearch.create();

plugins/storage/image/default/src/main/java/org/apache/cloudstack/storage/datastore/driver/CloudStackImageStoreDriverImpl.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,8 @@ public String createEntityExtractUrl(DataStore store, String installPath, ImageF
7171
// Create Symlink at ssvm
7272
String path = installPath;
7373
String uuid = UUID.randomUUID().toString() + "." + format.getFileExtension();
74-
CreateEntityDownloadURLCommand cmd = new CreateEntityDownloadURLCommand(((ImageStoreEntity)store).getMountPoint(), path, uuid, dataObject.getTO());
74+
CreateEntityDownloadURLCommand cmd = new CreateEntityDownloadURLCommand(((ImageStoreEntity)store).getMountPoint(),
75+
path, uuid, dataObject == null ? null: dataObject.getTO());
7576
Answer ans = null;
7677
if (ep == null) {
7778
String errMsg = "No remote endpoint to send command, check if host or ssvm is down?";

server/src/main/java/com/cloud/server/ManagementServerImpl.java

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -554,6 +554,10 @@
554554
import org.apache.cloudstack.storage.datastore.db.ImageStoreVO;
555555
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
556556
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
557+
import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao;
558+
import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO;
559+
import org.apache.cloudstack.storage.datastore.db.VolumeDataStoreDao;
560+
import org.apache.cloudstack.storage.datastore.db.VolumeDataStoreVO;
557561
import org.apache.cloudstack.utils.identity.ManagementServerNode;
558562
import org.apache.commons.codec.binary.Base64;
559563
import org.apache.commons.collections.CollectionUtils;
@@ -840,6 +844,10 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
840844
private DpdkHelper dpdkHelper;
841845
@Inject
842846
private PrimaryDataStoreDao _primaryDataStoreDao;
847+
@Inject
848+
private VolumeDataStoreDao _volumeStoreDao;
849+
@Inject
850+
private TemplateDataStoreDao _vmTemplateStoreDao;
843851

844852
private LockMasterListener _lockMasterListener;
845853
private final ScheduledExecutorService _eventExecutor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("EventChecker"));
@@ -3288,13 +3296,28 @@ protected void runInContext() {
32883296
}
32893297
}
32903298

3299+
private void cleanupDownloadUrlsInZone(final long zoneId) {
3300+
// clean download URLs when destroying ssvm
3301+
// clean only the volumes and templates of the zone to which ssvm belongs to
3302+
for (VolumeDataStoreVO volume :_volumeStoreDao.listVolumeDownloadUrlsByZoneId(zoneId)) {
3303+
volume.setExtractUrl(null);
3304+
_volumeStoreDao.update(volume.getId(), volume);
3305+
}
3306+
for (ImageStoreVO imageStore : _imgStoreDao.listStoresByZoneId(zoneId)) {
3307+
for (TemplateDataStoreVO template : _vmTemplateStoreDao.listTemplateDownloadUrlsByStoreId(imageStore.getId())) {
3308+
template.setExtractUrl(null);
3309+
template.setExtractUrlCreated(null);
3310+
_vmTemplateStoreDao.update(template.getId(), template);
3311+
}
3312+
}
3313+
}
3314+
32913315
private SecondaryStorageVmVO startSecondaryStorageVm(final long instanceId) {
32923316
return _secStorageVmMgr.startSecStorageVm(instanceId);
32933317
}
32943318

32953319
private SecondaryStorageVmVO stopSecondaryStorageVm(final VMInstanceVO systemVm, final boolean isForced)
32963320
throws ResourceUnavailableException, OperationTimedoutException, ConcurrentOperationException {
3297-
32983321
_itMgr.advanceStop(systemVm.getUuid(), isForced);
32993322
return _secStorageVmDao.findById(systemVm.getId());
33003323
}
@@ -3306,6 +3329,7 @@ public SecondaryStorageVmVO rebootSecondaryStorageVm(final long instanceId) {
33063329

33073330
protected SecondaryStorageVmVO destroySecondaryStorageVm(final long instanceId) {
33083331
final SecondaryStorageVmVO secStorageVm = _secStorageVmDao.findById(instanceId);
3332+
cleanupDownloadUrlsInZone(secStorageVm.getDataCenterId());
33093333
if (_secStorageVmMgr.destroySecStorageVm(instanceId)) {
33103334
return secStorageVm;
33113335
}

server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import java.util.HashMap;
2626
import java.util.List;
2727
import java.util.Map;
28+
import java.util.Optional;
2829
import java.util.UUID;
2930
import java.util.concurrent.ExecutionException;
3031

@@ -48,6 +49,7 @@
4849
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
4950
import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint;
5051
import org.apache.cloudstack.engine.subsystem.api.storage.HostScope;
52+
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine;
5153
import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreInfo;
5254
import org.apache.cloudstack.engine.subsystem.api.storage.Scope;
5355
import org.apache.cloudstack.engine.subsystem.api.storage.StoragePoolAllocator;
@@ -149,6 +151,8 @@
149151
import com.cloud.utils.component.ManagerBase;
150152
import com.cloud.utils.db.DB;
151153
import com.cloud.utils.db.EntityManager;
154+
import com.cloud.utils.db.Filter;
155+
import com.cloud.utils.db.SearchCriteria;
152156
import com.cloud.utils.db.Transaction;
153157
import com.cloud.utils.db.TransactionCallback;
154158
import com.cloud.utils.db.TransactionCallbackWithException;
@@ -2791,9 +2795,11 @@ public String extractVolume(ExtractVolumeCmd cmd) {
27912795
}
27922796

27932797
// Check if the url already exists
2794-
VolumeDataStoreVO volumeStoreRef = _volumeStoreDao.findByVolume(volumeId);
2795-
if (volumeStoreRef != null && volumeStoreRef.getExtractUrl() != null) {
2796-
return volumeStoreRef.getExtractUrl();
2798+
SearchCriteria<VolumeDataStoreVO> sc = _volumeStoreDao.createSearchCriteria();
2799+
2800+
Optional<String> extractUrl = setExtractVolumeSearchCriteria(sc, volume);
2801+
if (extractUrl.isPresent()) {
2802+
return extractUrl.get();
27972803
}
27982804

27992805
VMInstanceVO vm = null;
@@ -2848,6 +2854,45 @@ public String extractVolume(ExtractVolumeCmd cmd) {
28482854
return orchestrateExtractVolume(volume.getId(), zoneId);
28492855
}
28502856

2857+
private Optional<String> setExtractVolumeSearchCriteria(SearchCriteria<VolumeDataStoreVO> sc, VolumeVO volume) {
2858+
final long volumeId = volume.getId();
2859+
sc.addAnd("state", SearchCriteria.Op.EQ, ObjectInDataStoreStateMachine.State.Ready.toString());
2860+
sc.addAnd("volumeId", SearchCriteria.Op.EQ, volumeId);
2861+
sc.addAnd("destroyed", SearchCriteria.Op.EQ, false);
2862+
// the volume should not change (attached/detached, vm not updated) after created
2863+
if (volume.getVolumeType() == Volume.Type.ROOT) { // for ROOT disk
2864+
VMInstanceVO vm = _vmInstanceDao.findById(volume.getInstanceId());
2865+
sc.addAnd("updated", SearchCriteria.Op.GTEQ, vm.getUpdateTime());
2866+
} else if (volume.getVolumeType() == Volume.Type.DATADISK && volume.getInstanceId() == null) { // for not attached DATADISK
2867+
sc.addAnd("updated", SearchCriteria.Op.GTEQ, volume.getUpdated());
2868+
} else { // for attached DATA DISK
2869+
VMInstanceVO vm = _vmInstanceDao.findById(volume.getInstanceId());
2870+
sc.addAnd("updated", SearchCriteria.Op.GTEQ, vm.getUpdateTime());
2871+
sc.addAnd("updated", SearchCriteria.Op.GTEQ, volume.getUpdated());
2872+
}
2873+
Filter filter = new Filter(VolumeDataStoreVO.class, "created", false, 0L, 1L);
2874+
List<VolumeDataStoreVO> volumeStoreRefs = _volumeStoreDao.search(sc, filter);
2875+
VolumeDataStoreVO volumeStoreRef = null;
2876+
if (volumeStoreRefs != null && !volumeStoreRefs.isEmpty()) {
2877+
volumeStoreRef = volumeStoreRefs.get(0);
2878+
}
2879+
if (volumeStoreRef != null && volumeStoreRef.getExtractUrl() != null) {
2880+
return Optional.ofNullable(volumeStoreRef.getExtractUrl());
2881+
} else if (volumeStoreRef != null) {
2882+
s_logger.debug("volume " + volumeId + " is already installed on secondary storage, install path is " +
2883+
volumeStoreRef.getInstallPath());
2884+
ImageStoreEntity secStore = (ImageStoreEntity) dataStoreMgr.getDataStore(volumeStoreRef.getDataStoreId(), DataStoreRole.Image);
2885+
String extractUrl = secStore.createEntityExtractUrl(volumeStoreRef.getInstallPath(), volume.getFormat(), null);
2886+
volumeStoreRef = _volumeStoreDao.findByVolume(volumeId);
2887+
volumeStoreRef.setExtractUrl(extractUrl);
2888+
volumeStoreRef.setExtractUrlCreated(DateUtil.now());
2889+
_volumeStoreDao.update(volumeStoreRef.getId(), volumeStoreRef);
2890+
return Optional.ofNullable(extractUrl);
2891+
}
2892+
2893+
return Optional.empty();
2894+
}
2895+
28512896
private String orchestrateExtractVolume(long volumeId, long zoneId) {
28522897
// get latest volume state to make sure that it is not updated by other parallel operations
28532898
VolumeVO volume = _volsDao.findById(volumeId);

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -545,6 +545,9 @@ private String extract(Account caller, Long templateId, String url, Long zoneId,
545545
if (tmpltStoreRef != null) {
546546
if (tmpltStoreRef.getDownloadState() == com.cloud.storage.VMTemplateStorageResourceAssoc.Status.DOWNLOADED) {
547547
tmpltStore = (ImageStoreEntity)store;
548+
if (tmpltStoreRef.getExtractUrl() != null) {
549+
return tmpltStoreRef.getExtractUrl();
550+
}
548551
break;
549552
}
550553
}

0 commit comments

Comments
 (0)