From b16520bcecf5066259f9ee44c653fbb60847c18b Mon Sep 17 00:00:00 2001 From: Rajani Karuturi Date: Tue, 3 Mar 2015 17:22:40 +0530 Subject: [PATCH] volume upload: added max size check for temaplte/volume post upload used the existing configuration variables max.template.iso.size and storage.max.volume.upload.size for templates and volumes respectively. --- .../TemplateOrVolumePostUploadCommand.java | 10 +++++++ .../cloud/storage/VolumeApiServiceImpl.java | 2 ++ .../template/HypervisorTemplateAdapter.java | 3 ++ .../resource/HttpUploadServerHandler.java | 22 ++++++++++---- .../resource/NfsSecondaryStorageResource.java | 29 +++++++++++++++---- .../storage/template/UploadEntity.java | 7 +++++ 6 files changed, 63 insertions(+), 10 deletions(-) diff --git a/core/src/org/apache/cloudstack/storage/command/TemplateOrVolumePostUploadCommand.java b/core/src/org/apache/cloudstack/storage/command/TemplateOrVolumePostUploadCommand.java index 8872798e16a..cc9df7146a3 100644 --- a/core/src/org/apache/cloudstack/storage/command/TemplateOrVolumePostUploadCommand.java +++ b/core/src/org/apache/cloudstack/storage/command/TemplateOrVolumePostUploadCommand.java @@ -45,6 +45,8 @@ public class TemplateOrVolumePostUploadCommand { String remoteEndPoint; + String maxUploadSize; + public TemplateOrVolumePostUploadCommand(long entityId, String entityUUID, String absolutePath, String checksum, String type, String name, String imageFormat, String dataTo, String dataToRole) { this.entityId = entityId; @@ -156,4 +158,12 @@ public class TemplateOrVolumePostUploadCommand { public void setName(String name) { this.name = name; } + + public String getMaxUploadSize() { + return maxUploadSize; + } + + public void setMaxUploadSize(String maxUploadSize) { + this.maxUploadSize = maxUploadSize; + } } diff --git a/server/src/com/cloud/storage/VolumeApiServiceImpl.java b/server/src/com/cloud/storage/VolumeApiServiceImpl.java index 984009694ee..d2c1c69a537 100644 --- a/server/src/com/cloud/storage/VolumeApiServiceImpl.java +++ b/server/src/com/cloud/storage/VolumeApiServiceImpl.java @@ -337,6 +337,8 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic vol.getName(), vol.getFormat().toString(), dataObject.getDataStore().getUri(), dataObject.getDataStore().getRole().toString()); command.setLocalPath(volumeStore.getLocalDownloadPath()); + //using the existing max upload size configuration + command.setMaxUploadSize(_configDao.getValue(Config.MaxUploadVolumeSize.key())); Gson gson = new GsonBuilder().create(); String metadata = EncryptionUtil.encodeData(gson.toJson(command), key); response.setMetadata(metadata); diff --git a/server/src/com/cloud/template/HypervisorTemplateAdapter.java b/server/src/com/cloud/template/HypervisorTemplateAdapter.java index 6d81047a46f..0cb48fc07c5 100755 --- a/server/src/com/cloud/template/HypervisorTemplateAdapter.java +++ b/server/src/com/cloud/template/HypervisorTemplateAdapter.java @@ -26,6 +26,7 @@ import java.util.concurrent.ExecutionException; import javax.ejb.Local; import javax.inject.Inject; +import com.cloud.configuration.Config; import org.apache.cloudstack.api.command.user.template.GetUploadParamsForTemplateCmd; import org.apache.cloudstack.engine.subsystem.api.storage.DataObject; import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint; @@ -259,6 +260,8 @@ public class HypervisorTemplateAdapter extends TemplateAdapterBase { TemplateOrVolumePostUploadCommand payload = new TemplateOrVolumePostUploadCommand(template.getId(), template.getUuid(), tmpl.getInstallPath(), tmpl.getChecksum(), tmpl .getType().toString(), template.getName(), template.getFormat().toString(), templateOnStore.getDataStore().getUri(), templateOnStore.getDataStore().getRole() .toString()); + //using the existing max template size configuration + payload.setMaxUploadSize(_configDao.getValue(Config.MaxTemplateAndIsoSize.key())); payload.setRemoteEndPoint(ep.getPublicAddr()); payload.setRequiresHvm(template.requiresHvm()); payloads.add(payload); diff --git a/services/secondary-storage/server/src/org/apache/cloudstack/storage/resource/HttpUploadServerHandler.java b/services/secondary-storage/server/src/org/apache/cloudstack/storage/resource/HttpUploadServerHandler.java index 0c95707dc10..7a17ef19d49 100644 --- a/services/secondary-storage/server/src/org/apache/cloudstack/storage/resource/HttpUploadServerHandler.java +++ b/services/secondary-storage/server/src/org/apache/cloudstack/storage/resource/HttpUploadServerHandler.java @@ -108,6 +108,8 @@ public class HttpUploadServerHandler extends SimpleChannelInboundHandler entry : request.headers()) { switch (entry.getKey()) { case HEADER_SIGNATURE: @@ -122,12 +124,16 @@ public class HttpUploadServerHandler extends SimpleChannelInboundHandler maxSizeInGB) { + throw new InvalidParameterValueException("Maximum file upload size exceeded. Content Length received: " + contentLengthInGB + "GB. Maximum allowed size: " + + maxSizeInGB + "GB."); + } try { String absolutePath = cmd.getAbsolutePath(); uploadEntity = new UploadEntity(uuid, cmd.getEntityId(), UploadEntity.Status.IN_PROGRESS, cmd.getName(), absolutePath); @@ -2627,6 +2633,7 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S uploadEntity.setInstallPathPrefix(installPathPrefix); uploadEntity.setHvm(cmd.getRequiresHvm()); uploadEntity.setChksum(cmd.getChecksum()); + uploadEntity.setMaxSizeInGB(maxSizeInGB); // create a install dir if (!_storage.exists(installPathPrefix)) { _storage.mkdir(installPathPrefix); @@ -2634,13 +2641,16 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S uploadEntityStateMap.put(uuid, uploadEntity); } catch (Exception e) { //upload entity will be null incase an exception occurs and the handler will not proceed. - s_logger.debug("exception occured while creating upload entity " + e); + s_logger.error("exception occurred while creating upload entity ", e); updateStateMapWithError(uuid, e.getMessage()); } } return uploadEntity; } + private int getSizeInGB(long sizeInBytes) { + return (int)Math.ceil(sizeInBytes * 1.0d / (1024 * 1024 * 1024)); + } public String postUpload(String uuid, String filename) { UploadEntity uploadEntity = uploadEntityStateMap.get(uuid); @@ -2657,7 +2667,11 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S //} //dnld.setCheckSum(checkSum); - int imgSizeGigs = (int)Math.ceil(_storage.getSize(fileSavedTempLocation) * 1.0d / (1024 * 1024 * 1024)); + int imgSizeGigs = getSizeInGB(_storage.getSize(fileSavedTempLocation)); + int maxSize = uploadEntity.getMaxSizeInGB(); + if(imgSizeGigs > maxSize) { + throw new InvalidParameterValueException("Maximum file upload size exceeded. Physical file size: "+imgSizeGigs+"GB. Maximum allowed size: "+maxSize+"GB."); + } imgSizeGigs++; // add one just in case long timeout = (long)imgSizeGigs * installTimeoutPerGig; Script scr = new Script(getScriptLocation(resourceType), timeout, s_logger); @@ -2771,13 +2785,18 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S uploadEntityStateMap.put(uuid, uploadEntity); } - public void validatePostUploadRequest(String signature, String metadata, String timeout, String hostname, String uuid) throws InvalidParameterValueException{ + public void validatePostUploadRequest(String signature, String metadata, String timeout, String hostname,long contentLength, String uuid) throws InvalidParameterValueException{ // check none of the params are empty if(StringUtils.isEmpty(signature) || StringUtils.isEmpty(metadata) || StringUtils.isEmpty(timeout)) { updateStateMapWithError(uuid,"signature, metadata and expires are compulsory fields."); throw new InvalidParameterValueException("signature, metadata and expires are compulsory fields."); } + //check that contentLength exists and is greater than zero + if (contentLength <= 0) { + throw new InvalidParameterValueException("content length is not set in the request or has invalid value."); + } + //validate signature String fullUrl = "https://" + hostname + "/upload/" + uuid; String computedSignature = EncryptionUtil.generateSignature(metadata + fullUrl + timeout, getPostUploadPSK()); diff --git a/services/secondary-storage/server/src/org/apache/cloudstack/storage/template/UploadEntity.java b/services/secondary-storage/server/src/org/apache/cloudstack/storage/template/UploadEntity.java index 46ace7c12b2..15a6ef28c66 100644 --- a/services/secondary-storage/server/src/org/apache/cloudstack/storage/template/UploadEntity.java +++ b/services/secondary-storage/server/src/org/apache/cloudstack/storage/template/UploadEntity.java @@ -31,6 +31,7 @@ public class UploadEntity { private long entityId; private String chksum; private long physicalSize; + private int maxSizeInGB; public static enum ResourceType { VOLUME, TEMPLATE @@ -172,5 +173,11 @@ public class UploadEntity { return physicalSize; } + public int getMaxSizeInGB() { + return maxSizeInGB; + } + public void setMaxSizeInGB(int maxSizeInGB) { + this.maxSizeInGB = maxSizeInGB; + } }