Map<VirtualMachineProfile.Param, Object> additionalParams)
throws ConcurrentOperationException, ResourceUnavailableException,
InsufficientCapacityException {
// Input validation
Account callerAccount = CallContext.current().getCallingAccount();
UserVO callerUser = _userDao.findById(CallContext.current()
.getCallingUserId());
// if account is removed, return error
if (callerAccount != null && callerAccount.getRemoved() != null) {
throw new InvalidParameterValueException("The account "
+ callerAccount.getId() + " is removed");
}
UserVmVO vm = _vmDao.findById(vmId);
if (vm == null) {
throw new InvalidParameterValueException(
"unable to find a virtual machine with id " + vmId);
}
_accountMgr.checkAccess(callerAccount, null, true, vm);
Account owner = _accountDao.findById(vm.getAccountId());
if (owner == null) {
throw new InvalidParameterValueException("The owner of " + vm
+ " does not exist: " + vm.getAccountId());
}
if (owner.getState() == Account.State.disabled) {
throw new PermissionDeniedException("The owner of " + vm
+ " is disabled: " + vm.getAccountId());
}
Host destinationHost = null;
if (hostId != null) {
Account account = CallContext.current().getCallingAccount();
if (!_accountService.isRootAdmin(account.getType())) {
throw new PermissionDeniedException(
"Parameter hostid can only be specified by a Root Admin, permission denied");
}
destinationHost = _hostDao.findById(hostId);
if (destinationHost == null) {
throw new InvalidParameterValueException(
"Unable to find the host to deploy the VM, host id="
+ hostId);
}
}
// check if vm is security group enabled
if (_securityGroupMgr.isVmSecurityGroupEnabled(vmId) && _securityGroupMgr.getSecurityGroupsForVm(vmId).isEmpty() && !_securityGroupMgr.isVmMappedToDefaultSecurityGroup(vmId) && _networkModel.canAddDefaultSecurityGroup()) {
// if vm is not mapped to security group, create a mapping
if (s_logger.isDebugEnabled()) {
s_logger.debug("Vm "
+ vm
+ " is security group enabled, but not mapped to default security group; creating the mapping automatically");
}
SecurityGroup defaultSecurityGroup = _securityGroupMgr
.getDefaultSecurityGroup(vm.getAccountId());
if (defaultSecurityGroup != null) {
List<Long> groupList = new ArrayList<Long>();
groupList.add(defaultSecurityGroup.getId());
_securityGroupMgr.addInstanceToGroups(vmId, groupList);
}
}
DataCenterDeployment plan = null;
if (destinationHost != null) {
s_logger.debug("Destination Host to deploy the VM is specified, specifying a deployment plan to deploy the VM");
plan = new DataCenterDeployment(vm.getDataCenterId(),
destinationHost.getPodId(), destinationHost.getClusterId(),
destinationHost.getId(), null, null);
}
// Set parameters
Map<VirtualMachineProfile.Param, Object> params = null;
VMTemplateVO template = null;
if (vm.isUpdateParameters()) {
_vmDao.loadDetails(vm);
// Check that the password was passed in and is valid
template = _templateDao
.findByIdIncludingRemoved(vm.getTemplateId());
String password = "saved_password";
if (template.getEnablePassword()) {
password = generateRandomPassword();
}
if (!validPassword(password)) {
throw new InvalidParameterValueException(
"A valid password for this virtual machine was not provided.");
}
// Check if an SSH key pair was selected for the instance and if so
// use it to encrypt & save the vm password
encryptAndStorePassword(vm, password);
params = new HashMap<VirtualMachineProfile.Param, Object>();
if (additionalParams != null) {
params.putAll(additionalParams);
}
params.put(VirtualMachineProfile.Param.VmPassword, password);
}
VirtualMachineEntity vmEntity = _orchSrvc.getVirtualMachine(vm.getUuid());
// Get serviceOffering for Virtual Machine
ServiceOfferingVO offering = _serviceOfferingDao.findByIdIncludingRemoved(vm.getId(), vm.getServiceOfferingId());
String plannerName = offering.getDeploymentPlanner();
if (plannerName == null) {
if (vm.getHypervisorType() == HypervisorType.BareMetal) {
plannerName = "BareMetalPlanner";
} else {
plannerName = _configDao.getValue(Config.VmDeploymentPlanner.key());
}
}
String reservationId = vmEntity.reserve(plannerName, plan, new ExcludeList(), Long.toString(callerUser.getId()));
vmEntity.deploy(reservationId, Long.toString(callerUser.getId()), params);
Pair<UserVmVO, Map<VirtualMachineProfile.Param, Object>> vmParamPair = new Pair(vm, params);
if (vm != null && vm.isUpdateParameters()) {
// this value is not being sent to the backend; need only for api
// display purposes