You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by ah...@apache.org on 2013/08/19 23:12:18 UTC

[10/16] Divided NetworkManagerImpl into two files: NetworkManagerImpl and IpAddressManagerImpl

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/092e2020/server/src/com/cloud/network/NetworkManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/network/NetworkManagerImpl.java b/server/src/com/cloud/network/NetworkManagerImpl.java
index 3819fff..8c939f3 100755
--- a/server/src/com/cloud/network/NetworkManagerImpl.java
+++ b/server/src/com/cloud/network/NetworkManagerImpl.java
@@ -21,13 +21,11 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.Comparator;
-import java.util.Date;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.Random;
 import java.util.Set;
 import java.util.UUID;
 import java.util.concurrent.Executors;
@@ -42,13 +40,9 @@ import org.apache.log4j.Logger;
 import org.springframework.stereotype.Component;
 
 import org.apache.cloudstack.acl.ControlledEntity.ACLType;
-import org.apache.cloudstack.acl.SecurityChecker.AccessType;
 import org.apache.cloudstack.context.CallContext;
 import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
-import org.apache.cloudstack.region.PortableIp;
 import org.apache.cloudstack.region.PortableIpDao;
-import org.apache.cloudstack.region.PortableIpVO;
-import org.apache.cloudstack.region.Region;
 
 import com.cloud.agent.AgentManager;
 import com.cloud.agent.Listener;
@@ -66,15 +60,12 @@ import com.cloud.api.ApiDBUtils;
 import com.cloud.configuration.Config;
 import com.cloud.configuration.ConfigurationManager;
 import com.cloud.configuration.Resource.ResourceType;
-import com.cloud.dc.AccountVlanMapVO;
 import com.cloud.dc.DataCenter;
 import com.cloud.dc.DataCenter.NetworkType;
 import com.cloud.dc.DataCenterVO;
 import com.cloud.dc.DataCenterVnetVO;
-import com.cloud.dc.Pod;
 import com.cloud.dc.PodVlanMapVO;
 import com.cloud.dc.Vlan;
-import com.cloud.dc.Vlan.VlanType;
 import com.cloud.dc.VlanVO;
 import com.cloud.dc.dao.AccountVlanMapDao;
 import com.cloud.dc.dao.DataCenterDao;
@@ -86,18 +77,13 @@ import com.cloud.deploy.DeployDestination;
 import com.cloud.deploy.DeploymentPlan;
 import com.cloud.domain.Domain;
 import com.cloud.domain.dao.DomainDao;
-import com.cloud.event.ActionEventUtils;
-import com.cloud.event.EventTypes;
-import com.cloud.event.UsageEventUtils;
 import com.cloud.event.dao.UsageEventDao;
-import com.cloud.exception.AccountLimitException;
 import com.cloud.exception.ConcurrentOperationException;
 import com.cloud.exception.ConnectionException;
 import com.cloud.exception.InsufficientAddressCapacityException;
 import com.cloud.exception.InsufficientCapacityException;
 import com.cloud.exception.InsufficientVirtualNetworkCapcityException;
 import com.cloud.exception.InvalidParameterValueException;
-import com.cloud.exception.PermissionDeniedException;
 import com.cloud.exception.ResourceAllocationException;
 import com.cloud.exception.ResourceUnavailableException;
 import com.cloud.exception.UnsupportedServiceException;
@@ -111,9 +97,7 @@ import com.cloud.network.Network.Event;
 import com.cloud.network.Network.GuestType;
 import com.cloud.network.Network.Provider;
 import com.cloud.network.Network.Service;
-import com.cloud.network.Networks.AddressFormat;
 import com.cloud.network.Networks.BroadcastDomainType;
-import com.cloud.network.Networks.IsolationType;
 import com.cloud.network.Networks.TrafficType;
 import com.cloud.network.addr.PublicIp;
 import com.cloud.network.dao.AccountGuestVlanMapDao;
@@ -138,7 +122,6 @@ import com.cloud.network.dao.PhysicalNetworkVO;
 import com.cloud.network.dao.UserIpv6AddressDao;
 import com.cloud.network.element.DhcpServiceProvider;
 import com.cloud.network.element.IpDeployer;
-import com.cloud.network.element.IpDeployingRequester;
 import com.cloud.network.element.LoadBalancingServiceProvider;
 import com.cloud.network.element.NetworkElement;
 import com.cloud.network.element.StaticNatServiceProvider;
@@ -152,7 +135,6 @@ import com.cloud.network.rules.FirewallRuleVO;
 import com.cloud.network.rules.LoadBalancerContainer.Scheme;
 import com.cloud.network.rules.PortForwardingRuleVO;
 import com.cloud.network.rules.RulesManager;
-import com.cloud.network.rules.StaticNat;
 import com.cloud.network.rules.StaticNatRule;
 import com.cloud.network.rules.StaticNatRuleImpl;
 import com.cloud.network.rules.dao.PortForwardingRulesDao;
@@ -167,33 +149,27 @@ import com.cloud.offerings.NetworkOfferingVO;
 import com.cloud.offerings.dao.NetworkOfferingDao;
 import com.cloud.offerings.dao.NetworkOfferingDetailsDao;
 import com.cloud.offerings.dao.NetworkOfferingServiceMapDao;
-import com.cloud.org.Grouping;
 import com.cloud.server.ConfigurationServer;
 import com.cloud.user.Account;
 import com.cloud.user.AccountManager;
 import com.cloud.user.ResourceLimitService;
 import com.cloud.user.User;
-import com.cloud.user.UserVO;
 import com.cloud.user.dao.AccountDao;
 import com.cloud.user.dao.UserDao;
-import com.cloud.utils.Journal;
 import com.cloud.utils.NumbersUtil;
 import com.cloud.utils.Pair;
 import com.cloud.utils.component.AdapterBase;
 import com.cloud.utils.component.ManagerBase;
 import com.cloud.utils.concurrency.NamedThreadFactory;
 import com.cloud.utils.db.DB;
-import com.cloud.utils.db.Filter;
 import com.cloud.utils.db.GlobalLock;
 import com.cloud.utils.db.JoinBuilder.JoinType;
 import com.cloud.utils.db.SearchBuilder;
-import com.cloud.utils.db.SearchCriteria;
 import com.cloud.utils.db.SearchCriteria.Op;
 import com.cloud.utils.db.Transaction;
 import com.cloud.utils.exception.CloudRuntimeException;
 import com.cloud.utils.fsm.NoTransitionException;
 import com.cloud.utils.fsm.StateMachine2;
-import com.cloud.utils.net.Ip;
 import com.cloud.utils.net.NetUtils;
 import com.cloud.vm.Nic;
 import com.cloud.vm.Nic.ReservationStrategy;
@@ -275,6 +251,8 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L
     protected NicIpAliasDao _nicIpAliasDao;
     @Inject
     protected IPAddressDao _publicIpAddressDao;
