4949import org .apache .cloudstack .api .ApiConstants ;
5050import org .apache .cloudstack .api .BaseCmd .HTTPMethod ;
5151import org .apache .cloudstack .api .command .admin .vm .AssignVMCmd ;
52+ import org .apache .cloudstack .api .command .admin .vm .DeployVMCmdByAdmin ;
5253import org .apache .cloudstack .api .command .admin .vm .RecoverVMCmd ;
5354import org .apache .cloudstack .api .command .user .vm .AddNicToVMCmd ;
5455import org .apache .cloudstack .api .command .user .vm .DeployVMCmd ;
136137import com .cloud .dc .DataCenterVO ;
137138import com .cloud .dc .DedicatedResourceVO ;
138139import com .cloud .dc .HostPodVO ;
140+ import com .cloud .dc .Pod ;
139141import com .cloud .dc .Vlan ;
140142import com .cloud .dc .Vlan .VlanType ;
141143import com .cloud .dc .VlanVO ;
@@ -2755,7 +2757,7 @@ protected boolean applyUserData(HypervisorType hyperVisorType, UserVm vm, Nic ni
27552757 @ Override
27562758 @ ActionEvent (eventType = EventTypes .EVENT_VM_START , eventDescription = "starting Vm" , async = true )
27572759 public UserVm startVirtualMachine (StartVMCmd cmd ) throws ExecutionException , ConcurrentOperationException , ResourceUnavailableException , InsufficientCapacityException {
2758- return startVirtualMachine (cmd .getId (), cmd .getHostId (), null , cmd .getDeploymentPlanner ()).first ();
2760+ return startVirtualMachine (cmd .getId (), cmd .getPodId (), cmd . getClusterId (), cmd . getHostId (), null , cmd .getDeploymentPlanner ()).first ();
27592761 }
27602762
27612763 @ Override
@@ -4144,20 +4146,27 @@ protected String validateUserData(String userData, HTTPMethod httpmethod) {
41444146 @ Override
41454147 @ ActionEvent (eventType = EventTypes .EVENT_VM_CREATE , eventDescription = "starting Vm" , async = true )
41464148 public UserVm startVirtualMachine (DeployVMCmd cmd ) throws ResourceUnavailableException , InsufficientCapacityException , ConcurrentOperationException {
4147- return startVirtualMachine (cmd , null , cmd .getDeploymentPlanner ());
4149+ long vmId = cmd .getEntityId ();
4150+ Long podId = null ;
4151+ Long clusterId = null ;
4152+ Long hostId = cmd .getHostId ();
4153+ Map <Long , DiskOffering > diskOfferingMap = cmd .getDataDiskTemplateToDiskOfferingMap ();
4154+ if (cmd instanceof DeployVMCmdByAdmin ) {
4155+ DeployVMCmdByAdmin adminCmd = (DeployVMCmdByAdmin )cmd ;
4156+ podId = adminCmd .getPodId ();
4157+ clusterId = adminCmd .getClusterId ();
4158+ }
4159+ return startVirtualMachine (vmId , podId , clusterId , hostId , diskOfferingMap , null , cmd .getDeploymentPlanner ());
41484160 }
41494161
4150- private UserVm startVirtualMachine (DeployVMCmd cmd , Map <VirtualMachineProfile .Param , Object > additonalParams , String deploymentPlannerToUse )
4162+ private UserVm startVirtualMachine (long vmId , Long podId , Long clusterId , Long hostId , Map < Long , DiskOffering > diskOfferingMap , Map <VirtualMachineProfile .Param , Object > additonalParams , String deploymentPlannerToUse )
41514163 throws ResourceUnavailableException ,
41524164 InsufficientCapacityException , ConcurrentOperationException {
4153-
4154- long vmId = cmd .getEntityId ();
4155- Long hostId = cmd .getHostId ();
41564165 UserVmVO vm = _vmDao .findById (vmId );
4157-
41584166 Pair <UserVmVO , Map <VirtualMachineProfile .Param , Object >> vmParamPair = null ;
4167+
41594168 try {
4160- vmParamPair = startVirtualMachine (vmId , hostId , additonalParams , deploymentPlannerToUse );
4169+ vmParamPair = startVirtualMachine (vmId , podId , clusterId , hostId , additonalParams , deploymentPlannerToUse );
41614170 vm = vmParamPair .first ();
41624171
41634172 // At this point VM should be in "Running" state
@@ -4169,7 +4178,7 @@ private UserVm startVirtualMachine(DeployVMCmd cmd, Map<VirtualMachineProfile.Pa
41694178 }
41704179
41714180 try {
4172- if (!cmd . getDataDiskTemplateToDiskOfferingMap () .isEmpty ()) {
4181+ if (!diskOfferingMap .isEmpty ()) {
41734182 List <VolumeVO > vols = _volsDao .findByInstance (tmpVm .getId ());
41744183 for (VolumeVO vol : vols ) {
41754184 if (vol .getVolumeType () == Volume .Type .DATADISK ) {
@@ -4488,8 +4497,14 @@ public void finalizeStop(VirtualMachineProfile profile, Answer answer) {
44884497 @ Override
44894498 public Pair <UserVmVO , Map <VirtualMachineProfile .Param , Object >> startVirtualMachine (long vmId , Long hostId , Map <VirtualMachineProfile .Param , Object > additionalParams , String deploymentPlannerToUse )
44904499 throws ConcurrentOperationException , ResourceUnavailableException , InsufficientCapacityException {
4500+ return startVirtualMachine (vmId , null , null , hostId , additionalParams , deploymentPlannerToUse );
4501+ }
4502+
4503+ @ Override
4504+ public Pair <UserVmVO , Map <VirtualMachineProfile .Param , Object >> startVirtualMachine (long vmId , Long podId , Long clusterId , Long hostId , Map <VirtualMachineProfile .Param , Object > additionalParams , String deploymentPlannerToUse )
4505+ throws ConcurrentOperationException , ResourceUnavailableException , InsufficientCapacityException {
44914506 // Input validation
4492- Account callerAccount = CallContext .current ().getCallingAccount ();
4507+ final Account callerAccount = CallContext .current ().getCallingAccount ();
44934508 UserVO callerUser = _userDao .findById (CallContext .current ().getCallingUserId ());
44944509
44954510 // if account is removed, return error
@@ -4514,19 +4529,6 @@ public Pair<UserVmVO, Map<VirtualMachineProfile.Param, Object>> startVirtualMach
45144529 throw new PermissionDeniedException ("The owner of " + vm + " is disabled: " + vm .getAccountId ());
45154530 }
45164531
4517- Host destinationHost = null ;
4518- if (hostId != null ) {
4519- Account account = CallContext .current ().getCallingAccount ();
4520- if (!_accountService .isRootAdmin (account .getId ())) {
4521- throw new PermissionDeniedException (
4522- "Parameter hostid can only be specified by a Root Admin, permission denied" );
4523- }
4524- destinationHost = _hostDao .findById (hostId );
4525- if (destinationHost == null ) {
4526- throw new InvalidParameterValueException ("Unable to find the host to deploy the VM, host id=" + hostId );
4527- }
4528- }
4529-
45304532 // check if vm is security group enabled
45314533 if (_securityGroupMgr .isVmSecurityGroupEnabled (vmId ) && _securityGroupMgr .getSecurityGroupsForVm (vmId ).isEmpty ()
45324534 && !_securityGroupMgr .isVmMappedToDefaultSecurityGroup (vmId ) && _networkModel .canAddDefaultSecurityGroup ()) {
@@ -4542,7 +4544,13 @@ public Pair<UserVmVO, Map<VirtualMachineProfile.Param, Object>> startVirtualMach
45424544 _securityGroupMgr .addInstanceToGroups (vmId , groupList );
45434545 }
45444546 }
4545-
4547+ // Choose deployment planner
4548+ // Host takes 1st preference, Cluster takes 2nd preference and Pod takes 3rd
4549+ // Default behaviour is invoked when host, cluster or pod are not specified
4550+ boolean isRootAdmin = _accountService .isRootAdmin (callerAccount .getId ());
4551+ Pod destinationPod = getDestinationPod (podId , isRootAdmin );
4552+ Cluster destinationCluster = getDestinationCluster (clusterId , isRootAdmin );
4553+ Host destinationHost = getDestinationHost (hostId , isRootAdmin );
45464554 DataCenterDeployment plan = null ;
45474555 boolean deployOnGivenHost = false ;
45484556 if (destinationHost != null ) {
@@ -4551,6 +4559,18 @@ public Pair<UserVmVO, Map<VirtualMachineProfile.Param, Object>> startVirtualMach
45514559 if (!AllowDeployVmIfGivenHostFails .value ()) {
45524560 deployOnGivenHost = true ;
45534561 }
4562+ } else if (destinationCluster != null ) {
4563+ s_logger .debug ("Destination Cluster to deploy the VM is specified, specifying a deployment plan to deploy the VM" );
4564+ plan = new DataCenterDeployment (vm .getDataCenterId (), destinationCluster .getPodId (), destinationCluster .getId (), null , null , null );
4565+ if (!AllowDeployVmIfGivenHostFails .value ()) {
4566+ deployOnGivenHost = true ;
4567+ }
4568+ } else if (destinationPod != null ) {
4569+ s_logger .debug ("Destination Pod to deploy the VM is specified, specifying a deployment plan to deploy the VM" );
4570+ plan = new DataCenterDeployment (vm .getDataCenterId (), destinationPod .getId (), null , null , null , null );
4571+ if (!AllowDeployVmIfGivenHostFails .value ()) {
4572+ deployOnGivenHost = true ;
4573+ }
45544574 }
45554575
45564576 // Set parameters
@@ -4617,6 +4637,51 @@ public Pair<UserVmVO, Map<VirtualMachineProfile.Param, Object>> startVirtualMach
46174637 return vmParamPair ;
46184638 }
46194639
4640+ private Pod getDestinationPod (Long podId , boolean isRootAdmin ) {
4641+ Pod destinationPod = null ;
4642+ if (podId != null ) {
4643+ if (!isRootAdmin ) {
4644+ throw new PermissionDeniedException (
4645+ "Parameter " + ApiConstants .POD_ID + " can only be specified by a Root Admin, permission denied" );
4646+ }
4647+ destinationPod = _podDao .findById (podId );
4648+ if (destinationPod == null ) {
4649+ throw new InvalidParameterValueException ("Unable to find the pod to deploy the VM, pod id=" + podId );
4650+ }
4651+ }
4652+ return destinationPod ;
4653+ }
4654+
4655+ private Cluster getDestinationCluster (Long clusterId , boolean isRootAdmin ) {
4656+ Cluster destinationCluster = null ;
4657+ if (clusterId != null ) {
4658+ if (!isRootAdmin ) {
4659+ throw new PermissionDeniedException (
4660+ "Parameter " + ApiConstants .CLUSTER_ID + " can only be specified by a Root Admin, permission denied" );
4661+ }
4662+ destinationCluster = _clusterDao .findById (clusterId );
4663+ if (destinationCluster == null ) {
4664+ throw new InvalidParameterValueException ("Unable to find the cluster to deploy the VM, cluster id=" + clusterId );
4665+ }
4666+ }
4667+ return destinationCluster ;
4668+ }
4669+
4670+ private Host getDestinationHost (Long hostId , boolean isRootAdmin ) {
4671+ Host destinationHost = null ;
4672+ if (hostId != null ) {
4673+ if (!isRootAdmin ) {
4674+ throw new PermissionDeniedException (
4675+ "Parameter " + ApiConstants .HOST_ID + " can only be specified by a Root Admin, permission denied" );
4676+ }
4677+ destinationHost = _hostDao .findById (hostId );
4678+ if (destinationHost == null ) {
4679+ throw new InvalidParameterValueException ("Unable to find the host to deploy the VM, host id=" + hostId );
4680+ }
4681+ }
4682+ return destinationHost ;
4683+ }
4684+
46204685 @ Override
46214686 public UserVm destroyVm (long vmId , boolean expunge ) throws ResourceUnavailableException , ConcurrentOperationException {
46224687 // Account caller = CallContext.current().getCallingAccount();
0 commit comments