mirror of
https://github.com/apache/cloudstack.git
synced 2025-11-03 04:12:31 +01:00
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.
This commit is contained in:
parent
dd1a8da977
commit
b16520bcec
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -108,6 +108,8 @@ public class HttpUploadServerHandler extends SimpleChannelInboundHandler<HttpObj
|
||||
String expires = null;
|
||||
String metadata = null;
|
||||
String hostname = null;
|
||||
long contentLength = 0;
|
||||
|
||||
for (Entry<String, String> entry : request.headers()) {
|
||||
switch (entry.getKey()) {
|
||||
case HEADER_SIGNATURE:
|
||||
@ -122,12 +124,16 @@ public class HttpUploadServerHandler extends SimpleChannelInboundHandler<HttpObj
|
||||
case HEADER_HOST:
|
||||
hostname = entry.getValue();
|
||||
break;
|
||||
case HttpHeaders.Names.CONTENT_LENGTH:
|
||||
contentLength = Long.valueOf(entry.getValue());
|
||||
break;
|
||||
}
|
||||
}
|
||||
logger.info("HEADER: signature=" + signature);
|
||||
logger.info("HEADER: metadata=" + metadata);
|
||||
logger.info("HEADER: expires=" + expires);
|
||||
logger.info("HEADER: hostname=" + hostname);
|
||||
logger.info("HEADER: Content-Length=" + contentLength);
|
||||
QueryStringDecoder decoderQuery = new QueryStringDecoder(uri);
|
||||
Map<String, List<String>> uriAttributes = decoderQuery.parameters();
|
||||
uuid = uriAttributes.get("uuid").get(0);
|
||||
@ -136,9 +142,9 @@ public class HttpUploadServerHandler extends SimpleChannelInboundHandler<HttpObj
|
||||
UploadEntity uploadEntity = null;
|
||||
try {
|
||||
// Validate the request here
|
||||
storageResource.validatePostUploadRequest(signature, metadata, expires, hostname, uuid);
|
||||
storageResource.validatePostUploadRequest(signature, metadata, expires, hostname, contentLength, uuid);
|
||||
//create an upload entity. This will fail if entity already exists.
|
||||
uploadEntity = storageResource.createUploadEntity(uuid, metadata);
|
||||
uploadEntity = storageResource.createUploadEntity(uuid, metadata, contentLength);
|
||||
} catch (InvalidParameterValueException ex) {
|
||||
logger.error("post request validation failed", ex);
|
||||
responseContent.append(ex.getMessage());
|
||||
@ -185,9 +191,15 @@ public class HttpUploadServerHandler extends SimpleChannelInboundHandler<HttpObj
|
||||
return;
|
||||
}
|
||||
if (chunk instanceof LastHttpContent) {
|
||||
readFileUploadData();
|
||||
writeResponse(ctx.channel(), HttpResponseStatus.OK);
|
||||
reset();
|
||||
try {
|
||||
readFileUploadData();
|
||||
writeResponse(ctx.channel(), HttpResponseStatus.OK);
|
||||
reset();
|
||||
} catch (InvalidParameterValueException e) {
|
||||
logger.error("error during the file install.", e);
|
||||
responseContent.append("\n").append(e.getMessage());
|
||||
writeResponse(ctx.channel(), HttpResponseStatus.INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2602,7 +2602,7 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S
|
||||
return Script.findScript(scriptsDir, scriptname);
|
||||
}
|
||||
|
||||
public UploadEntity createUploadEntity(String uuid, String metadata) {
|
||||
public UploadEntity createUploadEntity(String uuid, String metadata, long contentLength) {
|
||||
TemplateOrVolumePostUploadCommand cmd = getTemplateOrVolumePostUploadCmd(metadata);
|
||||
UploadEntity uploadEntity = null;
|
||||
if(cmd == null ){
|
||||
@ -2610,10 +2610,16 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S
|
||||
throw new InvalidParameterValueException("unable to decode and deserialize metadata");
|
||||
} else {
|
||||
uuid = cmd.getEntityUUID();
|
||||
if(uploadEntityStateMap.containsKey(uuid)) {
|
||||
if (uploadEntityStateMap.containsKey(uuid)) {
|
||||
uploadEntity = uploadEntityStateMap.get(uuid);
|
||||
throw new InvalidParameterValueException("The one time post url is already used and the upload is in " + uploadEntity.getUploadState() + " state.");
|
||||
}
|
||||
int maxSizeInGB = Integer.valueOf(cmd.getMaxUploadSize());
|
||||
int contentLengthInGB = getSizeInGB(contentLength);
|
||||
if (contentLengthInGB > 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());
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user