+    @Inject
+    protected IpAddressManager _ipAddrMgr;
 
     List<NetworkGuru> _networkGurus;
     public List<NetworkGuru> getNetworkGurus() {
@@ -373,910 +351,7 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L
     HashMap<Long, Long> _lastNetworkIdsToFree = new HashMap<Long, Long>();
 
 
-    @Override
-    public PublicIp assignPublicIpAddress(long dcId, Long podId, Account owner, VlanType type, Long networkId, String requestedIp, boolean isSystem) throws InsufficientAddressCapacityException {
-        return fetchNewPublicIp(dcId, podId, null, owner, type, networkId, false, true, requestedIp, isSystem, null);
-    }
-
-    @Override
-    public PublicIp assignPublicIpAddressFromVlans(long dcId, Long podId, Account owner, VlanType type, List<Long> vlanDbIds, Long networkId, String requestedIp, boolean isSystem) throws InsufficientAddressCapacityException {
-        return fetchNewPublicIp(dcId, podId, vlanDbIds , owner, type, networkId, false, true, requestedIp, isSystem, null);
-    }
-    @DB
-    public PublicIp fetchNewPublicIp(long dcId, Long podId, List<Long> vlanDbIds, Account owner, VlanType vlanUse,
-            Long guestNetworkId, boolean sourceNat, boolean assign, String requestedIp, boolean isSystem, Long vpcId)
-            throws InsufficientAddressCapacityException {
-        StringBuilder errorMessage = new StringBuilder("Unable to get ip adress in ");
-        boolean fetchFromDedicatedRange = false;
-        List<Long> dedicatedVlanDbIds = new ArrayList<Long>();
-        List<Long> nonDedicatedVlanDbIds = new ArrayList<Long>();
-
-        Transaction txn = Transaction.currentTxn();
-        txn.start();
-        SearchCriteria<IPAddressVO> sc = null;
-        if (podId != null) {
-            sc = AssignIpAddressFromPodVlanSearch.create();
-            sc.setJoinParameters("podVlanMapSB", "podId", podId);
-            errorMessage.append(" pod id=" + podId);
-        } else {
-            sc = AssignIpAddressSearch.create();
-            errorMessage.append(" zone id=" + dcId);
-        }
-
-        // If owner has dedicated Public IP ranges, fetch IP from the dedicated range
-        // Otherwise fetch IP from the system pool
-        List<AccountVlanMapVO> maps = _accountVlanMapDao.listAccountVlanMapsByAccount(owner.getId());
-        for (AccountVlanMapVO map : maps) {
-            if (vlanDbIds == null || vlanDbIds.contains(map.getVlanDbId()))
-                dedicatedVlanDbIds.add(map.getVlanDbId());
-        }
-        List<VlanVO> nonDedicatedVlans = _vlanDao.listZoneWideNonDedicatedVlans(dcId);
-        for (VlanVO nonDedicatedVlan : nonDedicatedVlans) {
-            if (vlanDbIds == null || vlanDbIds.contains(nonDedicatedVlan.getId()))
-                nonDedicatedVlanDbIds.add(nonDedicatedVlan.getId());
-        }
-        if (dedicatedVlanDbIds != null && !dedicatedVlanDbIds.isEmpty()) {
-            fetchFromDedicatedRange = true;
-            sc.setParameters("vlanId", dedicatedVlanDbIds.toArray());
-            errorMessage.append(", vlanId id=" + dedicatedVlanDbIds.toArray());
-        } else if (nonDedicatedVlanDbIds != null && !nonDedicatedVlanDbIds.isEmpty()) {
-            sc.setParameters("vlanId", nonDedicatedVlanDbIds.toArray());
-            errorMessage.append(", vlanId id=" + nonDedicatedVlanDbIds.toArray());
-        } else {
-            if (podId != null) {
-                InsufficientAddressCapacityException ex = new InsufficientAddressCapacityException
-                        ("Insufficient address capacity", Pod.class, podId);
-                ex.addProxyObject(ApiDBUtils.findPodById(podId).getUuid());
-                throw ex;
-            }
-            s_logger.warn(errorMessage.toString());
-            InsufficientAddressCapacityException ex = new InsufficientAddressCapacityException
-                    ("Insufficient address capacity", DataCenter.class, dcId);
-            ex.addProxyObject(ApiDBUtils.findZoneById(dcId).getUuid());
-            throw ex;
-        }
-
-        sc.setParameters("dc", dcId);
-
-        DataCenter zone = _configMgr.getZone(dcId);
-
-        // for direct network take ip addresses only from the vlans belonging to the network
-        if (vlanUse == VlanType.DirectAttached) {
-            sc.setJoinParameters("vlan", "networkId", guestNetworkId);
-            errorMessage.append(", network id=" + guestNetworkId);
-        }
-        sc.setJoinParameters("vlan", "type", vlanUse);
-
-        if (requestedIp != null) {
-            sc.addAnd("address", SearchCriteria.Op.EQ, requestedIp);
-            errorMessage.append(": requested ip " + requestedIp + " is not available");
-        }
-
-        Filter filter = new Filter(IPAddressVO.class, "vlanId", true, 0l, 1l);
-
-        List<IPAddressVO> addrs = _ipAddressDao.lockRows(sc, filter, true);
-
-        // If all the dedicated IPs of the owner are in use fetch an IP from the system pool
-        if (addrs.size() == 0 && fetchFromDedicatedRange) {
-            // Verify if account is allowed to acquire IPs from the system
-            boolean useSystemIps = Boolean.parseBoolean(_configServer.getConfigValue(Config.UseSystemPublicIps.key(),
-                    Config.ConfigurationParameterScope.account.toString(), owner.getId()));
-            if(useSystemIps && nonDedicatedVlanDbIds != null && !nonDedicatedVlanDbIds.isEmpty()) {
-                fetchFromDedicatedRange = false;
-                sc.setParameters("vlanId", nonDedicatedVlanDbIds.toArray());
-                errorMessage.append(", vlanId id=" + nonDedicatedVlanDbIds.toArray());
-                addrs = _ipAddressDao.lockRows(sc, filter, true);
-            }
-        }
-
-        if (addrs.size() == 0) {
-            if (podId != null) {
-                InsufficientAddressCapacityException ex = new InsufficientAddressCapacityException
-                        ("Insufficient address capacity", Pod.class, podId);
-                // for now, we hardcode the table names, but we should ideally do a lookup for the tablename from the VO object.
-                ex.addProxyObject(ApiDBUtils.findPodById(podId).getUuid());
-                throw ex;
-            }
-            s_logger.warn(errorMessage.toString());
-            InsufficientAddressCapacityException ex = new InsufficientAddressCapacityException
-                    ("Insufficient address capacity", DataCenter.class, dcId);
-            ex.addProxyObject(ApiDBUtils.findZoneById(dcId).getUuid());
-            throw ex;
-        }
-
-        assert (addrs.size() == 1) : "Return size is incorrect: " + addrs.size();
-
-        if (!fetchFromDedicatedRange) {
-            // Check that the maximum number of public IPs for the given accountId will not be exceeded
-            try {
-                _resourceLimitMgr.checkResourceLimit(owner, ResourceType.public_ip);
-            } catch (ResourceAllocationException ex) {
-                s_logger.warn("Failed to allocate resource of type " + ex.getResourceType() + " for account " + owner);
-                throw new AccountLimitException("Maximum number of public IP addresses for account: " + owner.getAccountName() + " has been exceeded.");
-            }
-        }
-
-        IPAddressVO addr = addrs.get(0);
-        addr.setSourceNat(sourceNat);
-        addr.setAllocatedTime(new Date());
-        addr.setAllocatedInDomainId(owner.getDomainId());
-        addr.setAllocatedToAccountId(owner.getId());
-        addr.setSystem(isSystem);
-
-        if (assign) {
-            markPublicIpAsAllocated(addr);
-        } else {
-            addr.setState(IpAddress.State.Allocating);
-        }
-        addr.setState(assign ? IpAddress.State.Allocated : IpAddress.State.Allocating);
-
-        if (vlanUse != VlanType.DirectAttached || zone.getNetworkType() == NetworkType.Basic) {
-            addr.setAssociatedWithNetworkId(guestNetworkId);
-            addr.setVpcId(vpcId);
-        }
-
-        _ipAddressDao.update(addr.getId(), addr);
-
-        txn.commit();
-
-        if (vlanUse == VlanType.VirtualNetwork) {
-            _firewallMgr.addSystemFirewallRules(addr, owner);
-        }
 
-        return PublicIp.createFromAddrAndVlan(addr, _vlanDao.findById(addr.getVlanId()));
-    }
-
-    @DB
-    @Override
-    public 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.getAllocatedToAccountId());
-
-        txn.start();
-        addr.setState(IpAddress.State.Allocated);
-        _ipAddressDao.update(addr.getId(), addr);
-
-        // Save usage event
-        if (owner.getAccountId() != Account.ACCOUNT_ID_SYSTEM) {
-            VlanVO vlan = _vlanDao.findById(addr.getVlanId());
-
-            String guestType = vlan.getVlanType().toString();
-
-            if (!isIpDedicated(addr)) {
-                UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NET_IP_ASSIGN, owner.getId(),
-                        addr.getDataCenterId(), addr.getId(), addr.getAddress().toString(), addr.isSourceNat(), guestType,
-                        addr.getSystem(), addr.getClass().getName(), addr.getUuid());
-            }
-            // don't increment resource count for direct and dedicated ip addresses
-            if (addr.getAssociatedWithNetworkId() != null && !isIpDedicated(addr)) {
-                _resourceLimitMgr.incrementResourceCount(owner.getId(), ResourceType.public_ip);
-            }
-        }
-
-        txn.commit();
-    }
-
-    private boolean isIpDedicated(IPAddressVO addr) {
-        List<AccountVlanMapVO> maps = _accountVlanMapDao.listAccountVlanMapsByVlan(addr.getVlanId());
-        if (maps != null && !maps.isEmpty())
-            return true;
-        return false;
-    }
-
-    @Override
-    public PublicIp assignSourceNatIpAddressToGuestNetwork(Account owner, Network guestNetwork)
-            throws InsufficientAddressCapacityException, ConcurrentOperationException {
-        assert (guestNetwork.getTrafficType() != null) : "You're asking for a source nat but your network " +
-                "can't participate in source nat.  What do you have to say for yourself?";
-        long dcId = guestNetwork.getDataCenterId();
-
-        IPAddressVO sourceNatIp = getExistingSourceNatInNetwork(owner.getId(), guestNetwork.getId());
-
-        PublicIp ipToReturn = null;
-        if (sourceNatIp != null) {
-            ipToReturn = PublicIp.createFromAddrAndVlan(sourceNatIp, _vlanDao.findById(sourceNatIp.getVlanId()));
-        } else {
-            ipToReturn = assignDedicateIpAddress(owner, guestNetwork.getId(), null, dcId, true);
-        }
-
-        return ipToReturn;
-    }
-
-
-    @DB
-    @Override
-    public PublicIp assignDedicateIpAddress(Account owner, Long guestNtwkId, Long vpcId, long dcId, boolean isSourceNat)
-            throws ConcurrentOperationException, InsufficientAddressCapacityException {
-
-        long ownerId = owner.getId();
-
-        PublicIp ip = null;
-        Transaction txn = Transaction.currentTxn();
-        try {
-            txn.start();
-
-            owner = _accountDao.acquireInLockTable(ownerId);
-
-            if (owner == null) {
-                // this ownerId comes from owner or type Account. See the class "AccountVO" and the annotations in that class
-                // to get the table name and field name that is queried to fill this ownerid.
-                ConcurrentOperationException ex = new ConcurrentOperationException("Unable to lock account");
-                throw ex;
-            }
-            if (s_logger.isDebugEnabled()) {
-                s_logger.debug("lock account " + ownerId + " is acquired");
-            }
-
-            ip = fetchNewPublicIp(dcId, null, null, owner, VlanType.VirtualNetwork, guestNtwkId,
-                    isSourceNat, false, null, false, vpcId);
-            IPAddressVO publicIp = ip.ip();
-
-            markPublicIpAsAllocated(publicIp);
-            _ipAddressDao.update(publicIp.getId(), publicIp);
-
-            txn.commit();
-            return ip;
-        } finally {
-            if (owner != null) {
-                if (s_logger.isDebugEnabled()) {
-                    s_logger.debug("Releasing lock account " + ownerId);
-                }
-
-                _accountDao.releaseFromLockTable(ownerId);
-            }
-            if (ip == null) {
-                txn.rollback();
-                s_logger.error("Unable to get source nat ip address for account " + ownerId);
-            }
-        }
-    }
-
-    
-
-    @Override
-    public boolean applyIpAssociations(Network network, boolean continueOnError) throws ResourceUnavailableException {
-        List<IPAddressVO> userIps = _ipAddressDao.listByAssociatedNetwork(network.getId(), null);
-        boolean success = true;
-
-        // CloudStack will take a lazy approach to associate an acquired public IP to a network service provider as
-        // it will not know what service an acquired IP will be used for. An IP is actually associated with a provider when first
-        // rule is applied. Similarly when last rule on the acquired IP is revoked, IP is not associated with any provider
-        // but still be associated with the account. At this point just mark IP as allocated or released.
-        for (IPAddressVO addr : userIps) {
-            if (addr.getState() == IpAddress.State.Allocating) {
-                addr.setAssociatedWithNetworkId(network.getId());
-                markPublicIpAsAllocated(addr);
-            } else if (addr.getState() == IpAddress.State.Releasing) {
-                // Cleanup all the resources for ip address if there are any, and only then un-assign ip in the system
-                if (cleanupIpResources(addr.getId(), Account.ACCOUNT_ID_SYSTEM, _accountMgr.getSystemAccount())) {
-                    _ipAddressDao.unassignIpAddress(addr.getId());
-                } else {
-                    success = false;
-                    s_logger.warn("Failed to release resources for ip address id=" + addr.getId());
-                }
-            }
-        }
-
-        return success;
-    }
-
-
-    // CloudStack will take a lazy approach to associate an acquired public IP to a network service provider as
-    // it will not know what a acquired IP will be used for. An IP is actually associated with a provider when first
-    // rule is applied. Similarly when last rule on the acquired IP is revoked, IP is not associated with any provider
-    // but still be associated with the account. Its up to caller of this function to decide when to invoke IPAssociation
-    @Override
-    public boolean applyIpAssociations(Network network, boolean postApplyRules, boolean continueOnError,
-            List<? extends PublicIpAddress> publicIps) throws ResourceUnavailableException {
-        boolean success = true;
-
-        Map<PublicIpAddress, Set<Service>> ipToServices = _networkModel.getIpToServices(publicIps, postApplyRules, true);
-        Map<Provider, ArrayList<PublicIpAddress>> providerToIpList = _networkModel.getProviderToIpList(network, ipToServices);
-
-        for (Provider provider : providerToIpList.keySet()) {
-            try {
-                ArrayList<PublicIpAddress> ips = providerToIpList.get(provider);
-                if (ips == null || ips.isEmpty()) {
-                    continue;
-                }
-                IpDeployer deployer = null;
-                NetworkElement element = _networkModel.getElementImplementingProvider(provider.getName());
-                if (!(element instanceof IpDeployingRequester)) {
-                    throw new CloudRuntimeException("Element " + element + " is not a IpDeployingRequester!");
-                }
-                deployer = ((IpDeployingRequester)element).getIpDeployer(network);
-                if (deployer == null) {
-                    throw new CloudRuntimeException("Fail to get ip deployer for element: " + element);
-                }
-                Set<Service> services = new HashSet<Service>();
-                for (PublicIpAddress 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: " + provider.getName(), e);
-                }
-            }
-        }
-
-        return success;
-    }
-
-
-    
-    
-    protected List<? extends Network> getIsolatedNetworksWithSourceNATOwnedByAccountInZone(long zoneId, Account owner) {
-
-        return _networksDao.listSourceNATEnabledNetworks(owner.getId(), zoneId, Network.GuestType.Isolated);
-    }
-
-    
-
-    private IpAddress allocateIP(Account ipOwner, boolean isSystem, long zoneId)
-            throws ResourceAllocationException, InsufficientAddressCapacityException, ConcurrentOperationException {
-        Account caller = CallContext.current().getCallingAccount();
-        long callerUserId = CallContext.current().getCallingUserId();
-        // check permissions
-        _accountMgr.checkAccess(caller, null, false, ipOwner);
-
-        DataCenter zone = _configMgr.getZone(zoneId);
-        
-        return allocateIp(ipOwner, isSystem, caller, callerUserId, zone);
-    }
-
-    @DB
-    @Override
-    public IpAddress allocateIp(Account ipOwner, boolean isSystem, Account caller, long callerUserId, DataCenter zone)
-            throws ConcurrentOperationException, ResourceAllocationException,
-            InsufficientAddressCapacityException {
-
-        VlanType vlanType = VlanType.VirtualNetwork;
-        boolean assign = false;
-
-        if (Grouping.AllocationState.Disabled == zone.getAllocationState() && !_accountMgr.isRootAdmin(caller.getType())) {
-            // zone is of type DataCenter. See DataCenterVO.java.
-            PermissionDeniedException ex = new PermissionDeniedException("Cannot perform this operation, " +
-                    "Zone is currently disabled");
-            ex.addProxyObject(zone.getUuid(), "zoneId");
-            throw ex;
-        }
-
-        PublicIp ip = null;
-
-        Transaction txn = Transaction.currentTxn();
-        Account accountToLock = null;
-        try {
-            if (s_logger.isDebugEnabled()) {
-                s_logger.debug("Associate IP address called by the user " + callerUserId + " account " + ipOwner.getId());
-            }
-            accountToLock = _accountDao.acquireInLockTable(ipOwner.getId());
-            if (accountToLock == null) {
-                s_logger.warn("Unable to lock account: " + ipOwner.getId());
-                throw new ConcurrentOperationException("Unable to acquire account lock");
-            }
-
-            if (s_logger.isDebugEnabled()) {
-                s_logger.debug("Associate IP address lock acquired");
-            }
-
-            txn.start();
-
-            ip = fetchNewPublicIp(zone.getId(), null, null, ipOwner, vlanType, null, false, assign, null,
-                    isSystem, null);
-
-            if (ip == null) {
-                InsufficientAddressCapacityException ex = new InsufficientAddressCapacityException
-                        ("Unable to find available public IP addresses", DataCenter.class, zone.getId());
-                ex.addProxyObject(ApiDBUtils.findZoneById(zone.getId()).getUuid());
-                throw ex;
-            }
-            CallContext.current().setEventDetails("Ip Id: " + ip.getId());
-            Ip ipAddress = ip.getAddress();
-
-            s_logger.debug("Got " + ipAddress + " to assign for account " + ipOwner.getId() + " in zone " + zone.getId());
-
-            txn.commit();
-        } finally {
-            if (accountToLock != null) {
-                if (s_logger.isDebugEnabled()) {
-                    s_logger.debug("Releasing lock account " + ipOwner);
-                }
-                _accountDao.releaseFromLockTable(ipOwner.getId());
-                s_logger.debug("Associate IP address lock released");
-            }
-        }
-        return ip;
-    }
-
-    @Override
-    @DB
-    public IpAddress allocatePortableIp(Account ipOwner, Account caller, long dcId, Long networkId, Long vpcID)
-            throws ConcurrentOperationException, ResourceAllocationException, InsufficientAddressCapacityException {
-
-        Transaction txn = Transaction.currentTxn();
-        GlobalLock portableIpLock = GlobalLock.getInternLock("PortablePublicIpRange");
-        PortableIpVO allocatedPortableIp;
-        IPAddressVO ipaddr;
-
-        try {
-            portableIpLock.lock(5);
-
-            txn.start();
-
-            List<PortableIpVO> portableIpVOs = _portableIpDao.listByRegionIdAndState(1, PortableIp.State.Free);
-            if (portableIpVOs == null || portableIpVOs.isEmpty()) {
-                InsufficientAddressCapacityException ex = new InsufficientAddressCapacityException
-                        ("Unable to find available portable IP addresses", Region.class, new Long(1));
-                throw ex;
-            }
-
-            // allocate first portable IP to the user
-            allocatedPortableIp =   portableIpVOs.get(0);
-            allocatedPortableIp.setAllocatedTime(new Date());
-            allocatedPortableIp.setAllocatedToAccountId(ipOwner.getAccountId());
-            allocatedPortableIp.setAllocatedInDomainId(ipOwner.getDomainId());
-            allocatedPortableIp.setState(PortableIp.State.Allocated);
-            _portableIpDao.update(allocatedPortableIp.getId(), allocatedPortableIp);
-
-            // To make portable IP available as a zone level resource we need to emulate portable IP's (which are
-            // provisioned at region level) as public IP provisioned in a zone. user_ip_address and vlan combo give the
-            // identity of a public IP in zone. Create entry for portable ip in these tables.
-
-            // provision portable IP range VLAN into the zone
-            long physicalNetworkId = _networkModel.getDefaultPhysicalNetworkByZoneAndTrafficType(dcId, TrafficType.Public).getId();
-            Network network =_networkModel.getSystemNetworkByZoneAndTrafficType(dcId, TrafficType.Public);
-            String range = allocatedPortableIp.getAddress() + "-" + allocatedPortableIp.getAddress();
-            VlanVO vlan = new VlanVO(VlanType.VirtualNetwork, allocatedPortableIp.getVlan(), allocatedPortableIp.getGateway(),
-                    allocatedPortableIp.getNetmask(), dcId, range, network.getId(), physicalNetworkId, null, null, null);
-            vlan = _vlanDao.persist(vlan);
-
-            // provision the portable IP in to user_ip_address table
-            ipaddr = new IPAddressVO(new Ip(allocatedPortableIp.getAddress()), dcId, networkId, vpcID, physicalNetworkId,
-                    network.getId(), vlan.getId(), true);
-            ipaddr.setState(State.Allocated);
-            ipaddr.setAllocatedTime(new Date());
-            ipaddr.setAllocatedInDomainId(ipOwner.getDomainId());
-            ipaddr.setAllocatedToAccountId(ipOwner.getId());
-            ipaddr= _ipAddressDao.persist(ipaddr);
-
-            String guestType = vlan.getVlanType().toString();
-            UsageEventUtils.publishUsageEvent(EventTypes.EVENT_PORTABLE_IP_ASSIGN, ipaddr.getId(),
-                    ipaddr.getDataCenterId(), ipaddr.getId(), ipaddr.getAddress().toString(), ipaddr.isSourceNat(), null,
-                    ipaddr.getSystem(), ipaddr.getClass().getName(), ipaddr.getUuid());
-
-            txn.commit();
-
-        } finally {
-            portableIpLock.unlock();
-        }
-
-        return ipaddr;
-    }
-
-    protected IPAddressVO getExistingSourceNatInNetwork(long ownerId, Long networkId) {
-        
-        List<? extends IpAddress> addrs = _networkModel.listPublicIpsAssignedToGuestNtwk(ownerId, networkId, true);
-    
-        IPAddressVO sourceNatIp = null;
-        if (addrs.isEmpty()) {
-            return null;
-        } else {
-            // Account already has ip addresses
-            for (IpAddress addr : addrs) {
-                if (addr.isSourceNat()) {
-                    sourceNatIp = _ipAddressDao.findById(addr.getId());
-                    return sourceNatIp;
-                }
-            }
-    
-            assert (sourceNatIp != null) : "How do we get a bunch of ip addresses but none of them are source nat? " +
-                    "account=" + ownerId + "; networkId=" + networkId;
-        }
-
-        return sourceNatIp;
-    }
-    
-    @DB
-    @Override
-    public IPAddressVO associateIPToGuestNetwork(long ipId, long networkId, boolean releaseOnFailure)
-            throws ResourceAllocationException, ResourceUnavailableException,
-    InsufficientAddressCapacityException, ConcurrentOperationException {
-        Account caller = CallContext.current().getCallingAccount();
-        Account owner = null;
-
-        IPAddressVO ipToAssoc = _ipAddressDao.findById(ipId);
-        if (ipToAssoc != null) {
-            Network network = _networksDao.findById(networkId);
-            if (network == null) {
-                throw new InvalidParameterValueException("Invalid network id is given");
-            }
-
-            DataCenter zone = _configMgr.getZone(network.getDataCenterId());
-            if (zone.getNetworkType() == NetworkType.Advanced) {
-                if (network.getGuestType() == Network.GuestType.Shared) {
-                if (isSharedNetworkOfferingWithServices(network.getNetworkOfferingId())) {
-                    _accountMgr.checkAccess(CallContext.current().getCallingAccount(), AccessType.UseNetwork, false, network);
-                } else {
-                    throw new InvalidParameterValueException("IP can be associated with guest network of 'shared' type only if " +
-                        "network services Source Nat, Static Nat, Port Forwarding, Load balancing, firewall are enabled in the network");
-                }
-                }
-            } else {
-                _accountMgr.checkAccess(caller, null, true, ipToAssoc);
-            }
-            owner = _accountMgr.getAccount(ipToAssoc.getAllocatedToAccountId());
-        } else {
-            s_logger.debug("Unable to find ip address by id: " + ipId);
-            return null;
-        }
-
-        if (ipToAssoc.getAssociatedWithNetworkId() != null) {
-            s_logger.debug("IP " + ipToAssoc + " is already assocaited with network id" + networkId);
-            return ipToAssoc;
-        }
-
-        Network network = _networksDao.findById(networkId);
-        if (network != null) {
-            _accountMgr.checkAccess(owner, AccessType.UseNetwork, false, network);
-        } else {
-            s_logger.debug("Unable to find ip address by id: " + ipId);
-            return null;
-        }
-
-        DataCenter zone = _configMgr.getZone(network.getDataCenterId());
-
-        // allow associating IP addresses to guest network only
-        if (network.getTrafficType() != TrafficType.Guest) {
-            throw new InvalidParameterValueException("Ip address can be associated to the network with trafficType " + TrafficType.Guest);
-        }
-
-        // Check that network belongs to IP owner - skip this check
-        //     - if zone is basic zone as there is just one guest network,
-        //     - if shared network in Advanced zone
-        //     - and it belongs to the system
-        if (network.getAccountId() != owner.getId()) {
-            if (zone.getNetworkType() != NetworkType.Basic && !(zone.getNetworkType() == NetworkType.Advanced && network.getGuestType() == Network.GuestType.Shared)) {
-                throw new InvalidParameterValueException("The owner of the network is not the same as owner of the IP");
-            }
-        }
-
-        // In Advance zone only allow to do IP assoc
-        //      - for Isolated networks with source nat service enabled
-        //      - for shared networks with source nat service enabled
-        if (zone.getNetworkType() == NetworkType.Advanced &&
-            !(_networkModel.areServicesSupportedInNetwork(network.getId(), Service.SourceNat))) {
-            throw new InvalidParameterValueException("In zone of type " + NetworkType.Advanced +
-                    " ip address can be associated only to the network of guest type " + GuestType.Isolated + " with the "
-                    + Service.SourceNat.getName() + " enabled");
-        }
-
-        NetworkOffering offering = _networkOfferingDao.findById(network.getNetworkOfferingId());
-        boolean sharedSourceNat = offering.getSharedSourceNat();
-        boolean isSourceNat = false;
-        if (!sharedSourceNat) {
-            if (getExistingSourceNatInNetwork(owner.getId(), networkId) == null) {
-                if (network.getGuestType() == GuestType.Isolated && network.getVpcId() == null &&
-                        !ipToAssoc.isPortable()) {
-                    isSourceNat = true;
-                }
-            }
-        }
-
-        s_logger.debug("Associating ip " + ipToAssoc + " to network " + network);
-
-        IPAddressVO ip = _ipAddressDao.findById(ipId);
-        //update ip address with networkId
-        ip.setAssociatedWithNetworkId(networkId);
-        ip.setSourceNat(isSourceNat);
-        _ipAddressDao.update(ipId, ip);
-
-        boolean success = false;
-        try {
-            success = applyIpAssociations(network, false);
-            if (success) {
-                s_logger.debug("Successfully associated ip address " + ip.getAddress().addr() + " to network " + network);
-            } else {
-                s_logger.warn("Failed to associate ip address " + ip.getAddress().addr() + " to network " + network);
-            }
-            return ip;
-        } finally {
-            if (!success && releaseOnFailure) {
-                if (ip != null) {
-                    try {
-                        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
-                            // count and generating usage event as there is no need to keep it in the db
-                            _ipAddressDao.unassignIpAddress(ip.getId());
-                        }
-                    } catch (Exception e) {
-                        s_logger.warn("Unable to disassociate ip address for recovery", e);
-                    }
-                }
-            }
-        }
-    }
-
-    @Override
-    public IPAddressVO associatePortableIPToGuestNetwork(long ipAddrId, long networkId, boolean releaseOnFailure) throws ResourceAllocationException, ResourceUnavailableException,
-            InsufficientAddressCapacityException, ConcurrentOperationException {
-        return associateIPToGuestNetwork(ipAddrId, networkId, releaseOnFailure);
-    }
-
-    @DB
-    @Override
-    public IPAddressVO disassociatePortableIPToGuestNetwork(long ipId, long networkId)
-            throws ResourceAllocationException, ResourceUnavailableException,
-            InsufficientAddressCapacityException, ConcurrentOperationException {
-
-        Account caller = CallContext.current().getCallingAccount();
-        Account owner = null;
-
-        Network network = _networksDao.findById(networkId);
-        if (network == null) {
-            throw new InvalidParameterValueException("Invalid network id is given");
-        }
-
-        IPAddressVO ipToAssoc = _ipAddressDao.findById(ipId);
-        if (ipToAssoc != null) {
-
-            if (ipToAssoc.getAssociatedWithNetworkId() == null) {
-                throw new InvalidParameterValueException("IP " + ipToAssoc + " is not associated with any network");
-            }
-
-            if (ipToAssoc.getAssociatedWithNetworkId() != network.getId()) {
-                throw new InvalidParameterValueException("IP " + ipToAssoc + " is not associated with network id" + networkId);
-            }
-
-            DataCenter zone = _configMgr.getZone(network.getDataCenterId());
-            if (zone.getNetworkType() == NetworkType.Advanced) {
-                if (network.getGuestType() == Network.GuestType.Shared) {
-                    assert (isSharedNetworkOfferingWithServices(network.getNetworkOfferingId()));
-                    _accountMgr.checkAccess(CallContext.current().getCallingAccount(), AccessType.UseNetwork, false, network);
-                }
-            } else {
-                _accountMgr.checkAccess(caller, null, true, ipToAssoc);
-            }
-            owner = _accountMgr.getAccount(ipToAssoc.getAllocatedToAccountId());
-        } else {
-            s_logger.debug("Unable to find ip address by id: " + ipId);
-            return null;
-        }
-
-        DataCenter zone = _configMgr.getZone(network.getDataCenterId());
-
-        // Check that network belongs to IP owner - skip this check
-        //     - if zone is basic zone as there is just one guest network,
-        //     - if shared network in Advanced zone
-        //     - and it belongs to the system
-        if (network.getAccountId() != owner.getId()) {
-            if (zone.getNetworkType() != NetworkType.Basic && !(zone.getNetworkType() == NetworkType.Advanced && network.getGuestType() == Network.GuestType.Shared)) {
-                throw new InvalidParameterValueException("The owner of the network is not the same as owner of the IP");
-            }
-        }
-
-        // Check if IP has any services (rules) associated in the network
-        List<PublicIpAddress> ipList = new ArrayList<PublicIpAddress>();
-        PublicIp publicIp = PublicIp.createFromAddrAndVlan(ipToAssoc, _vlanDao.findById(ipToAssoc.getVlanId()));
-        ipList.add(publicIp);
-        Map<PublicIpAddress, Set<Service>> ipToServices = _networkModel.getIpToServices(ipList, false, true);
-        if (ipToServices != null & !ipToServices.isEmpty()) {
-            Set<Service> services = ipToServices.get(publicIp);
-            if (services != null && !services.isEmpty()) {
-                throw new InvalidParameterValueException("IP " + ipToAssoc + " has services and rules associated in the network " +  networkId);
-            }
-        }
-
-        IPAddressVO ip = _ipAddressDao.findById(ipId);
-        ip.setAssociatedWithNetworkId(null);
-        _ipAddressDao.update(ipId, ip);
-
-        try {
-            boolean success = applyIpAssociations(network, false);
-            if (success) {
-                s_logger.debug("Successfully associated ip address " + ip.getAddress().addr() + " to network " + network);
-            } else {
-                s_logger.warn("Failed to associate ip address " + ip.getAddress().addr() + " to network " + network);
-            }
-            return ip;
-        } finally {
-
-        }
-    }
-
-    @Override
-    public boolean isPortableIpTransferableFromNetwork(long ipAddrId, long networkId) {
-        Network network = _networksDao.findById(networkId);
-        if (network == null) {
-            throw new InvalidParameterValueException("Invalid network id is given");
-        }
-
-        IPAddressVO ip = _ipAddressDao.findById(ipAddrId);
-        if (ip == null) {
-            throw new InvalidParameterValueException("Invalid network id is given");
-        }
-
-        // Check if IP has any services (rules) associated in the network
-        List<PublicIpAddress> ipList = new ArrayList<PublicIpAddress>();
-        PublicIp publicIp = PublicIp.createFromAddrAndVlan(ip, _vlanDao.findById(ip.getVlanId()));
-        ipList.add(publicIp);
-        Map<PublicIpAddress, Set<Service>> ipToServices = _networkModel.getIpToServices(ipList, false, true);
-        if (ipToServices != null & !ipToServices.isEmpty()) {
-            Set<Service> ipServices = ipToServices.get(publicIp);
-            if (ipServices != null && !ipServices.isEmpty()) {
-                return false;
-            }
-        }
-
-        return true;
-    }
-
-    @DB
-    @Override
-    public void transferPortableIP(long ipAddrId, long currentNetworkId, long newNetworkId)  throws ResourceAllocationException, ResourceUnavailableException,
-            InsufficientAddressCapacityException, ConcurrentOperationException {
-
-        Network srcNetwork = _networksDao.findById(currentNetworkId);
-        if (srcNetwork == null) {
-            throw new InvalidParameterValueException("Invalid source network id " + currentNetworkId +" is given");
-        }
-
-        Network dstNetwork = _networksDao.findById(newNetworkId);
-        if (dstNetwork == null) {
-            throw new InvalidParameterValueException("Invalid source network id " + newNetworkId +" is given");
-        }
-
-        IPAddressVO ip = _ipAddressDao.findById(ipAddrId);
-        if (ip == null) {
-            throw new InvalidParameterValueException("Invalid portable ip address id is given");
-        }
-
-        Transaction txn = Transaction.currentTxn();
-
-        assert(isPortableIpTransferableFromNetwork(ipAddrId, currentNetworkId));
-
-        // disassociate portable IP with current network/VPC network
-        if (srcNetwork.getVpcId() != null) {
-            _vpcMgr.unassignIPFromVpcNetwork(ipAddrId, currentNetworkId);
-        } else {
-            disassociatePortableIPToGuestNetwork(ipAddrId, currentNetworkId);
-        }
-
-        // If portable IP need to be transferred across the zones, then mark the entry corresponding to portable ip
-        // in user_ip_address and vlan tables so as to emulate portable IP as provisioned in destination data center
-        if (srcNetwork.getDataCenterId() != dstNetwork.getDataCenterId()) {
-            txn.start();
-
-            long physicalNetworkId = _networkModel.getDefaultPhysicalNetworkByZoneAndTrafficType(
-                    dstNetwork.getDataCenterId(), TrafficType.Public).getId();
-            long publicNetworkId =_networkModel.getSystemNetworkByZoneAndTrafficType(
-                    dstNetwork.getDataCenterId(), TrafficType.Public).getId();
-
-            ip.setDataCenterId(dstNetwork.getDataCenterId());
-            ip.setPhysicalNetworkId(physicalNetworkId);
-            ip.setSourceNetworkId(publicNetworkId);
-            _ipAddressDao.update(ipAddrId, ip);
-
-            VlanVO vlan = _vlanDao.findById(ip.getVlanId());
-            vlan.setPhysicalNetworkId(physicalNetworkId);
-            vlan.setNetworkId(publicNetworkId);
-            vlan.setDataCenterId(dstNetwork.getDataCenterId());
-            _vlanDao.update(ip.getVlanId(), vlan);
-
-            txn.commit();
-        }
-
-        // associate portable IP with new network/VPC network
-        associatePortableIPToGuestNetwork(ipAddrId, newNetworkId, false);
-
-        txn.start();
-
-        if (dstNetwork.getVpcId() != null) {
-            ip.setVpcId(dstNetwork.getVpcId());
-        } else {
-            ip.setVpcId(null);
-        }
-
-        _ipAddressDao.update(ipAddrId, ip);
-
-        txn.commit();
-
-        // trigger an action event for the transfer of portable IP across the networks, so that external entities
-        // monitoring for this event can initiate the route advertisement for the availability of IP from the zoe
-        ActionEventUtils.onActionEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, Domain.ROOT_DOMAIN,
-                EventTypes.EVENT_PORTABLE_IP_TRANSFER, "Portable IP associated is transferred from network "
-                    + currentNetworkId + " to " + newNetworkId);
-    }
-
-    @Override
-    @DB
-    public boolean disassociatePublicIpAddress(long addrId, long userId, Account caller) {
-
-        boolean success = true;
-        // Cleanup all ip address resources - PF/LB/Static nat rules
-        if (!cleanupIpResources(addrId, userId, caller)) {
-            success = false;
-            s_logger.warn("Failed to release resources for ip address id=" + addrId);
-        }
-
-        IPAddressVO ip = markIpAsUnavailable(addrId);
-
-        assert (ip != null) : "Unable to mark the ip address id=" + addrId + " as unavailable.";
-        if (ip == null) {
-            return true;
-        }
-
-        if (s_logger.isDebugEnabled()) {
-            s_logger.debug("Releasing ip id=" + addrId + "; sourceNat = " + ip.isSourceNat());
-        }
-
-        if (ip.getAssociatedWithNetworkId() != null) {
-            Network network = _networksDao.findById(ip.getAssociatedWithNetworkId());
-            try {
-                if (!applyIpAssociations(network, true)) {
-                    s_logger.warn("Unable to apply ip address associations for " + network);
-                    success = false;
-                }
-            } catch (ResourceUnavailableException e) {
-                throw new CloudRuntimeException("We should never get to here because we used true when applyIpAssociations", e);
-            }
-        } else {
-            if (ip.getState() == IpAddress.State.Releasing) {
-                _ipAddressDao.unassignIpAddress(ip.getId());
-            }
-        }
-
-        if (success) {
-            if (ip.isPortable()) {
-                releasePortableIpAddress(addrId);
-            }
-            s_logger.debug("Released a public ip id=" + addrId);
-        }
-
-        return success;
-    }
-
-    @DB
-    @Override
-    public boolean releasePortableIpAddress(long addrId) {
-        Transaction txn = Transaction.currentTxn();
-        GlobalLock portableIpLock = GlobalLock.getInternLock("PortablePublicIpRange");
-
-        txn.start();
-        try {
-            portableIpLock.lock(5);
-            IPAddressVO ip = _ipAddressDao.findById(addrId);
-
-            // unassign portable IP
-            PortableIpVO portableIp = _portableIpDao.findByIpAddress(ip.getAddress().addr());
-            _portableIpDao.unassignIpAddress(portableIp.getId());
-
-            // removed the provisioned vlan
-            VlanVO vlan = _vlanDao.findById(ip.getVlanId());
-            _vlanDao.remove(vlan.getId());
-
-            // remove the provisioned public ip address
-            _ipAddressDao.remove(ip.getId());
-
-            txn.commit();
-            return true;
-        } finally {
-            portableIpLock.releaseRef();
-        }
-    }
 
     @Override
     @DB
