|
29 | 29 |
|
30 | 30 | import javax.inject.Inject; |
31 | 31 |
|
| 32 | +import com.cloud.user.AccountService; |
| 33 | +import com.cloud.utils.db.TransactionCallbackNoReturn; |
| 34 | +import org.apache.cloudstack.api.command.user.volume.AssignVolumeCmd; |
32 | 35 | import org.apache.cloudstack.api.command.user.volume.AttachVolumeCmd; |
33 | 36 | import org.apache.cloudstack.api.command.user.volume.CreateVolumeCmd; |
34 | 37 | import org.apache.cloudstack.api.command.user.volume.DetachVolumeCmd; |
@@ -197,6 +200,8 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic |
197 | 200 | @Inject |
198 | 201 | AccountManager _accountMgr; |
199 | 202 | @Inject |
| 203 | + private AccountService _accountService; |
| 204 | + @Inject |
200 | 205 | ConfigurationManager _configMgr; |
201 | 206 | @Inject |
202 | 207 | VolumeDao _volsDao; |
@@ -846,6 +851,85 @@ protected VolumeVO createVolumeFromSnapshot(VolumeVO volume, long snapshotId, Lo |
846 | 851 | return volumeVo; |
847 | 852 | } |
848 | 853 |
|
| 854 | + @Override |
| 855 | + @DB |
| 856 | + @ActionEvent(eventType = EventTypes.EVENT_VOLUME_ASSIGN, eventDescription = "assigning volume", async = false) |
| 857 | + public VolumeVO assignVolume(AssignVolumeCmd cmd) throws ResourceAllocationException { |
| 858 | + // VERIFICATIONS and VALIDATIONS |
| 859 | + |
| 860 | + // Verify the two users |
| 861 | + Account caller = CallContext.current().getCallingAccount(); |
| 862 | + if (!_accountMgr.isRootAdmin(caller.getId()) |
| 863 | + && !_accountMgr.isDomainAdmin(caller.getId())) { // only root and domain admins can assign Volumes |
| 864 | + throw new InvalidParameterValueException("Only domain admins are allowed to assign VMs and not " + caller.getType()); |
| 865 | + } |
| 866 | + |
| 867 | + VolumeVO volume = _volsDao.findById(cmd.getVolumeId()); |
| 868 | + if (volume == null) { |
| 869 | + throw new InvalidParameterValueException("There is no volume by that id " + cmd.getVolumeId()); |
| 870 | + } else if (volume.getInstanceId() != null) { |
| 871 | + throw new InvalidParameterValueException("Volume is currently attached to a vm, detatch first"); |
| 872 | + } else if (volume.getVolumeType() != Volume.Type.DATADISK) { |
| 873 | + throw new InvalidParameterValueException("Only able to assign data volumes"); |
| 874 | + } else if (volume.getState() != Volume.State.Ready && volume.getState() != Volume.State.Allocated) { |
| 875 | + throw new InvalidParameterValueException("Can't assign a volume that is not ready or allocated"); |
| 876 | + } |
| 877 | + |
| 878 | + final Account oldAccount = _accountService.getActiveAccountById(volume.getAccountId()); |
| 879 | + if (oldAccount == null) { |
| 880 | + throw new InvalidParameterValueException("Invalid account for Volume " + volume.getAccountId() + " in domain."); |
| 881 | + } |
| 882 | + final Account newAccount = _accountMgr.finalizeOwner(caller, cmd.getAccountName(), cmd.getDomainId(), cmd.getProjectId()); |
| 883 | + if (newAccount == null) { |
| 884 | + throw new InvalidParameterValueException("Invalid accountid=" + cmd.getAccountName() + " in domain " + cmd.getDomainId()); |
| 885 | + } |
| 886 | + |
| 887 | + if (newAccount.getState() == Account.State.disabled) { |
| 888 | + throw new InvalidParameterValueException("The new account owner " + cmd.getAccountName() + " is disabled."); |
| 889 | + } |
| 890 | + |
| 891 | + // Check caller has access to both the old and new account |
| 892 | + _accountMgr.checkAccess(caller, null, true, oldAccount); |
| 893 | + _accountMgr.checkAccess(caller, null, true, newAccount); |
| 894 | + |
| 895 | + // Make sure the accounts are not same |
| 896 | + if (oldAccount.getAccountId() == newAccount.getAccountId()) { |
| 897 | + throw new InvalidParameterValueException("The new account is the same as the old account. Account id =" + oldAccount.getAccountId()); |
| 898 | + } |
| 899 | + |
| 900 | + List<SnapshotVO> snapshots = _snapshotDao.listByStatusNotIn(volume.getId(), Snapshot.State.Destroyed,Snapshot.State.Error); |
| 901 | + if (snapshots != null && snapshots.size() > 0) { |
| 902 | + throw new InvalidParameterValueException( |
| 903 | + "Snapshots exists for volume: "+ volume.getName()+ ", remove snapshots for volume before assigning to another user."); |
| 904 | + } |
| 905 | + |
| 906 | + // Check if volume and primary storage space are with in resource limits |
| 907 | + _resourceLimitMgr.checkResourceLimit(newAccount, ResourceType.volume, 1); |
| 908 | + _resourceLimitMgr.checkResourceLimit(newAccount, ResourceType.primary_storage, volume.getSize()); |
| 909 | + |
| 910 | + Transaction.execute(new TransactionCallbackNoReturn() { |
| 911 | + @Override |
| 912 | + public void doInTransactionWithoutResult(TransactionStatus status) { |
| 913 | + UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_DELETE, volume.getAccountId(), volume.getDataCenterId(), volume.getId(), volume.getName(), |
| 914 | + Volume.class.getName(), volume.getUuid(), volume.isDisplayVolume()); |
| 915 | + _resourceLimitMgr.decrementResourceCount(oldAccount.getAccountId(), ResourceType.volume); |
| 916 | + _resourceLimitMgr.decrementResourceCount(oldAccount.getAccountId(), ResourceType.primary_storage, volume.getSize()); |
| 917 | + volume.setAccountId(newAccount.getAccountId()); |
| 918 | + volume.setDomainId(newAccount.getDomainId()); |
| 919 | + _volsDao.persist(volume); |
| 920 | + _resourceLimitMgr.incrementResourceCount(newAccount.getAccountId(), ResourceType.volume); |
| 921 | + _resourceLimitMgr.incrementResourceCount(newAccount.getAccountId(), ResourceType.primary_storage, volume.getSize()); |
| 922 | + UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_CREATE, volume.getAccountId(), volume.getDataCenterId(), volume.getId(), volume.getName(), |
| 923 | + volume.getDiskOfferingId(), volume.getTemplateId(), volume.getSize(), Volume.class.getName(), |
| 924 | + volume.getUuid(), volume.isDisplayVolume()); |
| 925 | + } |
| 926 | + }); |
| 927 | + |
| 928 | + s_logger.info("AssignVolume: volume " + volume.getName() + " now belongs to account " + newAccount.getAccountName()); |
| 929 | + |
| 930 | + return volume; |
| 931 | + } |
| 932 | + |
849 | 933 | @Override |
850 | 934 | @DB |
851 | 935 | @ActionEvent(eventType = EventTypes.EVENT_VOLUME_RESIZE, eventDescription = "resizing volume", async = true) |
|
0 commit comments