diff --git a/api/src/com/cloud/network/Network.java b/api/src/com/cloud/network/Network.java index a27843358a2..5d2053163f8 100644 --- a/api/src/com/cloud/network/Network.java +++ b/api/src/com/cloud/network/Network.java @@ -112,4 +112,6 @@ public interface Network extends ControlledEntity { String getDisplayText(); boolean isShared(); + + String getReservationId(); } diff --git a/server/src/com/cloud/configuration/Config.java b/server/src/com/cloud/configuration/Config.java index d9dba788bab..c59fc05f68e 100644 --- a/server/src/com/cloud/configuration/Config.java +++ b/server/src/com/cloud/configuration/Config.java @@ -157,6 +157,7 @@ public enum Config { CheckPodCIDRs("Advanced", ManagementServer.class, String.class, "check.pod.cidrs", "true", "If true, different pods must belong to different CIDR subnets.", "true,false"), MD5Hashed("Advanced", ManagementServer.class, Boolean.class, "security.password.md5hashed", "true", "If set to false password is sent in clear text or else md5hashed", null), NetworkGcWait("Advanced", ManagementServer.class, Integer.class, "network.gc.wait", "600", "Seconds to wait before shutting down a network that's not in used", null), + NetworkGcInterval("Advanced", ManagementServer.class, Integer.class, "network.gc.interval", "600", "Seconds to wait before checking for networks to shutdown", null), ControlCidr("Advanced", ManagementServer.class, String.class, "control.cidr", "169.254.0.0/16", "Changes the cidr for the control network traffic. Defaults to using link local. Must be unique within pods", null), ControlGateway("Advanced", ManagementServer.class, String.class, "control.gateway", "169.254.0.1", "gateway for the control network traffic", null), diff --git a/server/src/com/cloud/network/NetworkManagerImpl.java b/server/src/com/cloud/network/NetworkManagerImpl.java index 90176e4c842..0c792a9f928 100755 --- a/server/src/com/cloud/network/NetworkManagerImpl.java +++ b/server/src/com/cloud/network/NetworkManagerImpl.java @@ -26,7 +26,9 @@ import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; import javax.ejb.Local; import javax.naming.ConfigurationException; @@ -121,6 +123,7 @@ import com.cloud.utils.Pair; import com.cloud.utils.component.Adapters; import com.cloud.utils.component.Inject; import com.cloud.utils.component.Manager; +import com.cloud.utils.concurrency.NamedThreadFactory; import com.cloud.utils.db.DB; import com.cloud.utils.db.Filter; import com.cloud.utils.db.JoinBuilder; @@ -192,6 +195,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag SearchBuilder AssignIpAddressSearch; SearchBuilder IpAddressSearch; int _networkGcWait; + int _networkGcInterval; private Map _configs; @@ -754,6 +758,8 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag virtualNetworkVlanSB.and("vlanType", virtualNetworkVlanSB.entity().getVlanType(), Op.EQ); IpAddressSearch.join("virtualNetworkVlanSB", virtualNetworkVlanSB, IpAddressSearch.entity().getVlanId(), virtualNetworkVlanSB.entity().getId(), JoinBuilder.JoinType.INNER); IpAddressSearch.done(); + + _executor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("Network-Scavenger")); s_logger.info("Network Manager is configured."); @@ -767,6 +773,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag @Override public boolean start() { + _executor.scheduleWithFixedDelay(new NetworkGarbageCollector(), _networkGcInterval, _networkGcInterval, TimeUnit.SECONDS); return true; } @@ -1958,15 +1965,21 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag } } + txn.start(); if (success) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Unsuccessfully shutdown the network."); + } NetworkGuru guru = _networkGurus.get(network.getGuruName()); guru.destroy(network, _networkOfferingDao.findById(network.getNetworkOfferingId())); network.setState(Network.State.Allocated); _networksDao.update(network.getId(), network); + _networksDao.clearCheckForGc(networkId); } else { network.setState(Network.State.Implemented); _networksDao.update(network.getId(), network); } + txn.commit(); } @@ -2000,32 +2013,40 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag @Override public void run() { - List shutdownList = new ArrayList(); - long currentTime = System.currentTimeMillis() >> 10; - HashMap stillFree = new HashMap(); - - List networkIds = _networksDao.findNetworksToGarbageCollect(); - for (Long networkId : networkIds) { - Long time = _lastNetworkIdsToFree.remove(networkId); - if (time == null) { - if (s_logger.isDebugEnabled()) { - s_logger.debug("We found network " + networkId + " to be free for the first time. Adding it to the list: " + currentTime); + try { + List shutdownList = new ArrayList(); + long currentTime = System.currentTimeMillis() >> 10; + HashMap stillFree = new HashMap(); + + List networkIds = _networksDao.findNetworksToGarbageCollect(); + for (Long networkId : networkIds) { + Long time = _lastNetworkIdsToFree.remove(networkId); + if (time == null) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("We found network " + networkId + " to be free for the first time. Adding it to the list: " + currentTime); + } + stillFree.put(networkId, currentTime); + } else if (time < (currentTime + _networkGcWait)) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Network " + networkId + " is still free but it's not time to shutdown yet: " + time); + } + stillFree.put(networkId, time); + } else { + shutdownList.add(networkId); } - stillFree.put(networkId, currentTime); - } else if (time < (currentTime + _networkGcWait)) { - if (s_logger.isDebugEnabled()) { - s_logger.debug("Network " + networkId + " is still free but it's not time to shutdown yet: " + time); - } - stillFree.put(networkId, time); - } else { - shutdownList.add(networkId); } - } - - _lastNetworkIdsToFree = stillFree; - - for (Long networkId : shutdownList) { - shutdownNetwork(networkId); + + _lastNetworkIdsToFree = stillFree; + + for (Long networkId : shutdownList) { + try { + shutdownNetwork(networkId); + } catch (Exception e) { + s_logger.warn("Unable to shutdown network: " + networkId); + } + } + } catch (Exception e) { + s_logger.warn("Caught exception while running network gc: ", e); } } } diff --git a/server/src/com/cloud/network/NetworkVO.java b/server/src/com/cloud/network/NetworkVO.java index 5556fa6b262..8dcbd0d39cd 100644 --- a/server/src/com/cloud/network/NetworkVO.java +++ b/server/src/com/cloud/network/NetworkVO.java @@ -129,6 +129,8 @@ public class NetworkVO implements Network { @Column(name=GenericDao.CREATED_COLUMN) Date created; + @Column(name="reservation_id") + String reservationId; public NetworkVO() { } @@ -191,6 +193,15 @@ public class NetworkVO implements Network { this.isShared = isShared; } + @Override + public String getReservationId() { + return reservationId; + } + + public void setReservationId(String reservationId) { + this.reservationId = reservationId; + } + @Override public State getState() { return state; diff --git a/server/src/com/cloud/network/guru/GuestNetworkGuru.java b/server/src/com/cloud/network/guru/GuestNetworkGuru.java index 3aeef29c916..5291c6dfa09 100644 --- a/server/src/com/cloud/network/guru/GuestNetworkGuru.java +++ b/server/src/com/cloud/network/guru/GuestNetworkGuru.java @@ -39,7 +39,6 @@ import com.cloud.network.NetworkVO; import com.cloud.network.Networks.BroadcastDomainType; import com.cloud.network.Networks.Mode; import com.cloud.network.Networks.TrafficType; -import com.cloud.network.guru.NetworkGuru; import com.cloud.offering.NetworkOffering; import com.cloud.offering.NetworkOffering.GuestIpType; import com.cloud.resource.Resource.ReservationStrategy; @@ -87,7 +86,7 @@ public class GuestNetworkGuru extends AdapterBase implements NetworkGuru { } DataCenterVO dc = _dcDao.findById(plan.getDataCenterId()); - NetworkVO config = new NetworkVO(offering.getTrafficType(), offering.getGuestIpType(), mode, broadcastType, offering.getId(), plan.getDataCenterId()); + NetworkVO network = new NetworkVO(offering.getTrafficType(), offering.getGuestIpType(), mode, broadcastType, offering.getId(), plan.getDataCenterId()); if (userSpecified != null) { if ((userSpecified.getCidr() == null && userSpecified.getGateway() != null) || (userSpecified.getCidr() != null && userSpecified.getGateway() == null)) { @@ -95,75 +94,75 @@ public class GuestNetworkGuru extends AdapterBase implements NetworkGuru { } if (userSpecified.getCidr() != null) { - config.setCidr(userSpecified.getCidr()); - config.setGateway(userSpecified.getGateway()); + network.setCidr(userSpecified.getCidr()); + network.setGateway(userSpecified.getGateway()); } else { String guestNetworkCidr = dc.getGuestNetworkCidr(); String[] cidrTuple = guestNetworkCidr.split("\\/"); - config.setGateway(NetUtils.getIpRangeStartIpFromCidr(cidrTuple[0], Long.parseLong(cidrTuple[1]))); - config.setCidr(guestNetworkCidr); + network.setGateway(NetUtils.getIpRangeStartIpFromCidr(cidrTuple[0], Long.parseLong(cidrTuple[1]))); + network.setCidr(guestNetworkCidr); } - config.setDns1(dc.getDns1()); - config.setDns2(dc.getDns2()); + network.setDns1(dc.getDns1()); + network.setDns2(dc.getDns2()); if (userSpecified.getBroadcastUri() != null) { - config.setBroadcastUri(userSpecified.getBroadcastUri()); - config.setState(State.Setup); + network.setBroadcastUri(userSpecified.getBroadcastUri()); + network.setState(State.Setup); } } else { String guestNetworkCidr = dc.getGuestNetworkCidr(); String[] cidrTuple = guestNetworkCidr.split("\\/"); - config.setGateway(NetUtils.getIpRangeStartIpFromCidr(cidrTuple[0], Long.parseLong(cidrTuple[1]))); - config.setCidr(guestNetworkCidr); - config.setDns1(dc.getDns1()); - config.setDns2(dc.getDns2()); + network.setGateway(NetUtils.getIpRangeStartIpFromCidr(cidrTuple[0], Long.parseLong(cidrTuple[1]))); + network.setCidr(guestNetworkCidr); + network.setDns1(dc.getDns1()); + network.setDns2(dc.getDns2()); } - return config; + return network; } @Override - public void deallocate(Network config, NicProfile nic, VirtualMachineProfile vm) { + public void deallocate(Network network, NicProfile nic, VirtualMachineProfile vm) { } @Override - public Network implement(Network config, NetworkOffering offering, DeployDestination dest, ReservationContext context) { - assert (config.getState() == State.Allocated) : "Why implement are we implementing " + config; + public Network implement(Network network, NetworkOffering offering, DeployDestination dest, ReservationContext context) { + assert (network.getState() == State.Allocated) : "Why implement are we implementing " + network; long dcId = dest.getDataCenter().getId(); - NetworkVO implemented = new NetworkVO(config.getTrafficType(), config.getGuestType(), config.getMode(), config.getBroadcastDomainType(), config.getNetworkOfferingId(), config.getDataCenterId()); + NetworkVO implemented = new NetworkVO(network.getTrafficType(), network.getGuestType(), network.getMode(), network.getBroadcastDomainType(), network.getNetworkOfferingId(), network.getDataCenterId()); - if (config.getBroadcastUri() == null) { - String vnet = _dcDao.allocateVnet(dcId, config.getAccountId(), context.getReservationId()); + if (network.getBroadcastUri() == null) { + String vnet = _dcDao.allocateVnet(dcId, network.getAccountId(), context.getReservationId()); implemented.setBroadcastUri(BroadcastDomainType.Vlan.toUri(vnet)); } else { - implemented.setBroadcastUri(config.getBroadcastUri()); + implemented.setBroadcastUri(network.getBroadcastUri()); } - if (config.getGateway() != null) { - implemented.setGateway(config.getGateway()); + if (network.getGateway() != null) { + implemented.setGateway(network.getGateway()); } - if (config.getCidr() != null) { - implemented.setCidr(config.getCidr()); + if (network.getCidr() != null) { + implemented.setCidr(network.getCidr()); } - if (config.getDns1() != null) { - implemented.setDns1(config.getDns1()); + if (network.getDns1() != null) { + implemented.setDns1(network.getDns1()); } - if (config.getDns2() != null) { - implemented.setDns2(config.getDns2()); + if (network.getDns2() != null) { + implemented.setDns2(network.getDns2()); } return implemented; } @Override - public NicProfile allocate(Network config, NicProfile nic, VirtualMachineProfile vm) + public NicProfile allocate(Network network, NicProfile nic, VirtualMachineProfile vm) throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException { - if (config.getTrafficType() != TrafficType.Guest) { + if (network.getTrafficType() != TrafficType.Guest) { return null; } @@ -176,9 +175,9 @@ public class GuestNetworkGuru extends AdapterBase implements NetworkGuru { } if (nic.getMacAddress() == null) { - nic.setMacAddress(_networkMgr.getNextAvailableMacAddressInNetwork(config.getId())); + nic.setMacAddress(_networkMgr.getNextAvailableMacAddressInNetwork(network.getId())); if (nic.getMacAddress() == null) { - throw new InsufficientAddressCapacityException("Unable to allocate more mac addresses", Network.class, config.getId()); + throw new InsufficientAddressCapacityException("Unable to allocate more mac addresses", Network.class, network.getId()); } } @@ -186,9 +185,9 @@ public class GuestNetworkGuru extends AdapterBase implements NetworkGuru { } @DB - protected String acquireGuestIpAddress(Network config) { - List ips = _nicDao.listIpAddressInNetworkConfiguration(config.getId()); - String[] cidr = config.getCidr().split("/"); + protected String acquireGuestIpAddress(Network network) { + List ips = _nicDao.listIpAddressInNetworkConfiguration(network.getId()); + String[] cidr = network.getCidr().split("/"); Set allPossibleIps = NetUtils.getAllIpsFromCidr(cidr[0], Integer.parseInt(cidr[1])); Set usedIps = new TreeSet (); for (String ip : ips) { @@ -205,17 +204,17 @@ public class GuestNetworkGuru extends AdapterBase implements NetworkGuru { } @Override - public void reserve(NicProfile nic, Network config, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) throws InsufficientVirtualNetworkCapcityException, + public void reserve(NicProfile nic, Network network, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException { assert (nic.getReservationStrategy() == ReservationStrategy.Start) : "What can I do for nics that are not allocated at start? "; - nic.setBroadcastUri(config.getBroadcastUri()); - nic.setIsolationUri(config.getBroadcastUri()); - nic.setGateway(config.getGateway()); - nic.setIp4Address(acquireGuestIpAddress(config)); - nic.setNetmask(NetUtils.cidr2Netmask(config.getCidr())); - nic.setDns1(config.getDns1()); - nic.setDns2(config.getDns2()); + nic.setBroadcastUri(network.getBroadcastUri()); + nic.setIsolationUri(network.getBroadcastUri()); + nic.setGateway(network.getGateway()); + nic.setIp4Address(acquireGuestIpAddress(network)); + nic.setNetmask(NetUtils.cidr2Netmask(network.getCidr())); + nic.setDns1(network.getDns1()); + nic.setDns2(network.getDns2()); } @Override @@ -226,12 +225,12 @@ public class GuestNetworkGuru extends AdapterBase implements NetworkGuru { } @Override - public void destroy(Network config, NetworkOffering offering) { - config.getBroadcastUri(); + public void destroy(Network network, NetworkOffering offering) { + _dcDao.releaseVnet(network.getBroadcastUri().getHost(), network.getDataCenterId(), network.getAccountId(), network.getReservationId()); } @Override - public boolean trash(Network config, NetworkOffering offering, Account owner) { + public boolean trash(Network network, NetworkOffering offering, Account owner) { return true; } }