Skip to content

Commit 78cd64a

Browse files
committed
CLOUDSTACK-9203 refactorred DeployVM code to be used by UpdateVM as well
Conflicts: api/src/org/apache/cloudstack/api/command/user/vm/DeployVMCmd.java api/src/org/apache/cloudstack/api/command/user/vm/UpdateVMCmd.java
1 parent 5877293 commit 78cd64a

File tree

4 files changed

+252
-183
lines changed

4 files changed

+252
-183
lines changed

api/src/org/apache/cloudstack/api/command/user/vm/DeployVMCmd.java

Lines changed: 38 additions & 174 deletions
Original file line numberDiff line numberDiff line change
@@ -16,25 +16,14 @@
1616
// under the License.
1717
package org.apache.cloudstack.api.command.user.vm;
1818

19-
import com.cloud.dc.DataCenter;
20-
import com.cloud.dc.DataCenter.NetworkType;
21-
import com.cloud.event.EventTypes;
22-
import com.cloud.exception.ConcurrentOperationException;
23-
import com.cloud.exception.InsufficientCapacityException;
24-
import com.cloud.exception.InsufficientServerCapacityException;
25-
import com.cloud.exception.InvalidParameterValueException;
26-
import com.cloud.exception.ResourceAllocationException;
27-
import com.cloud.exception.ResourceUnavailableException;
28-
import com.cloud.hypervisor.Hypervisor.HypervisorType;
29-
import com.cloud.network.Network;
30-
import com.cloud.network.Network.IpAddresses;
31-
import com.cloud.offering.DiskOffering;
32-
import com.cloud.offering.ServiceOffering;
33-
import com.cloud.template.VirtualMachineTemplate;
34-
import com.cloud.user.Account;
35-
import com.cloud.uservm.UserVm;
36-
import com.cloud.utils.net.NetUtils;
37-
import com.cloud.vm.VirtualMachine;
19+
import java.util.ArrayList;
20+
import java.util.Collection;
21+
import java.util.HashMap;
22+
import java.util.Iterator;
23+
import java.util.LinkedHashMap;
24+
import java.util.List;
25+
import java.util.Map;
26+
3827
import org.apache.cloudstack.acl.RoleType;
3928
import org.apache.cloudstack.affinity.AffinityGroupResponse;
4029
import org.apache.cloudstack.api.ACL;
@@ -59,17 +48,23 @@
5948
import org.apache.cloudstack.context.CallContext;
6049
import org.apache.log4j.Logger;
6150

62-
import java.util.ArrayList;
63-
import java.util.Collection;
64-
import java.util.HashMap;
65-
import java.util.Iterator;
66-
import java.util.LinkedHashMap;
67-
import java.util.List;
68-
import java.util.Map;
51+
import com.cloud.event.EventTypes;
52+
import com.cloud.exception.ConcurrentOperationException;
53+
import com.cloud.exception.InsufficientCapacityException;
54+
import com.cloud.exception.InsufficientServerCapacityException;
55+
import com.cloud.exception.InvalidParameterValueException;
56+
import com.cloud.exception.ResourceAllocationException;
57+
import com.cloud.exception.ResourceUnavailableException;
58+
import com.cloud.hypervisor.Hypervisor.HypervisorType;
59+
import com.cloud.network.Network;
60+
import com.cloud.network.Network.IpAddresses;
61+
import com.cloud.uservm.UserVm;
62+
import com.cloud.utils.net.NetUtils;
63+
import com.cloud.vm.VirtualMachine;
6964

