Skip to content

Commit 14a4dd1

Browse files
JayapalKishan Kavala
authored andcommitted
CLOUDSTACK-2692 Assigning LB rule for vm nic secondary ips
Conflicts: setup/db/db/schema-430to440.sql
1 parent c1085ed commit 14a4dd1

10 files changed

Lines changed: 185 additions & 22 deletions

File tree

api/src/com/cloud/network/lb/LoadBalancingRulesService.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ LoadBalancer createPublicLoadBalancerRule(String xId, String name, String descri
9494
/**
9595
* Assign a virtual machine, or list of virtual machines, to a load balancer.
9696
*/
97-
boolean assignToLoadBalancer(long lbRuleId, List<Long> vmIds);
97+
boolean assignToLoadBalancer(long lbRuleId, List<Long> vmIds, Map<Long, List<String>> vmIdIpMap);
9898

9999
boolean assignSSLCertToLoadBalancerRule(Long lbRuleId, String certName, String publicCert, String privateKey);
100100

api/src/org/apache/cloudstack/api/ApiConstants.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,8 @@ public class ApiConstants {
262262
public static final String VALUE = "value";
263263
public static final String VIRTUAL_MACHINE_ID = "virtualmachineid";
264264
public static final String VIRTUAL_MACHINE_IDS = "virtualmachineids";
265+
public static final String VIRTUAL_MACHINE_ID_IP = "vmidipmap";
266+
265267
public static final String VLAN = "vlan";
266268
public static final String VLAN_RANGE = "vlanrange";
267269
public static final String REMOVE_VLAN = "removevlan";

api/src/org/apache/cloudstack/api/command/user/loadbalancer/AssignToLoadBalancerRuleCmd.java

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

19+
import java.util.HashMap;
1920
import java.util.List;
21+
import java.util.Map;
22+
import java.util.Collection;
23+
import java.util.Iterator;
24+
import java.util.ArrayList;
2025

2126
import org.apache.log4j.Logger;
2227

@@ -62,10 +67,12 @@ public class AssignToLoadBalancerRuleCmd extends BaseAsyncCmd {
6267
type = CommandType.LIST,
6368
collectionType = CommandType.UUID,
6469
entityType = UserVmResponse.class,
65-
required = true,
6670
description = "the list of IDs of the virtual machine that are being assigned to the load balancer rule(i.e. virtualMachineIds=1,2,3)")
6771
private List<Long> virtualMachineIds;
6872

73+
@Parameter(name = ApiConstants.VIRTUAL_MACHINE_ID_IP, type = CommandType.MAP, description = "VM ID and IP map, vmidipmap[0].vmid=1 vmidipmap[0].ip=10.1.1.75")
74+
private Map vmIdIpMap;
75+
6976
/////////////////////////////////////////////////////
7077
/////////////////// Accessors ///////////////////////
7178
/////////////////////////////////////////////////////
@@ -78,6 +85,10 @@ public List<Long> getVirtualMachineIds() {
7885
return virtualMachineIds;
7986
}
8087

88+
public Map<Long, String> getVmIdIpMap() {
89+
return vmIdIpMap;
90+
}
91+
8192
/////////////////////////////////////////////////////
8293
/////////////// API Implementation///////////////////
8394
/////////////////////////////////////////////////////
@@ -106,10 +117,42 @@ public String getEventDescription() {
106117
return "applying instances for load balancer: " + getLoadBalancerId() + " (ids: " + StringUtils.join(getVirtualMachineIds(), ",") + ")";
107118
}
108119

120+
121+
public Map<Long, List<String>> getVmIdIpListMap() {
122+
Map<Long, List<String>> vmIdIpsMap = null;
123+
if (vmIdIpMap != null && !vmIdIpMap.isEmpty()) {
124+
vmIdIpsMap = new HashMap<Long, List<String>>();
125+
Collection idIpsCollection = vmIdIpMap.values();
126+
Iterator iter = idIpsCollection.iterator();
127+
while (iter.hasNext()) {
128+
HashMap<String, String> idIpsMap = (HashMap<String, String>)iter.next();
129+
String vmId = idIpsMap.get("vmid");
130+
String vmIp = idIpsMap.get("vmip");
131+
132+
Long longVmId = new Long(vmId);
133+
134+
List<String> ipsList = null;
135+
if (vmIdIpsMap.containsKey(longVmId)) {
136+
ipsList = vmIdIpsMap.get(longVmId);
137+
} else {
138+
ipsList = new ArrayList<String>();
139+
}
140+
ipsList.add(vmIp);
141+
vmIdIpsMap.put(longVmId, ipsList);
142+
143+
}
144+
}
145+
146+
return vmIdIpsMap;
147+
}
148+
109149
@Override
110150
public void execute() {
111151
CallContext.current().setEventDetails("Load balancer Id: " + getLoadBalancerId() + " VmIds: " + StringUtils.join(getVirtualMachineIds(), ","));
112-
boolean result = _lbService.assignToLoadBalancer(getLoadBalancerId(), virtualMachineIds);
152+
153+
Map<Long, List<String>> vmIdIpsMap = getVmIdIpListMap();
154+
155+
boolean result = _lbService.assignToLoadBalancer(getLoadBalancerId(), virtualMachineIds, vmIdIpsMap);
113156
if (result) {
114157
SuccessResponse response = new SuccessResponse(getCommandName());
115158
this.setResponseObject(response);

engine/schema/src/com/cloud/network/dao/LoadBalancerVMMapDao.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,6 @@ public interface LoadBalancerVMMapDao extends GenericDao<LoadBalancerVMMapVO, Lo
3434
LoadBalancerVMMapVO findByLoadBalancerIdAndVmId(long loadBalancerId, long instanceId);
3535

3636
boolean isVmAttachedToLoadBalancer(long loadBalancerId);
37+
38+
List<LoadBalancerVMMapVO> listByInstanceIp(String instanceIp);
3739
}

engine/schema/src/com/cloud/network/dao/LoadBalancerVMMapDaoImpl.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,14 @@ public List<LoadBalancerVMMapVO> listByInstanceId(long instanceId) {
5959
return listBy(sc);
6060
}
6161

62+
@Override
63+
public List<LoadBalancerVMMapVO> listByInstanceIp(String instanceIp) {
64+
SearchCriteria<LoadBalancerVMMapVO> sc = createSearchCriteria();
65+
sc.addAnd("instanceIp", SearchCriteria.Op.EQ, instanceIp);
66+
67+
return listBy(sc);
68+
}
69+
6270
@Override
6371
public List<LoadBalancerVMMapVO> listByLoadBalancerId(long loadBalancerId) {
6472
SearchCriteria<LoadBalancerVMMapVO> sc = createSearchCriteria();

engine/schema/src/com/cloud/network/dao/LoadBalancerVMMapVO.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@ public class LoadBalancerVMMapVO implements InternalIdentity {
3939
@Column(name = "instance_id")
4040
private long instanceId;
4141

42+
@Column(name = "instance_ip")
43+
private String instanceIp;
44+
4245
@Column(name = "revoke")
4346
private boolean revoke = false;
4447

@@ -59,6 +62,13 @@ public LoadBalancerVMMapVO(long loadBalancerId, long instanceId, boolean revoke)
5962
this.revoke = revoke;
6063
}
6164

65+
public LoadBalancerVMMapVO(long loadBalancerId, long instanceId, String vmIp, boolean revoke) {
66+
this.loadBalancerId = loadBalancerId;
67+
this.instanceId = instanceId;
68+
this.instanceIp = vmIp;
69+
this.revoke = revoke;
70+
}
71+
6272
@Override
6373
public long getId() {
6474
return id;
@@ -87,4 +97,13 @@ public String getState() {
8797
public void setState(String state) {
8898
this.state = state;
8999
}
100+
101+
public String getInstanceIp() {
102+
return instanceIp;
103+
}
104+
105+
public void setInstanceIp(String instanceIp) {
106+
this.instanceIp = instanceIp;
107+
}
108+
90109
}

server/src/com/cloud/network/NetworkServiceImpl.java

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -113,10 +113,12 @@
113113
import com.cloud.network.dao.OvsProviderDao;
114114
import com.cloud.network.dao.PhysicalNetworkDao;
115115
import com.cloud.network.dao.PhysicalNetworkServiceProviderDao;
116+
import com.cloud.network.dao.LoadBalancerVMMapDao;
116117
import com.cloud.network.dao.PhysicalNetworkServiceProviderVO;
117118
import com.cloud.network.dao.PhysicalNetworkTrafficTypeDao;
118119
import com.cloud.network.dao.PhysicalNetworkTrafficTypeVO;
119120
import com.cloud.network.dao.PhysicalNetworkVO;
121+
import com.cloud.network.dao.LoadBalancerVMMapVO;
120122
import com.cloud.network.element.NetworkElement;
121123
import com.cloud.network.element.OvsProviderVO;
122124
import com.cloud.network.element.VirtualRouterElement;
@@ -307,6 +309,8 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService {
307309
IpAddressManager _ipAddrMgr;
308310
@Inject
309311
EntityManager _entityMgr;
312+
@Inject
313+
LoadBalancerVMMapDao _lbVmMapDao;
310314

311315
int _cidrLimit;
312316
boolean _allowSubdomainNetworkAccess;
@@ -806,7 +810,15 @@ public boolean releaseSecondaryIpFromNic(long ipAddressId) {
806810
s_logger.debug("VM nic IP " + secondaryIp + " is associated with the static NAT rule public IP address id " + publicIpVO.getId());
807811
throw new InvalidParameterValueException("Can' remove the ip " + secondaryIp + "is associate with static NAT rule public IP address id " + publicIpVO.getId());
808812
}
809-
} else if (dc.getNetworkType() == NetworkType.Basic || ntwkOff.getGuestType() == Network.GuestType.Shared) {
813+
814+
List<LoadBalancerVMMapVO> lbVmMap = _lbVmMapDao.listByInstanceIp(secondaryIp);
815+
if (lbVmMap != null && lbVmMap.size() != 0) {
816+
s_logger.debug("VM nic IP " + secondaryIp + " is mapped to load balancing rule");
817+
throw new InvalidParameterValueException("Can't remove the secondary ip " + secondaryIp + " is mapped to load balancing rule");
818+
819+
}
820+
821+
} else if (dc.getNetworkType() == NetworkType.Basic || ntwkOff.getGuestType() == Network.GuestType.Shared) {
810822
final IPAddressVO ip = _ipAddressDao.findByIpAndSourceNetworkId(secIpVO.getNetworkId(), secIpVO.getIp4Address());
811823
if (ip != null) {
812824
Transaction.execute(new TransactionCallbackNoReturn() {
@@ -3819,12 +3831,12 @@ private PhysicalNetworkServiceProvider addDefaultBaremetalProvidersToPhysicalNet
38193831
PhysicalNetworkVO pvo = _physicalNetworkDao.findById(physicalNetworkId);
38203832
DataCenterVO dvo = _dcDao.findById(pvo.getDataCenterId());
38213833
if (dvo.getNetworkType() == NetworkType.Basic) {
3822-
3823-
Provider provider = Network.Provider.getProvider("BaremetalDhcpProvider");
3824-
if (provider == null) {
3834+
3835+
Provider provider = Network.Provider.getProvider("BaremetalDhcpProvider");
3836+
if (provider == null) {
38253837
// baremetal is not loaded
38263838
return null;
3827-
}
3839+
}
38283840

38293841
addProviderToPhysicalNetwork(physicalNetworkId, "BaremetalDhcpProvider", null, null);
38303842
addProviderToPhysicalNetwork(physicalNetworkId, "BaremetalPxeProvider", null, null);

server/src/com/cloud/network/as/AutoScaleManagerImpl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1414,7 +1414,7 @@ private boolean assignLBruleToNewVm(long vmId, AutoScaleVmGroupVO asGroup) {
14141414
}
14151415
}
14161416
lstVmId.add(new Long(vmId));
1417-
return _loadBalancingRulesService.assignToLoadBalancer(lbId, lstVmId);
1417+
return _loadBalancingRulesService.assignToLoadBalancer(lbId, lstVmId, null);
14181418

14191419
}
14201420

server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java

Lines changed: 88 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import javax.ejb.Local;
3131
import javax.inject.Inject;
3232

33+
import com.cloud.vm.dao.NicSecondaryIpDao;
3334
import org.apache.cloudstack.api.ApiConstants;
3435
import org.apache.cloudstack.api.command.user.loadbalancer.CreateLBHealthCheckPolicyCmd;
3536
import org.apache.cloudstack.api.command.user.loadbalancer.CreateLBStickinessPolicyCmd;
@@ -258,6 +259,9 @@ public class LoadBalancingRulesManagerImpl<Type> extends ManagerBase implements
258259
@Inject
259260
LoadBalancerCertMapDao _lbCertMapDao;
260261

262+
@Inject
263+
NicSecondaryIpDao _nicSecondaryIpDao;
264+
261265
// Will return a string. For LB Stickiness this will be a json, for
262266
// autoscale this will be "," separated values
263267
@Override
@@ -923,7 +927,7 @@ private boolean isRollBackAllowedForProvider(LoadBalancerVO loadBalancer) {
923927
@Override
924928
@DB
925929
@ActionEvent(eventType = EventTypes.EVENT_ASSIGN_TO_LOAD_BALANCER_RULE, eventDescription = "assigning to load balancer", async = true)
926-
public boolean assignToLoadBalancer(long loadBalancerId, List<Long> instanceIds) {
930+
public boolean assignToLoadBalancer(long loadBalancerId, List<Long> instanceIds, Map<Long, List<String>> vmIdIpMap) {
927931
CallContext ctx = CallContext.current();
928932
Account caller = ctx.getCallingAccount();
929933

@@ -932,22 +936,68 @@ public boolean assignToLoadBalancer(long loadBalancerId, List<Long> instanceIds)
932936
throw new InvalidParameterValueException("Failed to assign to load balancer " + loadBalancerId + ", the load balancer was not found.");
933937
}
934938

939+
940+
if (instanceIds == null && vmIdIpMap == null) {
941+
throw new InvalidParameterValueException("Both instanceids and vmidipmap can't be null");
942+
}
943+
944+
// instanceIds and vmIdipmap is passed
945+
if (instanceIds != null && vmIdIpMap != null) {
946+
for(long instanceId: instanceIds) {
947+
if (!vmIdIpMap.containsKey(instanceId)) {
948+
vmIdIpMap.put(instanceId, null);
949+
}
950+
}
951+
}
952+
953+
//only instanceids list passed
954+
if (instanceIds != null && vmIdIpMap == null){
955+
vmIdIpMap = new HashMap<Long, List<String>>();
956+
for (long instanceId: instanceIds){
957+
vmIdIpMap.put(instanceId, null);
958+
}
959+
}
960+
935961
List<LoadBalancerVMMapVO> mappedInstances = _lb2VmMapDao.listByLoadBalancerId(loadBalancerId, false);
936962
Set<Long> mappedInstanceIds = new HashSet<Long>();
937963
for (LoadBalancerVMMapVO mappedInstance : mappedInstances) {
938964
mappedInstanceIds.add(Long.valueOf(mappedInstance.getInstanceId()));
939965
}
940966

941-
final List<UserVm> vmsToAdd = new ArrayList<UserVm>();
967+
Map<Long, List<String>> existingVmIdIps = new HashMap<Long, List<String>>();
968+
// now get the ips of vm and add it to map
969+
for (LoadBalancerVMMapVO mappedInstance : mappedInstances) {
942970

943-
if (instanceIds == null || instanceIds.isEmpty()) {
944-
s_logger.warn("List of vms to assign to the lb, is empty");
945-
return false;
971+
List<String> ipsList = null;
972+
if (existingVmIdIps.containsKey(mappedInstance.getInstanceId())) {
973+
ipsList = existingVmIdIps.get(mappedInstance.getInstanceId());
974+
} else {
975+
ipsList = new ArrayList<String>();
976+
}
977+
ipsList.add(mappedInstance.getInstanceIp());
978+
existingVmIdIps.put(mappedInstance.getInstanceId(), ipsList);
946979
}
947980

948-
for (Long instanceId : instanceIds) {
949-
if (mappedInstanceIds.contains(instanceId)) {
950-
throw new InvalidParameterValueException("VM " + instanceId + " is already mapped to load balancer.");
981+
982+
983+
984+
final List<UserVm> vmsToAdd = new ArrayList<UserVm>();
985+
986+
// check for conflict
987+
Set<Long> passedInstanceIds = vmIdIpMap.keySet();
988+
for (Long instanceId : passedInstanceIds) {
989+
if (existingVmIdIps.containsKey(instanceId)) {
990+
// now check for ip address
991+
List<String> mappedIps = existingVmIdIps.get(instanceId);
992+
List<String> newIps = vmIdIpMap.get(instanceId);
993+
994+
if (newIps != null) {
995+
for (String newIp: newIps) {
996+
if (mappedIps.contains(newIp)) {
997+
throw new InvalidParameterValueException("VM " + instanceId + " with " + newIp +" is already mapped to load balancer.");
998+
}
999+
}
1000+
}
9511001
}
9521002

9531003
UserVm vm = _vmDao.findById(instanceId);
@@ -985,18 +1035,43 @@ public boolean assignToLoadBalancer(long loadBalancerId, List<Long> instanceIds)
9851035
throw ex;
9861036
}
9871037

1038+
String priIp = nicInSameNetwork.getIp4Address();
1039+
List<String> vmIpsList = vmIdIpMap.get(instanceId);
1040+
String vmLbIp = null;
1041+
1042+
if (vmIpsList == null) {
1043+
vmIpsList = new ArrayList<String>();
1044+
vmIpsList.add(priIp);
1045+
vmIdIpMap.put(instanceId, vmIpsList);
1046+
} else {
1047+
//check if the ips belongs to nic secondary ip
1048+
for (String ip: vmIpsList) {
1049+
if(_nicSecondaryIpDao.findByIp4AddressAndNicId(ip,nicInSameNetwork.getId()) == null) {
1050+
throw new InvalidParameterValueException("VM ip specified " + ip + " is not belongs to nic in network " + nicInSameNetwork.getNetworkId());
1051+
}
1052+
}
1053+
}
1054+
1055+
9881056
if (s_logger.isDebugEnabled()) {
9891057
s_logger.debug("Adding " + vm + " to the load balancer pool");
9901058
}
9911059
vmsToAdd.add(vm);
9921060
}
9931061

1062+
final Set<Long> vmIds = vmIdIpMap.keySet();
1063+
final Map<Long, List<String>> newMap = vmIdIpMap;
1064+
9941065
Transaction.execute(new TransactionCallbackNoReturn() {
9951066
@Override
9961067
public void doInTransactionWithoutResult(TransactionStatus status) {
997-
for (UserVm vm : vmsToAdd) {
998-
LoadBalancerVMMapVO map = new LoadBalancerVMMapVO(loadBalancer.getId(), vm.getId(), false);
1068+
1069+
for (Long vmId : vmIds) {
1070+
final List<String> lbVmIps = newMap.get(vmId);
1071+
for (String vmIp: lbVmIps) {
1072+
LoadBalancerVMMapVO map = new LoadBalancerVMMapVO(loadBalancer.getId(), vmId, vmIp, false);
9991073
map = _lb2VmMapDao.persist(map);
1074+
}
10001075
}
10011076
}
10021077
});
@@ -1020,8 +1095,8 @@ public void doInTransactionWithoutResult(TransactionStatus status) {
10201095
Transaction.execute(new TransactionCallbackNoReturn() {
10211096
@Override
10221097
public void doInTransactionWithoutResult(TransactionStatus status) {
1023-
for (UserVm vm : vmsToAdd) {
1024-
vmInstanceIds.add(vm.getId());
1098+
for (Long vmId : vmIds) {
1099+
vmInstanceIds.add(vmId);
10251100
}
10261101
}
10271102
});
@@ -1875,7 +1950,7 @@ public List<LbDestination> getExistingDestinations(long lbId) {
18751950
for (LoadBalancerVMMapVO lbVmMap : lbVmMaps) {
18761951
UserVm vm = _vmDao.findById(lbVmMap.getInstanceId());
18771952
Nic nic = _nicDao.findByInstanceIdAndNetworkIdIncludingRemoved(lb.getNetworkId(), vm.getId());
1878-
dstIp = nic.getIp4Address();
1953+
dstIp = lbVmMap.getInstanceIp() == null ? nic.getIp4Address(): lbVmMap.getInstanceIp();
18791954
LbDestination lbDst = new LbDestination(lb.getDefaultPortStart(), lb.getDefaultPortEnd(), dstIp, lbVmMap.isRevoke());
18801955
dstList.add(lbDst);
18811956
}

0 commit comments

Comments
 (0)