@@ -1974,47 +1049,131 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L
                 ips = _ipAddressDao.listByAssociatedNetwork(network.getId(), true);
             }
 
-            if (ips.isEmpty()) {
-                s_logger.debug("Creating a source nat ip for network " + network);
-                Account owner = _accountMgr.getAccount(network.getAccountId());
-                assignSourceNatIpAddressToGuestNetwork(owner, network);
-            }
+            if (ips.isEmpty()) {
+                s_logger.debug("Creating a source nat ip for network " + network);
+                Account owner = _accountMgr.getAccount(network.getAccountId());
+                _ipAddrMgr.assignSourceNatIpAddressToGuestNetwork(owner, network);
+            }
+        }
+
+        // get providers to implement
+        List<Provider> providersToImplement = getNetworkProviders(network.getId());
+        for (NetworkElement element : _networkElements) {
+            if (providersToImplement.contains(element.getProvider())) {
+                if (!_networkModel.isProviderEnabledInPhysicalNetwork(_networkModel.getPhysicalNetworkId(network), element.getProvider().getName())) {
+                    // The physicalNetworkId will not get translated into a uuid by the reponse serializer,
+                    // because the serializer would look up the NetworkVO class's table and retrieve the
+                    // network id instead of the physical network id.
+                    // So just throw this exception as is. We may need to TBD by changing the serializer.
+                    throw new CloudRuntimeException("Service provider " + element.getProvider().getName() +
+                            " either doesn't exist or is not enabled in physical network id: " + network.getPhysicalNetworkId());
+                }
+
+                if (s_logger.isDebugEnabled()) {
+                    s_logger.debug("Asking " + element.getName() + " to implemenet " + network);
+                }
+
+                if (!element.implement(network, offering, dest, context)) {
+                    CloudRuntimeException ex = new CloudRuntimeException("Failed to implement provider " + element.getProvider().getName() + " for network with specified id");
+                    ex.addProxyObject(network.getUuid(), "networkId");
+                    throw ex;
+                }
+            }
+        }
+
+        // reapply all the firewall/staticNat/lb rules
+        s_logger.debug("Reprogramming network " + network + " as a part of network implement");
+        if (!reprogramNetworkRules(network.getId(), CallContext.current().getCallingAccount(), network)) {
+            s_logger.warn("Failed to re-program the network as a part of network " + network + " implement");
+            // see DataCenterVO.java
+            ResourceUnavailableException ex = new ResourceUnavailableException("Unable to apply network rules as a part of network " + network + " implement", DataCenter.class, network.getDataCenterId());
+            ex.addProxyObject(ApiDBUtils.findZoneById(network.getDataCenterId()).getUuid());
+            throw ex;
+        }
+    }
+
+    // This method re-programs the rules/ips for existing network
+    protected boolean reprogramNetworkRules(long networkId, Account caller, NetworkVO network) throws ResourceUnavailableException {
+        boolean success = true;
+        // associate all ip addresses
+        if (!_ipAddrMgr.applyIpAssociations(network, false)) {
+            s_logger.warn("Failed to apply ip addresses as a part of network id" + networkId + " restart");
+            success = false;
+        }
+
+        // apply static nat
+        if (!_rulesMgr.applyStaticNatsForNetwork(networkId, false, caller)) {
+            s_logger.warn("Failed to apply static nats a part of network id" + networkId + " restart");
+            success = false;
+        }
+
+        // apply firewall rules
+        List<FirewallRuleVO> firewallIngressRulesToApply = _firewallDao.listByNetworkPurposeTrafficType(networkId, Purpose.Firewall, FirewallRule.TrafficType.Ingress);
+        if (!_firewallMgr.applyFirewallRules(firewallIngressRulesToApply, false, caller)) {
+            s_logger.warn("Failed to reapply Ingress firewall rule(s) as a part of network id=" + networkId + " restart");
+            success = false;
+        }
+
+        List<FirewallRuleVO> firewallEgressRulesToApply = _firewallDao.listByNetworkPurposeTrafficType(networkId, Purpose.Firewall, FirewallRule.TrafficType.Egress);
+        if (firewallEgressRulesToApply.size() == 0) {
+            NetworkOfferingVO offering = _networkOfferingDao.findById(network.getNetworkOfferingId());
+            //there are no egress rules then apply the default egress rule
+            DataCenter zone = _dcDao.findById(network.getDataCenterId());
+            if (offering.getEgressDefaultPolicy() && _networkModel.areServicesSupportedInNetwork(network.getId(), Service.Firewall) &&
+                (network.getGuestType() == Network.GuestType.Isolated || (network.getGuestType() == Network.GuestType.Shared && zone.getNetworkType() == NetworkType.Advanced))) {
+                // add default egress rule to accept the traffic
+                _firewallMgr.applyDefaultEgressFirewallRule(network.getId(), true);
+            }
+        } else {
+            if (!_firewallMgr.applyFirewallRules(firewallEgressRulesToApply, false, caller)) {
+                s_logger.warn("Failed to reapply firewall Egress rule(s) as a part of network id=" + networkId + " restart");
+                success = false;
+            }
+        }
+
+        // apply port forwarding rules
+        if (!_rulesMgr.applyPortForwardingRulesForNetwork(networkId, false, caller)) {
+            s_logger.warn("Failed to reapply port forwarding rule(s) as a part of network id=" + networkId + " restart");
+            success = false;
         }
 
-        // get providers to implement
-        List<Provider> providersToImplement = getNetworkProviders(network.getId());
-        for (NetworkElement element : _networkElements) {
-            if (providersToImplement.contains(element.getProvider())) {
-                if (!_networkModel.isProviderEnabledInPhysicalNetwork(_networkModel.getPhysicalNetworkId(network), element.getProvider().getName())) {
-                    // The physicalNetworkId will not get translated into a uuid by the reponse serializer,
-                    // because the serializer would look up the NetworkVO class's table and retrieve the
-                    // network id instead of the physical network id.
-                    // So just throw this exception as is. We may need to TBD by changing the serializer.
-                    throw new CloudRuntimeException("Service provider " + element.getProvider().getName() +
-                            " either doesn't exist or is not enabled in physical network id: " + network.getPhysicalNetworkId());
-                }
+        // apply static nat rules
+        if (!_rulesMgr.applyStaticNatRulesForNetwork(networkId, false, caller)) {
+            s_logger.warn("Failed to reapply static nat rule(s) as a part of network id=" + networkId + " restart");
+            success = false;
+        }
 
-                if (s_logger.isDebugEnabled()) {
-                    s_logger.debug("Asking " + element.getName() + " to implemenet " + network);
-                }
+        // apply public load balancer rules
+        if (!_lbMgr.applyLoadBalancersForNetwork(networkId, Scheme.Public)) {
+            s_logger.warn("Failed to reapply Public load balancer rules as a part of network id=" + networkId + " restart");
+            success = false;
+        }
 
-                if (!element.implement(network, offering, dest, context)) {
-                    CloudRuntimeException ex = new CloudRuntimeException("Failed to implement provider " + element.getProvider().getName() + " for network with specified id");
-                    ex.addProxyObject(network.getUuid(), "networkId");
-                    throw ex;
+        // apply internal load balancer rules
+        if (!_lbMgr.applyLoadBalancersForNetwork(networkId, Scheme.Internal)) {
+            s_logger.warn("Failed to reapply internal load balancer rules as a part of network id=" + networkId + " restart");
+            success = false;
+        }
+
+        // apply vpn rules
+        List<? extends RemoteAccessVpn> vpnsToReapply = _vpnMgr.listRemoteAccessVpns(networkId);
+        if (vpnsToReapply != null) {
+            for (RemoteAccessVpn vpn : vpnsToReapply) {
+                // Start remote access vpn per ip
+                if (_vpnMgr.startRemoteAccessVpn(vpn.getServerAddressId(), false) == null) {
+                    s_logger.warn("Failed to reapply vpn rules as a part of network id=" + networkId + " restart");
+                    success = false;
                 }
             }
         }
 
-        // reapply all the firewall/staticNat/lb rules
-        s_logger.debug("Reprogramming network " + network + " as a part of network implement");
-        if (!reprogramNetworkRules(network.getId(), CallContext.current().getCallingAccount(), network)) {
-            s_logger.warn("Failed to re-program the network as a part of network " + network + " implement");
-            // see DataCenterVO.java
-            ResourceUnavailableException ex = new ResourceUnavailableException("Unable to apply network rules as a part of network " + network + " implement", DataCenter.class, network.getDataCenterId());
-            ex.addProxyObject(ApiDBUtils.findZoneById(network.getDataCenterId()).getUuid());
-            throw ex;
+        //apply network ACLs
+        if (!_networkACLMgr.applyACLToNetwork(networkId)) {
+            s_logger.warn("Failed to reapply network ACLs as a part of  of network id=" + networkId + " restart");
+            success = false;
         }
+
+        return success;
     }
 
     protected boolean prepareElement(NetworkElement element, NetworkVO network,
@@ -3041,104 +2200,6 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L
         return result;
     }
 
-    @Override
-    public boolean applyRules(List<? extends FirewallRule> rules, FirewallRule.Purpose purpose,
-            NetworkRuleApplier applier, boolean continueOnError) throws ResourceUnavailableException {
-        if (rules == null || rules.size() == 0) {
-            s_logger.debug("There are no rules to forward to the network elements");
-            return true;
-        }
-
-        boolean success = true;
-        Network network = _networksDao.findById(rules.get(0).getNetworkId());
-        FirewallRuleVO.TrafficType trafficType = rules.get(0).getTrafficType();
-        List<PublicIp> publicIps = new ArrayList<PublicIp>();
-
-        if (!(rules.get(0).getPurpose() == FirewallRule.Purpose.Firewall && trafficType == FirewallRule.TrafficType.Egress)) {
-            // get the list of public ip's owned by the network
-            List<IPAddressVO> userIps = _ipAddressDao.listByAssociatedNetwork(network.getId(), null);
-            if (userIps != null && !userIps.isEmpty()) {
-                for (IPAddressVO userIp : userIps) {
-                    PublicIp publicIp = PublicIp.createFromAddrAndVlan(userIp, _vlanDao.findById(userIp.getVlanId()));
-                    publicIps.add(publicIp);
-                }
-            }
-        }
-        // rules can not programmed unless IP is associated with network service provider, so run IP assoication for
-        // the network so as to ensure IP is associated before applying rules (in add state)
-        if (checkIfIpAssocRequired(network, false, publicIps)) {
-            applyIpAssociations(network, false, continueOnError, publicIps);
-        }
-
-        try {
-            applier.applyRules(network, purpose, rules);
-        } catch (ResourceUnavailableException e) {
-            if (!continueOnError) {
-                throw e;
-            }
-            s_logger.warn("Problems with applying " + purpose + " rules but pushing on", e);
-            success = false;
-        }
-
-        // if there are no active rules associated with a public IP, then public IP need not be associated with a provider.
-        // This IPAssoc ensures, public IP is dis-associated after last active rule is revoked.
-        if (checkIfIpAssocRequired(network, true, publicIps)) {
-            applyIpAssociations(network, true, continueOnError, publicIps);
-        }
-
-        return success;
-    }
-
-    // An IP association is required in below cases
-    //  1.there is at least one public IP associated with the network on which first rule (PF/static NAT/LB) is being applied.
-    //  2.last rule (PF/static NAT/LB) on the public IP has been revoked. So the public IP should not be associated with any provider
-    boolean checkIfIpAssocRequired(Network network, boolean postApplyRules, List<PublicIp> publicIps) {
-        for (PublicIp ip : publicIps) {
-            if (ip.isSourceNat()) {
-                continue;
-            } else if (ip.isOneToOneNat()) {
-                continue;
-            } else {
-                Long totalCount = null;
-                Long revokeCount = null;
-                Long activeCount = null;
-                Long addCount = null;
-
-                totalCount = _firewallDao.countRulesByIpId(ip.getId());
-                if (postApplyRules) {
-                    revokeCount = _firewallDao.countRulesByIpIdAndState(ip.getId(), FirewallRule.State.Revoke);
-                } else {
-                    activeCount = _firewallDao.countRulesByIpIdAndState(ip.getId(), FirewallRule.State.Active);
-                    addCount = _firewallDao.countRulesByIpIdAndState(ip.getId(), FirewallRule.State.Add);
-                }
-
-                if (totalCount == null || totalCount.longValue() == 0L) {
-                    continue;
-                }
-
-                if (postApplyRules) {
-
-                    if (revokeCount != null && revokeCount.longValue() == totalCount.longValue()) {
-                        s_logger.trace("All rules are in Revoke state, have to dis-assiciate IP from the backend");
-                        return true;
-                    }
-                } else {
-                    if (activeCount != null && activeCount > 0) {
-                        continue;
-                    } else if (addCount != null && addCount.longValue() == totalCount.longValue()) {
-                        s_logger.trace("All rules are in Add state, have to assiciate IP with the backend");
-                        return true;
-                    } else {
-                        continue;
-                    }
-                }
-            }
-        }
-
-        // there are no IP's corresponding to this network that need to be associated with provider
-        return false;
-    }
-
     public class NetworkGarbageCollector implements Runnable {
         @Override
         public void run() {
@@ -3199,297 +2260,94 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L
                             User caller = _accountMgr.getSystemUser();
                             Account owner = _accountMgr.getAccount(_networksDao.findById(networkId).getAccountId());
 
-                            ReservationContext context = new ReservationContextImpl(null, null, caller, owner);
-
-                            shutdownNetwork(networkId, context, false);
-                        } catch (Exception e) {
-                            s_logger.warn("Unable to shutdown network: " + networkId);
-                        }
-                    }
-                }
-            } catch (Exception e) {
-                s_logger.warn("Caught exception while running network gc: ", e);
-            }
-        }
-    }
-
-    
-
-    @Override
-    public boolean startNetwork(long networkId, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException {
-
-        // Check if network exists
-        NetworkVO network = _networksDao.findById(networkId);
-        if (network == null) {
-            InvalidParameterValueException ex = new InvalidParameterValueException("Network with specified id doesn't exist");
-            ex.addProxyObject(String.valueOf(networkId), "networkId");
-            throw ex;
-        }
-
-        // implement the network
-        s_logger.debug("Starting network " + network + "...");
-        Pair<NetworkGuru, NetworkVO> implementedNetwork = implementNetwork(networkId, dest, context);
-        if (implementedNetwork.first() == null) {
-            s_logger.warn("Failed to start the network " + network);
-            return false;
-        } else {
-            return true;
-        }
-    }
-
-    @Override
-    public boolean restartNetwork(Long networkId, Account callerAccount, User callerUser, boolean cleanup) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException {
-
-        NetworkVO network = _networksDao.findById(networkId);
-
-        s_logger.debug("Restarting network " + networkId + "...");
-
-        ReservationContext context = new ReservationContextImpl(null, null, callerUser, callerAccount);
-
-        if (cleanup) {
-            // shutdown the network
-            s_logger.debug("Shutting down the network id=" + networkId + " as a part of network restart");
-
-            if (!shutdownNetworkElementsAndResources(context, true, network)) {
-                s_logger.debug("Failed to shutdown the network elements and resources as a part of network restart: " + network.getState());
-                setRestartRequired(network, true);
-                return false;
-            }
-        } else {
-            s_logger.debug("Skip the shutting down of network id=" + networkId);
-        }
-
-        // implement the network elements and rules again
-        DeployDestination dest = new DeployDestination(_dcDao.findById(network.getDataCenterId()), null, null, null);
-
-        s_logger.debug("Implementing the network " + network + " elements and resources as a part of network restart");
-        NetworkOfferingVO offering = _networkOfferingDao.findById(network.getNetworkOfferingId());
-
-        try {
-            implementNetworkElementsAndResources(dest, context, network, offering);
-            setRestartRequired(network, true);
-        } catch (Exception ex) {
-            s_logger.warn("Failed to implement network " + network + " elements and resources as a part of network restart due to ", ex);
-            return false;
-        }
-        setRestartRequired(network, false);
-        return true;
-    }
-
-    private void setRestartRequired(NetworkVO network, boolean restartRequired) {
-        s_logger.debug("Marking network " + network + " with restartRequired=" + restartRequired);
-        network.setRestartRequired(restartRequired);
-        _networksDao.update(network.getId(), network);
-    }
-
-    // This method re-programs the rules/ips for existing network
-    protected boolean reprogramNetworkRules(long networkId, Account caller, NetworkVO network) throws ResourceUnavailableException {
-        boolean success = true;
-        // associate all ip addresses
-        if (!applyIpAssociations(network, false)) {
-            s_logger.warn("Failed to apply ip addresses as a part of network id" + networkId + " restart");
-            success = false;
-        }
-
-        // apply static nat
-        if (!_rulesMgr.applyStaticNatsForNetwork(networkId, false, caller)) {
-            s_logger.warn("Failed to apply static nats a part of network id" + networkId + " restart");
-            success = false;
-        }
-
-        // apply firewall rules
-        List<FirewallRuleVO> firewallIngressRulesToApply = _firewallDao.listByNetworkPurposeTrafficType(networkId, Purpose.Firewall, FirewallRule.TrafficType.Ingress);
-        if (!_firewallMgr.applyFirewallRules(firewallIngressRulesToApply, false, caller)) {
-            s_logger.warn("Failed to reapply Ingress firewall rule(s) as a part of network id=" + networkId + " restart");
-            success = false;
-        }
-
-        List<FirewallRuleVO> firewallEgressRulesToApply = _firewallDao.listByNetworkPurposeTrafficType(networkId, Purpose.Firewall, FirewallRule.TrafficType.Egress);
-        if (firewallEgressRulesToApply.size() == 0) {
-            NetworkOfferingVO offering = _networkOfferingDao.findById(network.getNetworkOfferingId());
-            //there are no egress rules then apply the default egress rule
-            DataCenter zone = _dcDao.findById(network.getDataCenterId());
-            if (offering.getEgressDefaultPolicy() && _networkModel.areServicesSupportedInNetwork(network.getId(), Service.Firewall)
-                    && (network.getGuestType() == Network.GuestType.Isolated ||
-                    (network.getGuestType() == Network.GuestType.Shared && zone.getNetworkType() == NetworkType.Advanced))) {
-                // add default egress rule to accept the traffic
-                _firewallMgr.applyDefaultEgressFirewallRule(network.getId(), true);
-            }
-        } else {
-            if (!_firewallMgr.applyFirewallRules(firewallEgressRulesToApply, false, caller)) {
-                s_logger.warn("Failed to reapply firewall Egress rule(s) as a part of network id=" + networkId + " restart");
-                success = false;
-            }
-        }
-
-        // apply port forwarding rules
-        if (!_rulesMgr.applyPortForwardingRulesForNetwork(networkId, false, caller)) {
-            s_logger.warn("Failed to reapply port forwarding rule(s) as a part of network id=" + networkId + " restart");
-            success = false;
-        }
-
-        // apply static nat rules
-        if (!_rulesMgr.applyStaticNatRulesForNetwork(networkId, false, caller)) {
-            s_logger.warn("Failed to reapply static nat rule(s) as a part of network id=" + networkId + " restart");
-            success = false;
-        }
-
-        // apply public load balancer rules
-        if (!_lbMgr.applyLoadBalancersForNetwork(networkId, Scheme.Public)) {
-            s_logger.warn("Failed to reapply Public load balancer rules as a part of network id=" + networkId + " restart");
-            success = false;
-        }
-        
-        // apply internal load balancer rules
-        if (!_lbMgr.applyLoadBalancersForNetwork(networkId, Scheme.Internal)) {
-            s_logger.warn("Failed to reapply internal load balancer rules as a part of network id=" + networkId + " restart");
-            success = false;
-        }
-
-        // apply vpn rules
-        List<? extends RemoteAccessVpn> vpnsToReapply = _vpnMgr.listRemoteAccessVpns(networkId);
-        if (vpnsToReapply != null) {
-            for (RemoteAccessVpn vpn : vpnsToReapply) {
-                // Start remote access vpn per ip
-                if (_vpnMgr.startRemoteAccessVpn(vpn.getServerAddressId(), false) == null) {
-                    s_logger.warn("Failed to reapply vpn rules as a part of network id=" + networkId + " restart");
-                    success = false;
+                            ReservationContext context = new ReservationContextImpl(null, null, caller, owner);
+
+                            shutdownNetwork(networkId, context, false);
+                        } catch (Exception e) {
+                            s_logger.warn("Unable to shutdown network: " + networkId);
+                        }
+                    }
                 }
+            } catch (Exception e) {
+                s_logger.warn("Caught exception while running network gc: ", e);
             }
         }
