bug 8962: moving vm from one account to other

This commit is contained in:
Abhinandan Prateek 2011-06-09 15:02:47 +05:30
parent 8a4e060dc9
commit 8e4ec4ce09
7 changed files with 164 additions and 2 deletions

View File

@ -0,0 +1,109 @@
/**
* Copyright (C) 2010 Cloud.com, Inc. All rights reserved.
*
* This software is licensed under the GNU General Public License v3 or later.
*
* It is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.cloud.api.commands;
import org.apache.log4j.Logger;
import com.cloud.api.ApiConstants;
import com.cloud.api.BaseAsyncCmd;
import com.cloud.api.BaseCmd;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
import com.cloud.api.ServerApiException;
import com.cloud.api.response.UserVmResponse;
import com.cloud.api.response.ZoneResponse;
import com.cloud.async.AsyncJob;
import com.cloud.event.EventTypes;
import com.cloud.user.Account;
import com.cloud.uservm.UserVm;
@Implementation(description="Move a user VM to another user under same domain.", responseObject=UserVmResponse.class)
public class MoveUserVMCmd extends BaseAsyncCmd {
public static final Logger s_logger = Logger.getLogger(MoveUserVMCmd.class.getName());
private static final String s_name = "moveuservmresponse";
/////////////////////////////////////////////////////
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////
@Parameter(name=ApiConstants.HOST_ID, type=CommandType.LONG, description="the host ID of the system VM to be moved")
private Long hostId;
@Parameter(name=ApiConstants.ACCOUNT_ID, type=CommandType.LONG, description="the accopunt id of the new owner account")
private Long accountId;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
public Long getHostId() {
return hostId;
}
public Long getAccountId() {
return accountId;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
@Override
public String getCommandName() {
return s_name;
}
@Override
public void execute(){
try {
UserVm userVm = _userVmService.moveVMToUser(this);
if (userVm == null){
throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to move vm");
}
UserVmResponse response = _responseGenerator.createUserVmResponse("virtualmachine", userVm).get(0);
response.setResponseName(DeployVMCmd.getResultObjectName());
this.setResponseObject(response);
}catch (Exception e){
e.printStackTrace();
throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to move vm " + e.getMessage());
}
}
@Override
public long getEntityOwnerId() {
UserVm vm = _responseGenerator.findUserVmById(getHostId());
if (vm != null) {
return vm.getAccountId();
}
return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this command to SYSTEM so ERROR events are tracked
}
@Override
public String getEventDescription() {
return "moving user vm: " + getHostId();
}
@Override
public String getEventType() {
return EventTypes.EVENT_VM_MOVE;
}
}

View File

@ -28,8 +28,9 @@ public class EventTypes {
public static final String EVENT_VM_UPDATE = "VM.UPDATE";
public static final String EVENT_VM_UPGRADE = "VM.UPGRADE";
public static final String EVENT_VM_RESETPASSWORD = "VM.RESETPASSWORD";
public static final String EVENT_VM_MIGRATE = "VM.MIGRATE";
public static final String EVENT_VM_MIGRATE = "VM.MIGRATE";
public static final String EVENT_VM_MOVE = "VM.MOVE";
// Domain Router
public static final String EVENT_ROUTER_CREATE = "ROUTER.CREATE";
public static final String EVENT_ROUTER_DESTROY = "ROUTER.DESTROY";

View File

@ -36,5 +36,7 @@ public interface UserVm extends VirtualMachine, ControlledEntity {
void setUserData(String userData);
String getDetail(String name);
void setAccountId(long accountId);
}

View File

@ -29,6 +29,7 @@ import com.cloud.api.commands.DeployVMCmd;
import com.cloud.api.commands.DestroyVMCmd;
import com.cloud.api.commands.DetachVolumeCmd;
import com.cloud.api.commands.ListVMsCmd;
import com.cloud.api.commands.MoveUserVMCmd;
import com.cloud.api.commands.RebootVMCmd;
import com.cloud.api.commands.RecoverVMCmd;
import com.cloud.api.commands.ResetVMPasswordCmd;
@ -369,4 +370,6 @@ public interface UserVmService {
* if the VM to be migrated is not in Running state
*/
UserVm migrateVirtualMachine(UserVm vm, Host destinationHost) throws ResourceUnavailableException, ConcurrentOperationException, ManagementServerException, VirtualMachineMigrationException;
UserVm moveVMToUser(MoveUserVMCmd moveUserVMCmd) throws ResourceAllocationException, ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException ;
}

View File

@ -47,6 +47,7 @@ recoverVirtualMachine=com.cloud.api.commands.RecoverVMCmd;7
listVirtualMachines=com.cloud.api.commands.ListVMsCmd;15
getVMPassword=com.cloud.api.commands.GetVMPasswordCmd;15
migrateVirtualMachine=com.cloud.api.commands.MigrateVMCmd;1
moveVirtualMachine=com.cloud.api.commands.MoveUserVMCmd;15
#### snapshot commands
createSnapshot=com.cloud.api.commands.CreateSnapshotCmd;15

View File

@ -139,5 +139,9 @@ public class UserVmVO extends VMInstanceVO implements UserVm {
public void setDetails(Map<String, String> details) {
this.details = details;
}
public void setAccountId(long accountId){
this.accountId = accountId;
}
}

View File

@ -63,6 +63,7 @@ import com.cloud.api.commands.DeployVMCmd;
import com.cloud.api.commands.DestroyVMCmd;
import com.cloud.api.commands.DetachVolumeCmd;
import com.cloud.api.commands.ListVMsCmd;
import com.cloud.api.commands.MoveUserVMCmd;
import com.cloud.api.commands.RebootVMCmd;
import com.cloud.api.commands.RecoverVMCmd;
import com.cloud.api.commands.ResetVMPasswordCmd;
@ -3200,5 +3201,46 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
UserVmVO migratedVm = _itMgr.migrate((UserVmVO) vm, srcHostId, dest);
return migratedVm;
}
@Override
@ActionEvent(eventType = EventTypes.EVENT_VM_MOVE, eventDescription = "move VM to another user", async = false)
public UserVm moveVMToUser(MoveUserVMCmd cmd) throws ResourceAllocationException, ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException {
//verify the two users
Account oldOwner = UserContext.current().getCaller();
Account newOwner = _accountService.getAccount(cmd.getAccountId());
if (newOwner == null) {
throw new InvalidParameterValueException("Unable to find account " + newOwner + " in domain " + oldOwner.getDomainId());
}
//get the VM
UserVmVO vm = _vmDao.findById(cmd.getHostId());
// update the owner
vm.setAccountId(newOwner.getAccountId());
DomainVO domain = _domainDao.findById(oldOwner.getDomainId());
// check that caller can operate with domain
_accountMgr.checkAccess(oldOwner, domain);
// check that vm owner can create vm in the domain
_accountMgr.checkAccess(newOwner, domain);
// check if account/domain is with in resource limits to create a new vm
if (_accountMgr.resourceLimitExceeded(newOwner, ResourceType.user_vm)) {
ResourceAllocationException rae = new ResourceAllocationException("Maximum number of virtual machines for account: " + newOwner.getAccountName() + " has been exceeded.");
rae.setResourceType("vm");
throw rae;
}
this.stopVirtualMachine(cmd.getHostId(), true);
//update ownership
vm.setAccountId(newOwner.getId());
_vmDao.persist(vm);
this.startVirtualMachine(cmd.getHostId());
return vm;
}
}