From 28bbf6c52798c9bd298952844250fbc3cb92dce0 Mon Sep 17 00:00:00 2001 From: Murali Reddy Date: Thu, 25 Oct 2012 20:35:34 +0530 Subject: [PATCH] Summary: partical check-in for L4-L7 network services in the shared network in the advanced zone Details: - changed associateIPAddr API to accept shared network Id and account Id. Ip will be owned by tuple (account Id, network Id) - chaged createNetwork API to accpet CIDR when network offering has external networking device providers Bug ID:CLOUDSTACK-312 enable L4-L7 network services in the shared network in the advanced zone --- .../api/commands/AssociateIPAddrCmd.java | 3 +- api/src/com/cloud/network/NetworkService.java | 3 +- .../com/cloud/network/NetworkManagerImpl.java | 117 +++++++++++++++++- .../cloud/network/MockNetworkManagerImpl.java | 34 ++--- .../com/cloud/vpc/MockNetworkManagerImpl.java | 46 ++----- 5 files changed, 140 insertions(+), 63 deletions(-) diff --git a/api/src/com/cloud/api/commands/AssociateIPAddrCmd.java b/api/src/com/cloud/api/commands/AssociateIPAddrCmd.java index 7aaa5b5790b..878a9fc4667 100644 --- a/api/src/com/cloud/api/commands/AssociateIPAddrCmd.java +++ b/api/src/com/cloud/api/commands/AssociateIPAddrCmd.java @@ -216,7 +216,8 @@ public class AssociateIPAddrCmd extends BaseAsyncCreateCmd { @Override public void create() throws ResourceAllocationException{ try { - IpAddress ip = _networkService.allocateIP(_accountService.getAccount(getEntityOwnerId()), false, getZoneId()); + IpAddress ip = _networkService.allocateIP(_accountService.getAccount(getEntityOwnerId()), getZoneId(), getNetworkId()); + if (ip != null) { this.setEntityId(ip.getId()); } else { diff --git a/api/src/com/cloud/network/NetworkService.java b/api/src/com/cloud/network/NetworkService.java index a20056152eb..e7b6defd413 100755 --- a/api/src/com/cloud/network/NetworkService.java +++ b/api/src/com/cloud/network/NetworkService.java @@ -41,7 +41,8 @@ public interface NetworkService { List getIsolatedNetworksOwnedByAccountInZone(long zoneId, Account owner); - IpAddress allocateIP(Account ipOwner, boolean isSystem, long zoneId) throws ResourceAllocationException, + + IpAddress allocateIP(Account ipOwner, long zoneId, Long networkId) throws ResourceAllocationException, InsufficientAddressCapacityException, ConcurrentOperationException; boolean releaseIpAddress(long ipAddressId) throws InsufficientAddressCapacityException; diff --git a/server/src/com/cloud/network/NetworkManagerImpl.java b/server/src/com/cloud/network/NetworkManagerImpl.java index 9841f106523..ece31c32da7 100755 --- a/server/src/com/cloud/network/NetworkManagerImpl.java +++ b/server/src/com/cloud/network/NetworkManagerImpl.java @@ -1016,6 +1016,38 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag @Override @ActionEvent(eventType = EventTypes.EVENT_NET_IP_ASSIGN, eventDescription = "allocating Ip", create = true) + public IpAddress allocateIP(Account ipOwner, long zoneId, Long networkId) + throws ResourceAllocationException, InsufficientAddressCapacityException, ConcurrentOperationException { + if (networkId != null) { + Network network = _networksDao.findById(networkId); + if (network == null) { + throw new InvalidParameterValueException("Invalid network id is given"); + } + + if (network.getGuestType() == Network.GuestType.Shared) { + DataCenter zone = _configMgr.getZone(zoneId); + if (zone == null) { + throw new InvalidParameterValueException("Invalid zone Id is given"); + } + + // if shared network in the advanced zone, then check the caller against the network for 'AccessType.UseNetwork' + if (isSharedNetworkOfferingWithServices(network.getNetworkOfferingId()) && zone.getNetworkType() == NetworkType.Advanced) { + Account caller = UserContext.current().getCaller(); + long callerUserId = UserContext.current().getCallerUserId(); + _accountMgr.checkAccess(caller, AccessType.UseNetwork, false, network); + if (s_logger.isDebugEnabled()) { + s_logger.debug("Associate IP address called by the user " + callerUserId + " account " + ipOwner.getId()); + } + return allocateIp(ipOwner, false, caller, callerUserId, zone); + } else { + throw new InvalidParameterValueException("Associate IP address can only called on the shared networks in the advanced zone" + + " with Firewall/Source Nat/Static Nat/Port Forwarding/Load balancing services enabled"); + } + } + } + + return allocateIP(ipOwner, false, zoneId); + } public IpAddress allocateIP(Account ipOwner, boolean isSystem, long zoneId) throws ResourceAllocationException, InsufficientAddressCapacityException, ConcurrentOperationException { @@ -2472,6 +2504,70 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag } } + private void checkSharedNetworkCidrOverlap(Long zoneId, String cidr) { + if (zoneId == null) { + return; + } + + if (cidr == null) { + return; + } + + List networks = _networksDao.listByZone(zoneId); + Map networkToCidr = new HashMap(); + for (NetworkVO network : networks) { + if (network.getGuestType() == GuestType.Isolated) { + continue; + } + if (network.getCidr() != null) { + networkToCidr.put(network.getId(), network.getCidr()); + } + } + + //TODO: check for CIDR overlap with all possible CIDR for guest networks in the zone + //when using external networking + + if (networkToCidr == null || networkToCidr.isEmpty()) { + return; + } + + for (long networkId : networkToCidr.keySet()) { + String ntwkCidr = networkToCidr.get(networkId); + if (NetUtils.isNetworksOverlap(ntwkCidr, cidr)) { + throw new InvalidParameterValueException("Warning: The specified existing network has conflict CIDR subnets with new network!"); + } + } + } + + public void checkVirtualNetworkCidrOverlap(Long zoneId, String cidr) { + if (zoneId == null) { + return; + } + if (cidr == null) { + return; + } + List networks = _networksDao.listByZone(zoneId); + Map networkToCidr = new HashMap(); + for (NetworkVO network : networks) { + if (network.getGuestType() != GuestType.Isolated) { + continue; + } + if (network.getCidr() != null) { + networkToCidr.put(network.getId(), network.getCidr()); + } + } + if (networkToCidr == null || networkToCidr.isEmpty()) { + return; + } + + for (long networkId : networkToCidr.keySet()) { + String ntwkCidr = networkToCidr.get(networkId); + if (NetUtils.isNetworksOverlap(ntwkCidr, cidr)) { + throw new InvalidParameterValueException("Warning: The specified existing network has conflict CIDR subnets with new network!"); + } + } + } + @Override @DB @ActionEvent(eventType = EventTypes.EVENT_NETWORK_CREATE, eventDescription = "creating network") @@ -2667,7 +2763,13 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag Collection ntwkProviders = finalizeServicesAndProvidersForNetwork(ntwkOff, physicalNetworkId).values(); if (cidr != null && providersConfiguredForExternalNetworking(ntwkProviders)) { - throw new InvalidParameterValueException("Cannot specify CIDR when using network offering with external devices!"); + if (ntwkOff.getGuestType() == GuestType.Shared && (zone.getNetworkType() == NetworkType.Advanced) && + isSharedNetworkOfferingWithServices(networkOfferingId)) { + // validate if CIDR specified overlaps with any of the CIDR's allocated for isolated networks and shared networks in the zone + checkSharedNetworkCidrOverlap(zoneId, cidr); + } else { + throw new InvalidParameterValueException("Cannot specify CIDR when using network offering with external devices!"); + } } @@ -4380,6 +4482,19 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag return false; } + public boolean isSharedNetworkOfferingWithServices(long networkOfferingId) { + NetworkOfferingVO networkOffering = _networkOfferingDao.findById(networkOfferingId); + if ( (networkOffering.getGuestType() == Network.GuestType.Shared) && ( + areServicesSupportedByNetworkOffering(networkOfferingId, Service.SourceNat) || + areServicesSupportedByNetworkOffering(networkOfferingId, Service.StaticNat) || + areServicesSupportedByNetworkOffering(networkOfferingId, Service.Firewall) || + areServicesSupportedByNetworkOffering(networkOfferingId, Service.PortForwarding) || + areServicesSupportedByNetworkOffering(networkOfferingId, Service.Lb))) { + return true; + } + return false; + } + @Override public boolean areServicesSupportedByNetworkOffering(long networkOfferingId, Service... services) { return (_ntwkOfferingSrvcDao.areServicesSupportedByNetworkOffering(networkOfferingId, services)); diff --git a/server/test/com/cloud/network/MockNetworkManagerImpl.java b/server/test/com/cloud/network/MockNetworkManagerImpl.java index a038e71c3a9..76b911a722e 100755 --- a/server/test/com/cloud/network/MockNetworkManagerImpl.java +++ b/server/test/com/cloud/network/MockNetworkManagerImpl.java @@ -16,14 +16,6 @@ // under the License. package com.cloud.network; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import javax.ejb.Local; -import javax.naming.ConfigurationException; - import com.cloud.acl.ControlledEntity.ACLType; import com.cloud.api.commands.CreateNetworkCmd; import com.cloud.api.commands.ListNetworksCmd; @@ -35,12 +27,7 @@ import com.cloud.dc.Vlan.VlanType; import com.cloud.deploy.DataCenterDeployment; import com.cloud.deploy.DeployDestination; import com.cloud.deploy.DeploymentPlan; -import com.cloud.exception.ConcurrentOperationException; -import com.cloud.exception.InsufficientAddressCapacityException; -import com.cloud.exception.InsufficientCapacityException; -import com.cloud.exception.InsufficientVirtualNetworkCapcityException; -import com.cloud.exception.ResourceAllocationException; -import com.cloud.exception.ResourceUnavailableException; +import com.cloud.exception.*; import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.network.Network.Capability; import com.cloud.network.Network.GuestType; @@ -61,13 +48,14 @@ import com.cloud.user.Account; import com.cloud.user.User; import com.cloud.utils.Pair; import com.cloud.utils.component.Manager; -import com.cloud.vm.Nic; -import com.cloud.vm.NicProfile; -import com.cloud.vm.ReservationContext; -import com.cloud.vm.VMInstanceVO; -import com.cloud.vm.VirtualMachine; -import com.cloud.vm.VirtualMachineProfile; -import com.cloud.vm.VirtualMachineProfileImpl; +import com.cloud.vm.*; + +import javax.ejb.Local; +import javax.naming.ConfigurationException; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Set; @Local(value = { NetworkManager.class, NetworkService.class }) public class MockNetworkManagerImpl implements NetworkManager, Manager, NetworkService { @@ -796,10 +784,10 @@ public class MockNetworkManagerImpl implements NetworkManager, Manager, NetworkS } /* (non-Javadoc) - * @see com.cloud.network.NetworkService#allocateIP(com.cloud.user.Account, boolean, long) + * @see com.cloud.network.NetworkService#allocateIP(com.cloud.user.Account, long, Long) */ @Override - public IpAddress allocateIP(Account ipOwner, boolean isSystem, long zoneId) throws ResourceAllocationException, InsufficientAddressCapacityException, ConcurrentOperationException { + public IpAddress allocateIP(Account ipOwner, long zoneId, Long networkId) throws ResourceAllocationException, InsufficientAddressCapacityException, ConcurrentOperationException { // TODO Auto-generated method stub return null; } diff --git a/server/test/com/cloud/vpc/MockNetworkManagerImpl.java b/server/test/com/cloud/vpc/MockNetworkManagerImpl.java index dc0e880996e..3536d66ea4f 100644 --- a/server/test/com/cloud/vpc/MockNetworkManagerImpl.java +++ b/server/test/com/cloud/vpc/MockNetworkManagerImpl.java @@ -16,17 +16,6 @@ // under the License. package com.cloud.vpc; -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 javax.naming.ConfigurationException; - -import org.apache.log4j.Logger; - import com.cloud.acl.ControlledEntity.ACLType; import com.cloud.api.commands.CreateNetworkCmd; import com.cloud.api.commands.ListNetworksCmd; @@ -38,30 +27,14 @@ import com.cloud.dc.Vlan.VlanType; import com.cloud.deploy.DataCenterDeployment; import com.cloud.deploy.DeployDestination; import com.cloud.deploy.DeploymentPlan; -import com.cloud.exception.ConcurrentOperationException; -import com.cloud.exception.InsufficientAddressCapacityException; -import com.cloud.exception.InsufficientCapacityException; -import com.cloud.exception.InsufficientVirtualNetworkCapcityException; -import com.cloud.exception.ResourceAllocationException; -import com.cloud.exception.ResourceUnavailableException; +import com.cloud.exception.*; import com.cloud.hypervisor.Hypervisor.HypervisorType; -import com.cloud.network.IPAddressVO; -import com.cloud.network.IpAddress; -import com.cloud.network.Network; +import com.cloud.network.*; import com.cloud.network.Network.Capability; import com.cloud.network.Network.GuestType; import com.cloud.network.Network.Provider; import com.cloud.network.Network.Service; -import com.cloud.network.NetworkManager; -import com.cloud.network.NetworkProfile; -import com.cloud.network.NetworkService; -import com.cloud.network.NetworkVO; import com.cloud.network.Networks.TrafficType; -import com.cloud.network.PhysicalNetwork; -import com.cloud.network.PhysicalNetworkServiceProvider; -import com.cloud.network.PhysicalNetworkSetupInfo; -import com.cloud.network.PhysicalNetworkTrafficType; -import com.cloud.network.PublicIpAddress; import com.cloud.network.addr.PublicIp; import com.cloud.network.dao.NetworkServiceMapDao; import com.cloud.network.element.NetworkElement; @@ -80,14 +53,13 @@ import com.cloud.utils.Pair; import com.cloud.utils.component.Adapters; import com.cloud.utils.component.Inject; import com.cloud.utils.component.Manager; -import com.cloud.vm.Nic; -import com.cloud.vm.NicProfile; -import com.cloud.vm.ReservationContext; -import com.cloud.vm.VMInstanceVO; -import com.cloud.vm.VirtualMachine; -import com.cloud.vm.VirtualMachineProfile; -import com.cloud.vm.VirtualMachineProfileImpl; +import com.cloud.vm.*; import com.cloud.vpc.dao.MockVpcVirtualRouterElement; +import org.apache.log4j.Logger; + +import javax.ejb.Local; +import javax.naming.ConfigurationException; +import java.util.*; @Local(value = { NetworkManager.class, NetworkService.class }) public class MockNetworkManagerImpl implements NetworkManager, Manager{ @@ -1493,7 +1465,7 @@ public class MockNetworkManagerImpl implements NetworkManager, Manager{ * @see com.cloud.network.NetworkService#allocateIP(com.cloud.user.Account, boolean, long) */ @Override - public IpAddress allocateIP(Account ipOwner, boolean isSystem, long zoneId) throws ResourceAllocationException, InsufficientAddressCapacityException, ConcurrentOperationException { + public IpAddress allocateIP(Account ipOwner, long zoneId, Long networkId) throws ResourceAllocationException, InsufficientAddressCapacityException, ConcurrentOperationException { // TODO Auto-generated method stub return null; }