diff --git a/api/src/com/cloud/api/commands/AuthorizeSecurityGroupIngressCmd.java b/api/src/com/cloud/api/commands/AuthorizeSecurityGroupIngressCmd.java index 17ff761afb9..fa155b3bbba 100644 --- a/api/src/com/cloud/api/commands/AuthorizeSecurityGroupIngressCmd.java +++ b/api/src/com/cloud/api/commands/AuthorizeSecurityGroupIngressCmd.java @@ -32,7 +32,6 @@ import com.cloud.api.BaseCmd; import com.cloud.api.Implementation; import com.cloud.api.Parameter; import com.cloud.api.ServerApiException; -import com.cloud.api.BaseCmd.CommandType; import com.cloud.api.response.IngressRuleResponse; import com.cloud.api.response.SecurityGroupResponse; import com.cloud.event.EventTypes; diff --git a/api/src/com/cloud/api/commands/CreateNetworkCmd.java b/api/src/com/cloud/api/commands/CreateNetworkCmd.java index 42ee2002da9..5abc7621a18 100644 --- a/api/src/com/cloud/api/commands/CreateNetworkCmd.java +++ b/api/src/com/cloud/api/commands/CreateNetworkCmd.java @@ -26,6 +26,8 @@ import com.cloud.api.Implementation; import com.cloud.api.Parameter; import com.cloud.api.ServerApiException; import com.cloud.api.response.NetworkResponse; +import com.cloud.exception.ConcurrentOperationException; +import com.cloud.exception.InsufficientCapacityException; import com.cloud.network.Network; @Implementation(description="Creates a network", responseObject=NetworkResponse.class) @@ -148,7 +150,7 @@ public class CreateNetworkCmd extends BaseCmd { } @Override - public void execute(){ + public void execute() throws InsufficientCapacityException, ConcurrentOperationException{ Network result = _networkService.createNetwork(this); if (result != null) { NetworkResponse response = _responseGenerator.createNetworkResponse(result); diff --git a/api/src/com/cloud/network/NetworkService.java b/api/src/com/cloud/network/NetworkService.java index a4c6dd1eff6..87973a88d3f 100644 --- a/api/src/com/cloud/network/NetworkService.java +++ b/api/src/com/cloud/network/NetworkService.java @@ -50,7 +50,7 @@ public interface NetworkService { IpAddress associateIP(AssociateIPAddrCmd cmd) throws ResourceAllocationException, InsufficientAddressCapacityException, ConcurrentOperationException, ResourceUnavailableException; boolean disassociateIpAddress(DisassociateIPAddrCmd cmd); - Network createNetwork(CreateNetworkCmd cmd) throws InvalidParameterValueException, PermissionDeniedException; + Network createNetwork(CreateNetworkCmd cmd) throws InsufficientCapacityException, ConcurrentOperationException; List searchForNetworks(ListNetworksCmd cmd) throws InvalidParameterValueException, PermissionDeniedException; boolean deleteNetwork(long networkId) throws InvalidParameterValueException, PermissionDeniedException; diff --git a/server/src/com/cloud/configuration/ConfigurationManager.java b/server/src/com/cloud/configuration/ConfigurationManager.java index d7bc5630ed5..91a044b9fd2 100644 --- a/server/src/com/cloud/configuration/ConfigurationManager.java +++ b/server/src/com/cloud/configuration/ConfigurationManager.java @@ -29,7 +29,6 @@ import com.cloud.exception.ConcurrentOperationException; import com.cloud.exception.InsufficientCapacityException; import com.cloud.exception.InvalidParameterValueException; import com.cloud.exception.PermissionDeniedException; -import com.cloud.exception.ResourceUnavailableException; import com.cloud.network.Networks.TrafficType; import com.cloud.offering.DiskOffering; import com.cloud.offering.NetworkOffering.Availability; @@ -170,7 +169,7 @@ public interface ConfigurationManager extends ConfigurationService, Manager { */ NetworkOfferingVO createNetworkOffering(long userId, String name, String displayText, TrafficType trafficType, String tags, Integer maxConnections, boolean specifyVlan, Availability availability); - Vlan createVlanAndPublicIpRange(Long userId, Long zoneId, Long podId, String startIP, String endIP, String vlanGateway, String vlanNetmask, boolean forVirtualNetwork, String vlanId, Account account, Long networkId) throws InsufficientCapacityException, ConcurrentOperationException, InvalidParameterValueException, ResourceUnavailableException; + Vlan createVlanAndPublicIpRange(Long userId, Long zoneId, Long podId, String startIP, String endIP, String vlanGateway, String vlanNetmask, boolean forVirtualNetwork, String vlanId, Account account, Long networkId) throws InsufficientCapacityException, ConcurrentOperationException, InvalidParameterValueException; void createDefaultNetworks(long zoneId) throws ConcurrentOperationException; @@ -181,4 +180,6 @@ public interface ConfigurationManager extends ConfigurationService, Manager { ClusterVO getCluster(long id); boolean deleteAccountSpecificVirtualRanges(long accountId); + + } diff --git a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java index ca4be99520f..013d1308451 100755 --- a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java +++ b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java @@ -1535,7 +1535,7 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura } } - @Override + @Override @DB public Vlan createVlanAndPublicIpRange(CreateVlanIpRangeCmd cmd) throws InsufficientCapacityException, ConcurrentOperationException, InvalidParameterValueException, ResourceUnavailableException { Long zoneId = cmd.getZoneId(); Long podId = cmd.getPodId(); @@ -1547,6 +1547,7 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura String vlanId = cmd.getVlan(); Boolean forVirtualNetwork = cmd.isForVirtualNetwork(); Long networkId = cmd.getNetworkID(); + // If an account name and domain ID are specified, look up the account String accountName = cmd.getAccountName(); Long domainId = cmd.getDomainId(); @@ -1559,7 +1560,7 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura } //Verify that network exists - NetworkVO network = null; + Network network = null; if (networkId != null) { network = _networkDao.findById(networkId); if (network == null) { @@ -1635,13 +1636,59 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura } } - return createVlanAndPublicIpRange(userId, zoneId, podId, startIP, endIP, vlanGateway, vlanNetmask, forVirtualNetwork, vlanId, account, networkId); + //if it's an account specific range, associate ip address list to the account + boolean associateIpRangeToAccount = false; + + if (forVirtualNetwork) { + if (account != null) { + // verify resource limits + long ipResourceLimit = _accountMgr.findCorrectResourceLimit((AccountVO)account, ResourceType.public_ip); + long accountIpRange = NetUtils.ip2Long(endIP) - NetUtils.ip2Long(startIP) + 1; + if (s_logger.isDebugEnabled()) { + s_logger.debug(" IPResourceLimit " +ipResourceLimit + " accountIpRange " + accountIpRange); + } + if (ipResourceLimit != -1 && accountIpRange > ipResourceLimit){ // -1 means infinite + throw new InvalidParameterValueException(" Public IP Resource Limit is set to " + ipResourceLimit + " which is less than the IP range of " + accountIpRange + " provided"); + } + associateIpRangeToAccount = true; + } + } + + Transaction txn = Transaction.currentTxn(); + txn.start(); + + Vlan vlan = createVlanAndPublicIpRange(userId, zoneId, podId, startIP, endIP, vlanGateway, vlanNetmask, forVirtualNetwork, vlanId, account, networkId); + + if (associateIpRangeToAccount) { + _networkMgr.associateIpAddressListToAccount(userId, account.getId(), zoneId, vlan.getId(), network); + if (network == null) { + List networks = _networkMgr.getVirtualNetworksOwnedByAccountInZone(account.getAccountName(), account.getDomainId(), zoneId); + network = networks.get(0); + } + if (network == null) { + throw new CloudRuntimeException("Failed to associate vlan to the account id=" + account.getId() + ", default network failed to create"); + } + } + txn.commit(); + + //Associate ips to the network + if (associateIpRangeToAccount) { + if (network.getState() == Network.State.Implemented) { + s_logger.debug("Applying ip associations for vlan id=" + vlanId + " in network " + network); + if (!_networkMgr.applyIpAssociations(network, false)) { + s_logger.warn("Failed to apply ip associations for vlan id=1 as a part of add vlan range for account id=" + account.getId()); + } + } else { + s_logger.trace("Network id=" + network.getId() + " is not Implemented, no need to apply ipAssociations"); + } + } + + return vlan; } - @Override - public Vlan createVlanAndPublicIpRange(Long userId, Long zoneId, Long podId, String startIP, String endIP, String vlanGateway, String vlanNetmask, boolean forVirtualNetwork, String vlanId, Account account, Long networkId) throws InsufficientCapacityException, ConcurrentOperationException, InvalidParameterValueException, ResourceUnavailableException{ - + @Override @DB + public Vlan createVlanAndPublicIpRange(Long userId, Long zoneId, Long podId, String startIP, String endIP, String vlanGateway, String vlanNetmask, boolean forVirtualNetwork, String vlanId, Account account, Long networkId){ // Check that the pod ID is valid if (podId != null && ((_podDao.findById(podId)) == null)) { throw new InvalidParameterValueException("Please specify a valid pod."); @@ -1677,21 +1724,8 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura //ACL check checkAccess(account, zone); - boolean associateIpRangeToAccount = false; - if (vlanType.equals(VlanType.VirtualNetwork)) { - if (account != null) { - // verify resource limits - long ipResourceLimit = _accountMgr.findCorrectResourceLimit((AccountVO)account, ResourceType.public_ip); - long accountIpRange = NetUtils.ip2Long(endIP) - NetUtils.ip2Long(startIP) + 1; - if (s_logger.isDebugEnabled()) { - s_logger.debug(" IPResourceLimit " +ipResourceLimit + " accountIpRange " + accountIpRange); - } - if (ipResourceLimit != -1 && accountIpRange > ipResourceLimit){ // -1 means infinite - throw new InvalidParameterValueException(" Public IP Resource Limit is set to " + ipResourceLimit + " which is less than the IP range of " + accountIpRange + " provided"); - } - associateIpRangeToAccount = true; - } - } else if (vlanType.equals(VlanType.DirectAttached)) { + + if (vlanType.equals(VlanType.DirectAttached)) { if (account != null) { // VLANs for an account must be tagged if (vlanId.equals(Vlan.UNTAGGED)) { @@ -1720,9 +1754,7 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura } } } - } else { - throw new InvalidParameterValueException("Please specify a valid IP range type. Valid types are: " + VlanType.values().toString()); - } + } // Make sure the gateway is valid if (!NetUtils.isValidIp(vlanGateway)) { @@ -1808,18 +1840,20 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura } } } - - // Everything was fine, so persist the VLAN + String ipRange = startIP; if (endIP != null) { ipRange += "-" + endIP; } + + // Everything was fine, so persist the VLAN + Transaction txn = Transaction.currentTxn(); + txn.start(); + VlanVO vlan = new VlanVO(vlanType, vlanId, vlanGateway, vlanNetmask, zone.getId(), ipRange, networkId); vlan = _vlanDao.persist(vlan); if (!savePublicIPRange(startIP, endIP, zoneId, vlan.getId(), networkId)) { - deletePublicIPRange(vlan.getId()); - _vlanDao.expunge(vlan.getId()); throw new CloudRuntimeException("Failed to save IP range. Please contact Cloud Support."); //It can be Direct IP or Public IP. } @@ -1833,14 +1867,8 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura _podVlanMapDao.persist(podVlanMapVO); } - String eventMsg = "Successfully created new IP range (tag = " + vlanId + ", gateway = " + vlanGateway + ", netmask = " + vlanNetmask + ", start IP = " + startIP; - if (endIP != null) { - eventMsg += ", end IP = " + endIP; - } - eventMsg += "."; - if (associateIpRangeToAccount) { - _networkMgr.associateIpAddressListToAccount(userId, account.getId(), zoneId, vlan.getId()); - } + txn.commit(); + return vlan; } diff --git a/server/src/com/cloud/network/NetworkManager.java b/server/src/com/cloud/network/NetworkManager.java index 11fec588342..85b12324563 100644 --- a/server/src/com/cloud/network/NetworkManager.java +++ b/server/src/com/cloud/network/NetworkManager.java @@ -27,8 +27,6 @@ import com.cloud.deploy.DeploymentPlan; import com.cloud.exception.ConcurrentOperationException; import com.cloud.exception.InsufficientAddressCapacityException; import com.cloud.exception.InsufficientCapacityException; -import com.cloud.exception.InvalidParameterValueException; -import com.cloud.exception.PermissionDeniedException; import com.cloud.exception.ResourceUnavailableException; import com.cloud.network.Network.Capability; import com.cloud.network.Network.Service; @@ -143,7 +141,7 @@ public interface NetworkManager extends NetworkService { boolean destroyNetwork(long networkId, long callerUserId); - Network createNetwork(long networkOfferingId, String name, String displayText, Boolean isShared, Boolean isDefault, Long zoneId, String gateway, String startIP, String endIP, String netmask, String vlanId, String networkDomain, Account owner) throws InvalidParameterValueException, PermissionDeniedException; + Network createNetwork(long networkOfferingId, String name, String displayText, Boolean isShared, Boolean isDefault, Long zoneId, String gateway, String cidr, String vlanId, String networkDomain, Account owner) throws ConcurrentOperationException, InsufficientCapacityException; /** * Associates an ip address list to an account. The list of ip addresses are all addresses associated with the given vlan id. @@ -154,7 +152,7 @@ public interface NetworkManager extends NetworkService { * @throws InsufficientAddressCapacityException * @throws */ - boolean associateIpAddressListToAccount(long userId, long accountId, long zoneId, Long vlanId) throws InsufficientAddressCapacityException, + boolean associateIpAddressListToAccount(long userId, long accountId, long zoneId, Long vlanId, Network networkToAssociateWith) throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException; Nic getNicInNetwork(long vmId, long networkId); @@ -172,7 +170,9 @@ public interface NetworkManager extends NetworkService { void unassignPublicIpAddress(IPAddressVO addr); Map getServiceCapability(long zoneId, Service service); + + boolean applyIpAssociations(Network network, boolean continueOnError) throws ResourceUnavailableException; - boolean deleteNetworkInternal(long networkId) throws InvalidParameterValueException, PermissionDeniedException; + boolean deleteNetworkInternal(long networkId); } diff --git a/server/src/com/cloud/network/NetworkManagerImpl.java b/server/src/com/cloud/network/NetworkManagerImpl.java index f12115c0493..b9d15a7e996 100755 --- a/server/src/com/cloud/network/NetworkManagerImpl.java +++ b/server/src/com/cloud/network/NetworkManagerImpl.java @@ -79,6 +79,7 @@ import com.cloud.exception.InvalidParameterValueException; import com.cloud.exception.PermissionDeniedException; import com.cloud.exception.ResourceAllocationException; import com.cloud.exception.ResourceUnavailableException; +import com.cloud.network.IpAddress.State; import com.cloud.network.Network.Capability; import com.cloud.network.Network.GuestIpType; import com.cloud.network.Network.Service; @@ -259,6 +260,11 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag addr.setAllocatedInDomainId(owner.getDomainId()); addr.setAllocatedToAccountId(owner.getId()); + if (assign) { + markPublicIpAsAllocated(addr); + } else { + addr.setState(IpAddress.State.Allocating); + } addr.setState(assign ? IpAddress.State.Allocated : IpAddress.State.Allocating); if (vlanUse != VlanType.DirectAttached) { @@ -275,6 +281,9 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag @DB protected void markPublicIpAsAllocated(IPAddressVO addr) { + + assert (addr.getState() == IpAddress.State.Allocating || addr.getState() == IpAddress.State.Free) : "Unable to transition from state " + addr.getState() + " to " + IpAddress.State.Allocated; + Transaction txn = Transaction.currentTxn(); Account owner = _accountMgr.getAccount(addr.getAccountId()); @@ -288,9 +297,9 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag if (owner.getAccountId() != Account.ACCOUNT_ID_SYSTEM) { UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_NET_IP_ASSIGN, owner.getId(), addr.getDataCenterId(), addr.getId(), addr.getAddress().toString(), isSourceNat); _usageEventDao.persist(usageEvent); - } - - _accountMgr.incrementResourceCount(owner.getId(), ResourceType.public_ip); + _accountMgr.incrementResourceCount(owner.getId(), ResourceType.public_ip); + } + txn.commit(); } @@ -1353,7 +1362,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag } @Override @ActionEvent (eventType=EventTypes.EVENT_NETWORK_CREATE, eventDescription="creating network") - public Network createNetwork(CreateNetworkCmd cmd) throws InvalidParameterValueException, PermissionDeniedException { + public Network createNetwork(CreateNetworkCmd cmd) throws InsufficientCapacityException, ConcurrentOperationException { Long networkOfferingId = cmd.getNetworkOfferingId(); Long zoneId = cmd.getZoneId(); String gateway = cmd.getGateway(); @@ -1366,6 +1375,9 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag String displayText = cmd.getDisplayText(); Boolean isShared = cmd.getIsShared(); Boolean isDefault = cmd.isDefault(); + Long userId = UserContext.current().getCallerUserId(); + + Transaction txn = Transaction.currentTxn(); // finalize owner for the network Account ctxAccount = UserContext.current().getCaller(); @@ -1373,21 +1385,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag Long domainId = cmd.getDomainId(); Account owner = _accountMgr.finalizeOwner(ctxAccount, accountName, domainId); - - return createNetwork(networkOfferingId, name, displayText, isShared, isDefault, zoneId, gateway, startIP, endIP, netmask, vlanId, networkDomain, owner); - } - - @Override - @DB - public Network createNetwork(long networkOfferingId, String name, String displayText, Boolean isShared, Boolean isDefault, Long zoneId, String gateway, String startIP, String endIP, String netmask, String vlanId, String networkDomain, Account owner) - throws InvalidParameterValueException, PermissionDeniedException { - Account ctxAccount = UserContext.current().getCaller(); - Long userId = UserContext.current().getCallerUserId(); - String cidr = null; - if (gateway != null && netmask != null) { - cidr = NetUtils.ipAndNetMaskToCidr(gateway, netmask); - } - + // if end ip is not specified, default it to startIp if (endIP == null && startIP != null) { endIP = startIP; @@ -1426,7 +1424,12 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag if (zone.getNetworkType() == NetworkType.Basic) { throw new InvalidParameterValueException("Network creation is not allowed in zone with network type " + NetworkType.Basic); } - + + String cidr = null; + if (gateway != null && netmask != null) { + cidr = NetUtils.ipAndNetMaskToCidr(gateway, netmask); + } + // Don't allow to create network with vlan that already exists in the system if (vlanId != null) { String uri = "vlan://" + vlanId; @@ -1441,86 +1444,89 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag throw new InvalidParameterValueException("Can't specify vlan because network offering doesn't support it"); } + txn.start(); + Network network = createNetwork(networkOfferingId, name, displayText, isShared, isDefault, zoneId, gateway, cidr, vlanId, networkDomain, owner); + + // Don't pass owner to create vlan when network offering is of type Direct - done to prevent accountVlanMap entry + // creation when vlan is mapped to network + if (network.getGuestType() == GuestIpType.Direct) { + owner = null; + } + + if (ctxAccount.getType() == Account.ACCOUNT_TYPE_ADMIN && network.getGuestType() == GuestIpType.Direct && startIP != null && endIP != null && gateway != null) { + // Create vlan ip range + _configMgr.createVlanAndPublicIpRange(userId, zoneId, null, startIP, endIP, gateway, netmask, false, vlanId, owner, network.getId()); + } + + txn.commit(); + + return network; + } + + @Override @DB + public Network createNetwork(long networkOfferingId, String name, String displayText, Boolean isShared, Boolean isDefault, Long zoneId, String gateway, String cidr, String vlanId, String networkDomain, Account owner) + throws ConcurrentOperationException, InsufficientCapacityException { + Account ctxAccount = UserContext.current().getCaller(); + Long userId = UserContext.current().getCallerUserId(); + + NetworkOfferingVO networkOffering = _networkOfferingDao.findById(networkOfferingId); + DataCenterVO zone = _dcDao.findById(zoneId); + Transaction txn = Transaction.currentTxn(); txn.start(); - try { - // Create network - DataCenterDeployment plan = new DataCenterDeployment(zoneId, null, null, null); - NetworkVO userNetwork = new NetworkVO(); - userNetwork.setNetworkDomain(networkDomain); - // cidr should be set only when the user is admin - if (ctxAccount.getType() == Account.ACCOUNT_TYPE_ADMIN) { - if (cidr != null && gateway != null) { - userNetwork.setCidr(cidr); - userNetwork.setGateway(gateway); - if (vlanId != null) { - userNetwork.setBroadcastUri(URI.create("vlan://" + vlanId)); + // Create network + DataCenterDeployment plan = new DataCenterDeployment(zoneId, null, null, null); + NetworkVO userNetwork = new NetworkVO(); + userNetwork.setNetworkDomain(networkDomain); + + // cidr should be set only when the user is admin + if (ctxAccount.getType() == Account.ACCOUNT_TYPE_ADMIN) { + if (cidr != null && gateway != null) { + userNetwork.setCidr(cidr); + userNetwork.setGateway(gateway); + if (vlanId != null) { + userNetwork.setBroadcastUri(URI.create("vlan://" + vlanId)); + userNetwork.setBroadcastDomainType(BroadcastDomainType.Vlan); + if (!vlanId.equalsIgnoreCase(Vlan.UNTAGGED)) { userNetwork.setBroadcastDomainType(BroadcastDomainType.Vlan); - if (!vlanId.equalsIgnoreCase(Vlan.UNTAGGED)) { - userNetwork.setBroadcastDomainType(BroadcastDomainType.Vlan); - } else { - userNetwork.setBroadcastDomainType(BroadcastDomainType.Native); - } + } else { + userNetwork.setBroadcastDomainType(BroadcastDomainType.Native); } } } - - List networks = setupNetwork(owner, networkOffering, userNetwork, plan, name, displayText, isShared, isDefault); - Long networkId = null; - - Network network = null; - if (networks == null || networks.isEmpty()) { - txn.rollback(); - throw new CloudRuntimeException("Fail to create a network"); - } else { - if (networks.size() > 0 && networks.get(0).getGuestType() == GuestIpType.Virtual && networks.get(0).getTrafficType() == TrafficType.Guest) { - Network defaultGuestNetwork = networks.get(0); - for (Network nw : networks) { - if (nw.getCidr() != null && nw.getCidr().equals(zone.getGuestNetworkCidr())) { - defaultGuestNetwork = nw; - } - } - network = defaultGuestNetwork; - } else { - network = networks.get(0); - } - - networkId = networks.get(0).getId(); - - if (network.getGuestType() == GuestIpType.Virtual) { - s_logger.debug("Creating a source natp ip for " + network); - PublicIp ip = assignSourceNatIpAddress(owner, network, userId); - if (ip == null) { - throw new InsufficientAddressCapacityException("Unable to assign source nat ip address to owner for this network", DataCenter.class, zoneId); - } - } - } - - // Don't pass owner to create vlan when network offering is of type Direct - done to prevent accountVlanMap entry - // creation when vlan is mapped to network - if (network.getGuestType() == GuestIpType.Direct) { - owner = null; - } - - if (ctxAccount.getType() == Account.ACCOUNT_TYPE_ADMIN && network.getGuestType() == GuestIpType.Direct && startIP != null && endIP != null && gateway != null) { - // Create vlan ip range - Vlan vlan = _configMgr.createVlanAndPublicIpRange(userId, zoneId, null, startIP, endIP, gateway, netmask, false, vlanId, owner, networkId); - if (vlan == null) { - txn.rollback(); - throw new CloudRuntimeException("Failed to create a vlan"); - } - } - txn.commit(); - UserContext.current().setEventDetails("Network Id: "+networkId); - return networks.get(0); - } catch (Exception ex) { - s_logger.warn("Unexpected exception while creating network ", ex); - txn.rollback(); - } finally { - txn.close(); } - return null; + + List networks = setupNetwork(owner, networkOffering, userNetwork, plan, name, displayText, isShared, isDefault); + + Network network = null; + if (networks == null || networks.isEmpty()) { + throw new CloudRuntimeException("Fail to create a network"); + } else { + if (networks.size() > 0 && networks.get(0).getGuestType() == GuestIpType.Virtual && networks.get(0).getTrafficType() == TrafficType.Guest) { + Network defaultGuestNetwork = networks.get(0); + for (Network nw : networks) { + if (nw.getCidr() != null && nw.getCidr().equals(zone.getGuestNetworkCidr())) { + defaultGuestNetwork = nw; + } + } + network = defaultGuestNetwork; + } else { + network = networks.get(0); + } + + if (network.getGuestType() == GuestIpType.Virtual) { + s_logger.debug("Creating a source natp ip for " + network); + PublicIp ip = assignSourceNatIpAddress(owner, network, userId); + if (ip == null) { + throw new InsufficientAddressCapacityException("Unable to assign source nat ip address to owner for this network", DataCenter.class, zoneId); + } + } + } + + txn.commit(); + UserContext.current().setEventDetails("Network Id: "+ network.getId()); + return network; } @Override @@ -1644,7 +1650,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag sc.addAnd("trafficType", SearchCriteria.Op.EQ, trafficType); } - if (path != null) { + if (path != null && (isShared == null || !isShared)) { sc.setJoinParameters("domainSearch", "path", path + "%"); } @@ -2070,56 +2076,54 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag return _nicDao.findByInstanceIdAndNetworkId(networkId, vmId); } - @Override - @DB - public boolean associateIpAddressListToAccount(long userId, long accountId, long zoneId, Long vlanId) throws InsufficientAddressCapacityException, ConcurrentOperationException, ResourceUnavailableException { - - Account account = _accountMgr.getActiveAccount(accountId); - if (account == null) { - s_logger.warn("Unable to find active account: " + accountId); + @Override @DB + public boolean associateIpAddressListToAccount(long userId, long accountId, long zoneId, Long vlanId, Network network) throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException { + Account owner = _accountMgr.getActiveAccount(accountId); + boolean createNetwork = true; + + Transaction txn= Transaction.currentTxn(); + + txn.start(); + + if (network != null) { + createNetwork = false; + } else { + List networks = getVirtualNetworksOwnedByAccountInZone(owner.getAccountName(), owner.getDomainId(), zoneId); + if (networks.size() == 0) { + createNetwork = true; + } else { + network = networks.get(0); + } } - - Network network = null; - long allocatedIps = 0; - + // create new Virtual network for the user if it doesn't exist - List networks = getVirtualNetworksOwnedByAccountInZone(account.getAccountName(), account.getDomainId(), zoneId); - if (networks.size() == 0) { + if (createNetwork) { List offerings = _configMgr.listNetworkOfferings(TrafficType.Guest, false); - network = createNetwork(offerings.get(0).getId(), account.getAccountName() + "-network", account.getAccountName() + "-network", false, null, zoneId, null, null, null, null, null, null, account); + network = createNetwork(offerings.get(0).getId(), owner.getAccountName() + "-network", owner.getAccountName() + "-network", false, true, zoneId, null, null, null, null, owner); if (network == null) { s_logger.warn("Failed to create default Virtual network for the account " + accountId + "in zone " + zoneId); return false; - } else { - // sourceNat ip is allocated as a part of networkCreate - allocatedIps++; - } - } else { - assert (networks.size() <= 1) : "Too many virtual networks. This logic should be obsolete"; - network = networks.get(0); + } } - - // Associate ip addresses - long ipCount = _ipAddressDao.countIPs(zoneId, vlanId, false); - if (ipCount > 0) { - while (allocatedIps < ipCount) { - PublicIp ip = fetchNewPublicIp(zoneId, null, vlanId, account, VlanType.VirtualNetwork, network.getId(), false, true); - markPublicIpAsAllocated(ip.ip()); - allocatedIps++; + + + //update all ips with a network id, mark them as allocated and update resourceCount/usage + List ips = _ipAddressDao.listByVlanId(vlanId); + for (IPAddressVO addr : ips) { + if (!addr.isSourceNat() && addr.getState() != State.Allocated) { + addr.setAssociatedWithNetworkId(network.getId()); + addr.setSourceNat(false); + addr.setAllocatedTime(new Date()); + addr.setAllocatedInDomainId(owner.getDomainId()); + addr.setAllocatedToAccountId(owner.getId()); + addr.setState(IpAddress.State.Allocating); + markPublicIpAsAllocated(addr); } - - if (network.getState() == Network.State.Implemented) { - s_logger.debug("Applying ip associations for vlan id=" + vlanId + " in network " + network); - return applyIpAssociations(network, false); - } else { - s_logger.trace("Network id=" + network.getId() + " is not Implemented, no need to apply ipAssociations"); - return true; - } - } else { - s_logger.trace("Found 0 ips to assign in vlan id=" + vlanId); - return true; } + + txn.commit(); + return true; } @Override