-
-        //apply network ACLs
-        if (!_networkACLMgr.applyACLToNetwork(networkId)) {
-            s_logger.warn("Failed to reapply network ACLs as a part of  of network id=" + networkId + " restart");
-            success = false;
-        }
-
-        return success;
     }
 
     
-    protected int getActiveNicsInNetwork(long networkId) {
-        return _networksDao.getActiveNicsIn(networkId);
-    }
 
-    
     @Override
-    @DB
-    public boolean associateIpAddressListToAccount(long userId, long accountId, long zoneId, Long vlanId, Network guestNetwork)
-            throws InsufficientCapacityException, ConcurrentOperationException,
-            ResourceUnavailableException, ResourceAllocationException {
-        Account owner = _accountMgr.getActiveAccountById(accountId);
-        boolean createNetwork = false;
+    public boolean startNetwork(long networkId, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException {
 
-        if (guestNetwork != null && guestNetwork.getTrafficType() != TrafficType.Guest) {
-            throw new InvalidParameterValueException("Network " + guestNetwork + " is not of a type " + TrafficType.Guest);
+        // Check if network exists
+        NetworkVO network = _networksDao.findById(networkId);
+        if (network == null) {
+            InvalidParameterValueException ex = new InvalidParameterValueException("Network with specified id doesn't exist");
+            ex.addProxyObject(String.valueOf(networkId), "networkId");
+            throw ex;
         }
 
-        Transaction txn = Transaction.currentTxn();
-        txn.start();
-
-        if (guestNetwork == null) {
-            List<? extends Network> networks = getIsolatedNetworksWithSourceNATOwnedByAccountInZone(zoneId, owner);
-            if (networks.size() == 0) {
-                createNetwork = true;
-            } else if (networks.size() == 1)  {
-                guestNetwork = networks.get(0);
-            } else {
-                throw new InvalidParameterValueException("Error, more than 1 Guest Isolated Networks with SourceNAT " +
-                        "service enabled found for this account, cannot assosiate the IP range, please provide the network ID");
-            }
+        // implement the network
+        s_logger.debug("Starting network " + network + "...");
+        Pair<NetworkGuru, NetworkVO> implementedNetwork = implementNetwork(networkId, dest, context);
+        if (implementedNetwork.first() == null) {
+            s_logger.warn("Failed to start the network " + network);
+            return false;
+        } else {
+            return true;
         }
+    }
 
-        // create new Virtual network (Isolated with SourceNAT) for the user if it doesn't exist
-        List<NetworkOfferingVO> requiredOfferings = _networkOfferingDao.listByAvailability(Availability.Required, false);
-        if (requiredOfferings.size() < 1) {
-            throw new CloudRuntimeException("Unable to find network offering with availability=" +
-        Availability.Required + " to automatically create the network as part of createVlanIpRange");
-        }
-        if (createNetwork) {
-            if (requiredOfferings.get(0).getState() == NetworkOffering.State.Enabled) {
-                long physicalNetworkId = _networkModel.findPhysicalNetworkId(zoneId, requiredOfferings.get(0).getTags(), requiredOfferings.get(0).getTrafficType());
-                // Validate physical network
-                PhysicalNetwork physicalNetwork = _physicalNetworkDao.findById(physicalNetworkId);
-                if (physicalNetwork == null) {
-                    throw new InvalidParameterValueException("Unable to find physical network with id: "+physicalNetworkId   + " and tag: " +requiredOfferings.get(0).getTags());
-                }
+    @Override
+    public boolean restartNetwork(Long networkId, Account callerAccount, User callerUser, boolean cleanup) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException {
 
-                s_logger.debug("Creating network for account " + owner + " from the network offering id=" +
-            requiredOfferings.get(0).getId() + " as a part of createVlanIpRange process");
-                guestNetwork = createGuestNetwork(requiredOfferings.get(0).getId(), owner.getAccountName() + "-network"
-                        , owner.getAccountName() + "-network", null, null, null, null, owner, null, physicalNetwork,
-                        zoneId, ACLType.Account,
-                        null, null, null, null, true, null);
-                if (guestNetwork == null) {
-                    s_logger.warn("Failed to create default Virtual network for the account " + accountId + "in zone " + zoneId);
-                    throw new CloudRuntimeException("Failed to create a Guest Isolated Networks with SourceNAT " +
-                            "service enabled as a part of createVlanIpRange, for the account " + accountId + "in zone " + zoneId);
-                }
-            } else {
-                throw new CloudRuntimeException("Required network offering id=" + requiredOfferings.get(0).getId()
-                        + " is not in " + NetworkOffering.State.Enabled);
-            }
-        }
+        NetworkVO network = _networksDao.findById(networkId);
 
-        // Check if there is a source nat ip address for this account; if not - we have to allocate one
-        boolean allocateSourceNat = false;
-        List<IPAddressVO> sourceNat = _ipAddressDao.listByAssociatedNetwork(guestNetwork.getId(), true);
-        if (sourceNat.isEmpty()) {
-            allocateSourceNat = true;
-        }
+        s_logger.debug("Restarting network " + networkId + "...");
 
-        // update all ips with a network id, mark them as allocated and update resourceCount/usage
-        List<IPAddressVO> ips = _ipAddressDao.listByVlanId(vlanId);
-        boolean isSourceNatAllocated = false;
-        for (IPAddressVO addr : ips) {
-            if (addr.getState() != State.Allocated) {
-                if (!isSourceNatAllocated && allocateSourceNat) {
-                    addr.setSourceNat(true);
-                    isSourceNatAllocated = true;
-                } else {
-                    addr.setSourceNat(false);
-                }
-                addr.setAssociatedWithNetworkId(guestNetwork.getId());
-                addr.setVpcId(guestNetwork.getVpcId());
-                addr.setAllocatedTime(new Date());
-                addr.setAllocatedInDomainId(owner.getDomainId());
-                addr.setAllocatedToAccountId(owner.getId());
-                addr.setSystem(false);
-                addr.setState(IpAddress.State.Allocating);
-                markPublicIpAsAllocated(addr);
+        ReservationContext context = new ReservationContextImpl(null, null, callerUser, callerAccount);
+
+        if (cleanup) {
+            // shutdown the network
+            s_logger.debug("Shutting down the network id=" + networkId + " as a part of network restart");
+
+            if (!shutdownNetworkElementsAndResources(context, true, network)) {
+                s_logger.debug("Failed to shutdown the network elements and resources as a part of network restart: " + network.getState());
+                setRestartRequired(network, true);
+                return false;
             }
+        } else {
+            s_logger.debug("Skip the shutting down of network id=" + networkId);
         }
 
-        txn.commit();
+        // implement the network elements and rules again
+        DeployDestination dest = new DeployDestination(_dcDao.findById(network.getDataCenterId()), null, null, null);
 
-        // if the network offering has persistent set to true, implement the network
-        if ( createNetwork && requiredOfferings.get(0).getIsPersistent() ) {
-            DataCenter zone = _dcDao.findById(zoneId);
-            DeployDestination dest = new DeployDestination(zone, null, null, null);
-            Account callerAccount = CallContext.current().getCallingAccount();
-            UserVO callerUser = _userDao.findById(CallContext.current().getCallingUserId());
-            Journal journal = new Journal.LogJournal("Implementing " + guestNetwork, s_logger);
-            ReservationContext context = new ReservationContextImpl(UUID.randomUUID().toString(), journal, callerUser, callerAccount);
-            s_logger.debug("Implementing network " + guestNetwork + " as a part of network provision for persistent network");
-            try {
-                Pair<NetworkGuru, NetworkVO> implementedNetwork = implementNetwork(guestNetwork.getId(), dest, context);
-                if (implementedNetwork.first() == null) {
-                    s_logger.warn("Failed to implement the network " + guestNetwork);
-                }
-                guestNetwork = implementedNetwork.second();
-            } catch (Exception ex) {
-                s_logger.warn("Failed to implement network " + guestNetwork + " elements and resources as a part of" +
-                        " network provision due to ", ex);
-                CloudRuntimeException e = new CloudRuntimeException("Failed to implement network (with specified id)" +
-                        " elements and resources as a part of network provision for persistent network");
-                e.addProxyObject(guestNetwork.getUuid(), "networkId");
-                throw e;
-            }
+        s_logger.debug("Implementing the network " + network + " elements and resources as a part of network restart");
+        NetworkOfferingVO offering = _networkOfferingDao.findById(network.getNetworkOfferingId());
+
+        try {
+            implementNetworkElementsAndResources(dest, context, network, offering);
+            setRestartRequired(network, true);
+        } catch (Exception ex) {
+            s_logger.warn("Failed to implement network " + network + " elements and resources as a part of network restart due to ", ex);
+            return false;
         }
+        setRestartRequired(network, false);
         return true;
     }
 
+    private void setRestartRequired(NetworkVO network, boolean restartRequired) {
+        s_logger.debug("Marking network " + network + " with restartRequired=" + restartRequired);
+        network.setRestartRequired(restartRequired);
+        _networksDao.update(network.getId(), network);
+    }
+
+    protected int getActiveNicsInNetwork(long networkId) {
+        return _networksDao.getActiveNicsIn(networkId);
+    }
+
+    
     @Override
     public NetworkProfile convertNetworkToNetworkProfile(long networkId) {
         NetworkVO network = _networksDao.findById(networkId);
@@ -3563,99 +2421,6 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L
     }
 
 
-    protected boolean cleanupIpResources(long ipId, long userId, Account caller) {
-        boolean success = true;
-
-        // Revoke all firewall rules for the ip
-        try {
-            s_logger.debug("Revoking all " + Purpose.Firewall + "rules as a part of public IP id=" + ipId + " release...");
-            if (!_firewallMgr.revokeFirewallRulesForIp(ipId, userId, caller)) {
-                s_logger.warn("Unable to revoke all the firewall rules for ip id=" + ipId + " as a part of ip release");
-                success = false;
-            }
-        } catch (ResourceUnavailableException e) {
-            s_logger.warn("Unable to revoke all firewall rules for ip id=" + ipId + " as a part of ip release", e);
-            success = false;
-        }
-
-        // Revoke all PF/Static nat rules for the ip
-        try {
-            s_logger.debug("Revoking all " + Purpose.PortForwarding + "/" + Purpose.StaticNat + " rules as a part of public IP id=" + ipId + " release...");
-            if (!_rulesMgr.revokeAllPFAndStaticNatRulesForIp(ipId, userId, caller)) {
-                s_logger.warn("Unable to revoke all the port forwarding rules for ip id=" + ipId + " as a part of ip release");
-                success = false;
-            }
-        } catch (ResourceUnavailableException e) {
-            s_logger.warn("Unable to revoke all the port forwarding rules for ip id=" + ipId + " as a part of ip release", e);
-            success = false;
-        }
-
-        s_logger.debug("Revoking all " + Purpose.LoadBalancing + " rules as a part of public IP id=" + ipId + " release...");
-        if (!_lbMgr.removeAllLoadBalanacersForIp(ipId, caller, userId)) {
-            s_logger.warn("Unable to revoke all the load balancer rules for ip id=" + ipId + " as a part of ip release");
-            success = false;
-        }
-
-        // remote access vpn can be enabled only for static nat ip, so this part should never be executed under normal
-        // conditions
-        // only when ip address failed to be cleaned up as a part of account destroy and was marked as Releasing, this part of
-        // the code would be triggered
-        s_logger.debug("Cleaning up remote access vpns as a part of public IP id=" + ipId + " release...");
-        try {
-            _vpnMgr.destroyRemoteAccessVpnForIp(ipId, caller);
-        } catch (ResourceUnavailableException e) {
-            s_logger.warn("Unable to destroy remote access vpn for ip id=" + ipId + " as a part of ip release", e);
-            success = false;
-        }
-
-        return success;
-    }
-
-    @DB
-    @Override
-    public IPAddressVO markIpAsUnavailable(long addrId) {
-        Transaction txn = Transaction.currentTxn();
-
-        IPAddressVO ip = _ipAddressDao.findById(addrId);
-
-        if (ip.getAllocatedToAccountId() == null && ip.getAllocatedTime() == null) {
-            s_logger.trace("Ip address id=" + addrId + " is already released");
-            return ip;
-        }
-
-        if (ip.getState() != State.Releasing) {
-            txn.start();
-
-            // don't decrement resource count for direct and dedicated ips
-            if (ip.getAssociatedWithNetworkId() != null && !isIpDedicated(ip)) {
-                _resourceLimitMgr.decrementResourceCount(_ipAddressDao.findById(addrId).getAllocatedToAccountId(), ResourceType.public_ip);
-            }
-
-            // Save usage event
-            if (ip.getAllocatedToAccountId() != null && ip.getAllocatedToAccountId() != Account.ACCOUNT_ID_SYSTEM) {
-                VlanVO vlan = _vlanDao.findById(ip.getVlanId());
-
-                String guestType = vlan.getVlanType().toString();
-                if (!isIpDedicated(ip)) {
-                    String eventType =  ip.isPortable() ? EventTypes.EVENT_PORTABLE_IP_RELEASE : EventTypes.EVENT_NET_IP_RELEASE;
-                    UsageEventUtils.publishUsageEvent( eventType,
-                            ip.getAllocatedToAccountId(), ip.getDataCenterId(), addrId, ip.getAddress().addr(),
-                            ip.isSourceNat(), guestType, ip.getSystem(), ip.getClass().getName(), ip.getUuid());
-                }
-            }
-
-            ip = _ipAddressDao.markAsUnavailable(addrId);
-
-            txn.commit();
-        }
-
-        return ip;
-    }
-
-    
-
-    Random _rand = new Random(System.currentTimeMillis());
-
     @Override
     public List<? extends Nic> listVmNics(Long vmId, Long nicId) {
         List<NicVO> result = null;
@@ -3667,144 +2432,8 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L
         return result;
     }
 
-    @Override
-    public String allocateGuestIP(Account ipOwner, boolean isSystem, long zoneId, Long networkId, String requestedIp)
-    throws InsufficientAddressCapacityException {
-        String ipaddr = null;
-        Account caller = CallContext.current().getCallingAccount();
-        // check permissions
-        Network network = _networksDao.findById(networkId);
-
-        _accountMgr.checkAccess(caller, null, false, network);
-
-        ipaddr = acquireGuestIpAddress(network, requestedIp);
-        return ipaddr;
-    }
-
-
-    @Override
-    @DB
-    public String acquireGuestIpAddress(Network network, String requestedIp) {
-        if (requestedIp != null && requestedIp.equals(network.getGateway())) {
-            s_logger.warn("Requested ip address " + requestedIp + " is used as a gateway address in network " + network);
-            return null;
-        }
-
-        Set<Long> availableIps = _networkModel.getAvailableIps(network, requestedIp);
-
-        if (availa

<TRUNCATED>