CLOUDSTACK-2692 Assigning LB rule for vm nic secondary ips

This commit is contained in:
Jayapal 2014-03-14 22:28:45 +05:30 committed by Kishan Kavala
parent ee99d5ee8d
commit 384eeaf792
10 changed files with 185 additions and 22 deletions

View File

@ -94,7 +94,7 @@ public interface LoadBalancingRulesService {
/**
* Assign a virtual machine, or list of virtual machines, to a load balancer.
*/
boolean assignToLoadBalancer(long lbRuleId, List<Long> vmIds);
boolean assignToLoadBalancer(long lbRuleId, List<Long> vmIds, Map<Long, List<String>> vmIdIpMap);
boolean assignSSLCertToLoadBalancerRule(Long lbRuleId, String certName, String publicCert, String privateKey);

View File

@ -262,6 +262,8 @@ public class ApiConstants {
public static final String VALUE = "value";
public static final String VIRTUAL_MACHINE_ID = "virtualmachineid";
public static final String VIRTUAL_MACHINE_IDS = "virtualmachineids";
public static final String VIRTUAL_MACHINE_ID_IP = "vmidipmap";
public static final String VLAN = "vlan";
public static final String VLAN_RANGE = "vlanrange";
public static final String REMOVE_VLAN = "removevlan";

View File

@ -16,7 +16,12 @@
// under the License.
package org.apache.cloudstack.api.command.user.loadbalancer;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Collection;
import java.util.Iterator;
import java.util.ArrayList;
import org.apache.log4j.Logger;
@ -62,10 +67,12 @@ public class AssignToLoadBalancerRuleCmd extends BaseAsyncCmd {
type = CommandType.LIST,
collectionType = CommandType.UUID,
entityType = UserVmResponse.class,
required = true,
description = "the list of IDs of the virtual machine that are being assigned to the load balancer rule(i.e. virtualMachineIds=1,2,3)")
private List<Long> virtualMachineIds;
@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")
private Map vmIdIpMap;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@ -78,6 +85,10 @@ public class AssignToLoadBalancerRuleCmd extends BaseAsyncCmd {
return virtualMachineIds;
}
public Map<Long, String> getVmIdIpMap() {
return vmIdIpMap;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
@ -106,10 +117,42 @@ public class AssignToLoadBalancerRuleCmd extends BaseAsyncCmd {
return "applying instances for load balancer: " + getLoadBalancerId() + " (ids: " + StringUtils.join(getVirtualMachineIds(), ",") + ")";
}
public Map<Long, List<String>> getVmIdIpListMap() {
Map<Long, List<String>> vmIdIpsMap = null;
if (vmIdIpMap != null && !vmIdIpMap.isEmpty()) {
vmIdIpsMap = new HashMap<Long, List<String>>();
Collection idIpsCollection = vmIdIpMap.values();
Iterator iter = idIpsCollection.iterator();
while (iter.hasNext()) {
HashMap<String, String> idIpsMap = (HashMap<String, String>)iter.next();
String vmId = idIpsMap.get("vmid");
String vmIp = idIpsMap.get("vmip");
Long longVmId = new Long(vmId);
List<String> ipsList = null;
if (vmIdIpsMap.containsKey(longVmId)) {
ipsList = vmIdIpsMap.get(longVmId);
} else {
ipsList = new ArrayList<String>();
}
ipsList.add(vmIp);
vmIdIpsMap.put(longVmId, ipsList);
}
}
return vmIdIpsMap;
}
@Override
public void execute() {
CallContext.current().setEventDetails("Load balancer Id: " + getLoadBalancerId() + " VmIds: " + StringUtils.join(getVirtualMachineIds(), ","));
boolean result = _lbService.assignToLoadBalancer(getLoadBalancerId(), virtualMachineIds);
Map<Long, List<String>> vmIdIpsMap = getVmIdIpListMap();
boolean result = _lbService.assignToLoadBalancer(getLoadBalancerId(), virtualMachineIds, vmIdIpsMap);
if (result) {
SuccessResponse response = new SuccessResponse(getCommandName());
this.setResponseObject(response);

View File

@ -34,4 +34,6 @@ public interface LoadBalancerVMMapDao extends GenericDao<LoadBalancerVMMapVO, Lo
LoadBalancerVMMapVO findByLoadBalancerIdAndVmId(long loadBalancerId, long instanceId);
boolean isVmAttachedToLoadBalancer(long loadBalancerId);
List<LoadBalancerVMMapVO> listByInstanceIp(String instanceIp);
}

View File

@ -59,6 +59,14 @@ public class LoadBalancerVMMapDaoImpl extends GenericDaoBase<LoadBalancerVMMapVO
return listBy(sc);
}
@Override
public List<LoadBalancerVMMapVO> listByInstanceIp(String instanceIp) {
SearchCriteria<LoadBalancerVMMapVO> sc = createSearchCriteria();
sc.addAnd("instanceIp", SearchCriteria.Op.EQ, instanceIp);
return listBy(sc);
}
@Override
public List<LoadBalancerVMMapVO> listByLoadBalancerId(long loadBalancerId) {
SearchCriteria<LoadBalancerVMMapVO> sc = createSearchCriteria();

View File

@ -39,6 +39,9 @@ public class LoadBalancerVMMapVO implements InternalIdentity {
@Column(name = "instance_id")
private long instanceId;
@Column(name = "instance_ip")
private String instanceIp;
@Column(name = "revoke")
private boolean revoke = false;
@ -59,6 +62,13 @@ public class LoadBalancerVMMapVO implements InternalIdentity {
this.revoke = revoke;
}
public LoadBalancerVMMapVO(long loadBalancerId, long instanceId, String vmIp, boolean revoke) {
this.loadBalancerId = loadBalancerId;
this.instanceId = instanceId;
this.instanceIp = vmIp;
this.revoke = revoke;
}
@Override
public long getId() {
return id;
@ -87,4 +97,13 @@ public class LoadBalancerVMMapVO implements InternalIdentity {
public void setState(String state) {
this.state = state;
}
public String getInstanceIp() {
return instanceIp;
}
public void setInstanceIp(String instanceIp) {
this.instanceIp = instanceIp;
}
}

View File

@ -113,10 +113,12 @@ import com.cloud.network.dao.NetworkVO;
import com.cloud.network.dao.OvsProviderDao;
import com.cloud.network.dao.PhysicalNetworkDao;
import com.cloud.network.dao.PhysicalNetworkServiceProviderDao;
import com.cloud.network.dao.LoadBalancerVMMapDao;
import com.cloud.network.dao.PhysicalNetworkServiceProviderVO;
import com.cloud.network.dao.PhysicalNetworkTrafficTypeDao;
import com.cloud.network.dao.PhysicalNetworkTrafficTypeVO;
import com.cloud.network.dao.PhysicalNetworkVO;
import com.cloud.network.dao.LoadBalancerVMMapVO;
import com.cloud.network.element.NetworkElement;
import com.cloud.network.element.OvsProviderVO;
import com.cloud.network.element.VirtualRouterElement;
@ -307,6 +309,8 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService {
IpAddressManager _ipAddrMgr;
@Inject
EntityManager _entityMgr;
@Inject
LoadBalancerVMMapDao _lbVmMapDao;
int _cidrLimit;
boolean _allowSubdomainNetworkAccess;
@ -806,7 +810,15 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService {
s_logger.debug("VM nic IP " + secondaryIp + " is associated with the static NAT rule public IP address id " + publicIpVO.getId());
throw new InvalidParameterValueException("Can' remove the ip " + secondaryIp + "is associate with static NAT rule public IP address id " + publicIpVO.getId());
}
} else if (dc.getNetworkType() == NetworkType.Basic || ntwkOff.getGuestType() == Network.GuestType.Shared) {
List<LoadBalancerVMMapVO> lbVmMap = _lbVmMapDao.listByInstanceIp(secondaryIp);
if (lbVmMap != null && lbVmMap.size() != 0) {
s_logger.debug("VM nic IP " + secondaryIp + " is mapped to load balancing rule");
throw new InvalidParameterValueException("Can't remove the secondary ip " + secondaryIp + " is mapped to load balancing rule");
}
} else if (dc.getNetworkType() == NetworkType.Basic || ntwkOff.getGuestType() == Network.GuestType.Shared) {
final IPAddressVO ip = _ipAddressDao.findByIpAndSourceNetworkId(secIpVO.getNetworkId(), secIpVO.getIp4Address());
if (ip != null) {
Transaction.execute(new TransactionCallbackNoReturn() {
@ -3819,12 +3831,12 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService {
PhysicalNetworkVO pvo = _physicalNetworkDao.findById(physicalNetworkId);
DataCenterVO dvo = _dcDao.findById(pvo.getDataCenterId());
if (dvo.getNetworkType() == NetworkType.Basic) {
Provider provider = Network.Provider.getProvider("BaremetalDhcpProvider");
if (provider == null) {
Provider provider = Network.Provider.getProvider("BaremetalDhcpProvider");
if (provider == null) {
// baremetal is not loaded
return null;
}
}
addProviderToPhysicalNetwork(physicalNetworkId, "BaremetalDhcpProvider", null, null);
addProviderToPhysicalNetwork(physicalNetworkId, "BaremetalPxeProvider", null, null);

View File

@ -1414,7 +1414,7 @@ public class AutoScaleManagerImpl<Type> extends ManagerBase implements AutoScale
}
}
lstVmId.add(new Long(vmId));
return _loadBalancingRulesService.assignToLoadBalancer(lbId, lstVmId);
return _loadBalancingRulesService.assignToLoadBalancer(lbId, lstVmId, null);
}

View File

@ -30,6 +30,7 @@ import java.util.Set;
import javax.ejb.Local;
import javax.inject.Inject;
import com.cloud.vm.dao.NicSecondaryIpDao;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.command.user.loadbalancer.CreateLBHealthCheckPolicyCmd;
import org.apache.cloudstack.api.command.user.loadbalancer.CreateLBStickinessPolicyCmd;
@ -258,6 +259,9 @@ public class LoadBalancingRulesManagerImpl<Type> extends ManagerBase implements
@Inject
LoadBalancerCertMapDao _lbCertMapDao;
@Inject
NicSecondaryIpDao _nicSecondaryIpDao;
// Will return a string. For LB Stickiness this will be a json, for
// autoscale this will be "," separated values
@Override
@ -923,7 +927,7 @@ public class LoadBalancingRulesManagerImpl<Type> extends ManagerBase implements
@Override
@DB
@ActionEvent(eventType = EventTypes.EVENT_ASSIGN_TO_LOAD_BALANCER_RULE, eventDescription = "assigning to load balancer", async = true)
public boolean assignToLoadBalancer(long loadBalancerId, List<Long> instanceIds) {
public boolean assignToLoadBalancer(long loadBalancerId, List<Long> instanceIds, Map<Long, List<String>> vmIdIpMap) {
CallContext ctx = CallContext.current();
Account caller = ctx.getCallingAccount();
@ -932,22 +936,68 @@ public class LoadBalancingRulesManagerImpl<Type> extends ManagerBase implements
throw new InvalidParameterValueException("Failed to assign to load balancer " + loadBalancerId + ", the load balancer was not found.");
}
if (instanceIds == null && vmIdIpMap == null) {
throw new InvalidParameterValueException("Both instanceids and vmidipmap can't be null");
}
// instanceIds and vmIdipmap is passed
if (instanceIds != null && vmIdIpMap != null) {
for(long instanceId: instanceIds) {
if (!vmIdIpMap.containsKey(instanceId)) {
vmIdIpMap.put(instanceId, null);
}
}
}
//only instanceids list passed
if (instanceIds != null && vmIdIpMap == null){
vmIdIpMap = new HashMap<Long, List<String>>();
for (long instanceId: instanceIds){
vmIdIpMap.put(instanceId, null);
}
}
List<LoadBalancerVMMapVO> mappedInstances = _lb2VmMapDao.listByLoadBalancerId(loadBalancerId, false);
Set<Long> mappedInstanceIds = new HashSet<Long>();
for (LoadBalancerVMMapVO mappedInstance : mappedInstances) {
mappedInstanceIds.add(Long.valueOf(mappedInstance.getInstanceId()));
}
final List<UserVm> vmsToAdd = new ArrayList<UserVm>();
Map<Long, List<String>> existingVmIdIps = new HashMap<Long, List<String>>();
// now get the ips of vm and add it to map
for (LoadBalancerVMMapVO mappedInstance : mappedInstances) {
if (instanceIds == null || instanceIds.isEmpty()) {
s_logger.warn("List of vms to assign to the lb, is empty");
return false;
List<String> ipsList = null;
if (existingVmIdIps.containsKey(mappedInstance.getInstanceId())) {
ipsList = existingVmIdIps.get(mappedInstance.getInstanceId());
} else {
ipsList = new ArrayList<String>();
}
ipsList.add(mappedInstance.getInstanceIp());
existingVmIdIps.put(mappedInstance.getInstanceId(), ipsList);
}
for (Long instanceId : instanceIds) {
if (mappedInstanceIds.contains(instanceId)) {
throw new InvalidParameterValueException("VM " + instanceId + " is already mapped to load balancer.");
final List<UserVm> vmsToAdd = new ArrayList<UserVm>();
// check for conflict
Set<Long> passedInstanceIds = vmIdIpMap.keySet();
for (Long instanceId : passedInstanceIds) {
if (existingVmIdIps.containsKey(instanceId)) {
// now check for ip address
List<String> mappedIps = existingVmIdIps.get(instanceId);
List<String> newIps = vmIdIpMap.get(instanceId);
if (newIps != null) {
for (String newIp: newIps) {
if (mappedIps.contains(newIp)) {
throw new InvalidParameterValueException("VM " + instanceId + " with " + newIp +" is already mapped to load balancer.");
}
}
}
}
UserVm vm = _vmDao.findById(instanceId);
@ -985,18 +1035,43 @@ public class LoadBalancingRulesManagerImpl<Type> extends ManagerBase implements
throw ex;
}
String priIp = nicInSameNetwork.getIp4Address();
List<String> vmIpsList = vmIdIpMap.get(instanceId);
String vmLbIp = null;
if (vmIpsList == null) {
vmIpsList = new ArrayList<String>();
vmIpsList.add(priIp);
vmIdIpMap.put(instanceId, vmIpsList);
} else {
//check if the ips belongs to nic secondary ip
for (String ip: vmIpsList) {
if(_nicSecondaryIpDao.findByIp4AddressAndNicId(ip,nicInSameNetwork.getId()) == null) {
throw new InvalidParameterValueException("VM ip specified " + ip + " is not belongs to nic in network " + nicInSameNetwork.getNetworkId());
}
}
}
if (s_logger.isDebugEnabled()) {
s_logger.debug("Adding " + vm + " to the load balancer pool");
}
vmsToAdd.add(vm);
}
final Set<Long> vmIds = vmIdIpMap.keySet();
final Map<Long, List<String>> newMap = vmIdIpMap;
Transaction.execute(new TransactionCallbackNoReturn() {
@Override
public void doInTransactionWithoutResult(TransactionStatus status) {
for (UserVm vm : vmsToAdd) {
LoadBalancerVMMapVO map = new LoadBalancerVMMapVO(loadBalancer.getId(), vm.getId(), false);
for (Long vmId : vmIds) {
final List<String> lbVmIps = newMap.get(vmId);
for (String vmIp: lbVmIps) {
LoadBalancerVMMapVO map = new LoadBalancerVMMapVO(loadBalancer.getId(), vmId, vmIp, false);
map = _lb2VmMapDao.persist(map);
}
}
}
});
@ -1020,8 +1095,8 @@ public class LoadBalancingRulesManagerImpl<Type> extends ManagerBase implements
Transaction.execute(new TransactionCallbackNoReturn() {
@Override
public void doInTransactionWithoutResult(TransactionStatus status) {
for (UserVm vm : vmsToAdd) {
vmInstanceIds.add(vm.getId());
for (Long vmId : vmIds) {
vmInstanceIds.add(vmId);
}
}
});
@ -1875,7 +1950,7 @@ public class LoadBalancingRulesManagerImpl<Type> extends ManagerBase implements
for (LoadBalancerVMMapVO lbVmMap : lbVmMaps) {
UserVm vm = _vmDao.findById(lbVmMap.getInstanceId());
Nic nic = _nicDao.findByInstanceIdAndNetworkIdIncludingRemoved(lb.getNetworkId(), vm.getId());
dstIp = nic.getIp4Address();
dstIp = lbVmMap.getInstanceIp() == null ? nic.getIp4Address(): lbVmMap.getInstanceIp();
LbDestination lbDst = new LbDestination(lb.getDefaultPortStart(), lb.getDefaultPortEnd(), dstIp, lbVmMap.isRevoke());
dstList.add(lbDst);
}

View File

@ -745,3 +745,5 @@ ALTER TABLE `cloud`.`vpc` ADD COLUMN uses_distributed_router boolean default fa
INSERT INTO `cloud`.`storage_pool_details` (pool_id,name,value,display) SELECT storage_pool.id,data_center_details.name,data_center_details.value,data_center_details.display FROM `cloud`.`storage_pool` JOIN `cloud`.`data_center_details` ON data_center_details.dc_id=storage_pool.data_center_id WHERE data_center_details.name = "storage.overprovisioning.factor";
DELETE FROM `cloud`.`data_center_details` WHERE name="storage.overprovisioning.factor";
ALTER TABLE `cloud`.`load_balancer_vm_map` ADD COLUMN instance_ip VARCHAR(40);
ALTER TABLE `cloud`.`load_balancer_vm_map` DROP KEY `load_balancer_id`, ADD UNIQUE KEY load_balancer_id (`load_balancer_id`, `instance_id`, `instance_ip`);