Repository: cloudstack Updated Branches: refs/heads/master 569e94908 -> 05c01a7dc
CLOUDSTACK-6941: Can't choose storage for the volume, when attaching uploaded data volume to VM Changes: - Only way to choose a certain storage pool is by using disk_offering_tags - Added a parameter to take in a disk offering Id. - Admin will have to create a custom sized disk offering and tag it as necessary for the user - This custom offering Id should be passed during uploadVolume to associate the volume with this disk offering Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/05c01a7d Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/05c01a7d Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/05c01a7d Branch: refs/heads/master Commit: 05c01a7dc958391c086d7b100a2aa94a98c252d6 Parents: 569e949 Author: Prachi Damle <pra...@cloud.com> Authored: Wed Jun 18 16:09:51 2014 -0700 Committer: Prachi Damle <pra...@cloud.com> Committed: Wed Jun 18 16:37:43 2014 -0700 ---------------------------------------------------------------------- .../command/user/volume/UploadVolumeCmd.java | 8 ++++ .../com/cloud/storage/VolumeApiServiceImpl.java | 44 ++++++++++++++++---- 2 files changed, 44 insertions(+), 8 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cloudstack/blob/05c01a7d/api/src/org/apache/cloudstack/api/command/user/volume/UploadVolumeCmd.java ---------------------------------------------------------------------- diff --git a/api/src/org/apache/cloudstack/api/command/user/volume/UploadVolumeCmd.java b/api/src/org/apache/cloudstack/api/command/user/volume/UploadVolumeCmd.java index 7a08abf..c360c14 100644 --- a/api/src/org/apache/cloudstack/api/command/user/volume/UploadVolumeCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/volume/UploadVolumeCmd.java @@ -25,6 +25,7 @@ import org.apache.cloudstack.api.BaseAsyncCmd; import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.ResponseObject.ResponseView; import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.response.DiskOfferingResponse; import org.apache.cloudstack.api.response.DomainResponse; import org.apache.cloudstack.api.response.ProjectResponse; import org.apache.cloudstack.api.response.VolumeResponse; @@ -89,6 +90,9 @@ public class UploadVolumeCmd extends BaseAsyncCmd { @Parameter(name = ApiConstants.PROJECT_ID, type = CommandType.UUID, entityType = ProjectResponse.class, description = "Upload volume for the project") private Long projectId; + @Parameter(name = ApiConstants.DISK_OFFERING_ID, required = false, type = CommandType.UUID, entityType = DiskOfferingResponse.class, description = "the ID of the disk offering. This must be a custom sized offering since during uploadVolume volume size is unknown.") + private Long diskOfferingId; + ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// @@ -125,6 +129,10 @@ public class UploadVolumeCmd extends BaseAsyncCmd { return imageStoreUuid; } + public Long getDiskOfferingId() { + return diskOfferingId; + } + ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// http://git-wip-us.apache.org/repos/asf/cloudstack/blob/05c01a7d/server/src/com/cloud/storage/VolumeApiServiceImpl.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/storage/VolumeApiServiceImpl.java b/server/src/com/cloud/storage/VolumeApiServiceImpl.java index de46ee3..8a7b220 100644 --- a/server/src/com/cloud/storage/VolumeApiServiceImpl.java +++ b/server/src/com/cloud/storage/VolumeApiServiceImpl.java @@ -247,12 +247,13 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic String volumeName = cmd.getVolumeName(); String url = cmd.getUrl(); String format = cmd.getFormat(); + Long diskOfferingId = cmd.getDiskOfferingId(); String imageStoreUuid = cmd.getImageStoreUuid(); DataStore store = _tmpltMgr.getImageStore(imageStoreUuid, zoneId); - validateVolume(caller, ownerId, zoneId, volumeName, url, format); + validateVolume(caller, ownerId, zoneId, volumeName, url, format, diskOfferingId); - VolumeVO volume = persistVolume(owner, zoneId, volumeName, url, cmd.getFormat()); + VolumeVO volume = persistVolume(owner, zoneId, volumeName, url, cmd.getFormat(), diskOfferingId); VolumeInfo vol = volFactory.getVolume(volume.getId()); @@ -263,13 +264,15 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic return volume; } - private boolean validateVolume(Account caller, long ownerId, Long zoneId, String volumeName, String url, String format) throws ResourceAllocationException { + private boolean validateVolume(Account caller, long ownerId, Long zoneId, String volumeName, String url, + String format, Long diskOfferingId) throws ResourceAllocationException { // permission check - _accountMgr.checkAccess(caller, null, true, _accountMgr.getActiveAccountById(ownerId)); + Account volumeOwner = _accountMgr.getActiveAccountById(ownerId); + _accountMgr.checkAccess(caller, null, true, volumeOwner); // Check that the resource limit for volumes won't be exceeded - _resourceLimitMgr.checkResourceLimit(_accountMgr.getAccount(ownerId), ResourceType.volume); + _resourceLimitMgr.checkResourceLimit(volumeOwner, ResourceType.volume); // Verify that zone exists DataCenterVO zone = _dcDao.findById(zoneId); @@ -316,9 +319,28 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic } UriUtils.validateUrl(url); + // Check that the resource limit for secondary storage won't be exceeded _resourceLimitMgr.checkResourceLimit(_accountMgr.getAccount(ownerId), ResourceType.secondary_storage, UriUtils.getRemoteSize(url)); + // Check that the the disk offering specified is valid + if (diskOfferingId != null) { + DiskOfferingVO diskOffering = _diskOfferingDao.findById(diskOfferingId); + if ((diskOffering == null) || diskOffering.getRemoved() != null + || !DiskOfferingVO.Type.Disk.equals(diskOffering.getType())) { + throw new InvalidParameterValueException("Please specify a valid disk offering."); + } + if (!diskOffering.isCustomized()) { + throw new InvalidParameterValueException("Please specify a custom sized disk offering."); + } + + if (diskOffering.getDomainId() == null) { + // do nothing as offering is public + } else { + _configMgr.checkDiskOfferingAccess(volumeOwner, diskOffering); + } + } + return false; } @@ -327,7 +349,8 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic } @DB - protected VolumeVO persistVolume(final Account owner, final Long zoneId, final String volumeName, final String url, final String format) { + protected VolumeVO persistVolume(final Account owner, final Long zoneId, final String volumeName, final String url, + final String format, final Long diskOfferingId) { return Transaction.execute(new TransactionCallback<VolumeVO>() { @Override public VolumeVO doInTransaction(TransactionStatus status) { @@ -339,8 +362,13 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic // TODO Decide if this is valid or whether throwing a CloudRuntimeException is more appropriate volume.setAccountId((owner == null) ? Account.ACCOUNT_ID_SYSTEM : owner.getAccountId()); volume.setDomainId((owner == null) ? Domain.ROOT_DOMAIN : owner.getDomainId()); - long diskOfferingId = _diskOfferingDao.findByUniqueName("Cloud.com-Custom").getId(); - volume.setDiskOfferingId(diskOfferingId); + + if (diskOfferingId == null) { + long defaultDiskOfferingId = _diskOfferingDao.findByUniqueName("Cloud.com-Custom").getId(); + volume.setDiskOfferingId(defaultDiskOfferingId); + } else { + volume.setDiskOfferingId(diskOfferingId); + } // volume.setSize(size); volume.setInstanceId(null); volume.setUpdated(new Date());