Skip to content

Commit ab0d04d

Browse files
committed
CLOUDSTACK-7985: assignVM in Advanced zone with Security Groups
1 parent 3f16740 commit ab0d04d

4 files changed

Lines changed: 158 additions & 4 deletions

File tree

api/src/org/apache/cloudstack/api/command/admin/vm/AssignVMCmd.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import org.apache.cloudstack.api.response.SecurityGroupResponse;
3434
import org.apache.cloudstack.api.response.UserVmResponse;
3535

36+
import com.cloud.exception.InvalidParameterValueException;
3637
import com.cloud.user.Account;
3738
import com.cloud.uservm.UserVm;
3839
import com.cloud.vm.VirtualMachine;
@@ -133,6 +134,9 @@ public void execute() {
133134
UserVmResponse response = _responseGenerator.createUserVmResponse(ResponseView.Full, "virtualmachine", userVm).get(0);
134135
response.setResponseName(getCommandName());
135136
setResponseObject(response);
137+
} catch (InvalidParameterValueException e){
138+
e.printStackTrace();
139+
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, e.getMessage());
136140
} catch (Exception e) {
137141
e.printStackTrace();
138142
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to move vm " + e.getMessage());

server/src/com/cloud/vm/UserVmManagerImpl.java

Lines changed: 125 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5240,8 +5240,131 @@ public void doInTransactionWithoutResult(TransactionStatus status) {
52405240

52415241
s_logger.debug("AssignVM: Basic zone, adding security groups no " + securityGroupIdList.size() + " to " + vm.getInstanceName());
52425242
} else {
5243-
if (zone.isSecurityGroupEnabled()) {
5244-
throw new InvalidParameterValueException("Not yet implemented for SecurityGroupEnabled advanced networks.");
5243+
if (zone.isSecurityGroupEnabled()) { // advanced zone with security groups
5244+
// cleanup the old security groups
5245+
_securityGroupMgr.removeInstanceFromGroups(cmd.getVmId());
5246+
5247+
Set<NetworkVO> applicableNetworks = new HashSet<NetworkVO>();
5248+
String requestedIPv4ForDefaultNic = null;
5249+
String requestedIPv6ForDefaultNic = null;
5250+
// if networkIdList is null and the first network of vm is shared network, then keep it if possible
5251+
if (networkIdList == null || networkIdList.isEmpty()) {
5252+
NicVO defaultNicOld = _nicDao.findDefaultNicForVM(vm.getId());
5253+
if (defaultNicOld != null) {
5254+
NetworkVO defaultNetworkOld = _networkDao.findById(defaultNicOld.getNetworkId());
5255+
if (defaultNetworkOld != null && defaultNetworkOld.getGuestType() == Network.GuestType.Shared && defaultNetworkOld.getAclType() == ACLType.Domain) {
5256+
try {
5257+
_networkModel.checkNetworkPermissions(newAccount, defaultNetworkOld);
5258+
applicableNetworks.add(defaultNetworkOld);
5259+
requestedIPv4ForDefaultNic = defaultNicOld.getIPv4Address();
5260+
requestedIPv6ForDefaultNic = defaultNicOld.getIPv6Address();
5261+
s_logger.debug("AssignVM: use old shared network " + defaultNetworkOld.getName() + " with old ip " + requestedIPv4ForDefaultNic + " on default nic of vm:" + vm.getInstanceName());
5262+
} catch (PermissionDeniedException e) {
5263+
s_logger.debug("AssignVM: the shared network on old default nic can not be applied to new account");
5264+
}
5265+
}
5266+
}
5267+
}
5268+
// cleanup the network for the oldOwner
5269+
_networkMgr.cleanupNics(vmOldProfile);
5270+
_networkMgr.expungeNics(vmOldProfile);
5271+
5272+
if (networkIdList != null && !networkIdList.isEmpty()) {
5273+
// add any additional networks
5274+
for (Long networkId : networkIdList) {
5275+
NetworkVO network = _networkDao.findById(networkId);
5276+
if (network == null) {
5277+
InvalidParameterValueException ex = new InvalidParameterValueException(
5278+
"Unable to find specified network id");
5279+
ex.addProxyObject(networkId.toString(), "networkId");
5280+
throw ex;
5281+
}
5282+
5283+
_networkModel.checkNetworkPermissions(newAccount, network);
5284+
5285+
// don't allow to use system networks
5286+
NetworkOffering networkOffering = _entityMgr.findById(NetworkOffering.class, network.getNetworkOfferingId());
5287+
if (networkOffering.isSystemOnly()) {
5288+
InvalidParameterValueException ex = new InvalidParameterValueException(
5289+
"Specified Network id is system only and can't be used for vm deployment");
5290+
ex.addProxyObject(network.getUuid(), "networkId");
5291+
throw ex;
5292+
}
5293+
applicableNetworks.add(network);
5294+
}
5295+
}
5296+
5297+
// add the new nics
5298+
LinkedHashMap<Network, List<? extends NicProfile>> networks = new LinkedHashMap<Network, List<? extends NicProfile>>();
5299+
int toggle = 0;
5300+
NetworkVO defaultNetwork = null;
5301+
for (NetworkVO appNet : applicableNetworks) {
5302+
NicProfile defaultNic = new NicProfile();
5303+
if (toggle == 0) {
5304+
defaultNic.setDefaultNic(true);
5305+
defaultNic.setRequestedIPv4(requestedIPv4ForDefaultNic);
5306+
defaultNic.setRequestedIPv6(requestedIPv6ForDefaultNic);
5307+
defaultNetwork = appNet;
5308+
toggle++;
5309+
}
5310+
networks.put(appNet, new ArrayList<NicProfile>(Arrays.asList(defaultNic)));
5311+
5312+
}
5313+
5314+
boolean isVmWare = (template.getHypervisorType() == HypervisorType.VMware);
5315+
if (securityGroupIdList != null && isVmWare) {
5316+
throw new InvalidParameterValueException("Security group feature is not supported for vmWare hypervisor");
5317+
} else if (!isVmWare && (defaultNetwork == null || _networkModel.isSecurityGroupSupportedInNetwork(defaultNetwork)) && _networkModel.canAddDefaultSecurityGroup()) {
5318+
if (securityGroupIdList == null) {
5319+
securityGroupIdList = new ArrayList<Long>();
5320+
}
5321+
SecurityGroup defaultGroup = _securityGroupMgr
5322+
.getDefaultSecurityGroup(newAccount.getId());
5323+
if (defaultGroup != null) {
5324+
// check if security group id list already contains Default
5325+
// security group, and if not - add it
5326+
boolean defaultGroupPresent = false;
5327+
for (Long securityGroupId : securityGroupIdList) {
5328+
if (securityGroupId.longValue() == defaultGroup.getId()) {
5329+
defaultGroupPresent = true;
5330+
break;
5331+
}
5332+
}
5333+
5334+
if (!defaultGroupPresent) {
5335+
securityGroupIdList.add(defaultGroup.getId());
5336+
}
5337+
5338+
} else {
5339+
// create default security group for the account
5340+
if (s_logger.isDebugEnabled()) {
5341+
s_logger.debug("Couldn't find default security group for the account "
5342+
+ newAccount + " so creating a new one");
5343+
}
5344+
defaultGroup = _securityGroupMgr.createSecurityGroup(
5345+
SecurityGroupManager.DEFAULT_GROUP_NAME,
5346+
SecurityGroupManager.DEFAULT_GROUP_DESCRIPTION,
5347+
newAccount.getDomainId(), newAccount.getId(),
5348+
newAccount.getAccountName());
5349+
securityGroupIdList.add(defaultGroup.getId());
5350+
}
5351+
}
5352+
5353+
VirtualMachine vmi = _itMgr.findById(vm.getId());
5354+
VirtualMachineProfileImpl vmProfile = new VirtualMachineProfileImpl(vmi);
5355+
5356+
if (applicableNetworks.isEmpty()) {
5357+
throw new InvalidParameterValueException("No network is specified, please specify one when you move the vm. For now, please add a network to VM on NICs tab.");
5358+
} else {
5359+
_networkMgr.allocate(vmProfile, networks);
5360+
}
5361+
5362+
_securityGroupMgr.addInstanceToGroups(vm.getId(),
5363+
securityGroupIdList);
5364+
s_logger.debug("AssignVM: Advanced zone, adding security groups no "
5365+
+ securityGroupIdList.size() + " to "
5366+
+ vm.getInstanceName());
5367+
52455368
} else {
52465369
if (securityGroupIdList != null && !securityGroupIdList.isEmpty()) {
52475370
throw new InvalidParameterValueException("Can't move vm with security groups; security group feature is not enabled in this zone");

ui/l10n/en.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1908,6 +1908,7 @@ var dictionary = {"ICMP.code":"ICMP Code",
19081908
"message.alert.state.detected":"Alert state detected",
19091909
"message.allow.vpn.access":"Please enter a username and password of the user that you want to allow VPN access.",
19101910
"message.apply.snapshot.policy":"You have successfully updated your current snapshot policy.",
1911+
"message.assign.instance.another":"Please specify the account type, domain, account name and network (optional) of the new account. <br> If the default nic of the vm is on a shared network, CloudStack will check if the network can be used by the new account if you do not specify one network. <br> If the default nic of the vm is on a isolated network, and the new account has more one isolated networks, you should specify one.",
19111912
"message.attach.iso.confirm":"Please confirm that you want to attach the ISO to this virtual instance.",
19121913
"message.attach.volume":"Please fill in the following data to attach a new volume. If you are attaching a disk volume to a Windows based virtual machine, you will need to reboot the instance to see the attached disk.",
19131914
"message.basic.mode.desc":"Choose this network model if you do <b>*<u>not</u>*</b> want to enable any VLAN support. All virtual instances created under this network model will be assigned an IP directly from the network and security groups are used to provide security and segregation.",
@@ -2281,4 +2282,4 @@ var dictionary = {"ICMP.code":"ICMP Code",
22812282
"state.detached":"Detached",
22822283
"title.upload.volume":"Upload Volume",
22832284
"ui.listView.filters.all":"All",
2284-
"ui.listView.filters.mine":"Mine"};
2285+
"ui.listView.filters.mine":"Mine"};

ui/scripts/instances.js

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1905,7 +1905,25 @@
19051905
label: 'label.assign.instance.another',
19061906
createForm: {
19071907
title: 'label.assign.instance.another',
1908-
desc: 'Please specify the account type, domain, account name and network (optional) of the new account. <br> If the default nic of the vm is on a shared network, CloudStack will check if the network can be used by the new account if you do not specify one network. <br> If the default nic of the vm is on a isolated network, and the new account has more one isolated networks, you should specify one.',
1908+
desc: 'message.assign.instance.another',
1909+
preFilter: function(args) {
1910+
var zone;
1911+
$.ajax({
1912+
url: createURL('listZones'),
1913+
data: {
1914+
id: args.context.instances[0].zoneid
1915+
},
1916+
async: false,
1917+
success: function(json) {
1918+
zone = json.listzonesresponse.zone[0];
1919+
}
1920+
});
1921+
if (zone.securitygroupsenabled == true) {
1922+
args.$form.find('.form-item[rel=securitygroup]').css('display', 'inline-block');
1923+
} else {
1924+
args.$form.find('.form-item[rel=securitygroup]').hide();
1925+
}
1926+
},
19091927
fields: {
19101928
accountType: {
19111929
label: 'Account Type',
@@ -2157,6 +2175,11 @@
21572175
networkIds: args.data.network
21582176
});
21592177
}
2178+
if (args.data.securitygroup != null && args.data.securitygroup != '') {
2179+
$.extend(dataObj, {
2180+
securitygroupIds: args.data.securitygroup
2181+
});
2182+
}
21602183

21612184
$.ajax({
21622185
url: createURL('assignVirtualMachine', {
@@ -2168,6 +2191,9 @@
21682191
args.response.success({
21692192
data: item
21702193
});
2194+
},
2195+
error: function(data) {
2196+
args.response.error(parseXMLHttpResponse(data));
21712197
}
21722198
});
21732199
},

0 commit comments

Comments
 (0)