createTemplate/createSnapshot for project - allow to execute for Projects in Active state only

This commit is contained in:
Alena Prokharchyk 2011-12-19 16:20:10 -08:00
parent e081dd3c91
commit ceb0a918a1
26 changed files with 95 additions and 72 deletions

View File

@ -35,6 +35,7 @@ import com.cloud.domain.Domain;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.PermissionDeniedException;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.network.NetworkService;
@ -459,7 +460,7 @@ public abstract class BaseCmd {
return this.fullUrlParams;
}
public Long getAccountId(String accountName, Long domainId, Long projectId, boolean enabledOnly) {
public Long finalyzeAccountId(String accountName, Long domainId, Long projectId, boolean enabledOnly) {
if (accountName != null) {
if (domainId == null) {
throw new InvalidParameterValueException("Account must be specified with domainId parameter");
@ -475,7 +476,7 @@ public abstract class BaseCmd {
if (!enabledOnly || account.getState() == Account.State.enabled) {
return account.getId();
} else {
throw new InvalidParameterValueException("Can't add resources to the account id=" + account.getId() + " in state=" + account.getState() + " as it's no longer active");
throw new PermissionDeniedException("Can't add resources to the account id=" + account.getId() + " in state=" + account.getState() + " as it's no longer active");
}
} else {
throw new InvalidParameterValueException("Unable to find account by name " + accountName + " in domain id=" + domainId);
@ -488,14 +489,12 @@ public abstract class BaseCmd {
if (!enabledOnly || project.getState() == Project.State.Active) {
return project.getProjectAccountId();
} else {
throw new InvalidParameterValueException("Can't add resources to the project id=" + projectId + " in state=" + project.getState() + " as it's no longer active");
throw new PermissionDeniedException("Can't add resources to the project id=" + projectId + " in state=" + project.getState() + " as it's no longer active");
}
} else {
throw new InvalidParameterValueException("Unable to find project by id " + projectId);
}
}
return null;
}
}

View File

@ -96,7 +96,7 @@ public class AddVpnUserCmd extends BaseAsyncCreateCmd {
@Override
public long getEntityOwnerId() {
Long accountId = getAccountId(accountName, domainId, projectId, true);
Long accountId = finalyzeAccountId(accountName, domainId, projectId, true);
if (accountId == null) {
return UserContext.current().getCaller().getId();
}

View File

@ -129,7 +129,7 @@ public class AssociateIPAddrCmd extends BaseAsyncCreateCmd {
@Override
public long getEntityOwnerId() {
Long accountId = getAccountId(accountName, domainId, projectId, true);
Long accountId = finalyzeAccountId(accountName, domainId, projectId, true);
if (accountId == null) {
return UserContext.current().getCaller().getId();
}

View File

@ -164,7 +164,7 @@ public class AuthorizeSecurityGroupEgressCmd extends BaseAsyncCmd {
@Override
public long getEntityOwnerId() {
Long accountId = getAccountId(accountName, domainId, projectId, true);
Long accountId = finalyzeAccountId(accountName, domainId, projectId, true);
if (accountId == null) {
return UserContext.current().getCaller().getId();
}

View File

@ -166,7 +166,7 @@ public class AuthorizeSecurityGroupIngressCmd extends BaseAsyncCmd {
@Override
public long getEntityOwnerId() {
Long accountId = getAccountId(accountName, domainId, projectId, true);
Long accountId = finalyzeAccountId(accountName, domainId, projectId, true);
if (accountId == null) {
return UserContext.current().getCaller().getId();
}

View File

@ -199,7 +199,7 @@ public class CreateNetworkCmd extends BaseCmd {
@Override
public long getEntityOwnerId() {
Long accountId = getAccountId(accountName, domainId, projectId, true);
Long accountId = finalyzeAccountId(accountName, domainId, projectId, true);
if (accountId == null) {
return UserContext.current().getCaller().getId();
}

View File

@ -80,7 +80,7 @@ public class CreateSSHKeyPairCmd extends BaseCmd {
/////////////////////////////////////////////////////
@Override
public long getEntityOwnerId() {
Long accountId = getAccountId(accountName, domainId, projectId, true);
Long accountId = finalyzeAccountId(accountName, domainId, projectId, true);
if (accountId == null) {
return UserContext.current().getCaller().getId();
}

View File

@ -30,7 +30,10 @@ import com.cloud.api.ServerApiException;
import com.cloud.api.response.SnapshotResponse;
import com.cloud.async.AsyncJob;
import com.cloud.event.EventTypes;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.PermissionDeniedException;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.projects.Project;
import com.cloud.storage.Snapshot;
import com.cloud.storage.Volume;
import com.cloud.user.Account;
@ -103,13 +106,29 @@ public class CreateSnapshotCmd extends BaseAsyncCreateCmd {
@Override
public long getEntityOwnerId() {
Volume volume = _entityMgr.findById(Volume.class, getVolumeId());
if (volume != null) {
return volume.getAccountId();
}
Long volumeId = getVolumeId();
Long accountId = null;
// bad id given, parent this command to SYSTEM so ERROR events are tracked
return Account.ACCOUNT_ID_SYSTEM;
Volume volume = _entityMgr.findById(Volume.class, volumeId);
if (volume != null) {
accountId = volume.getAccountId();
} else {
throw new InvalidParameterValueException("Unable to find volume by id=" + volumeId);
}
Account account = _accountService.getAccount(accountId);
//Can create templates for enabled projects/accounts only
if (account.getType() == Account.ACCOUNT_TYPE_PROJECT) {
Project project = _projectService.findByProjectAccountId(accountId);
if (project.getState() != Project.State.Active) {
throw new PermissionDeniedException("Can't add resources to the project id=" + project.getId() + " in state=" + project.getState() + " as it's no longer active");
}
} else if (account.getState() == Account.State.disabled) {
throw new PermissionDeniedException("The owner of template is disabled: " + account);
}
return accountId;
}
@Override
@ -140,7 +159,7 @@ public class CreateSnapshotCmd extends BaseAsyncCreateCmd {
@Override
public void execute() {
UserContext.current().setEventDetails("Volume Id: "+getVolumeId());
Snapshot snapshot = _snapshotService.createSnapshot(getVolumeId(), getPolicyId(), getEntityId());
Snapshot snapshot = _snapshotService.createSnapshot(getVolumeId(), getPolicyId(), getEntityId(), _accountService.getAccount(getEntityOwnerId()));
if (snapshot != null) {
SnapshotResponse response = _responseGenerator.createSnapshotResponse(snapshot);
response.setResponseName(getCommandName());

View File

@ -35,7 +35,10 @@ import com.cloud.api.response.StoragePoolResponse;
import com.cloud.api.response.TemplateResponse;
import com.cloud.async.AsyncJob;
import com.cloud.event.EventTypes;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.PermissionDeniedException;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.projects.Project;
import com.cloud.storage.Snapshot;
import com.cloud.storage.Volume;
import com.cloud.template.VirtualMachineTemplate;
@ -185,20 +188,35 @@ import com.cloud.user.UserContext;
public long getEntityOwnerId() {
Long volumeId = getVolumeId();
Long snapshotId = getSnapshotId();
Long accountId = null;
if (volumeId != null) {
Volume volume = _entityMgr.findById(Volume.class, volumeId);
if (volume != null) {
return volume.getAccountId();
accountId = volume.getAccountId();
} else {
throw new InvalidParameterValueException("Unable to find volume by id=" + volumeId);
}
} else {
Snapshot snapshot = _entityMgr.findById(Snapshot.class, snapshotId);
if (snapshot != null) {
return snapshot.getAccountId();
accountId = snapshot.getAccountId();
} else {
throw new InvalidParameterValueException("Unable to find snapshot by id=" + snapshotId);
}
}
// bad id given, parent this command to SYSTEM so ERROR events are tracked
return Account.ACCOUNT_ID_SYSTEM;
Account account = _accountService.getAccount(accountId);
//Can create templates for enabled projects/accounts only
if (account.getType() == Account.ACCOUNT_TYPE_PROJECT) {
Project project = _projectService.findByProjectAccountId(accountId);
if (project.getState() != Project.State.Active) {
throw new PermissionDeniedException("Can't add resources to the project id=" + project.getId() + " in state=" + project.getState() + " as it's no longer active");
}
} else if (account.getState() == Account.State.disabled) {
throw new PermissionDeniedException("The owner of template is disabled: " + account);
}
return accountId;
}
@Override
@ -223,13 +241,12 @@ import com.cloud.user.UserContext;
@Override
public void create() throws ResourceAllocationException {
if (isBareMetal()) {
_bareMetalVmService.createPrivateTemplateRecord(this);
_bareMetalVmService.createPrivateTemplateRecord(this, _accountService.getAccount(getEntityOwnerId()));
/*Baremetal creates template record after taking image proceeded, use vmId as entity id here*/
this.setEntityId(vmId);
} else {
VirtualMachineTemplate template = null;
template = _userVmService.createPrivateTemplateRecord(this);
template = _userVmService.createPrivateTemplateRecord(this, _accountService.getAccount(getEntityOwnerId()));
if (template != null) {
this.setEntityId(template.getId());
} else {

View File

@ -84,7 +84,7 @@ public class CreateVMGroupCmd extends BaseCmd{
@Override
public long getEntityOwnerId() {
Long accountId = getAccountId(accountName, domainId, projectId, true);
Long accountId = finalyzeAccountId(accountName, domainId, projectId, true);
if (accountId == null) {
return UserContext.current().getCaller().getId();
}

View File

@ -131,7 +131,7 @@ public class CreateVolumeCmd extends BaseAsyncCreateCmd {
@Override
public long getEntityOwnerId() {
Long accountId = getAccountId(accountName, domainId, projectId, true);
Long accountId = finalyzeAccountId(accountName, domainId, projectId, true);
if (accountId == null) {
return UserContext.current().getCaller().getId();
}

View File

@ -89,7 +89,7 @@ public class DeleteSecurityGroupCmd extends BaseCmd {
@Override
public long getEntityOwnerId() {
Long accountId = getAccountId(accountName, domainId, projectId, true);
Long accountId = finalyzeAccountId(accountName, domainId, projectId, true);
if (accountId == null) {
return UserContext.current().getCaller().getId();
}

View File

@ -281,7 +281,7 @@ public class DeployVMCmd extends BaseAsyncCreateCmd {
@Override
public long getEntityOwnerId() {
Long accountId = getAccountId(accountName, domainId, projectId, true);
Long accountId = finalyzeAccountId(accountName, domainId, projectId, true);
if (accountId == null) {
return UserContext.current().getCaller().getId();
}

View File

@ -94,7 +94,7 @@ public class ListResourceLimitsCmd extends BaseListCmd {
@Override
public void execute(){
List<? extends ResourceLimit> result = _resourceLimitService.searchForLimits(id, getAccountId(accountName, domainId, projectId, false), domainId, resourceType, this.getStartIndex(), this.getPageSizeVal());
List<? extends ResourceLimit> result = _resourceLimitService.searchForLimits(id, finalyzeAccountId(accountName, domainId, projectId, false), domainId, resourceType, this.getStartIndex(), this.getPageSizeVal());
ListResponse<ResourceLimitResponse> response = new ListResponse<ResourceLimitResponse>();
List<ResourceLimitResponse> limitResponses = new ArrayList<ResourceLimitResponse>();
for (ResourceLimit limit : result) {

View File

@ -152,7 +152,7 @@ public class RegisterIsoCmd extends BaseCmd {
@Override
public long getEntityOwnerId() {
Long accountId = getAccountId(accountName, domainId, projectId, true);
Long accountId = finalyzeAccountId(accountName, domainId, projectId, true);
if (accountId == null) {
return UserContext.current().getCaller().getId();
}

View File

@ -87,7 +87,7 @@ public class RegisterSSHKeyPairCmd extends BaseCmd {
@Override
public long getEntityOwnerId() {
Long accountId = getAccountId(accountName, domainId, projectId, true);
Long accountId = finalyzeAccountId(accountName, domainId, projectId, true);
if (accountId == null) {
return UserContext.current().getCaller().getId();
}

View File

@ -213,7 +213,7 @@ public class RegisterTemplateCmd extends BaseCmd {
@Override
public long getEntityOwnerId() {
Long accountId = getAccountId(accountName, domainId, projectId, true);
Long accountId = finalyzeAccountId(accountName, domainId, projectId, true);
if (accountId == null) {
return UserContext.current().getCaller().getId();
}

View File

@ -88,7 +88,7 @@ public class RemoveVpnUserCmd extends BaseAsyncCmd {
@Override
public long getEntityOwnerId() {
Long accountId = getAccountId(accountName, domainId, projectId, true);
Long accountId = finalyzeAccountId(accountName, domainId, projectId, true);
if (accountId == null) {
return UserContext.current().getCaller().getId();
}

View File

@ -112,7 +112,7 @@ public class UpdateResourceCountCmd extends BaseCmd {
@Override
public void execute(){
List<? extends ResourceCount> result = _resourceLimitService.recalculateResourceCount(getAccountId(accountName, domainId, projectId, true), getDomainId(), getResourceType());
List<? extends ResourceCount> result = _resourceLimitService.recalculateResourceCount(finalyzeAccountId(accountName, domainId, projectId, true), getDomainId(), getResourceType());
if ((result != null) && (result.size()>0)){
ListResponse<ResourceCountResponse> response = new ListResponse<ResourceCountResponse>();

View File

@ -89,7 +89,7 @@ public class UpdateResourceLimitCmd extends BaseCmd {
@Override
public long getEntityOwnerId() {
Long accountId = getAccountId(accountName, domainId, projectId, true);
Long accountId = finalyzeAccountId(accountName, domainId, projectId, true);
if (accountId == null) {
return UserContext.current().getCaller().getId();
}
@ -99,7 +99,7 @@ public class UpdateResourceLimitCmd extends BaseCmd {
@Override
public void execute(){
ResourceLimit result = _resourceLimitService.updateResourceLimit(getAccountId(accountName, domainId, projectId, true), getDomainId(), resourceType, max);
ResourceLimit result = _resourceLimitService.updateResourceLimit(finalyzeAccountId(accountName, domainId, projectId, true), getDomainId(), resourceType, max);
if (result != null || (result == null && max != null && max.longValue() == -1L)){
ResourceLimitResponse response = _responseGenerator.createResourceLimitResponse(result);
response.setResponseName(getCommandName());

View File

@ -27,6 +27,7 @@ import com.cloud.api.commands.ListSnapshotsCmd;
import com.cloud.exception.PermissionDeniedException;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.storage.Snapshot;
import com.cloud.user.Account;
public interface SnapshotService {
@ -82,10 +83,11 @@ public interface SnapshotService {
/**
* Create a snapshot of a volume
*
* @param snapshotOwner TODO
* @param cmd
* the API command wrapping the parameters for creating the snapshot (mainly volumeId)
*
* @return the Snapshot that was created
*/
Snapshot createSnapshot(Long volumeId, Long policyId, Long snapshotId);
Snapshot createSnapshot(Long volumeId, Long policyId, Long snapshotId, Account snapshotOwner);
}

View File

@ -123,10 +123,11 @@ public interface UserVmService {
* @param cmd
* the command object that defines the name, display text, snapshot/volume, bits, public/private, etc. for the
* private template
* @param templateOwner TODO
* @return the vm template object if successful, null otherwise
* @throws ResourceAllocationException
*/
VirtualMachineTemplate createPrivateTemplateRecord(CreateTemplateCmd cmd) throws ResourceAllocationException;
VirtualMachineTemplate createPrivateTemplateRecord(CreateTemplateCmd cmd, Account templateOwner) throws ResourceAllocationException;
/**
* Creates a private template from a snapshot of a VM

View File

@ -140,7 +140,7 @@ public class BareMetalVmManagerImpl extends UserVmManagerImpl implements BareMet
}
@Override
public VMTemplateVO createPrivateTemplateRecord(CreateTemplateCmd cmd) throws ResourceAllocationException {
public VMTemplateVO createPrivateTemplateRecord(CreateTemplateCmd cmd, Account templateOwner) throws ResourceAllocationException {
/*Baremetal creates record after host rebooting for imaging, in createPrivateTemplate*/
return null;
}

View File

@ -117,7 +117,6 @@ import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.Transaction;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.fsm.NoTransitionException;
import com.cloud.vm.UserVmVO;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VirtualMachine.State;
@ -369,14 +368,12 @@ public class SnapshotManagerImpl implements SnapshotManager, SnapshotService, Ma
@Override
@DB
@ActionEvent(eventType = EventTypes.EVENT_SNAPSHOT_CREATE, eventDescription = "creating snapshot", async = true)
public SnapshotVO createSnapshot(Long volumeId, Long policyId, Long snapshotId) {
VolumeVO volume = _volsDao.findById(volumeId);
public SnapshotVO createSnapshot(Long volumeId, Long policyId, Long snapshotId, Account snapshotOwner) {
VolumeVO volume = _volsDao.findById(volumeId);
if (volume == null) {
throw new InvalidParameterValueException("No such volume exist");
}
Account owner = _accountMgr.getAccount(volume.getAccountId());
SnapshotVO snapshot = null;
boolean backedUp = false;
@ -481,7 +478,7 @@ public class SnapshotManagerImpl implements SnapshotManager, SnapshotService, Ma
snapshot.setStatus(Status.Error);
_snapshotDao.update(snapshot.getId(), snapshot);
} else {
_resourceLimitMgr.incrementResourceCount(owner.getId(), ResourceType.snapshot);
_resourceLimitMgr.incrementResourceCount(snapshotOwner.getId(), ResourceType.snapshot);
}
} else {
snapshot = _snapshotDao.findById(snapshotId);

View File

@ -1287,19 +1287,13 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
@Override
@ActionEvent(eventType = EventTypes.EVENT_TEMPLATE_CREATE, eventDescription = "creating template", create = true)
public VMTemplateVO createPrivateTemplateRecord(CreateTemplateCmd cmd) throws ResourceAllocationException {
public VMTemplateVO createPrivateTemplateRecord(CreateTemplateCmd cmd, Account templateOwner) throws ResourceAllocationException {
Long userId = UserContext.current().getCallerUserId();
Account caller = UserContext.current().getCaller();
boolean isAdmin = ((caller == null) || isAdmin(caller.getType()));
boolean isAdmin = (isAdmin(caller.getType()));
VMTemplateVO privateTemplate = null;
UserVO user = _userDao.findById(userId);
if (user == null) {
throw new InvalidParameterValueException("User " + userId + " does not exist");
}
_accountMgr.checkAccess(caller, null, templateOwner);
String name = cmd.getTemplateName();
if ((name == null) || (name.length() > 32)) {
@ -1307,7 +1301,7 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
}
if(cmd.getTemplateTag() != null){
if(!_accountService.isRootAdmin(caller.getType())){
if (!_accountService.isRootAdmin(caller.getType())){
throw new PermissionDeniedException("Parameter templatetag can only be specified by a Root Admin, permission denied");
}
}
@ -1338,10 +1332,9 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
throw new InvalidParameterValueException("Failed to create private template record, please specify only one of volume ID (" + volumeId + ") and snapshot ID (" + snapshotId + ")");
}
long domainId;
long accountId;
HypervisorType hyperType;
VolumeVO volume = null;
VMTemplateVO privateTemplate = null;
if (volumeId != null) { // create template from volume
volume = _volsDao.findById(volumeId);
if (volume == null) {
@ -1359,17 +1352,15 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
}
throw new CloudRuntimeException(msg);
}
domainId = volume.getDomainId();
accountId = volume.getAccountId();
hyperType = _volsDao.getHypervisorType(volumeId);
} else { // create template from snapshot
SnapshotVO snapshot = _snapshotDao.findById(snapshotId);
volume = _volsDao.findById(snapshot.getVolumeId());
VolumeVO snapshotVolume = _volsDao.findByIdIncludingRemoved(snapshot.getVolumeId());
if (snapshot == null) {
throw new InvalidParameterValueException("Failed to create private template record, unable to find snapshot " + snapshotId);
}
volume = _volsDao.findById(snapshot.getVolumeId());
VolumeVO snapshotVolume = _volsDao.findByIdIncludingRemoved(snapshot.getVolumeId());
//check permissions
_accountMgr.checkAccess(caller, null, snapshot);
@ -1383,13 +1374,10 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
throw new UnsupportedServiceException("operation not supported, snapshot with id " + snapshotId + " is created from Data Disk");
}
domainId = snapshot.getDomainId();
accountId = snapshot.getAccountId();
hyperType = snapshot.getHypervisorType();
}
AccountVO ownerAccount = _accountDao.findById(accountId);
_resourceLimitMgr.checkResourceLimit(ownerAccount, ResourceType.template);
_resourceLimitMgr.checkResourceLimit(templateOwner, ResourceType.template);
if (!isAdmin || featured == null) {
featured = Boolean.FALSE;
@ -1421,7 +1409,7 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
s_logger.debug("Adding template tag: "+templateTag);
}
}
privateTemplate = new VMTemplateVO(nextTemplateId, uniqueName, name, ImageFormat.RAW, isPublic, featured, isExtractable, TemplateType.USER, null, null, requiresHvmValue, bitsValue, accountId,
privateTemplate = new VMTemplateVO(nextTemplateId, uniqueName, name, ImageFormat.RAW, isPublic, featured, isExtractable, TemplateType.USER, null, null, requiresHvmValue, bitsValue, templateOwner.getId(),
null, description, passwordEnabledValue, guestOS.getId(), true, hyperType, templateTag, cmd.getDetails());
if(sourceTemplateId != null){
if(s_logger.isDebugEnabled()){
@ -1437,7 +1425,7 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
_templateDetailsDao.persist(template.getId(), cmd.getDetails());
}
_resourceLimitMgr.incrementResourceCount(accountId, ResourceType.template);
_resourceLimitMgr.incrementResourceCount(templateOwner.getId(), ResourceType.template);
}
if (template != null){

View File

@ -260,7 +260,7 @@ public class MockUserVmManagerImpl implements UserVmManager, UserVmService, Mana
}
@Override
public VirtualMachineTemplate createPrivateTemplateRecord(CreateTemplateCmd cmd) throws ResourceAllocationException {
public VirtualMachineTemplate createPrivateTemplateRecord(CreateTemplateCmd cmd, Account templateOwner) throws ResourceAllocationException {
// TODO Auto-generated method stub
return null;
}