CLOUDSTACK-9203 security group update on running instance

cherry-picked from a exoscale internal fix:

      Implement security group move on updateVM API call
      Prevent security group update while instance is running

Conflicts:
	api/src/org/apache/cloudstack/api/command/user/vm/UpdateVMCmd.java
	server/src/com/cloud/vm/UserVmManager.java
	server/src/com/cloud/vm/UserVmManagerImpl.java
This commit is contained in:
Loic Lambiel 2015-05-15 15:15:26 +02:00 committed by Daan Hoogland
parent 570b676b1f
commit 5877293434
3 changed files with 59 additions and 5 deletions

View File

@ -29,6 +29,7 @@ import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.ResponseObject.ResponseView;
import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.response.GuestOSResponse;
import org.apache.cloudstack.api.response.SecurityGroupResponse;
import org.apache.cloudstack.api.response.UserVmResponse;
import org.apache.cloudstack.context.CallContext;
@ -39,6 +40,7 @@ import com.cloud.uservm.UserVm;
import com.cloud.vm.VirtualMachine;
import java.util.Collection;
import java.util.List;
import java.util.Map;
@APICommand(name = "updateVirtualMachine", description="Updates properties of a virtual machine. The VM has to be stopped and restarted for the " +
@ -96,6 +98,14 @@ public class UpdateVMCmd extends BaseCustomIdCmd {
@Parameter(name = ApiConstants.DETAILS, type = CommandType.MAP, description = "Details in key/value pairs.")
protected Map<String, String> details;
@ACL
@Parameter(name = ApiConstants.SECURITY_GROUP_IDS,
type = CommandType.LIST,
collectionType = CommandType.UUID,
entityType = SecurityGroupResponse.class,
description = "list of security group ids to be applied on the virtual machine.")
private List<Long> securityGroupIdList;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@ -145,7 +155,11 @@ public class UpdateVMCmd extends BaseCustomIdCmd {
return (Map<String, String>) (paramsCollection.toArray())[0];
}
/////////////////////////////////////////////////////
public List<Long> getSecurityGroupIdList() {
return securityGroupIdList;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////

View File

@ -103,7 +103,7 @@ public interface UserVmManager extends UserVmService {
void collectVmDiskStatistics(UserVmVO userVm);
UserVm updateVirtualMachine(long id, String displayName, String group, Boolean ha, Boolean isDisplayVmEnabled, Long osTypeId, String userData,
Boolean isDynamicallyScalable, HTTPMethod httpMethod, String customId, String hostName, String instanceName) throws ResourceUnavailableException, InsufficientCapacityException;
Boolean isDynamicallyScalable, HTTPMethod httpMethod, String customId, String hostName, String instanceName, List<Long> securityGroupIdList) throws ResourceUnavailableException, InsufficientCapacityException;
//the validateCustomParameters, save and remove CustomOfferingDetils functions can be removed from the interface once we can
//find a common place for all the scaling and upgrading code of both user and systemvms.

View File

@ -2289,6 +2289,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
String hostName = cmd.getHostName();
Map<String,String> details = cmd.getDetails();
Account caller = CallContext.current().getCallingAccount();
List<Long> securityGroupIdList = cmd.getSecurityGroupIdList();
// Input validation and permission checks
UserVmVO vmInstance = _vmDao.findById(id);
@ -2339,7 +2340,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
}
return updateVirtualMachine(id, displayName, group, ha, isDisplayVm, osTypeId, userData, isDynamicallyScalable,
cmd.getHttpMethod(), cmd.getCustomId(), hostName, cmd.getInstanceName());
cmd.getHttpMethod(), cmd.getCustomId(), hostName, cmd.getInstanceName(), securityGroupIdList);
}
private void saveUsageEvent(UserVmVO vm) {
@ -2389,10 +2390,11 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
@Override
public UserVm updateVirtualMachine(long id, String displayName, String group, Boolean ha, Boolean isDisplayVmEnabled, Long osTypeId, String userData,
Boolean isDynamicallyScalable, HTTPMethod httpMethod, String customId, String hostName, String instanceName) throws ResourceUnavailableException, InsufficientCapacityException {
Boolean isDynamicallyScalable, HTTPMethod httpMethod, String customId, String hostName, String instanceName, List<Long> securityGroupIdList)
throws ResourceUnavailableException, InsufficientCapacityException {
UserVmVO vm = _vmDao.findById(id);
if (vm == null) {
throw new CloudRuntimeException("Unable to find virual machine with id " + id);
throw new CloudRuntimeException("Unable to find virtual machine with id " + id);
}
if(instanceName != null){
@ -2451,6 +2453,44 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
isDynamicallyScalable = vm.isDynamicallyScalable();
}
boolean isVMware = (vm.getHypervisorType() == HypervisorType.VMware);
if (securityGroupIdList != null && isVMware) {
throw new InvalidParameterValueException("Security group feature is not supported for vmWare hypervisor");
} else {
// Get default guest network in Basic zone
Network defaultNetwork = null;
try {
DataCenterVO zone = _dcDao.findById(vm.getDataCenterId());
if (zone.getNetworkType() == NetworkType.Basic) {
// Get default guest network in Basic zone
defaultNetwork = _networkModel.getExclusiveGuestNetwork(zone.getId());
} else if (zone.isSecurityGroupEnabled()) {
NicVO defaultNic = _nicDao.findDefaultNicForVM(vm.getId());
if (defaultNic != null) {
defaultNetwork = _networkDao.findById(defaultNic.getNetworkId());
}
}
} catch (InvalidParameterValueException e) {
if(s_logger.isDebugEnabled()) {
s_logger.debug(e.getMessage(),e);
}
defaultNetwork = _networkModel.getDefaultNetworkForVm(id);
}
if (securityGroupIdList != null && _networkModel.isSecurityGroupSupportedInNetwork(defaultNetwork) && _networkModel.canAddDefaultSecurityGroup()) {
if (vm.getState() == State.Stopped) {
// Remove instance from security groups
_securityGroupMgr.removeInstanceFromGroups(id);
// Add instance in provided groups
_securityGroupMgr.addInstanceToGroups(id, securityGroupIdList);
} else {
throw new InvalidParameterValueException("Virtual machine must be stopped prior to update security groups ");
}
}
}
if (hostName != null) {
// Check is hostName is RFC compliant
checkNameForRFCCompliance(hostName);