From 49199d00220a4c948b1386e8f0c6f719a2c49cf7 Mon Sep 17 00:00:00 2001 From: Alena Prokharchyk Date: Fri, 20 Jul 2012 16:27:54 -0700 Subject: [PATCH] VPC: when VPC router gets destroyed and recreated, plug public nic for each Vlan where VPC public ips belong to --- .../src/com/cloud/network/NetworkManager.java | 3 +- .../com/cloud/network/NetworkManagerImpl.java | 12 +- .../lb/LoadBalancingRulesManagerImpl.java | 3 +- ...VpcVirtualNetworkApplianceManagerImpl.java | 109 ++++++++++++++++-- .../cloud/network/rules/RulesManagerImpl.java | 4 +- .../cloud/network/MockNetworkManagerImpl.java | 2 +- 6 files changed, 109 insertions(+), 24 deletions(-) diff --git a/server/src/com/cloud/network/NetworkManager.java b/server/src/com/cloud/network/NetworkManager.java index 56e735db9d7..4ab8e8f75b0 100755 --- a/server/src/com/cloud/network/NetworkManager.java +++ b/server/src/com/cloud/network/NetworkManager.java @@ -395,8 +395,9 @@ public interface NetworkManager extends NetworkService { /** * @param ipAddrId * @param networkId + * @param releaseOnFailure TODO */ - IPAddressVO associateIPToGuestNetwork(long ipAddrId, long networkId) throws ResourceAllocationException, ResourceUnavailableException, + IPAddressVO associateIPToGuestNetwork(long ipAddrId, long networkId, boolean releaseOnFailure) throws ResourceAllocationException, ResourceUnavailableException, InsufficientAddressCapacityException, ConcurrentOperationException; diff --git a/server/src/com/cloud/network/NetworkManagerImpl.java b/server/src/com/cloud/network/NetworkManagerImpl.java index 97fca01800f..b231d3e11a0 100755 --- a/server/src/com/cloud/network/NetworkManagerImpl.java +++ b/server/src/com/cloud/network/NetworkManagerImpl.java @@ -1141,7 +1141,8 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag @DB @Override - public IPAddressVO associateIPToGuestNetwork(long ipId, long networkId) throws ResourceAllocationException, ResourceUnavailableException, + public IPAddressVO associateIPToGuestNetwork(long ipId, long networkId, boolean releaseOnFailure) + throws ResourceAllocationException, ResourceUnavailableException, InsufficientAddressCapacityException, ConcurrentOperationException { Account caller = UserContext.current().getCaller(); Account owner = null; @@ -1219,14 +1220,11 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag s_logger.warn("Failed to associate ip address " + ip.getAddress().addr() + " to network " + network); } return ip; - } catch (ResourceUnavailableException e) { - s_logger.error("Unable to associate ip address due to resource unavailable exception", e); - return null; } finally { - if (!success) { + if (!success && releaseOnFailure) { if (ip != null) { try { - s_logger.warn("Failed to associate ip address " + ip); + s_logger.warn("Failed to associate ip address, so releasing ip from the database " + ip); _ipAddressDao.markAsUnavailable(ip.getId()); if (!applyIpAssociations(network, true)) { // if fail to apply ip assciations again, unassign ip address without updating resource @@ -7210,7 +7208,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag throw new InvalidParameterValueException("Can't assign ip to the network directly when network belongs" + " to VPC.Specify vpcId to associate ip address to VPC", null); } - return associateIPToGuestNetwork(ipId, networkId); + return associateIPToGuestNetwork(ipId, networkId, true); } return null; diff --git a/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java b/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java index 19ef4dd2ec1..88c3d11dea5 100755 --- a/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java +++ b/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java @@ -756,11 +756,10 @@ public class LoadBalancingRulesManagerImpl implements LoadBalancingRulesMa && ipVO.getVpcId() != null && ipVO.getVpcId().longValue() == network.getVpcId(); if (assignToVpcNtwk) { //set networkId just for verification purposes - ipVO.setAssociatedWithNetworkId(lb.getNetworkId()); _networkMgr.checkIpForService(ipVO, Service.Lb, lb.getNetworkId()); s_logger.debug("The ip is not associated with the VPC network id="+ lb.getNetworkId() + " so assigning"); - ipVO = _networkMgr.associateIPToGuestNetwork(ipAddrId, lb.getNetworkId()); + ipVO = _networkMgr.associateIPToGuestNetwork(ipAddrId, lb.getNetworkId(), false); performedIpAssoc = true; } } else { diff --git a/server/src/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImpl.java b/server/src/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImpl.java index 65f138edafe..1537895123d 100644 --- a/server/src/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImpl.java +++ b/server/src/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImpl.java @@ -18,6 +18,7 @@ import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.TreeSet; import javax.ejb.Local; @@ -95,6 +96,7 @@ import com.cloud.network.vpc.Dao.PrivateIpDao; import com.cloud.network.vpc.Dao.StaticRouteDao; import com.cloud.network.vpc.Dao.VpcDao; import com.cloud.network.vpc.Dao.VpcOfferingDao; +import com.cloud.offerings.NetworkOfferingVO; import com.cloud.user.Account; import com.cloud.utils.Pair; import com.cloud.utils.component.Inject; @@ -532,9 +534,10 @@ public class VpcVirtualNetworkApplianceManagerImpl extends VirtualNetworkApplian //only one router is supported in VPC now VirtualRouter router = routers.get(0); - //1) check which nics need to be plugged/unplugged and plug/unplug them - Map nicsToPlug = new HashMap(); - Map nicsToUnPlug = new HashMap(); + Pair, Map> nicsToChange = getNicsToChangeOnRouter(ipAddress, router); + Map nicsToPlug = nicsToChange.first(); + Map nicsToUnplug = nicsToChange.second(); + //find out nics to unplug for (PublicIpAddress ip : ipAddress) { @@ -548,7 +551,7 @@ public class VpcVirtualNetworkApplianceManagerImpl extends VirtualNetworkApplian if (ip.getState() == IpAddress.State.Releasing) { Nic nic = _nicDao.findByIp4AddressAndNetworkIdAndInstanceId(publicNtwkId, router.getId(), ip.getAddress().addr()); if (nic != null) { - nicsToUnPlug.put(ip.getVlanTag(), ip); + nicsToUnplug.put(ip.getVlanTag(), ip); s_logger.debug("Need to unplug the nic for ip=" + ip + "; vlan=" + ip.getVlanTag() + " in public network id =" + publicNtwkId); } @@ -570,7 +573,7 @@ public class VpcVirtualNetworkApplianceManagerImpl extends VirtualNetworkApplian Nic nic = _nicDao.findByInstanceIdNetworkIdAndBroadcastUri(publicNtwkId, router.getId(), broadcastUri.toString()); - if ((nic == null && nicsToPlug.get(ip.getVlanTag()) == null) || nicsToUnPlug.get(ip.getVlanTag()) != null) { + if ((nic == null && nicsToPlug.get(ip.getVlanTag()) == null) || nicsToUnplug.get(ip.getVlanTag()) != null) { nicsToPlug.put(ip.getVlanTag(), ip); s_logger.debug("Need to plug the nic for ip=" + ip + "; vlan=" + ip.getVlanTag() + " in public network id =" + publicNtwkId); @@ -625,10 +628,10 @@ public class VpcVirtualNetworkApplianceManagerImpl extends VirtualNetworkApplian }); //4) Unplug the nics - for (String vlanTag : nicsToUnPlug.keySet()) { + for (String vlanTag : nicsToUnplug.keySet()) { Network publicNtwk = null; try { - publicNtwk = _networkMgr.getNetwork(nicsToUnPlug.get(vlanTag).getNetworkId()); + publicNtwk = _networkMgr.getNetwork(nicsToUnplug.get(vlanTag).getNetworkId()); URI broadcastUri = BroadcastDomainType.Vlan.toUri(vlanTag); _itMgr.removeVmFromNetwork(router, publicNtwk, broadcastUri); } catch (ConcurrentOperationException e) { @@ -1155,13 +1158,18 @@ public class VpcVirtualNetworkApplianceManagerImpl extends VirtualNetworkApplian protected List> createVpcRouterNetworks(Account owner, boolean isRedundant, - DeploymentPlan plan, Pair publicNetwork, long vpcId) throws ConcurrentOperationException, + DeploymentPlan plan, Pair sourceNatIp, long vpcId) throws ConcurrentOperationException, InsufficientAddressCapacityException { List> networks = new ArrayList>(4); - networks = super.createRouterNetworks(owner, isRedundant, plan, null, publicNetwork); - //1) allocate nic for private gateway if needed + TreeSet publicVlans = new TreeSet(); + publicVlans.add(sourceNatIp.second().getVlanTag()); + + //1) allocate nic for control and source nat public ip + networks = super.createRouterNetworks(owner, isRedundant, plan, null, sourceNatIp); + + //2) allocate nic for private gateway if needed VpcGateway privateGateway = _vpcMgr.getPrivateGatewayForVpc(vpcId); if (privateGateway != null) { NicProfile privateNic = createPrivateNicProfileForGateway(privateGateway); @@ -1169,7 +1177,7 @@ public class VpcVirtualNetworkApplianceManagerImpl extends VirtualNetworkApplian networks.add(new Pair((NetworkVO) privateNetwork, privateNic)); } - //2) allocate nic for guest gateway if needed + //3) allocate nic for guest gateway if needed List guestNetworks = _vpcMgr.getVpcNetworks(vpcId); for (Network guestNetwork : guestNetworks) { if (guestNetwork.getState() == Network.State.Implemented) { @@ -1178,6 +1186,30 @@ public class VpcVirtualNetworkApplianceManagerImpl extends VirtualNetworkApplian } } + //4) allocate nic for additional public network(s) + List ips = _ipAddressDao.listByAssociatedVpc(vpcId, false); + for (IPAddressVO ip : ips) { + PublicIp publicIp = new PublicIp(ip, _vlanDao.findById(ip.getVlanId()), + NetUtils.createSequenceBasedMacAddress(ip.getMacAddress())); + if ((ip.getState() == IpAddress.State.Allocated || ip.getState() == IpAddress.State.Allocating) + && _networkMgr.ipUsedInVpc(ip)&& !publicVlans.contains(publicIp.getVlanTag())) { + s_logger.debug("Allocating nic for router in vlan " + publicIp.getVlanTag()); + NicProfile publicNic = new NicProfile(); + publicNic.setDefaultNic(false); + publicNic.setIp4Address(publicIp.getAddress().addr()); + publicNic.setGateway(publicIp.getGateway()); + publicNic.setNetmask(publicIp.getNetmask()); + publicNic.setMacAddress(publicIp.getMacAddress()); + publicNic.setBroadcastType(BroadcastDomainType.Vlan); + publicNic.setBroadcastUri(BroadcastDomainType.Vlan.toUri(publicIp.getVlanTag())); + publicNic.setIsolationUri(IsolationType.Vlan.toUri(publicIp.getVlanTag())); + NetworkOfferingVO publicOffering = _networkMgr.getSystemAccountNetworkOfferings(NetworkOfferingVO.SystemPublicNetwork).get(0); + List publicNetworks = _networkMgr.setupNetwork(_systemAcct, publicOffering, plan, null, null, false); + networks.add(new Pair(publicNetworks.get(0), publicNic)); + publicVlans.add(publicIp.getVlanTag()); + } + } + return networks; } @@ -1215,4 +1247,59 @@ public class VpcVirtualNetworkApplianceManagerImpl extends VirtualNetworkApplian return guestNic; } + + protected Pair, Map> getNicsToChangeOnRouter + (final List publicIps, VirtualRouter router) { + //1) check which nics need to be plugged/unplugged and plug/unplug them + + Map nicsToPlug = new HashMap(); + Map nicsToUnplug = new HashMap(); + + + //find out nics to unplug + for (PublicIpAddress ip : publicIps) { + long publicNtwkId = ip.getNetworkId(); + + //if ip is not associated to any network, and there are no firewall rules, release it on the backend + if (!_networkMgr.ipUsedInVpc(ip)) { + ip.setState(IpAddress.State.Releasing); + } + + if (ip.getState() == IpAddress.State.Releasing) { + Nic nic = _nicDao.findByIp4AddressAndNetworkIdAndInstanceId(publicNtwkId, router.getId(), ip.getAddress().addr()); + if (nic != null) { + nicsToUnplug.put(ip.getVlanTag(), ip); + s_logger.debug("Need to unplug the nic for ip=" + ip + "; vlan=" + ip.getVlanTag() + + " in public network id =" + publicNtwkId); + } + } + } + + //find out nics to plug + for (PublicIpAddress ip : publicIps) { + URI broadcastUri = BroadcastDomainType.Vlan.toUri(ip.getVlanTag()); + long publicNtwkId = ip.getNetworkId(); + + //if ip is not associated to any network, and there are no firewall rules, release it on the backend + if (!_networkMgr.ipUsedInVpc(ip)) { + ip.setState(IpAddress.State.Releasing); + } + + if (ip.getState() == IpAddress.State.Allocated || ip.getState() == IpAddress.State.Allocating) { + //nic has to be plugged only when there are no nics for this vlan tag exist on VR + Nic nic = _nicDao.findByInstanceIdNetworkIdAndBroadcastUri(publicNtwkId, router.getId(), + broadcastUri.toString()); + + if ((nic == null && nicsToPlug.get(ip.getVlanTag()) == null) || nicsToUnplug.get(ip.getVlanTag()) != null) { + nicsToPlug.put(ip.getVlanTag(), ip); + s_logger.debug("Need to plug the nic for ip=" + ip + "; vlan=" + ip.getVlanTag() + + " in public network id =" + publicNtwkId); + } + } + } + + Pair, Map> nicsToChange = + new Pair, Map>(nicsToPlug, nicsToUnplug); + return nicsToChange; + } } diff --git a/server/src/com/cloud/network/rules/RulesManagerImpl.java b/server/src/com/cloud/network/rules/RulesManagerImpl.java index 3ba4cabc7ea..dd975d5867a 100755 --- a/server/src/com/cloud/network/rules/RulesManagerImpl.java +++ b/server/src/com/cloud/network/rules/RulesManagerImpl.java @@ -196,7 +196,7 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager { s_logger.debug("The ip is not associated with the VPC network id="+ networkId + ", so assigning"); try { - ipAddress = _networkMgr.associateIPToGuestNetwork(ipAddrId, networkId); + ipAddress = _networkMgr.associateIPToGuestNetwork(ipAddrId, networkId, false); performedIpAssoc = true; } catch (Exception ex) { throw new CloudRuntimeException("Failed to associate ip to VPC network as " + @@ -430,7 +430,7 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager { s_logger.debug("The ip is not associated with the VPC network id="+ networkId + ", so assigning"); try { - ipAddress = _networkMgr.associateIPToGuestNetwork(ipId, networkId); + ipAddress = _networkMgr.associateIPToGuestNetwork(ipId, networkId, false); } catch (Exception ex) { s_logger.warn("Failed to associate ip id=" + ipId + " to VPC network id=" + networkId + " as " + "a part of enable static nat"); diff --git a/server/test/com/cloud/network/MockNetworkManagerImpl.java b/server/test/com/cloud/network/MockNetworkManagerImpl.java index b500e0ccbb5..2311d805ea1 100755 --- a/server/test/com/cloud/network/MockNetworkManagerImpl.java +++ b/server/test/com/cloud/network/MockNetworkManagerImpl.java @@ -76,7 +76,7 @@ public class MockNetworkManagerImpl implements NetworkManager, Manager, NetworkS } @Override - public IPAddressVO associateIPToGuestNetwork(long ipId, long networkId) throws ResourceAllocationException, InsufficientAddressCapacityException, ConcurrentOperationException, ResourceUnavailableException { + public IPAddressVO associateIPToGuestNetwork(long ipId, long networkId, boolean releaseOnFailure) throws ResourceAllocationException, InsufficientAddressCapacityException, ConcurrentOperationException, ResourceUnavailableException { // TODO Auto-generated method stub return null; }