Extending extract functionlity for volumes to allow download. The

extraction can have two modes FTP_UPLOAD and HTTP_DOWNLOAD. In the former one
the user would provide the ftp url where the entity needs to be uploaded and in
the later the user would be provided a HTTP URL where from he/she can download
the entity. This url would be exposed for a specific time limit and would not
function after the time limit
This commit is contained in:
nit 2010-10-26 18:33:50 +05:30
parent cfdd6999ad
commit 497c60d63d
11 changed files with 235 additions and 73 deletions

View File

@ -1,12 +1,16 @@
package com.cloud.agent.api.storage;
import com.cloud.storage.Upload;
public class DeleteEntityDownloadURLCommand extends AbstractDownloadCommand {
String path;
Upload.Type type;
public DeleteEntityDownloadURLCommand(String path) {
public DeleteEntityDownloadURLCommand(String path, Upload.Type type) {
super();
this.path = path;
this.type = type;
}
public DeleteEntityDownloadURLCommand() {
@ -20,6 +24,13 @@ public class DeleteEntityDownloadURLCommand extends AbstractDownloadCommand {
public void setPath(String path) {
this.path = path;
}
public Upload.Type getType() {
return type;
}
public void setType(Upload.Type type) {
this.type = type;
}
}

View File

@ -96,6 +96,7 @@ public class EventTypes {
public static final String EVENT_VOLUME_DELETE = "VOLUME.DELETE";
public static final String EVENT_VOLUME_ATTACH = "VOLUME.ATTACH";
public static final String EVENT_VOLUME_DETACH = "VOLUME.DETACH";
public static final String EVENT_VOLUME_EXTRACT = "VOLUME.EXTRACT";
public static final String EVENT_VOLUME_UPLOAD = "VOLUME.UPLOAD";
// Domains

View File

@ -26,6 +26,7 @@ import com.cloud.agent.api.storage.UploadProgressCommand;
import com.cloud.agent.api.storage.UploadCommand;
import com.cloud.storage.StorageLayer;
import com.cloud.storage.StorageResource;
import com.cloud.storage.Upload;
import com.cloud.storage.UploadVO;
import com.cloud.storage.Storage.ImageFormat;
import com.cloud.storage.template.TemplateUploader.UploadCompleteCallback;
@ -338,7 +339,7 @@ public class UploadManagerImpl implements UploadManager {
return new CreateEntityDownloadURLAnswer(errorString, CreateEntityDownloadURLAnswer.RESULT_FAILURE);
}
// Create a symbolic link from the actual directory to the template location
// Create a symbolic link from the actual directory to the template location. The entity would be directly visible under /var/www/html/
cmd.getInstallPath();
command = new Script("/bin/bash", s_logger);
command.add("-c");
@ -357,6 +358,7 @@ public class UploadManagerImpl implements UploadManager {
@Override
public DeleteEntityDownloadURLAnswer handleDeleteEntityDownloadURLCommand(DeleteEntityDownloadURLCommand cmd){
//Delete the soft link
s_logger.debug("handleDeleteEntityDownloadURLCommand "+cmd.getPath());
Script command = new Script("/bin/bash", s_logger);
command.add("-c");
@ -367,6 +369,20 @@ public class UploadManagerImpl implements UploadManager {
s_logger.warn(errorString);
return new DeleteEntityDownloadURLAnswer(errorString, CreateEntityDownloadURLAnswer.RESULT_FAILURE);
}
// If its a volume also delete the Hard link
if(cmd.getType() == Upload.Type.VOLUME){
command = new Script("/bin/bash", s_logger);
command.add("-c");
command.add("rm -f " + publicTemplateRepo + cmd.getPath());
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 DeleteEntityDownloadURLAnswer("", CreateEntityDownloadURLAnswer.RESULT_SUCCESS);
}

View File

@ -23,8 +23,10 @@ import com.cloud.api.ApiDBUtils;
import com.cloud.api.BaseAsyncCmd;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
import com.cloud.api.BaseCmd.CommandType;
import com.cloud.api.response.ExtractResponse;
import com.cloud.event.EventTypes;
import com.cloud.storage.UploadVO;
import com.cloud.storage.VolumeVO;
import com.cloud.user.Account;
@ -39,16 +41,19 @@ public class ExtractVolumeCmd extends BaseAsyncCmd {
/////////////////////////////////////////////////////
//FIXME - add description
@Parameter(name="id", type=CommandType.LONG, required=true)
@Parameter(name="id", type=CommandType.LONG, required=true, description="the ID of the volume")
private Long id;
//FIXME - add description
@Parameter(name="url", type=CommandType.STRING, required=true)
@Parameter(name="url", type=CommandType.STRING, required=false, description="the url to which the volume would be extracted")
private String url;
//FIXME - add description
@Parameter(name="zoneid", type=CommandType.LONG, required=true)
@Parameter(name="zoneid", type=CommandType.LONG, required=true, description="the ID of the zone where the volume is located")
private Long zoneId;
@Parameter(name="mode", type=CommandType.STRING, required=true, description="the mode of extraction - HTTP_DOWNLOAD or FTP_UPLOAD")
private String mode;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
@ -65,12 +70,16 @@ public class ExtractVolumeCmd extends BaseAsyncCmd {
public Long getZoneId() {
return zoneId;
}
public String getMode() {
return mode;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
@Override
@Override
public String getName() {
return s_name;
}
@ -79,7 +88,7 @@ public class ExtractVolumeCmd extends BaseAsyncCmd {
public long getAccountId() {
VolumeVO volume = ApiDBUtils.findVolumeById(getId());
if (volume != null) {
return volume.getId();
return volume.getAccountId();
}
// invalid id, parent this command to SYSTEM so ERROR events are tracked
@ -88,7 +97,7 @@ public class ExtractVolumeCmd extends BaseAsyncCmd {
@Override
public String getEventType() {
return EventTypes.EVENT_VOLUME_UPLOAD;
return EventTypes.EVENT_VOLUME_EXTRACT;
}
@Override
@ -98,9 +107,22 @@ public class ExtractVolumeCmd extends BaseAsyncCmd {
@Override @SuppressWarnings("unchecked")
public ExtractResponse getResponse() {
ExtractResponse response = (ExtractResponse)getResponseObject();
response.setResponseName(getName());
return response;
Long uploadId = (Long)getResponseObject();
UploadVO uploadInfo = ApiDBUtils.findUploadById(uploadId);
ExtractResponse response = new ExtractResponse();
response.setResponseName(getName());
response.setId(id);
response.setName(ApiDBUtils.findVolumeById(id).getName());
response.setZoneId(zoneId);
response.setZoneName(ApiDBUtils.findZoneById(zoneId).getName());
response.setMode(mode);
response.setUploadId(uploadId);
response.setState(uploadInfo.getUploadState().toString());
response.setAccountId(getAccountId());
//FIX ME - Need to set the url once the gson jar is upgraded since it is throwing an error right now.
//response.setUrl(uploadInfo.getUploadUrl());
return response;
}
public static String getStaticName() {

View File

@ -29,13 +29,13 @@ public class ExtractResponse extends BaseResponse {
@SerializedName("name") @Param(description="the name of the extracted object")
private String name;
@SerializedName("uploadId") @Param(description="the upload id of extracted object")
@SerializedName("extractId") @Param(description="the upload id of extracted object")
private Long uploadId;
@SerializedName("uploadpercentage") @Param(description="the percentage of the entity uploaded to the specified location")
private Integer uploadPercent;
@SerializedName("status") @Param(description="the status of the ")
@SerializedName("status") @Param(description="the status of the extraction")
private String status;
@SerializedName("accountid") @Param(description="the account id to which the extracted object belongs")
@ -68,8 +68,20 @@ public class ExtractResponse extends BaseResponse {
private String mode;
@SerializedName("url") @Param(description="if mode = upload then url of the uploaded entity. if mode = download the url from which the entity can be downloaded")
private String url;
private String url;
public ExtractResponse(){
}
public ExtractResponse(Long volumeId, String volName, long accountId,
String state, Long uploadId) {
this.id = volumeId;
this.name = volName;
this.accountId = accountId;
this.state = state;
this.uploadId = uploadId;
}
public Long getId() {
return id;
}

View File

3
server/src/com/cloud/server/ManagementServer.java Normal file → Executable file
View File

@ -1207,9 +1207,10 @@ public interface ManagementServer {
* @param cmd the command specifying url (where the volume needs to be extracted to), zoneId (zone where the volume exists), id (the id of the volume)
* @throws URISyntaxException
* @throws InternalErrorException
* @throws PermissionDeniedException
*
*/
void extractVolume(ExtractVolumeCmd cmd) throws URISyntaxException, InternalErrorException;
Long extractVolume(ExtractVolumeCmd cmd) throws URISyntaxException, InternalErrorException, PermissionDeniedException;
/**
* return an array of available hypervisors

View File

@ -137,6 +137,7 @@ import com.cloud.api.commands.UpdateTemplatePermissionsCmd;
import com.cloud.api.commands.UpdateUserCmd;
import com.cloud.api.commands.UpdateVMGroupCmd;
import com.cloud.api.commands.UploadCustomCertificateCmd;
import com.cloud.api.response.ExtractResponse;
import com.cloud.async.AsyncInstanceCreateStatus;
import com.cloud.async.AsyncJobExecutor;
import com.cloud.async.AsyncJobManager;
@ -233,6 +234,7 @@ import com.cloud.storage.StorageManager;
import com.cloud.storage.StoragePoolHostVO;
import com.cloud.storage.StoragePoolVO;
import com.cloud.storage.StorageStats;
import com.cloud.storage.Upload.Mode;
import com.cloud.storage.Upload.Type;
import com.cloud.storage.UploadVO;
import com.cloud.storage.VMTemplateVO;
@ -6675,41 +6677,66 @@ public class ManagementServerImpl implements ManagementServer {
}
@Override
public void extractVolume(ExtractVolumeCmd cmd) throws URISyntaxException, InternalErrorException {
public Long extractVolume(ExtractVolumeCmd cmd) throws URISyntaxException, InternalErrorException, PermissionDeniedException {
Long volumeId = cmd.getId();
String url = cmd.getUrl();
Long zoneId = cmd.getZoneId();
AsyncJobVO job = cmd.getJob();
String mode = cmd.getMode();
Account account = UserContext.current().getAccount();
VolumeVO volume = _volumeDao.findById(volumeId);
if (volume == null) {
throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Unable to find volume with id " + volumeId);
throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to find volume with id " + volumeId);
}
URI uri = new URI(url);
if ( (uri.getScheme() == null) || (!uri.getScheme().equalsIgnoreCase("ftp") )) {
throw new IllegalArgumentException("Unsupported scheme for url: " + url);
}
String host = uri.getHost();
try {
InetAddress hostAddr = InetAddress.getByName(host);
if (hostAddr.isAnyLocalAddress() || hostAddr.isLinkLocalAddress() || hostAddr.isLoopbackAddress() || hostAddr.isMulticastAddress() ) {
throw new IllegalArgumentException("Illegal host specified in url");
}
if (hostAddr instanceof Inet6Address) {
throw new IllegalArgumentException("IPV6 addresses not supported (" + hostAddr.getHostAddress() + ")");
}
} catch (UnknownHostException uhe) {
throw new IllegalArgumentException("Unable to resolve " + host);
}
if (_dcDao.findById(zoneId) == null) {
throw new IllegalArgumentException("Please specify a valid zone.");
throw new ServerApiException(BaseCmd.PARAM_ERROR, "Please specify a valid zone.");
}
Upload.Mode extractMode;
if( mode == null || (!mode.equals(Upload.Mode.FTP_UPLOAD.toString()) && !mode.equals(Upload.Mode.HTTP_DOWNLOAD.toString())) ){
throw new ServerApiException(BaseCmd.PARAM_ERROR, "Please specify a valid extract Mode ");
}else{
extractMode = mode.equals(Upload.Mode.FTP_UPLOAD.toString()) ? Upload.Mode.FTP_UPLOAD : Upload.Mode.HTTP_DOWNLOAD;
}
if ( _uploadMonitor.isTypeUploadInProgress(volumeId, Type.VOLUME) ){
throw new IllegalArgumentException(volume.getName() + " upload is in progress. Please wait for some time to schedule another upload for the same");
if (account != null) {
if(!isAdmin(account.getType())){
if (volume.getAccountId() != account.getId()){
throw new PermissionDeniedException("Unable to find volume with ID: " + volumeId + " for account: " + account.getAccountName());
}
} else {
Account userAccount = _accountDao.findById(volume.getAccountId());
if((userAccount == null) || !_domainDao.isChildDomain(account.getDomainId(), userAccount.getDomainId())) {
throw new PermissionDeniedException("Unable to extract volume:" + volumeId + " - permission denied.");
}
}
}
// If mode is upload perform extra checks on url and also see if there is an ongoing upload on the same.
if (extractMode == Upload.Mode.FTP_UPLOAD){
URI uri = new URI(url);
if ( (uri.getScheme() == null) || (!uri.getScheme().equalsIgnoreCase("ftp") )) {
throw new IllegalArgumentException("Unsupported scheme for url: " + url);
}
String host = uri.getHost();
try {
InetAddress hostAddr = InetAddress.getByName(host);
if (hostAddr.isAnyLocalAddress() || hostAddr.isLinkLocalAddress() || hostAddr.isLoopbackAddress() || hostAddr.isMulticastAddress() ) {
throw new IllegalArgumentException("Illegal host specified in url");
}
if (hostAddr instanceof Inet6Address) {
throw new IllegalArgumentException("IPV6 addresses not supported (" + hostAddr.getHostAddress() + ")");
}
} catch (UnknownHostException uhe) {
throw new IllegalArgumentException("Unable to resolve " + host);
}
if ( _uploadMonitor.isTypeUploadInProgress(volumeId, Type.VOLUME) ){
throw new IllegalArgumentException(volume.getName() + " upload is in progress. Please wait for some time to schedule another upload for the same");
}
}
long userId = UserContext.current().getUserId();
@ -6721,42 +6748,59 @@ public class ManagementServerImpl implements ManagementServer {
List<HostVO> storageServers = _hostDao.listByTypeDataCenter(Host.Type.SecondaryStorage, zoneId);
HostVO sserver = storageServers.get(0);
EventUtils.saveStartedEvent(1L, volume.getAccountId(), EventTypes.EVENT_VOLUME_UPLOAD, "Starting upload of " +volume.getName()+ " to " +url, cmd.getStartEventId());
UploadVO uploadJob = _uploadMonitor.createNewUploadEntry(sserver.getId(), volumeId, UploadVO.Status.COPY_IN_PROGRESS, 0, Type.VOLUME, null, null, url);
uploadJob = _uploadDao.createForUpdate(uploadJob.getId());
EventUtils.saveStartedEvent(userId, accountId, EventTypes.EVENT_VOLUME_UPLOAD, "Starting extraction of " +volume.getName()+ " mode:"+mode, cmd.getStartEventId());
List<UploadVO> extractURLList = _uploadDao.listByTypeUploadStatus(volumeId, Upload.Type.VOLUME, UploadVO.Status.DOWNLOAD_URL_CREATED);
// Update the async Job
ExtractJobResultObject resultObj = new ExtractJobResultObject(volume.getAccountId(), volume.getName(), UploadVO.Status.COPY_IN_PROGRESS.toString(), 0, uploadJob.getId());
_asyncMgr.updateAsyncJobAttachment(job.getId(), Type.VOLUME.toString(), volumeId);
_asyncMgr.updateAsyncJobStatus(job.getId(), AsyncJobResult.STATUS_IN_PROGRESS, resultObj);
if (extractMode == Upload.Mode.HTTP_DOWNLOAD && extractURLList.size() > 0){
return extractURLList.get(0).getId(); // If download url already exists then return
}else {
UploadVO uploadJob = _uploadMonitor.createNewUploadEntry(sserver.getId(), volumeId, UploadVO.Status.COPY_IN_PROGRESS, 0, Type.VOLUME, null, null, url);
uploadJob = _uploadDao.createForUpdate(uploadJob.getId());
// Update the async Job
ExtractResponse resultObj = new ExtractResponse(volumeId, volume.getName(), accountId, UploadVO.Status.COPY_IN_PROGRESS.toString(), uploadJob.getId());
_asyncMgr.updateAsyncJobAttachment(job.getId(), Type.VOLUME.toString(), volumeId);
_asyncMgr.updateAsyncJobStatus(job.getId(), AsyncJobResult.STATUS_IN_PROGRESS, resultObj);
// Copy the volume from the source storage pool to secondary storage
CopyVolumeCommand cvCmd = new CopyVolumeCommand(volume.getId(), volume.getPath(), srcPool, secondaryStorageURL, true);
CopyVolumeAnswer cvAnswer = (CopyVolumeAnswer) _agentMgr.easySend(sourceHostId, cvCmd);
// Copy the volume from the source storage pool to secondary storage
CopyVolumeCommand cvCmd = new CopyVolumeCommand(volume.getId(), volume.getPath(), srcPool, secondaryStorageURL, true);
CopyVolumeAnswer cvAnswer = (CopyVolumeAnswer) _agentMgr.easySend(sourceHostId, cvCmd);
// Check if you got a valid answer.
if (cvAnswer == null || !cvAnswer.getResult()) {
String errorString = "Failed to copy the volume from the source primary storage pool to secondary storage.";
//Update the async job.
resultObj.setResultString(errorString);
resultObj.setUploadStatus(UploadVO.Status.COPY_ERROR.toString());
_asyncMgr.completeAsyncJob(job.getId(), AsyncJobResult.STATUS_FAILED, 0, resultObj);
//Update the DB that volume couldn't be copied
uploadJob.setUploadState(UploadVO.Status.COPY_ERROR);
uploadJob.setErrorString(errorString);
uploadJob.setLastUpdated(new Date());
_uploadDao.update(uploadJob.getId(), uploadJob);
if (cvAnswer == null || !cvAnswer.getResult()) {
EventUtils.saveEvent(userId, accountId, EventTypes.EVENT_VOLUME_UPLOAD, errorString);
throw new InternalErrorException(errorString);
}
String errorString = "Failed to copy the volume from the source primary storage pool to secondary storage.";
resultObj.setResult_string(errorString);
resultObj.setUploadStatus(UploadVO.Status.COPY_ERROR.toString());
_asyncMgr.completeAsyncJob(job.getId(), AsyncJobResult.STATUS_FAILED, 0, resultObj);
uploadJob.setUploadState(UploadVO.Status.COPY_ERROR);
uploadJob.setErrorString(errorString);
String volumeLocalPath = "volumes/"+volume.getId()+"/"+cvAnswer.getVolumePath()+".vhd";
//Update the DB that volume is copied
uploadJob.setUploadState(UploadVO.Status.COPY_COMPLETE);
uploadJob.setLastUpdated(new Date());
_uploadDao.update(uploadJob.getId(), uploadJob);
EventUtils.saveEvent(1L, volume.getAccountId(), EventTypes.EVENT_VOLUME_UPLOAD, errorString);
throw new InternalErrorException(errorString);
if (extractMode == Mode.FTP_UPLOAD){ // Now that the volume is copied perform the actual uploading
_uploadMonitor.extractVolume(uploadJob, sserver, volume, url, zoneId, volumeLocalPath, cmd.getStartEventId(), job.getId(), _asyncMgr);
return uploadJob.getId();
}else{ // Volume is copied now make it visible under apache and create a URL.
s_logger.debug("volumepath " +volumeLocalPath);
_uploadMonitor.createVolumeDownloadURL(volumeId, volumeLocalPath, Type.VOLUME, zoneId, uploadJob.getId());
EventUtils.saveEvent(userId, accountId, EventVO.LEVEL_INFO, cmd.getEventType(), "Completed extraction of "+volume.getName()+ " in mode:" +mode, null, cmd.getStartEventId());
return uploadJob.getId();
}
}
String volumeLocalPath = "volumes/"+volume.getId()+"/"+cvAnswer.getVolumePath()+".vhd";
uploadJob.setUploadState(UploadVO.Status.COPY_COMPLETE);
uploadJob.setLastUpdated(new Date());
_uploadDao.update(uploadJob.getId(), uploadJob);
_uploadMonitor.extractVolume(uploadJob, sserver, volume, url, zoneId, volumeLocalPath, cmd.getStartEventId(), job.getId(), _asyncMgr);
}
@Override

View File

@ -27,6 +27,7 @@ import com.cloud.storage.VMTemplateHostVO;
import com.cloud.storage.VMTemplateVO;
import com.cloud.storage.VolumeVO;
import com.cloud.utils.component.Manager;
import com.cloud.utils.exception.CloudRuntimeException;
/**
* Monitor upload progress of all entities.
@ -55,4 +56,7 @@ public interface UploadMonitor extends Manager{
UploadVO createEntityDownloadURL(VMTemplateVO template,
VMTemplateHostVO vmTemplateHost, Long dataCenterId, long eventId);
void createVolumeDownloadURL(Long entityId, String path, Type type,
Long dataCenterId, Long uploadId) throws CloudRuntimeException;
}

View File

@ -24,6 +24,7 @@ import com.cloud.agent.api.storage.CreateEntityDownloadURLCommand;
import com.cloud.agent.api.storage.DeleteEntityDownloadURLCommand;
import com.cloud.agent.api.storage.UploadCommand;
import com.cloud.agent.api.storage.UploadProgressCommand.RequestType;
import com.cloud.api.ApiDBUtils;
import com.cloud.async.AsyncJobManager;
import com.cloud.configuration.dao.ConfigurationDao;
import com.cloud.event.EventTypes;
@ -118,7 +119,7 @@ public class UploadMonitorImpl implements UploadMonitor {
String errorString, String jobId, String uploadUrl){
UploadVO uploadObj = new UploadVO(hostId, typeId, new Date(),
uploadState, 0, type, null, "jobid0000", uploadUrl);
uploadState, 0, type, null, null, uploadUrl);
_uploadDao.persist(uploadObj);
return uploadObj;
@ -175,6 +176,9 @@ public class UploadMonitorImpl implements UploadMonitor {
}
@Override
public UploadVO createEntityDownloadURL(VMTemplateVO template, VMTemplateHostVO vmTemplateHost, Long dataCenterId, long eventId) {
@ -225,10 +229,57 @@ public class UploadMonitorImpl implements UploadMonitor {
_uploadDao.update(uploadTemplateObj.getId(), vo);
return _uploadDao.findById(uploadTemplateObj.getId(), true);
}
throw new CloudRuntimeException("Couldnt find a running SSVM in the zone" + dataCenterId+ ".couldnt create the extraction URL.");
throw new CloudRuntimeException("Couldnt find a running SSVM in the zone" + dataCenterId+ ". Couldnt create the extraction URL.");
}
@Override
public void createVolumeDownloadURL(Long entityId, String path, Type type, Long dataCenterId, Long uploadId) throws CloudRuntimeException{
List<HostVO> storageServers = _serverDao.listByTypeDataCenter(Host.Type.SecondaryStorage, dataCenterId);
if(storageServers == null )
throw new CloudRuntimeException("No Storage Server found at the datacenter - " +dataCenterId);
// Update DB for state = DOWNLOAD_URL_NOT_CREATED.
UploadVO uploadJob = _uploadDao.createForUpdate(uploadId);
uploadJob.setUploadState(Status.DOWNLOAD_URL_NOT_CREATED);
uploadJob.setLastUpdated(new Date());
_uploadDao.update(uploadJob.getId(), uploadJob);
// Create Symlink at ssvm
CreateEntityDownloadURLCommand cmd = new CreateEntityDownloadURLCommand(path);
long result = send(ApiDBUtils.findUploadById(uploadId).getHostId(), cmd, null);
if (result == -1){
String errorString = "Unable to create a link for " +type+ " id:"+entityId;
s_logger.warn(errorString);
throw new CloudRuntimeException(errorString);
}
//Construct actual URL locally now that the symlink exists at SSVM
List<SecondaryStorageVmVO> ssVms = _secStorageVmDao.getSecStorageVmListInStates(dataCenterId, State.Running);
if (ssVms.size() > 0) {
SecondaryStorageVmVO ssVm = ssVms.get(0);
if (ssVm.getPublicIpAddress() == null) {
s_logger.warn("A running secondary storage vm has a null public ip?");
throw new CloudRuntimeException("SSVM has null public IP - couldnt create the URL");
}
String extractURL = generateCopyUrl(ssVm.getPublicIpAddress(), path);
UploadVO vo = _uploadDao.createForUpdate();
vo.setLastUpdated(new Date());
vo.setUploadUrl(extractURL);
vo.setUploadState(Status.DOWNLOAD_URL_CREATED);
if(extractURL == null){
vo.setUploadState(Status.ERROR);
vo.setErrorString("Could not create the download URL");
}
_uploadDao.update(uploadId, vo);
return;
}
throw new CloudRuntimeException("Couldnt find a running SSVM in the zone" + dataCenterId+ ". Couldnt create the extraction URL.");
}
private String generateCopyUrl(String ipAddress, String path){
String hostname = ipAddress;
String scheme = "http";
@ -401,7 +452,7 @@ public class UploadMonitorImpl implements UploadMonitor {
for (UploadVO extractURL : extractURLs){
if( getTimeDiff(extractURL.getLastUpdated()) < EXTRACT_URL_TIME_LIMIT) continue;
String path = extractURL.getUploadUrl().substring( (extractURL.getUploadUrl().lastIndexOf("/")) +1 );
DeleteEntityDownloadURLCommand cmd = new DeleteEntityDownloadURLCommand(path);
DeleteEntityDownloadURLCommand cmd = new DeleteEntityDownloadURLCommand(path, extractURL.getType());
long result = send(extractURL.getHostId(), cmd, null);
if (result == -1){
s_logger.warn("Unable to delete the link for " +extractURL.getType()+ " id=" +extractURL.getTypeId()+ " url="+extractURL.getUploadUrl());

View File

@ -537,10 +537,10 @@ public class TemplateManagerImpl implements TemplateManager {
if (vo!=null){
ExtractJobResultObject resultObject = new ExtractJobResultObject(template.getAccountId(), template.getName(), Upload.Status.DOWNLOAD_URL_CREATED.toString(), vo.getId(), url);
mgr.completeAsyncJob(job.getId(), AsyncJobResult.STATUS_SUCCEEDED, 1, resultObject);
EventUtils.saveEvent(userId, accountId, EventVO.LEVEL_INFO, event, "Completed extraction of "+template.getName()+ " in mode:" +extractMode.toString(), null, eventId);
EventUtils.saveEvent(userId, accountId, EventVO.LEVEL_INFO, event, "Completed extraction of "+template.getName()+ " in mode:" +mode, null, eventId);
return vo.getId();
}else{
EventUtils.saveEvent(userId, accountId, EventVO.LEVEL_ERROR, event, "Failed extraction of "+template.getName()+ " in mode:" +extractMode.toString(), null, eventId);
EventUtils.saveEvent(userId, accountId, EventVO.LEVEL_ERROR, event, "Failed extraction of "+template.getName()+ " in mode:" +mode, null, eventId);
mgr.completeAsyncJob(job.getId(), AsyncJobResult.STATUS_FAILED, 2, null);
return null;
}