From ba23973d53f0832c85b341663d9dfeef191de4c2 Mon Sep 17 00:00:00 2001 From: Sheng Yang Date: Tue, 3 Jan 2012 16:30:45 -0800 Subject: [PATCH] bug 12656: Refactor IP associate process Introduce the concept of Ip Deployer. The IP deployer would be responible for apply IP to the element. Most element's IP deployer is itself, but it can be someone else if we want to implement inline mode in the future. --- .../element/FirewallServiceProvider.java | 10 - .../com/cloud/network/element/IpDeployer.java | 20 ++ .../element/LoadBalancingServiceProvider.java | 10 +- .../PortForwardingServiceProvider.java | 10 +- .../RemoteAccessVPNServiceProvider.java | 2 + .../element/SourceNatServiceProvider.java | 14 +- .../element/StaticNatServiceProvider.java | 10 +- .../src/com/cloud/network/NetworkManager.java | 5 + .../com/cloud/network/NetworkManagerImpl.java | 338 ++++++++++++------ .../cloud/network/dao/FirewallRulesDao.java | 4 + .../network/dao/FirewallRulesDaoImpl.java | 16 + .../element/ElasticLoadBalancerElement.java | 18 +- .../F5ExternalLoadBalancerElement.java | 16 +- .../JuniperSRXExternalFirewallElement.java | 11 +- .../NetscalerExternalLoadBalancerElement.java | 16 +- .../network/element/VirtualRouterElement.java | 34 +- .../VirtualNetworkApplianceManagerImpl.java | 19 +- 17 files changed, 344 insertions(+), 209 deletions(-) create mode 100644 api/src/com/cloud/network/element/IpDeployer.java diff --git a/api/src/com/cloud/network/element/FirewallServiceProvider.java b/api/src/com/cloud/network/element/FirewallServiceProvider.java index 6600831db77..6f65a0a6928 100644 --- a/api/src/com/cloud/network/element/FirewallServiceProvider.java +++ b/api/src/com/cloud/network/element/FirewallServiceProvider.java @@ -4,7 +4,6 @@ import java.util.List; import com.cloud.exception.ResourceUnavailableException; import com.cloud.network.Network; -import com.cloud.network.PublicIpAddress; import com.cloud.network.rules.FirewallRule; public interface FirewallServiceProvider extends NetworkElement { @@ -16,13 +15,4 @@ public interface FirewallServiceProvider extends NetworkElement { * @throws ResourceUnavailableException */ boolean applyFWRules(Network network, List rules) throws ResourceUnavailableException; - - /** - * Apply ip addresses to this network - * @param network - * @param ipAddress - * @return - * @throws ResourceUnavailableException - */ - boolean applyIps(Network network, List ipAddress) throws ResourceUnavailableException; } diff --git a/api/src/com/cloud/network/element/IpDeployer.java b/api/src/com/cloud/network/element/IpDeployer.java new file mode 100644 index 00000000000..1e458da14d9 --- /dev/null +++ b/api/src/com/cloud/network/element/IpDeployer.java @@ -0,0 +1,20 @@ +package com.cloud.network.element; + +import java.util.List; +import java.util.Set; + +import com.cloud.exception.ResourceUnavailableException; +import com.cloud.network.Network; +import com.cloud.network.Network.Service; +import com.cloud.network.PublicIpAddress; + +public interface IpDeployer { + /** + * Apply ip addresses to this network + * @param network + * @param ipAddress + * @return + * @throws ResourceUnavailableException + */ + boolean applyIps(Network network, List ipAddress, Set services) throws ResourceUnavailableException; +} diff --git a/api/src/com/cloud/network/element/LoadBalancingServiceProvider.java b/api/src/com/cloud/network/element/LoadBalancingServiceProvider.java index 7d31f3cd7fe..d1f3dc65de9 100644 --- a/api/src/com/cloud/network/element/LoadBalancingServiceProvider.java +++ b/api/src/com/cloud/network/element/LoadBalancingServiceProvider.java @@ -4,7 +4,6 @@ import java.util.List; import com.cloud.exception.ResourceUnavailableException; import com.cloud.network.Network; -import com.cloud.network.PublicIpAddress; import com.cloud.network.lb.LoadBalancingRule; public interface LoadBalancingServiceProvider extends NetworkElement { @@ -17,12 +16,5 @@ public interface LoadBalancingServiceProvider extends NetworkElement { */ boolean applyLBRules(Network network, List rules) throws ResourceUnavailableException; - /** - * Apply ip addresses to this network service provider - * @param network - * @param ipAddress - * @return - * @throws ResourceUnavailableException - */ - boolean applyLoadBalancerIp(Network network, List ipAddress) throws ResourceUnavailableException; + IpDeployer getIpDeployer(Network network); } diff --git a/api/src/com/cloud/network/element/PortForwardingServiceProvider.java b/api/src/com/cloud/network/element/PortForwardingServiceProvider.java index 2bcdc8c7fa0..4437a9645c7 100644 --- a/api/src/com/cloud/network/element/PortForwardingServiceProvider.java +++ b/api/src/com/cloud/network/element/PortForwardingServiceProvider.java @@ -4,7 +4,6 @@ import java.util.List; import com.cloud.exception.ResourceUnavailableException; import com.cloud.network.Network; -import com.cloud.network.PublicIpAddress; import com.cloud.network.rules.PortForwardingRule; public interface PortForwardingServiceProvider extends NetworkElement { @@ -17,12 +16,5 @@ public interface PortForwardingServiceProvider extends NetworkElement { */ boolean applyPFRules(Network network, List rules) throws ResourceUnavailableException; - /** - * Apply ip addresses to this network service provider - * @param network - * @param ipAddress - * @return - * @throws ResourceUnavailableException - */ - boolean applyIps(Network network, List ipAddress) throws ResourceUnavailableException; + IpDeployer getIpDeployer(Network network); } diff --git a/api/src/com/cloud/network/element/RemoteAccessVPNServiceProvider.java b/api/src/com/cloud/network/element/RemoteAccessVPNServiceProvider.java index 522a4593a5d..57d44e89f46 100644 --- a/api/src/com/cloud/network/element/RemoteAccessVPNServiceProvider.java +++ b/api/src/com/cloud/network/element/RemoteAccessVPNServiceProvider.java @@ -13,4 +13,6 @@ public interface RemoteAccessVPNServiceProvider extends NetworkElement { boolean startVpn(Network network, RemoteAccessVpn vpn) throws ResourceUnavailableException; boolean stopVpn(Network network, RemoteAccessVpn vpn) throws ResourceUnavailableException; + + IpDeployer getIpDeployer(Network network); } diff --git a/api/src/com/cloud/network/element/SourceNatServiceProvider.java b/api/src/com/cloud/network/element/SourceNatServiceProvider.java index f42c445997c..3c91a683467 100644 --- a/api/src/com/cloud/network/element/SourceNatServiceProvider.java +++ b/api/src/com/cloud/network/element/SourceNatServiceProvider.java @@ -1,19 +1,7 @@ package com.cloud.network.element; -import java.util.List; - -import com.cloud.exception.ResourceUnavailableException; import com.cloud.network.Network; -import com.cloud.network.PublicIpAddress; public interface SourceNatServiceProvider extends NetworkElement { - - /** - * Apply ip addresses to this network - * @param network - * @param ipAddress - * @return - * @throws ResourceUnavailableException - */ - boolean applyIps(Network network, List ipAddress) throws ResourceUnavailableException; + IpDeployer getIpDeployer(Network network); } diff --git a/api/src/com/cloud/network/element/StaticNatServiceProvider.java b/api/src/com/cloud/network/element/StaticNatServiceProvider.java index c5c0608fe76..74da0718917 100644 --- a/api/src/com/cloud/network/element/StaticNatServiceProvider.java +++ b/api/src/com/cloud/network/element/StaticNatServiceProvider.java @@ -4,7 +4,6 @@ import java.util.List; import com.cloud.exception.ResourceUnavailableException; import com.cloud.network.Network; -import com.cloud.network.PublicIpAddress; import com.cloud.network.rules.StaticNat; public interface StaticNatServiceProvider extends NetworkElement { @@ -17,12 +16,5 @@ public interface StaticNatServiceProvider extends NetworkElement { */ boolean applyStaticNats(Network config, List rules) throws ResourceUnavailableException; - /** - * Apply ip addresses to this network service provider - * @param network - * @param ipAddress - * @return - * @throws ResourceUnavailableException - */ - boolean applyIps(Network network, List ipAddress) throws ResourceUnavailableException; + IpDeployer getIpDeployer(Network network); } diff --git a/server/src/com/cloud/network/NetworkManager.java b/server/src/com/cloud/network/NetworkManager.java index 747bbff4538..7192c9fcf48 100644 --- a/server/src/com/cloud/network/NetworkManager.java +++ b/server/src/com/cloud/network/NetworkManager.java @@ -19,6 +19,7 @@ */ package com.cloud.network; +import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Set; @@ -264,4 +265,8 @@ public interface NetworkManager extends NetworkService { List listNetworkOfferingServices(long networkOfferingId); boolean areServicesEnabledInZone(long zoneId, long networkOfferingId, String tags, List services); + + public Map> getIpToServices(Network network, List publicIps, boolean rulesRevoked); + + public Map> getProviderToIpList(Network network, Map> ipToServices); } diff --git a/server/src/com/cloud/network/NetworkManagerImpl.java b/server/src/com/cloud/network/NetworkManagerImpl.java index 99eb3422abb..a787e95ff35 100755 --- a/server/src/com/cloud/network/NetworkManagerImpl.java +++ b/server/src/com/cloud/network/NetworkManagerImpl.java @@ -126,10 +126,12 @@ import com.cloud.network.dao.PhysicalNetworkTrafficTypeDao; import com.cloud.network.dao.PhysicalNetworkTrafficTypeVO; import com.cloud.network.element.DhcpServiceProvider; import com.cloud.network.element.FirewallServiceProvider; +import com.cloud.network.element.IpDeployer; import com.cloud.network.element.LoadBalancingServiceProvider; import com.cloud.network.element.NetworkElement; import com.cloud.network.element.PortForwardingServiceProvider; import com.cloud.network.element.RemoteAccessVPNServiceProvider; +import com.cloud.network.element.SourceNatServiceProvider; import com.cloud.network.element.StaticNatServiceProvider; import com.cloud.network.element.UserDataServiceProvider; import com.cloud.network.element.VirtualRouterElement; @@ -310,7 +312,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag private static HashMap> s_serviceToImplementedProvidersMap = new HashMap>(); private static HashMap s_providerToNetworkElementMap = new HashMap(); - private NetworkElement getElementImplementingProvider(String providerName){ + public NetworkElement getElementImplementingProvider(String providerName){ String elementName = s_providerToNetworkElementMap.get(providerName); NetworkElement element = _networkElements.get(elementName); return element; @@ -603,104 +605,218 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag return success; } - protected boolean applyIpAssociations(Network network, boolean rulesRevoked, boolean continueOnError, List publicIps) throws ResourceUnavailableException { - boolean success = true; - List firewallPublicIps = new ArrayList(); - List loadbalncerPublicIps = new ArrayList(); + private Map> getProviderServiceMap(long networkId) { + Map> map = new HashMap>(); + List nsms = _ntwkSrvcDao.getServicesInNetwork(networkId); + for (NetworkServiceMapVO nsm : nsms) { + Set services = map.get(Provider.getProvider(nsm.getProvider())); + if (services == null) { + services = new HashSet(); + } + services.add(Service.getService(nsm.getService())); + map.put(Provider.getProvider(nsm.getProvider()), services); + } + return map; + } + + private Map> getServiceProviderMap(long networkId) { + Map> map = new HashMap>(); + List nsms = _ntwkSrvcDao.getServicesInNetwork(networkId); + for (NetworkServiceMapVO nsm : nsms) { + Set providers = map.get(Service.getService(nsm.getService())); + if (providers == null) { + providers = new HashSet(); + } + providers.add(Provider.getProvider(nsm.getProvider())); + map.put(Service.getService(nsm.getService()), providers); + } + return map; + } + + /* Get a list of IPs, classify them by service */ + @Override + public Map> getIpToServices(Network network, List publicIps, boolean rulesRevoked) { + Map> ipToServices = new HashMap>(); if (publicIps != null && !publicIps.isEmpty()) { + boolean gotSNAT = false; for (PublicIp ip : publicIps) { + Set services = ipToServices.get(ip); + if (services == null) { + services = new HashSet(); + } if (ip.isSourceNat()) { - // Source nat ip address should always be sent first - firewallPublicIps.add(0, ip); - } else if (ip.isOneToOneNat()) { - firewallPublicIps.add(ip); - } else { - //if IP in allocating state then it will not have any rules attached so skip IPAssoc to network service provider - if (ip.getState() == State.Allocating) { - continue; - } - - // check if any active rules are applied on the public IP - Purpose purpose = getPublicIpPurpose(ip, false); - if (purpose == null) { - // since no active rules are there check if any rules are applied on the public IP but are in revoking state - purpose = getPublicIpPurpose(ip, true); - if (purpose == null) { - // IP is not being used for any purpose so skip IPAssoc to network service provider - continue; - } else { - if (rulesRevoked) { - // no active rules/revoked rules are associated with this public IP, so remove the association with the provider - ip.setState(State.Releasing); - } else { - if (ip.getState() == State.Releasing) { - // rules are not revoked yet, so don't let the network service provider revoke the IP association - // mark IP is allocated so that IP association will not be removed from the provider - ip.setState(State.Allocated); - } - } - } + if (!gotSNAT) { + services.add(Service.SourceNat); + gotSNAT = true; + } else { + //TODO throw proper exception + throw new CloudRuntimeException("Multiply generic source NAT IPs in network " + network.getId() + "!"); } + } + ipToServices.put(ip, services); + + //if IP in allocating state then it will not have any rules attached so skip IPAssoc to network service provider + if (ip.getState() == State.Allocating) { + continue; + } - switch(purpose) { - case LoadBalancing: - loadbalncerPublicIps.add(ip); - break; - - case PortForwarding: - case StaticNat: - case Firewall: - firewallPublicIps.add(ip); - break; - default: + // check if any active rules are applied on the public IP + Set purposes = getPublicIpPurposeInRules(ip, false); + if (purposes == null || purposes.isEmpty()) { + // since no active rules are there check if any rules are applied on the public IP but are in revoking state + purposes = getPublicIpPurposeInRules(ip, true); + if (purposes == null || purposes.isEmpty()) { + // IP is not being used for any purpose so skip IPAssoc to network service provider + continue; + } else { + if (rulesRevoked) { + // no active rules/revoked rules are associated with this public IP, so remove the association with the provider + ip.setState(State.Releasing); + } else { + if (ip.getState() == State.Releasing) { + // rules are not revoked yet, so don't let the network service provider revoke the IP association + // mark IP is allocated so that IP association will not be removed from the provider + ip.setState(State.Allocated); + } + } } } + if (purposes.contains(Purpose.StaticNat)) { + services.add(Service.StaticNat); + } + if (purposes.contains(Purpose.LoadBalancing)) { + services.add(Service.Lb); + } + if (purposes.contains(Purpose.PortForwarding)) { + services.add(Service.PortForwarding); + } + if (purposes.contains(Purpose.Vpn)) { + services.add(Service.Vpn); + } + if (services.isEmpty()) { + continue; + } + ipToServices.put(ip, services); + } + } + return ipToServices; + } + + public boolean canIpUsedForService(Network network, PublicIp ip, Service service) { + // We need to check if it's non-conserve mode, then the new ip should not be used by any other services + NetworkOffering offering = _networkOfferingDao.findById(network.getNetworkOfferingId()); + if (offering.isConserveMode()) { + List ipList = new ArrayList(); + ipList.add(ip); + Map> ipToServices = getIpToServices(network, ipList, false); + Set currentServices = ipToServices.get(ip); + // Not used currently, safe + if (currentServices == null || currentServices.isEmpty()) { + return true; + } + } + Map> serviceToProviders = getServiceProviderMap(network.getId()); + Set currentProviders = serviceToProviders.get(service); + if (currentProviders.size() > 1) { + throw new CloudRuntimeException("Can't support multiply providers for same service now!"); + } + Provider currentProvider = (Provider)currentProviders.toArray()[0]; + + return true; + } + + /* Return a mapping between NetworkElement in the network and the IP they should applied */ + @Override + public Map> getProviderToIpList(Network network, Map> ipToServices) { + NetworkOffering offering = _networkOfferingDao.findById(network.getNetworkOfferingId()); + if (!offering.isConserveMode()) { + for (PublicIp ip : ipToServices.keySet()) { + Set services = ipToServices.get(ip); + if (services != null && services.size() > 1) { + //TODO throw proper exception + throw new CloudRuntimeException(""); + } } } - - String lbProvider = _ntwkSrvcDao.getProviderForServiceInNetwork(network.getId(), Service.Lb); - String fwProvider = _ntwkSrvcDao.getProviderForServiceInNetwork(network.getId(), Service.Firewall); - - for (NetworkElement element : _networkElements) { - try { - if (element instanceof FirewallServiceProvider && element instanceof LoadBalancingServiceProvider) { - List allIps = new ArrayList(); - - if (lbProvider.equalsIgnoreCase(element.getProvider().getName()) && fwProvider.equalsIgnoreCase(element.getProvider().getName())) { - allIps.addAll(firewallPublicIps); - allIps.addAll(loadbalncerPublicIps); - } else if (fwProvider.equalsIgnoreCase(element.getProvider().getName())) { - allIps.addAll(firewallPublicIps); - } else if (lbProvider.equalsIgnoreCase(element.getProvider().getName())) { - allIps.addAll(loadbalncerPublicIps); - } else { - continue; - } - - FirewallServiceProvider fwElement = (FirewallServiceProvider)element; - fwElement.applyIps(network, allIps); - } else if (element instanceof FirewallServiceProvider) { - FirewallServiceProvider fwElement = (FirewallServiceProvider)element; - if (fwProvider.equalsIgnoreCase(element.getProvider().getName())) { - fwElement.applyIps(network, firewallPublicIps); - } - } else if (element instanceof LoadBalancingServiceProvider) { - LoadBalancingServiceProvider lbElement = (LoadBalancingServiceProvider) element; - if (lbProvider.equalsIgnoreCase(element.getProvider().getName())) { - if (loadbalncerPublicIps != null && !loadbalncerPublicIps.isEmpty()) { - lbElement.applyLoadBalancerIp(network, publicIps); - } - } - } else { + Map> serviceToIps = new HashMap>(); + for (PublicIp ip : ipToServices.keySet()) { + for (Service service : ipToServices.get(ip)) { + Set ips = serviceToIps.get(service); + if (ips == null) { + ips = new HashSet(); + } + ips.add(ip); + serviceToIps.put(service, ips); + } + } + //TODO Check different provider for same IP + Map> providerToServices = getProviderServiceMap(network.getId()); + Map> providerToIpList = new HashMap>(); + for (Provider provider: providerToServices.keySet()) { + Set services = providerToServices.get(provider); + //TODO add checking for services, multiply services may bind to one provider, which is invalid in non-conserved mode + ArrayList ipList = new ArrayList(); + Set ipSet = new HashSet(); + for (Service service: services) { + Set serviceIps = serviceToIps.get(service); + if (serviceIps == null || serviceIps.isEmpty()) { continue; } + ipSet.addAll(serviceIps); + } + Set sourceNatIps = serviceToIps.get(Service.SourceNat); + if (sourceNatIps != null && !sourceNatIps.isEmpty()) { + ipList.addAll(0, sourceNatIps); + ipSet.removeAll(sourceNatIps); + } + ipList.addAll(ipSet); + providerToIpList.put(provider, ipList); + } + return providerToIpList; + } + + protected boolean applyIpAssociations(Network network, boolean rulesRevoked, boolean continueOnError, List publicIps) throws ResourceUnavailableException { + boolean success = true; + + Map> ipToServices = getIpToServices(network, publicIps, rulesRevoked); + Map> providerToIpList = getProviderToIpList(network, ipToServices); + + for (Provider provider : providerToIpList.keySet()) { + try { + ArrayList ips = providerToIpList.get(provider); + if (ips == null || ips.isEmpty()) { + continue; + } + IpDeployer deployer = null; + NetworkElement element = getElementImplementingProvider(provider.getName()); + if (element instanceof SourceNatServiceProvider) { + deployer = ((SourceNatServiceProvider)element).getIpDeployer(network); + } else if (element instanceof StaticNatServiceProvider) { + deployer = ((StaticNatServiceProvider)element).getIpDeployer(network); + } else if (element instanceof LoadBalancingServiceProvider) { + deployer = ((LoadBalancingServiceProvider)element).getIpDeployer(network); + } else if (element instanceof PortForwardingServiceProvider) { + deployer = ((PortForwardingServiceProvider)element).getIpDeployer(network); + } else if (element instanceof RemoteAccessVPNServiceProvider) { + deployer = ((RemoteAccessVPNServiceProvider)element).getIpDeployer(network); + } else { + throw new CloudRuntimeException("Fail to get ip deployer for element: " + element); + } + Set services = new HashSet(); + for (PublicIp ip : ips) { + if (!ipToServices.containsKey(ip)) { + continue; + } + services.addAll(ipToServices.get(ip)); + } + deployer.applyIps(network, ips, services); } catch (ResourceUnavailableException e) { success = false; if (!continueOnError) { throw e; } else { - s_logger.debug("Resource is not available: " + element.getName(), e); + s_logger.debug("Resource is not available: " + provider.getName(), e); } } } @@ -708,51 +824,35 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag return success; } - Purpose getPublicIpPurpose(PublicIp ip, boolean includeRevoked) { + Set getPublicIpPurposeInRules(PublicIp ip, boolean includeRevoked) { + Set result = new HashSet(); if (includeRevoked) { - List loadBalancingRules = _firewallDao.listByIpAndPurpose(ip.getId(), Purpose.LoadBalancing); - if (loadBalancingRules != null && !loadBalancingRules.isEmpty()) { - return Purpose.LoadBalancing; + List rules = _firewallDao.listByIp(ip.getId()); + if (rules == null || rules.isEmpty()) { + return null; } - - List firewall_rules = _firewallDao.listByIpAndPurpose(ip.getId(), Purpose.Firewall); - if (firewall_rules != null && !firewall_rules.isEmpty()) { - return Purpose.Firewall; - } - - List staticNatRules = _firewallDao.listByIpAndPurpose(ip.getId(), Purpose.StaticNat); - if (staticNatRules != null && !staticNatRules.isEmpty()) { - return Purpose.StaticNat; - } - - List pfRules = _portForwardingDao.listByIp(ip.getId()); - if (pfRules != null && !pfRules.isEmpty()) { - return Purpose.PortForwarding; + + for (FirewallRuleVO rule : rules) { + // Firewall should attach to others, firewall rule alone make no sense + if (rule.getPurpose() != Purpose.Firewall) { + result.add(rule.getPurpose()); + } } } else { - List loadBalancingRules = _firewallDao.listByIpAndPurposeAndNotRevoked(ip.getId(), Purpose.LoadBalancing); - if (loadBalancingRules != null && !loadBalancingRules.isEmpty()) { - return Purpose.LoadBalancing; + List rules = _firewallDao.listByIpAndNotRevoked(ip.getId()); + if (rules == null || rules.isEmpty()) { + return null; } - - List firewall_rules = _firewallDao.listByIpAndPurposeAndNotRevoked(ip.getId(), Purpose.Firewall); - if (firewall_rules != null && !firewall_rules.isEmpty()) { - return Purpose.Firewall; - } - - List staticNatRules = _firewallDao.listByIpAndPurposeAndNotRevoked(ip.getId(), Purpose.StaticNat); - if (staticNatRules != null && !staticNatRules.isEmpty()) { - return Purpose.StaticNat; - } - - List pfRules = _portForwardingDao.listByIpAndNotRevoked(ip.getId()); - if (pfRules != null && !pfRules.isEmpty()) { - return Purpose.PortForwarding; + + for (FirewallRuleVO rule : rules) { + // Firewall is attached to others, firewall rule alone make no sense + if (rule.getPurpose() != Purpose.Firewall) { + result.add(rule.getPurpose()); + } } } - // we are here means, public IP has no active/revoked rules to know the purpose - return null; + return result; } @Override diff --git a/server/src/com/cloud/network/dao/FirewallRulesDao.java b/server/src/com/cloud/network/dao/FirewallRulesDao.java index cea32ea4887..001647bcab3 100644 --- a/server/src/com/cloud/network/dao/FirewallRulesDao.java +++ b/server/src/com/cloud/network/dao/FirewallRulesDao.java @@ -50,4 +50,8 @@ public interface FirewallRulesDao extends GenericDao { FirewallRuleVO findByRelatedId(long ruleId); List listSystemRules(); + + List listByIp(long ipAddressId); + + List listByIpAndNotRevoked(long ipAddressId); } diff --git a/server/src/com/cloud/network/dao/FirewallRulesDaoImpl.java b/server/src/com/cloud/network/dao/FirewallRulesDaoImpl.java index 949f86d6ae2..e38e5a34699 100644 --- a/server/src/com/cloud/network/dao/FirewallRulesDaoImpl.java +++ b/server/src/com/cloud/network/dao/FirewallRulesDaoImpl.java @@ -241,5 +241,21 @@ public class FirewallRulesDaoImpl extends GenericDaoBase i return findOneBy(sc); } + + @Override + public List listByIp(long ipId) { + SearchCriteria sc = AllFieldsSearch.create(); + sc.setParameters("ipId", ipId); + + return listBy(sc); + } + @Override + public List listByIpAndNotRevoked(long ipId) { + SearchCriteria sc = NotRevokedSearch.create(); + sc.setParameters("ipId", ipId); + sc.setParameters("state", State.Revoke); + + return listBy(sc); + } } diff --git a/server/src/com/cloud/network/element/ElasticLoadBalancerElement.java b/server/src/com/cloud/network/element/ElasticLoadBalancerElement.java index 3fc8f11bbb4..ba40ee73602 100644 --- a/server/src/com/cloud/network/element/ElasticLoadBalancerElement.java +++ b/server/src/com/cloud/network/element/ElasticLoadBalancerElement.java @@ -20,6 +20,7 @@ package com.cloud.network.element; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Set; import javax.ejb.Local; import javax.naming.ConfigurationException; @@ -54,7 +55,7 @@ import com.cloud.vm.VirtualMachineProfile; @Local(value=NetworkElement.class) -public class ElasticLoadBalancerElement extends AdapterBase implements LoadBalancingServiceProvider { +public class ElasticLoadBalancerElement extends AdapterBase implements LoadBalancingServiceProvider, IpDeployer { private static final Logger s_logger = Logger.getLogger(ElasticLoadBalancerElement.class); private static final Map> capabilities = setCapabilities(); @Inject NetworkManager _networkManager; @@ -181,9 +182,14 @@ public class ElasticLoadBalancerElement extends AdapterBase implements LoadBalan return true; } - @Override - public boolean applyLoadBalancerIp(Network network, List ipAddress) throws ResourceUnavailableException { - // TODO Auto-generated method stub - return false; - } + @Override + public boolean applyIps(Network network, List ipAddress, Set services) throws ResourceUnavailableException { + // TODO Auto-generated method stub + return false; + } + + @Override + public IpDeployer getIpDeployer(Network network) { + return this; + } } diff --git a/server/src/com/cloud/network/element/F5ExternalLoadBalancerElement.java b/server/src/com/cloud/network/element/F5ExternalLoadBalancerElement.java index 68567f88dbc..be62b4dd246 100644 --- a/server/src/com/cloud/network/element/F5ExternalLoadBalancerElement.java +++ b/server/src/com/cloud/network/element/F5ExternalLoadBalancerElement.java @@ -23,6 +23,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Set; import javax.ejb.Local; @@ -88,7 +89,7 @@ import com.cloud.vm.VirtualMachineProfile; import com.google.gson.Gson; @Local(value=NetworkElement.class) -public class F5ExternalLoadBalancerElement extends ExternalLoadBalancerDeviceManagerImpl implements LoadBalancingServiceProvider, F5ExternalLoadBalancerElementService, ExternalLoadBalancerDeviceManager { +public class F5ExternalLoadBalancerElement extends ExternalLoadBalancerDeviceManagerImpl implements LoadBalancingServiceProvider, IpDeployer, F5ExternalLoadBalancerElementService, ExternalLoadBalancerDeviceManager { private static final Logger s_logger = Logger.getLogger(F5ExternalLoadBalancerElement.class); @@ -442,9 +443,14 @@ public class F5ExternalLoadBalancerElement extends ExternalLoadBalancerDeviceMan return true; } - @Override - public boolean applyLoadBalancerIp(Network network, List ipAddress) throws ResourceUnavailableException { + @Override + public boolean applyIps(Network network, List ipAddress, Set service) throws ResourceUnavailableException { // return true, as IP will be associated as part of LB rule configuration - return true; - } + return false; + } + + @Override + public IpDeployer getIpDeployer(Network network) { + return this; + } } diff --git a/server/src/com/cloud/network/element/JuniperSRXExternalFirewallElement.java b/server/src/com/cloud/network/element/JuniperSRXExternalFirewallElement.java index 17daa651b69..25da8ea2ba4 100644 --- a/server/src/com/cloud/network/element/JuniperSRXExternalFirewallElement.java +++ b/server/src/com/cloud/network/element/JuniperSRXExternalFirewallElement.java @@ -23,6 +23,8 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Set; + import javax.ejb.Local; import org.apache.log4j.Logger; @@ -87,7 +89,7 @@ import com.cloud.vm.VirtualMachineProfile; @Local(value=NetworkElement.class) public class JuniperSRXExternalFirewallElement extends ExternalFirewallDeviceManagerImpl implements SourceNatServiceProvider, FirewallServiceProvider, - PortForwardingServiceProvider, RemoteAccessVPNServiceProvider, JuniperSRXFirewallElementService{ + PortForwardingServiceProvider, RemoteAccessVPNServiceProvider, IpDeployer, JuniperSRXFirewallElementService{ private static final Logger s_logger = Logger.getLogger(JuniperSRXExternalFirewallElement.class); @@ -496,8 +498,13 @@ public class JuniperSRXExternalFirewallElement extends ExternalFirewallDeviceMan return true; } + @Override + public IpDeployer getIpDeployer(Network network) { + return this; + } + @Override - public boolean applyIps(Network network, List ipAddress) throws ResourceUnavailableException { + public boolean applyIps(Network network, List ipAddress, Set service) throws ResourceUnavailableException { // TODO Auto-generated method stub return false; } diff --git a/server/src/com/cloud/network/element/NetscalerExternalLoadBalancerElement.java b/server/src/com/cloud/network/element/NetscalerExternalLoadBalancerElement.java index a87e9a98327..87330cfc944 100644 --- a/server/src/com/cloud/network/element/NetscalerExternalLoadBalancerElement.java +++ b/server/src/com/cloud/network/element/NetscalerExternalLoadBalancerElement.java @@ -24,6 +24,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Set; import javax.ejb.Local; @@ -88,7 +89,7 @@ import com.cloud.vm.VirtualMachineProfile; import com.google.gson.Gson; @Local(value=NetworkElement.class) -public class NetscalerExternalLoadBalancerElement extends ExternalLoadBalancerDeviceManagerImpl implements LoadBalancingServiceProvider, NetscalerLoadBalancerElementService, ExternalLoadBalancerDeviceManager { +public class NetscalerExternalLoadBalancerElement extends ExternalLoadBalancerDeviceManagerImpl implements LoadBalancingServiceProvider, NetscalerLoadBalancerElementService, ExternalLoadBalancerDeviceManager, IpDeployer { private static final Logger s_logger = Logger.getLogger(NetscalerExternalLoadBalancerElement.class); @@ -467,9 +468,14 @@ public class NetscalerExternalLoadBalancerElement extends ExternalLoadBalancerDe return true; } - @Override - public boolean applyLoadBalancerIp(Network network, List ipAddress) throws ResourceUnavailableException { + @Override + public boolean applyIps(Network network, List ipAddress, Set service) throws ResourceUnavailableException { // return true, as IP will be associated as part of LB rule configuration - return true; - } + return false; + } + + @Override + public IpDeployer getIpDeployer(Network network) { + return this; + } } \ No newline at end of file diff --git a/server/src/com/cloud/network/element/VirtualRouterElement.java b/server/src/com/cloud/network/element/VirtualRouterElement.java index 897b37fba57..b7e183f48a9 100644 --- a/server/src/com/cloud/network/element/VirtualRouterElement.java +++ b/server/src/com/cloud/network/element/VirtualRouterElement.java @@ -21,6 +21,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Set; import javax.ejb.Local; @@ -84,9 +85,8 @@ import com.cloud.vm.dao.DomainRouterDao; import com.cloud.vm.dao.UserVmDao; import com.google.gson.Gson; - @Local(value=NetworkElement.class) -public class VirtualRouterElement extends AdapterBase implements VirtualRouterElementService, DhcpServiceProvider, UserDataServiceProvider, SourceNatServiceProvider, StaticNatServiceProvider, FirewallServiceProvider, LoadBalancingServiceProvider, PortForwardingServiceProvider, RemoteAccessVPNServiceProvider { +public class VirtualRouterElement extends AdapterBase implements VirtualRouterElementService, DhcpServiceProvider, UserDataServiceProvider, SourceNatServiceProvider, StaticNatServiceProvider, FirewallServiceProvider, LoadBalancingServiceProvider, PortForwardingServiceProvider, RemoteAccessVPNServiceProvider, IpDeployer { private static final Logger s_logger = Logger.getLogger(VirtualRouterElement.class); private static final Map> capabilities = setCapabilities(); @@ -256,8 +256,15 @@ public class VirtualRouterElement extends AdapterBase implements VirtualRouterEl } @Override - public boolean applyIps(Network network, List ipAddress) throws ResourceUnavailableException { - if (canHandle(network, Service.Firewall)) { + public boolean applyIps(Network network, List ipAddress, Set services) throws ResourceUnavailableException { + boolean canHandle = true; + for (Service service : services) { + if (!canHandle(network, service)) { + canHandle = false; + break; + } + } + if (canHandle) { List routers = _routerDao.listByNetworkAndRole(network.getId(), Role.VIRTUAL_ROUTER); if (routers == null || routers.isEmpty()) { s_logger.debug("Virtual router elemnt doesn't need to associate ip addresses on the backend; virtual router doesn't exist in the network " + network.getId()); @@ -270,21 +277,6 @@ public class VirtualRouterElement extends AdapterBase implements VirtualRouterEl } } - @Override - public boolean applyLoadBalancerIp(Network network, List ipAddress) throws ResourceUnavailableException { - if (canHandle(network, Service.Lb)) { - List routers = _routerDao.listByNetworkAndRole(network.getId(), Role.VIRTUAL_ROUTER); - if (routers == null || routers.isEmpty()) { - s_logger.debug("Virtual router element doesn't need to associate load balancer ip addresses on the backend; virtual router doesn't exist in the network " + network.getId()); - return true; - } - - return _routerMgr.associateIP(network, ipAddress, routers); - } else { - return false; - } - } - @Override public Provider getProvider() { return Provider.VirtualRouter; @@ -660,4 +652,8 @@ public class VirtualRouterElement extends AdapterBase implements VirtualRouterEl return true; } + @Override + public IpDeployer getIpDeployer(Network network) { + return this; + } } diff --git a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java index 42b5d9bca22..4bc68607eda 100755 --- a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java +++ b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java @@ -146,6 +146,7 @@ import com.cloud.network.dao.PhysicalNetworkServiceProviderDao; import com.cloud.network.dao.RemoteAccessVpnDao; import com.cloud.network.dao.VirtualRouterProviderDao; import com.cloud.network.dao.VpnUserDao; +import com.cloud.network.element.NetworkElement; import com.cloud.network.lb.LoadBalancingRule; import com.cloud.network.lb.LoadBalancingRule.LbDestination; import com.cloud.network.lb.LoadBalancingRule.LbStickinessPolicy; @@ -1781,13 +1782,20 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian long zoneId = router.getDataCenterIdToDeployIn(); final List userIps = _networkMgr.listPublicIpAddressesInVirtualNetwork(ownerId, zoneId, null, null); - List publicIps = new ArrayList(); + List allPublicIps = new ArrayList(); if (userIps != null && !userIps.isEmpty()) { for (IPAddressVO userIp : userIps) { PublicIp publicIp = new PublicIp(userIp, _vlanDao.findById(userIp.getVlanId()), NetUtils.createSequenceBasedMacAddress(userIp.getMacAddress())); - publicIps.add(publicIp); + allPublicIps.add(publicIp); } } + + //Get public Ips that should be handled by router + Network network = _networkDao.findById(networkId); + Map> ipToServices = _networkMgr.getIpToServices(network, allPublicIps, false); + Map> providerToIpList = _networkMgr.getProviderToIpList(network, ipToServices); + // Only cover virtual router for now, if ELB use it this need to be modified + ArrayList publicIps = providerToIpList.get(Provider.VirtualRouter); s_logger.debug("Found " + publicIps.size() + " ip(s) to apply as a part of domR " + router + " start."); @@ -1799,8 +1807,13 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian List staticNats = new ArrayList(); List firewallRules = new ArrayList(); + // Re-apply public ip addresses - should come before PF/LB/VPN + if (_networkMgr.isProviderSupportServiceInNetwork(router.getNetworkId(), Service.Firewall, provider)) { + createAssociateIPCommands(router, publicIps, cmds, 0); + } + //Get information about all the rules (StaticNats and StaticNatRules; PFVPN to reapply on domR start) - for (PublicIpAddress ip : publicIps) { + for (PublicIp ip : publicIps) { if (_networkMgr.isProviderSupportServiceInNetwork(router.getNetworkId(), Service.PortForwarding, provider)) { pfRules.addAll(_pfRulesDao.listForApplication(ip.getId())); }