7065
@APICommand(name = "deployVirtualMachine", description = "Creates and automatically starts a virtual machine based on a service offering, disk offering, and template.", responseObject = UserVmResponse.class, responseView = ResponseView.Restricted, entityType = {VirtualMachine.class},
7166
requestHasSensitiveInfo = false, responseHasSensitiveInfo = true)
72-
public class DeployVMCmd extends BaseAsyncCreateCustomIdCmd {
67+
public class DeployVMCmd extends BaseAsyncCreateCustomIdCmd implements SecurityGroupAction {
7368
public static final Logger s_logger = Logger.getLogger(DeployVMCmd.class.getName());
7469

7570
private static final String s_name = "deployvirtualmachineresponse";
@@ -257,26 +252,12 @@ public boolean isDisplay() {
257252
return displayVm;
258253
}
259254

260-
public List<Long> getSecurityGroupIdList() {
261-
if (securityGroupNameList != null && securityGroupIdList != null) {
262-
throw new InvalidParameterValueException("securitygroupids parameter is mutually exclusive with securitygroupnames parameter");
263-
}
255+
public List<String> getSecurityGroupNameList() {
256+
return securityGroupNameList;
257+
}
264258

265-
//transform group names to ids here
266-
if (securityGroupNameList != null) {
267-
List<Long> securityGroupIds = new ArrayList<Long>();
268-
for (String groupName : securityGroupNameList) {
269-
Long groupId = _responseGenerator.getSecurityGroupId(groupName, getEntityOwnerId());
270-
if (groupId == null) {
271-
throw new InvalidParameterValueException("Unable to find group by name " + groupName);
272-
} else {
273-
securityGroupIds.add(groupId);
274-
}
275-
}
276-
return securityGroupIds;
277-
} else {
278-
return securityGroupIdList;
279-
}
259+
public List<Long> getSecurityGroupIdList() {
260+
return securityGroupIdList;
280261
}
281262

282263
public Long getServiceOfferingId() {
@@ -328,7 +309,7 @@ public boolean getStartVm() {
328309
return startVm == null ? true : startVm;
329310
}
330311

331-
private Map<Long, IpAddresses> getIpToNetworkMap() {
312+
public Map<Long, IpAddresses> getIpToNetworkMap() {
332313
if ((networkIds != null || ipAddress != null || getIp6Address() != null) && ipToNetworkList != null) {
333314
throw new InvalidParameterValueException("NetworkIds and ipAddress can't be specified along with ipToNetworkMap parameter");
334315
}
@@ -363,6 +344,10 @@ private Map<Long, IpAddresses> getIpToNetworkMap() {
363344
return ipToNetworkMap;
364345
}
365346

347+
public String getIpAddress() {
348+
return ipAddress;
349+
}
350+
366351
public String getIp6Address() {
367352
if (ip6Address == null) {
368353
return null;
@@ -392,6 +377,11 @@ public List<Long> getAffinityGroupIdList() {
392377
}
393378
}
394379

380+
public String getKeyboard() {
381+
// TODO Auto-generated method stub
382+
return keyboard;
383+
}
384+
395385
/////////////////////////////////////////////////////
396386
/////////////// API Implementation///////////////////
397387
/////////////////////////////////////////////////////
@@ -478,137 +468,11 @@ public void execute() {
478468
}
479469
}
480470

481-
// this is an opportunity to verify that parameters that came in via the Details Map are OK
482-
// for example, minIops and maxIops should either both be specified or neither be specified and,
483-
// if specified, minIops should be <= maxIops
484-
private void verifyDetails() {
485-
Map<String, String> map = getDetails();
486-
487-
if (map != null) {
488-
String minIops = (String)map.get("minIops");
489-
String maxIops = (String)map.get("maxIops");
490-
491-
verifyMinAndMaxIops(minIops, maxIops);
492-
493-
minIops = (String)map.get("minIopsDo");
494-
maxIops = (String)map.get("maxIopsDo");
495-
496-
verifyMinAndMaxIops(minIops, maxIops);
497-
}
498-
}
499-
500-
private void verifyMinAndMaxIops(String minIops, String maxIops) {
501-
if ((minIops != null && maxIops == null) || (minIops == null && maxIops != null)) {
502-
throw new InvalidParameterValueException("Either 'Min IOPS' and 'Max IOPS' must both be specified or neither be specified.");
503-
}
504-
505-
long lMinIops;
506-
507-
try {
508-
if (minIops != null) {
509-
lMinIops = Long.parseLong(minIops);
510-
}
511-
else {
512-
lMinIops = 0;
513-
}
514-
}
515-
catch (NumberFormatException ex) {
516-
throw new InvalidParameterValueException("'Min IOPS' must be a whole number.");
517-
}
518-
519-
long lMaxIops;
520-
521-
try {
522-
if (maxIops != null) {
523-
lMaxIops = Long.parseLong(maxIops);
524-
}
525-
else {
526-
lMaxIops = 0;
527-
}
528-
}
529-
catch (NumberFormatException ex) {
530-
throw new InvalidParameterValueException("'Max IOPS' must be a whole number.");
531-
}
532-
533-
if (lMinIops > lMaxIops) {
534-
throw new InvalidParameterValueException("'Min IOPS' must be less than or equal to 'Max IOPS'.");
535-
}
536-
}
537471

538472
@Override
539473
public void create() throws ResourceAllocationException {
540474
try {
541-
//Verify that all objects exist before passing them to the service
542-
Account owner = _accountService.getActiveAccountById(getEntityOwnerId());
543-
544-
verifyDetails();
545-
546-
DataCenter zone = _entityMgr.findById(DataCenter.class, zoneId);
547-
if (zone == null) {
548-
throw new InvalidParameterValueException("Unable to find zone by id=" + zoneId);
549-
}
550-
551-
ServiceOffering serviceOffering = _entityMgr.findById(ServiceOffering.class, serviceOfferingId);
552-
if (serviceOffering == null) {
553-
throw new InvalidParameterValueException("Unable to find service offering: " + serviceOfferingId);
554-
}
555-
556-
if(!serviceOffering.isDynamic()) {
557-
for(String detail: getDetails().keySet()) {
558-
if(detail.equalsIgnoreCase("cpuNumber") || detail.equalsIgnoreCase("cpuSpeed") || detail.equalsIgnoreCase("memory")) {
559-
throw new InvalidParameterValueException("cpuNumber or cpuSpeed or memory should not be specified for static service offering");
560-
}
561-
}
562-
}
563-
564-
VirtualMachineTemplate template = _entityMgr.findById(VirtualMachineTemplate.class, templateId);
565-
// Make sure a valid template ID was specified
566-
if (template == null) {
567-
throw new InvalidParameterValueException("Unable to find the template " + templateId);
568-
}
569-
570-
DiskOffering diskOffering = null;
571-
if (diskOfferingId != null) {
572-
diskOffering = _entityMgr.findById(DiskOffering.class, diskOfferingId);
573-
if (diskOffering == null) {
574-
throw new InvalidParameterValueException("Unable to find disk offering " + diskOfferingId);
575-
}
576-
}
577-
578-
if (!zone.isLocalStorageEnabled()) {
579-
if (serviceOffering.getUseLocalStorage()) {
580-
throw new InvalidParameterValueException("Zone is not configured to use local storage but service offering " + serviceOffering.getName() + " uses it");
581-
}
582-
if (diskOffering != null && diskOffering.getUseLocalStorage()) {
583-
throw new InvalidParameterValueException("Zone is not configured to use local storage but disk offering " + diskOffering.getName() + " uses it");
584-
}
585-
}
586-
587-
UserVm vm = null;
588-
IpAddresses addrs = new IpAddresses(ipAddress, getIp6Address());
589-
if (zone.getNetworkType() == NetworkType.Basic) {
590-
if (getNetworkIds() != null) {
591-
throw new InvalidParameterValueException("Can't specify network Ids in Basic zone");
592-
} else {
593-
vm = _userVmService.createBasicSecurityGroupVirtualMachine(zone, serviceOffering, template, getSecurityGroupIdList(), owner, name, displayName, diskOfferingId,
594-
size, group, getHypervisor(), getHttpMethod(), userData, sshKeyPairName, getIpToNetworkMap(), addrs, displayVm, keyboard, getAffinityGroupIdList(),
595-
getDetails(), getCustomId());
596-
}
597-
} else {
598-
if (zone.isSecurityGroupEnabled()) {
599-
vm = _userVmService.createAdvancedSecurityGroupVirtualMachine(zone, serviceOffering, template, getNetworkIds(), getSecurityGroupIdList(), owner, name,
600-
displayName, diskOfferingId, size, group, getHypervisor(), getHttpMethod(), userData, sshKeyPairName, getIpToNetworkMap(), addrs, displayVm, keyboard,
601-
getAffinityGroupIdList(), getDetails(), getCustomId());
602-
603-
} else {
604-
if (getSecurityGroupIdList() != null && !getSecurityGroupIdList().isEmpty()) {
605-
throw new InvalidParameterValueException("Can't create vm with security groups; security group feature is not enabled per zone");
606-
}
607-
vm = _userVmService.createAdvancedVirtualMachine(zone, serviceOffering, template, getNetworkIds(), owner, name, displayName, diskOfferingId, size, group,
608-
getHypervisor(), getHttpMethod(), userData, sshKeyPairName, getIpToNetworkMap(), addrs, displayVm, keyboard, getAffinityGroupIdList(), getDetails(),
609-
getCustomId());
610-
}
611-
}
475+
UserVm vm = _userVmService.createVirtualMachine(this);
612476

613477
if (vm != null) {
614478
setEntityId(vm.getId());
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
package org.apache.cloudstack.api.command.user.vm;
18+
19+
import java.util.List;
20+
21+
public interface SecurityGroupAction {
22+
List<Long> getSecurityGroupIdList();
23+
List<String> getSecurityGroupNameList();
24+
long getEntityOwnerId();
25+
}

api/src/org/apache/cloudstack/api/command/user/vm/UpdateVMCmd.java

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@
1616
// under the License.
1717
package org.apache.cloudstack.api.command.user.vm;
1818

19-
import org.apache.log4j.Logger;
19+
import java.util.Collection;
20+
import java.util.List;
21+
import java.util.Map;
2022

2123
import org.apache.cloudstack.acl.RoleType;
2224
import org.apache.cloudstack.acl.SecurityChecker.AccessType;
@@ -32,22 +34,19 @@
3234
import org.apache.cloudstack.api.response.SecurityGroupResponse;
3335
import org.apache.cloudstack.api.response.UserVmResponse;
3436
import org.apache.cloudstack.context.CallContext;
37+
import org.apache.log4j.Logger;
3538

3639
import com.cloud.exception.InsufficientCapacityException;
3740
import com.cloud.exception.ResourceUnavailableException;
3841
import com.cloud.user.Account;
3942
import com.cloud.uservm.UserVm;
4043
import com.cloud.vm.VirtualMachine;
4144

42-
import java.util.Collection;
43-
import java.util.List;
44-
import java.util.Map;
45-
4645
@APICommand(name = "updateVirtualMachine", description="Updates properties of a virtual machine. The VM has to be stopped and restarted for the " +
4746
"new properties to take effect. UpdateVirtualMachine does not first check whether the VM is stopped. " +
4847
"Therefore, stop the VM manually before issuing this call.", responseObject = UserVmResponse.class, responseView = ResponseView.Restricted, entityType = {VirtualMachine.class},
4948
requestHasSensitiveInfo = false, responseHasSensitiveInfo = true)
50-
public class UpdateVMCmd extends BaseCustomIdCmd {
49+
public class UpdateVMCmd extends BaseCustomIdCmd implements SecurityGroupAction {
5150
public static final Logger s_logger = Logger.getLogger(UpdateVMCmd.class.getName());
5251
private static final String s_name = "updatevirtualmachineresponse";
5352

@@ -106,6 +105,17 @@ public class UpdateVMCmd extends BaseCustomIdCmd {
106105
description = "list of security group ids to be applied on the virtual machine.")
107106
private List<Long> securityGroupIdList;
108107

108+
@ACL
109+
@Parameter(name = ApiConstants.SECURITY_GROUP_NAMES,
110+
type = CommandType.LIST,
111+
collectionType = CommandType.STRING,
112+
entityType = SecurityGroupResponse.class,
113+
description = "comma separated list of security groups names that going to be applied to the virtual machine. " +
114+
"Should be passed only when vm is created from a zone with Basic Network support. " +
115+
"Mutually exclusive with securitygroupids parameter"
116+
)
117+
private List<String> securityGroupNameList;
118+
109119
/////////////////////////////////////////////////////
110120
/////////////////// Accessors ///////////////////////
111121
/////////////////////////////////////////////////////
@@ -159,6 +169,10 @@ public List<Long> getSecurityGroupIdList() {
159169
return securityGroupIdList;
160170
}
161171

172+
public List<String> getSecurityGroupNameList() {
173+
return securityGroupNameList;
174+
}
175+
162176
/////////////////////////////////////////////////////
163177
/////////////// API Implementation///////////////////
164178
/////////////////////////////////////////////////////

0 commit comments

Comments
 (0)