mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
CLOUDSTACK-6599:
1. Adding the missing Template/Volume URLs expiration functionality 2. Improvement - While deleting the volume during expiration use rm -rf as vmware now contains directoy 3. Improvement - Use standard Answer so that the error gets logged in case deletion of expiration link didnt work fine. 4. Improvement - In case of domain change, expire the old urls
This commit is contained in:
parent
bdde5335f9
commit
5393387bbd
@ -1,37 +0,0 @@
|
||||
// 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 com.cloud.agent.api.storage;
|
||||
|
||||
import com.cloud.agent.api.Answer;
|
||||
|
||||
public class DeleteEntityDownloadURLAnswer extends Answer {
|
||||
|
||||
String resultString;
|
||||
short resultCode;
|
||||
public static final short RESULT_SUCCESS = 1;
|
||||
public static final short RESULT_FAILURE = 0;
|
||||
|
||||
public DeleteEntityDownloadURLAnswer(String resultString, short resultCode) {
|
||||
super();
|
||||
this.resultString = resultString;
|
||||
this.resultCode = resultCode;
|
||||
}
|
||||
|
||||
public DeleteEntityDownloadURLAnswer() {
|
||||
}
|
||||
|
||||
}
|
||||
@ -20,6 +20,7 @@ package org.apache.cloudstack.storage.image.datastore;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import com.cloud.storage.Upload;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
|
||||
@ -43,4 +44,6 @@ public interface ImageStoreEntity extends DataStore, ImageStore {
|
||||
String getMountPoint(); // get the mount point on ssvm.
|
||||
|
||||
String createEntityExtractUrl(String installPath, ImageFormat format, DataObject dataObject); // get the entity download URL
|
||||
|
||||
void deleteExtractUrl(String installPath, String url, Upload.Type volume);
|
||||
}
|
||||
|
||||
@ -74,4 +74,6 @@ public interface TemplateDataStoreDao extends GenericDao<TemplateDataStoreVO, Lo
|
||||
List<TemplateDataStoreVO> listOnCache(long templateId);
|
||||
|
||||
void updateStoreRoleToCachce(long storeId);
|
||||
|
||||
List<TemplateDataStoreVO> listTemplateDownloadUrls();
|
||||
}
|
||||
|
||||
@ -98,6 +98,13 @@ public class TemplateDataStoreVO implements StateObject<ObjectInDataStoreStateMa
|
||||
@Column(name = "url")
|
||||
private String downloadUrl;
|
||||
|
||||
@Column(name = "download_url")
|
||||
private String extractUrl;
|
||||
|
||||
@Column(name = "download_url_created")
|
||||
@Temporal(value = TemporalType.TIMESTAMP)
|
||||
private Date extractUrlCreated = null;
|
||||
|
||||
@Column(name = "is_copy")
|
||||
private boolean isCopy = false;
|
||||
|
||||
@ -379,4 +386,20 @@ public class TemplateDataStoreVO implements StateObject<ObjectInDataStoreStateMa
|
||||
}
|
||||
}
|
||||
|
||||
public String getExtractUrl() {
|
||||
return extractUrl;
|
||||
}
|
||||
|
||||
public void setExtractUrl(String extractUrl) {
|
||||
this.extractUrl = extractUrl;
|
||||
}
|
||||
|
||||
public Date getExtractUrlCreated() {
|
||||
return extractUrlCreated;
|
||||
}
|
||||
|
||||
public void setExtractUrlCreated(Date extractUrlCreated) {
|
||||
this.extractUrlCreated = extractUrlCreated;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -42,4 +42,6 @@ public interface VolumeDataStoreDao extends GenericDao<VolumeDataStoreVO, Long>,
|
||||
List<VolumeDataStoreVO> listDestroyed(long storeId);
|
||||
|
||||
void duplicateCacheRecordsOnRegionStore(long storeId);
|
||||
|
||||
List<VolumeDataStoreVO> listVolumeDownloadUrls();
|
||||
}
|
||||
|
||||
@ -102,6 +102,10 @@ public class VolumeDataStoreVO implements StateObject<ObjectInDataStoreStateMach
|
||||
@Column(name = "download_url")
|
||||
private String extractUrl;
|
||||
|
||||
@Column(name = "download_url_created")
|
||||
@Temporal(value = TemporalType.TIMESTAMP)
|
||||
private Date extractUrlCreated = null;
|
||||
|
||||
@Column(name = "destroyed")
|
||||
boolean destroyed = false;
|
||||
|
||||
@ -369,4 +373,12 @@ public class VolumeDataStoreVO implements StateObject<ObjectInDataStoreStateMach
|
||||
public void setExtractUrl(String extractUrl) {
|
||||
this.extractUrl = extractUrl;
|
||||
}
|
||||
|
||||
public Date getExtractUrlCreated() {
|
||||
return extractUrlCreated;
|
||||
}
|
||||
|
||||
public void setExtractUrlCreated(Date extractUrlCreated) {
|
||||
this.extractUrlCreated = extractUrlCreated;
|
||||
}
|
||||
}
|
||||
|
||||
@ -24,6 +24,7 @@ import java.util.concurrent.ExecutionException;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import com.cloud.storage.Upload;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
|
||||
@ -203,4 +204,10 @@ public class ImageStoreImpl implements ImageStoreEntity {
|
||||
return driver.createEntityExtractUrl(this, installPath, format, dataObject);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteExtractUrl(String installPath, String url, Upload.Type entityType) {
|
||||
driver.deleteEntityExtractUrl(this, installPath, url, entityType);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -25,6 +25,7 @@ import java.util.Map;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import com.cloud.storage.Upload;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult;
|
||||
@ -271,4 +272,8 @@ public abstract class BaseImageStoreDriverImpl implements ImageStoreDriver {
|
||||
@Override
|
||||
public void resize(DataObject data, AsyncCompletionCallback<CreateCmdResult> callback) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteEntityExtractUrl(DataStore store, String installPath, String url, Upload.Type entityType){
|
||||
}
|
||||
}
|
||||
|
||||
@ -18,6 +18,7 @@
|
||||
*/
|
||||
package org.apache.cloudstack.storage.image;
|
||||
|
||||
import com.cloud.storage.Upload;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreDriver;
|
||||
@ -26,4 +27,6 @@ import com.cloud.storage.Storage.ImageFormat;
|
||||
|
||||
public interface ImageStoreDriver extends DataStoreDriver {
|
||||
String createEntityExtractUrl(DataStore store, String installPath, ImageFormat format, DataObject dataObject);
|
||||
|
||||
void deleteEntityExtractUrl(DataStore store, String installPath, String url, Upload.Type entityType);
|
||||
}
|
||||
|
||||
@ -63,6 +63,7 @@ public class TemplateDataStoreDaoImpl extends GenericDaoBase<TemplateDataStoreVO
|
||||
private SearchBuilder<TemplateDataStoreVO> storeTemplateSearch;
|
||||
private SearchBuilder<TemplateDataStoreVO> storeTemplateStateSearch;
|
||||
private SearchBuilder<TemplateDataStoreVO> storeTemplateDownloadStatusSearch;
|
||||
private SearchBuilder<TemplateDataStoreVO> downloadTemplateSearch;
|
||||
|
||||
@Inject
|
||||
private DataStoreManager _storeMgr;
|
||||
@ -131,6 +132,11 @@ public class TemplateDataStoreDaoImpl extends GenericDaoBase<TemplateDataStoreVO
|
||||
storeTemplateSearch.and("destroyed", storeTemplateSearch.entity().getDestroyed(), SearchCriteria.Op.EQ);
|
||||
storeTemplateSearch.done();
|
||||
|
||||
downloadTemplateSearch = createSearchBuilder();
|
||||
downloadTemplateSearch.and("download_url", downloadTemplateSearch.entity().getExtractUrl(), Op.NNULL);
|
||||
downloadTemplateSearch.and("destroyed", downloadTemplateSearch.entity().getDestroyed(), SearchCriteria.Op.EQ);
|
||||
downloadTemplateSearch.done();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -488,4 +494,11 @@ public class TemplateDataStoreDaoImpl extends GenericDaoBase<TemplateDataStoreVO
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TemplateDataStoreVO> listTemplateDownloadUrls() {
|
||||
SearchCriteria<TemplateDataStoreVO> sc = downloadTemplateSearch.create();
|
||||
sc.setParameters("destroyed", false);
|
||||
return listBy(sc);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -50,6 +50,7 @@ public class VolumeDataStoreDaoImpl extends GenericDaoBase<VolumeDataStoreVO, Lo
|
||||
private SearchBuilder<VolumeDataStoreVO> storeSearch;
|
||||
private SearchBuilder<VolumeDataStoreVO> cacheSearch;
|
||||
private SearchBuilder<VolumeDataStoreVO> storeVolumeSearch;
|
||||
private SearchBuilder<VolumeDataStoreVO> downloadVolumeSearch;
|
||||
|
||||
@Inject
|
||||
DataStoreManager storeMgr;
|
||||
@ -85,6 +86,12 @@ public class VolumeDataStoreDaoImpl extends GenericDaoBase<VolumeDataStoreVO, Lo
|
||||
updateStateSearch.and("state", updateStateSearch.entity().getState(), Op.EQ);
|
||||
updateStateSearch.and("updatedCount", updateStateSearch.entity().getUpdatedCount(), Op.EQ);
|
||||
updateStateSearch.done();
|
||||
|
||||
downloadVolumeSearch = createSearchBuilder();
|
||||
downloadVolumeSearch.and("download_url", downloadVolumeSearch.entity().getExtractUrl(), Op.NNULL);
|
||||
downloadVolumeSearch.and("destroyed", downloadVolumeSearch.entity().getDestroyed(), SearchCriteria.Op.EQ);
|
||||
downloadVolumeSearch.done();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -253,4 +260,11 @@ public class VolumeDataStoreDaoImpl extends GenericDaoBase<VolumeDataStoreVO, Lo
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<VolumeDataStoreVO> listVolumeDownloadUrls() {
|
||||
SearchCriteria<VolumeDataStoreVO> sc = downloadVolumeSearch.create();
|
||||
sc.setParameters("destroyed", false);
|
||||
return listBy(sc);
|
||||
}
|
||||
}
|
||||
|
||||
@ -22,6 +22,8 @@ import java.util.UUID;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import com.cloud.agent.api.storage.DeleteEntityDownloadURLCommand;
|
||||
import com.cloud.storage.Upload;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
|
||||
@ -109,4 +111,28 @@ public class CloudStackImageStoreDriverImpl extends BaseImageStoreDriverImpl {
|
||||
return scheme + "://" + hostname + "/userdata/" + uuid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteEntityExtractUrl(DataStore store, String installPath, String downloadUrl, Upload.Type entityType) {
|
||||
// find an endpoint to send command
|
||||
EndPoint ep = _epSelector.select(store);
|
||||
|
||||
// Delete Symlink at ssvm. In case of volume also delete the volume.
|
||||
DeleteEntityDownloadURLCommand cmd = new DeleteEntityDownloadURLCommand(installPath, entityType, downloadUrl, ((ImageStoreEntity) store).getMountPoint());
|
||||
|
||||
Answer ans = null;
|
||||
if (ep == null) {
|
||||
String errMsg = "No remote endpoint to send command, check if host or ssvm is down?";
|
||||
s_logger.error(errMsg);
|
||||
ans = new Answer(cmd, false, errMsg);
|
||||
} else {
|
||||
ans = ep.sendMessage(cmd);
|
||||
}
|
||||
if (ans == null || !ans.getResult()) {
|
||||
String errorString = "Unable to delete the url " + downloadUrl + " for path " + installPath + " on ssvm, " + ans.getDetails();
|
||||
s_logger.error(errorString);
|
||||
throw new CloudRuntimeException(errorString);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -17,6 +17,7 @@
|
||||
package com.cloud.configuration;
|
||||
|
||||
import java.net.URI;
|
||||
import java.sql.Date;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
@ -36,6 +37,7 @@ import javax.ejb.Local;
|
||||
import javax.inject.Inject;
|
||||
import javax.naming.ConfigurationException;
|
||||
|
||||
import com.cloud.storage.StorageManager;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import org.apache.cloudstack.acl.SecurityChecker;
|
||||
@ -315,6 +317,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
||||
AffinityGroupDao _affinityGroupDao;
|
||||
@Inject
|
||||
AffinityGroupService _affinityGroupService;
|
||||
@Inject
|
||||
StorageManager _storageManager;
|
||||
|
||||
// FIXME - why don't we have interface for DataCenterLinkLocalIpAddressDao?
|
||||
@Inject
|
||||
@ -585,6 +589,27 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
||||
throw new CloudRuntimeException("Failed to update SecondaryStorage offering's use_local_storage option to value:" + useLocalStorage);
|
||||
}
|
||||
}
|
||||
}else if (Config.SecStorageSecureCopyCert.key().equalsIgnoreCase(name)) {
|
||||
//FIXME - Ideally there should be a listener model to listen to global config changes and be able to take action gracefully.
|
||||
//Expire the download urls
|
||||
String sqlTemplate = "update template_store_ref set download_url_created=?";
|
||||
String sqlVolume = "update volume_store_ref set download_url_created=?";
|
||||
try {
|
||||
// Change for templates
|
||||
pstmt = txn.prepareAutoCloseStatement(sqlTemplate);
|
||||
pstmt.setDate(1, new Date(-1l));// Set the time before the epoch time.
|
||||
pstmt.executeUpdate();
|
||||
// Change for volumes
|
||||
pstmt = txn.prepareAutoCloseStatement(sqlVolume);
|
||||
pstmt.setDate(1, new Date(-1l));// Set the time before the epoch time.
|
||||
pstmt.executeUpdate();
|
||||
// Cleanup the download urls
|
||||
_storageManager.cleanupDownloadUrls();
|
||||
} catch (Throwable e) {
|
||||
throw new CloudRuntimeException("Failed to clean up download URLs in template_store_ref or volume_store_ref due to exception ", e);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
txn.commit();
|
||||
|
||||
@ -114,4 +114,6 @@ public interface StorageManager extends StorageService {
|
||||
Long getDiskIopsReadRate(ServiceOfferingVO offering, DiskOfferingVO diskOffering);
|
||||
|
||||
Long getDiskIopsWriteRate(ServiceOfferingVO offering, DiskOfferingVO diskOffering);
|
||||
|
||||
void cleanupDownloadUrls();
|
||||
}
|
||||
|
||||
@ -41,6 +41,8 @@ import javax.ejb.Local;
|
||||
import javax.inject.Inject;
|
||||
import javax.naming.ConfigurationException;
|
||||
|
||||
import com.cloud.utils.DateUtil;
|
||||
import org.apache.cloudstack.storage.image.datastore.ImageStoreEntity;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@ -284,6 +286,8 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C
|
||||
boolean _templateCleanupEnabled = true;
|
||||
int _storageCleanupInterval;
|
||||
int _storagePoolAcquisitionWaitSeconds = 1800; // 30 minutes
|
||||
int _downloadUrlCleanupInterval;
|
||||
int _downloadUrlExpirationInterval;
|
||||
// protected BigDecimal _overProvisioningFactor = new BigDecimal(1);
|
||||
private long _serverId;
|
||||
|
||||
@ -455,6 +459,12 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C
|
||||
s_logger.info("Storage cleanup enabled: " + _storageCleanupEnabled + ", interval: " + _storageCleanupInterval + ", template cleanup enabled: " +
|
||||
_templateCleanupEnabled);
|
||||
|
||||
String cleanupInterval = configs.get("extract.url.cleanup.interval");
|
||||
_downloadUrlCleanupInterval = NumbersUtil.parseInt(cleanupInterval, 7200);
|
||||
|
||||
String urlExpirationInterval = configs.get("extract.url.expiration.interval");
|
||||
_downloadUrlExpirationInterval = NumbersUtil.parseInt(urlExpirationInterval, 14400);
|
||||
|
||||
String workers = configs.get("expunge.workers");
|
||||
int wrks = NumbersUtil.parseInt(workers, 10);
|
||||
_executor = Executors.newScheduledThreadPool(wrks, new NamedThreadFactory("StorageManager-Scavenger"));
|
||||
@ -507,6 +517,9 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C
|
||||
} else {
|
||||
s_logger.debug("Storage cleanup is not enabled, so the storage cleanup thread is not being scheduled.");
|
||||
}
|
||||
|
||||
_executor.scheduleWithFixedDelay(new DownloadURLGarbageCollector(), _downloadUrlCleanupInterval, _downloadUrlCleanupInterval, TimeUnit.SECONDS);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1962,6 +1975,80 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C
|
||||
return true;
|
||||
}
|
||||
|
||||
protected class DownloadURLGarbageCollector implements Runnable {
|
||||
|
||||
public DownloadURLGarbageCollector() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
s_logger.trace("Download URL Garbage Collection Thread is running.");
|
||||
|
||||
cleanupDownloadUrls();
|
||||
|
||||
} catch (Exception e) {
|
||||
s_logger.error("Caught the following Exception", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanupDownloadUrls(){
|
||||
|
||||
// Cleanup expired volume URLs
|
||||
List<VolumeDataStoreVO> volumesOnImageStoreList = _volumeStoreDao.listVolumeDownloadUrls();
|
||||
for(VolumeDataStoreVO volumeOnImageStore : volumesOnImageStoreList){
|
||||
|
||||
try {
|
||||
long downloadUrlCurrentAgeInSecs = DateUtil.getTimeDifference(DateUtil.now(), volumeOnImageStore.getExtractUrlCreated());
|
||||
if(downloadUrlCurrentAgeInSecs < _downloadUrlExpirationInterval){ // URL hasnt expired yet
|
||||
continue;
|
||||
}
|
||||
|
||||
s_logger.debug("Removing download url " + volumeOnImageStore.getExtractUrl() + " for volume id " + volumeOnImageStore.getVolumeId());
|
||||
|
||||
// Remove it from image store
|
||||
ImageStoreEntity secStore = (ImageStoreEntity) _dataStoreMgr.getDataStore(volumeOnImageStore.getDataStoreId(), DataStoreRole.Image);
|
||||
secStore.deleteExtractUrl(volumeOnImageStore.getInstallPath(), volumeOnImageStore.getExtractUrl(), Upload.Type.VOLUME);
|
||||
|
||||
// Now expunge it from DB since this entry was created only for download purpose
|
||||
_volumeStoreDao.expunge(volumeOnImageStore.getId());
|
||||
}catch(Throwable th){
|
||||
s_logger.warn("Caught exception while deleting download url " +volumeOnImageStore.getExtractUrl() +
|
||||
" for volume id " + volumeOnImageStore.getVolumeId(), th);
|
||||
}
|
||||
}
|
||||
|
||||
// Cleanup expired template URLs
|
||||
List<TemplateDataStoreVO> templatesOnImageStoreList = _templateStoreDao.listTemplateDownloadUrls();
|
||||
for(TemplateDataStoreVO templateOnImageStore : templatesOnImageStoreList){
|
||||
|
||||
try {
|
||||
long downloadUrlCurrentAgeInSecs = DateUtil.getTimeDifference(DateUtil.now(), templateOnImageStore.getExtractUrlCreated());
|
||||
if(downloadUrlCurrentAgeInSecs < _downloadUrlExpirationInterval){ // URL hasnt expired yet
|
||||
continue;
|
||||
}
|
||||
|
||||
s_logger.debug("Removing download url " + templateOnImageStore.getExtractUrl() + " for template id " + templateOnImageStore.getTemplateId());
|
||||
|
||||
// Remove it from image store
|
||||
ImageStoreEntity secStore = (ImageStoreEntity) _dataStoreMgr.getDataStore(templateOnImageStore.getDataStoreId(), DataStoreRole.Image);
|
||||
secStore.deleteExtractUrl(templateOnImageStore.getInstallPath(), templateOnImageStore.getExtractUrl(), Upload.Type.TEMPLATE);
|
||||
|
||||
// Now remove download details from DB.
|
||||
templateOnImageStore.setExtractUrl(null);
|
||||
templateOnImageStore.setExtractUrlCreated(null);
|
||||
_templateStoreDao.update(templateOnImageStore.getId(), templateOnImageStore);
|
||||
}catch(Throwable th){
|
||||
s_logger.warn("caught exception while deleting download url " +templateOnImageStore.getExtractUrl() +
|
||||
" for template id " +templateOnImageStore.getTemplateId(), th);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// get bytesReadRate from service_offering, disk_offering and vm.disk.throttling.bytes_read_rate
|
||||
@Override
|
||||
public Long getDiskBytesReadRate(ServiceOfferingVO offering, DiskOfferingVO diskOffering) {
|
||||
|
||||
@ -26,6 +26,7 @@ import java.util.concurrent.ExecutionException;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import com.cloud.utils.DateUtil;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import org.apache.cloudstack.api.command.user.volume.AttachVolumeCmd;
|
||||
@ -1910,6 +1911,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
|
||||
String extractUrl = secStore.createEntityExtractUrl(vol.getPath(), vol.getFormat(), vol);
|
||||
volumeStoreRef = _volumeStoreDao.findByVolume(volumeId);
|
||||
volumeStoreRef.setExtractUrl(extractUrl);
|
||||
volumeStoreRef.setExtractUrlCreated(DateUtil.now());
|
||||
_volumeStoreDao.update(volumeStoreRef.getId(), volumeStoreRef);
|
||||
|
||||
return extractUrl;
|
||||
|
||||
@ -31,6 +31,7 @@ import javax.ejb.Local;
|
||||
import javax.inject.Inject;
|
||||
import javax.naming.ConfigurationException;
|
||||
|
||||
import com.cloud.utils.DateUtil;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import org.apache.cloudstack.acl.SecurityChecker.AccessType;
|
||||
@ -437,12 +438,20 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
|
||||
throw new InvalidParameterValueException("The " + desc + " has not been downloaded ");
|
||||
}
|
||||
|
||||
// Check if the url already exists
|
||||
if(tmpltStoreRef.getExtractUrl() != null){
|
||||
return tmpltStoreRef.getExtractUrl();
|
||||
}
|
||||
|
||||
// Handle NFS to S3 object store migration case, we trigger template sync from NFS to S3 during extract template or copy template
|
||||
_tmpltSvr.syncTemplateToRegionStore(templateId, tmpltStore);
|
||||
|
||||
TemplateInfo templateObject = _tmplFactory.getTemplate(templateId, tmpltStore);
|
||||
|
||||
return tmpltStore.createEntityExtractUrl(templateObject.getInstallPath(), template.getFormat(), templateObject);
|
||||
String extractUrl = tmpltStore.createEntityExtractUrl(tmpltStoreRef.getInstallPath(), template.getFormat(), templateObject);
|
||||
tmpltStoreRef.setExtractUrl(extractUrl);
|
||||
tmpltStoreRef.setExtractUrlCreated(DateUtil.now());
|
||||
_tmplStoreDao.update(tmpltStoreRef.getId(), tmpltStoreRef);
|
||||
return extractUrl;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -19,6 +19,7 @@ package org.apache.cloudstack.networkoffering;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import com.cloud.storage.StorageManager;
|
||||
import org.mockito.Mockito;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
@ -132,7 +133,8 @@ import com.cloud.vm.dao.VMInstanceDaoImpl;
|
||||
PortableIpRangeDaoImpl.class, RegionDaoImpl.class, PortableIpDaoImpl.class, AccountGuestVlanMapDaoImpl.class},
|
||||
includeFilters = {@Filter(value = ChildTestConfiguration.Library.class, type = FilterType.CUSTOM)},
|
||||
useDefaultFilters = false)
|
||||
public class ChildTestConfiguration {
|
||||
public class
|
||||
ChildTestConfiguration {
|
||||
|
||||
@Bean
|
||||
public ManagementService managementService() {
|
||||
@ -329,6 +331,11 @@ public class ChildTestConfiguration {
|
||||
return Mockito.mock(AffinityGroupService.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public StorageManager storageManager() {
|
||||
return Mockito.mock(StorageManager.class);
|
||||
}
|
||||
|
||||
public static class Library implements TypeFilter {
|
||||
|
||||
@Override
|
||||
|
||||
@ -16,11 +16,11 @@
|
||||
// under the License.
|
||||
package org.apache.cloudstack.storage.template;
|
||||
|
||||
import com.cloud.agent.api.Answer;
|
||||
import org.apache.cloudstack.storage.resource.SecondaryStorageResource;
|
||||
|
||||
import com.cloud.agent.api.storage.CreateEntityDownloadURLAnswer;
|
||||
import com.cloud.agent.api.storage.CreateEntityDownloadURLCommand;
|
||||
import com.cloud.agent.api.storage.DeleteEntityDownloadURLAnswer;
|
||||
import com.cloud.agent.api.storage.DeleteEntityDownloadURLCommand;
|
||||
import com.cloud.agent.api.storage.UploadAnswer;
|
||||
import com.cloud.agent.api.storage.UploadCommand;
|
||||
@ -77,6 +77,6 @@ public interface UploadManager extends Manager {
|
||||
|
||||
CreateEntityDownloadURLAnswer handleCreateEntityURLCommand(CreateEntityDownloadURLCommand cmd);
|
||||
|
||||
DeleteEntityDownloadURLAnswer handleDeleteEntityDownloadURLCommand(DeleteEntityDownloadURLCommand cmd);
|
||||
Answer handleDeleteEntityDownloadURLCommand(DeleteEntityDownloadURLCommand cmd);
|
||||
|
||||
}
|
||||
|
||||
@ -29,13 +29,13 @@ import java.util.concurrent.Executors;
|
||||
|
||||
import javax.naming.ConfigurationException;
|
||||
|
||||
import com.cloud.agent.api.Answer;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import org.apache.cloudstack.storage.resource.SecondaryStorageResource;
|
||||
|
||||
import com.cloud.agent.api.storage.CreateEntityDownloadURLAnswer;
|
||||
import com.cloud.agent.api.storage.CreateEntityDownloadURLCommand;
|
||||
import com.cloud.agent.api.storage.DeleteEntityDownloadURLAnswer;
|
||||
import com.cloud.agent.api.storage.DeleteEntityDownloadURLCommand;
|
||||
import com.cloud.agent.api.storage.UploadAnswer;
|
||||
import com.cloud.agent.api.storage.UploadCommand;
|
||||
@ -303,7 +303,7 @@ public class UploadManagerImpl extends ManagerBase implements UploadManager {
|
||||
}
|
||||
|
||||
@Override
|
||||
public DeleteEntityDownloadURLAnswer handleDeleteEntityDownloadURLCommand(DeleteEntityDownloadURLCommand cmd) {
|
||||
public Answer handleDeleteEntityDownloadURLCommand(DeleteEntityDownloadURLCommand cmd) {
|
||||
|
||||
//Delete the soft link. Example path = volumes/8/74eeb2c6-8ab1-4357-841f-2e9d06d1f360.vhd
|
||||
s_logger.warn("handleDeleteEntityDownloadURLCommand Path:" + cmd.getPath() + " Type:" + cmd.getType().toString());
|
||||
@ -318,24 +318,24 @@ public class UploadManagerImpl extends ManagerBase implements UploadManager {
|
||||
if (result != null) {
|
||||
String errorString = "Error in deleting =" + result;
|
||||
s_logger.warn(errorString);
|
||||
return new DeleteEntityDownloadURLAnswer(errorString, CreateEntityDownloadURLAnswer.RESULT_FAILURE);
|
||||
return new Answer(cmd, false, errorString);
|
||||
}
|
||||
|
||||
// If its a volume also delete the Hard link since it was created only for the purpose of download.
|
||||
if (cmd.getType() == Upload.Type.VOLUME) {
|
||||
command = new Script("/bin/bash", s_logger);
|
||||
command.add("-c");
|
||||
command.add("rm -f /mnt/SecStorage/" + cmd.getParentPath() + File.separator + path);
|
||||
command.add("rm -rf /mnt/SecStorage/" + cmd.getParentPath() + File.separator + path);
|
||||
s_logger.warn(" " + parentDir + File.separator + path);
|
||||
result = command.execute();
|
||||
if (result != null) {
|
||||
String errorString = "Error in linking err=" + result;
|
||||
s_logger.warn(errorString);
|
||||
return new DeleteEntityDownloadURLAnswer(errorString, CreateEntityDownloadURLAnswer.RESULT_FAILURE);
|
||||
return new Answer(cmd, false, errorString);
|
||||
}
|
||||
}
|
||||
|
||||
return new DeleteEntityDownloadURLAnswer("", CreateEntityDownloadURLAnswer.RESULT_SUCCESS);
|
||||
return new Answer(cmd, true, "");
|
||||
}
|
||||
|
||||
private String getInstallPath(String jobId) {
|
||||
|
||||
@ -1685,3 +1685,8 @@ alter table `cloud`.`vlan` add column created datetime NULL COMMENT 'date create
|
||||
|
||||
alter table `cloud`.`user_ip_address` drop key public_ip_address;
|
||||
alter table `cloud`.`user_ip_address` add UNIQUE KEY public_ip_address (public_ip_address,source_network_id, removed);
|
||||
|
||||
ALTER TABLE `cloud`.`volume_store_ref` ADD `download_url_created` datetime;
|
||||
ALTER TABLE `cloud`.`template_store_ref` ADD `download_url_created` datetime;
|
||||
ALTER TABLE `cloud`.`template_store_ref` ADD `download_url` varchar(255);
|
||||
|
||||
|
||||
@ -261,6 +261,17 @@ public class DateUtil {
|
||||
}
|
||||
}
|
||||
|
||||
public static long getTimeDifference(Date date1, Date date2){
|
||||
|
||||
Calendar dateCalendar1 = Calendar.getInstance();
|
||||
dateCalendar1.setTime(date1);
|
||||
Calendar dateCalendar2 = Calendar.getInstance();
|
||||
dateCalendar2.setTime(date2);
|
||||
|
||||
return (dateCalendar1.getTimeInMillis() - dateCalendar2.getTimeInMillis() )/1000;
|
||||
|
||||
}
|
||||
|
||||
// test only
|
||||
public static void main(String[] args) {
|
||||
TimeZone localTimezone = Calendar.getInstance().getTimeZone();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user