From 2d4432d87e2f25ef97fb79cb8bd5b5ad5544fb10 Mon Sep 17 00:00:00 2001 From: Alex Huang Date: Thu, 9 Dec 2010 20:57:32 -0800 Subject: [PATCH] network shutdown code --- core/src/com/cloud/storage/VMTemplateVO.java | 22 ++-- .../com/cloud/network/NetworkManagerImpl.java | 87 +++++++++++++- server/src/com/cloud/vm/dao/NicDao.java | 2 + server/src/com/cloud/vm/dao/NicDaoImpl.java | 23 +++- utils/src/com/cloud/utils/db/Attribute.java | 5 + .../com/cloud/utils/db/GenericDaoBase.java | 34 +++--- .../cloud/utils/db/GenericSearchBuilder.java | 22 ++-- utils/src/com/cloud/utils/db/GroupBy.java | 109 ++++++++++++++++++ .../com/cloud/utils/db/SearchCriteria.java | 22 +++- 9 files changed, 283 insertions(+), 43 deletions(-) create mode 100644 utils/src/com/cloud/utils/db/GroupBy.java diff --git a/core/src/com/cloud/storage/VMTemplateVO.java b/core/src/com/cloud/storage/VMTemplateVO.java index 0b24d70d828..5db5eaf0e38 100755 --- a/core/src/com/cloud/storage/VMTemplateVO.java +++ b/core/src/com/cloud/storage/VMTemplateVO.java @@ -23,6 +23,8 @@ import java.util.UUID; import javax.persistence.Column; import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; import javax.persistence.Id; import javax.persistence.Table; import javax.persistence.TableGenerator; @@ -104,7 +106,8 @@ public class VMTemplateVO implements VirtualMachineTemplate { private boolean crossZones = false; @Column(name="hypervisor_type") - private String hypervisorType; + @Enumerated(value=EnumType.STRING) + private HypervisorType hypervisorType; @Column(name="extractable") private boolean extractable = true; @@ -145,7 +148,7 @@ public class VMTemplateVO implements VirtualMachineTemplate { this.created = created; this.guestOSId = guestOSId; this.bootable = bootable; - this.hypervisorType = hyperType.toString(); + this.hypervisorType = hyperType; } // Has an extra attribute - isExtractable @@ -168,7 +171,7 @@ public class VMTemplateVO implements VirtualMachineTemplate { this.created = created; this.guestOSId = guestOSId; this.bootable = bootable; - this.hypervisorType = hyperType.toString(); + this.hypervisorType = hyperType; } @Override @@ -217,7 +220,8 @@ public class VMTemplateVO implements VirtualMachineTemplate { return requiresHvm; } - public int getBits() { + @Override + public int getBits() { return bits; } @@ -247,6 +251,7 @@ public class VMTemplateVO implements VirtualMachineTemplate { this.publicTemplate = publicTemplate; } + @Override public boolean isFeatured() { return featured; } @@ -332,11 +337,11 @@ public class VMTemplateVO implements VirtualMachineTemplate { @Override public HypervisorType getHypervisorType() { - return HypervisorType.getType(hypervisorType); + return hypervisorType; } public void setHypervisorType(HypervisorType hyperType) { - hypervisorType = hyperType.toString(); + hypervisorType = hyperType; } @Override @@ -355,8 +360,9 @@ public class VMTemplateVO implements VirtualMachineTemplate { @Override public boolean equals(Object that) { - if (this == that ) - return true; + if (this == that ) { + return true; + } if (!(that instanceof VMTemplateVO)){ return false; } diff --git a/server/src/com/cloud/network/NetworkManagerImpl.java b/server/src/com/cloud/network/NetworkManagerImpl.java index d663c5a0486..bd14abe5f28 100755 --- a/server/src/com/cloud/network/NetworkManagerImpl.java +++ b/server/src/com/cloud/network/NetworkManagerImpl.java @@ -191,6 +191,8 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag SearchBuilder IpAddressSearch; private Map _configs; + + HashMap _lastNetworkIdsToFree = new HashMap(); @Override @DB public PublicIp fetchNewPublicIp(long dcId, VlanType vlanUse, Account owner, Long networkId, boolean sourceNat) throws InsufficientAddressCapacityException { @@ -761,7 +763,6 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag NetworkOfferingVO defaultGuestDirectPodBasedNetworkOffering = new NetworkOfferingVO(NetworkOffering.DefaultDirectPodBasedNetworkOffering, "DirectPodBased", TrafficType.Public, GuestIpType.DirectPodBased, true, false, rateMbps, multicastRateMbps, null, true); defaultGuestNetworkOffering = _networkOfferingDao.persistDefaultNetworkOffering(defaultGuestDirectPodBasedNetworkOffering); - AccountsUsingNetworkSearch = _accountDao.createSearchBuilder(); SearchBuilder networkAccountSearch = _networksDao.createSearchBuilderForAccount(); AccountsUsingNetworkSearch.join("nc", networkAccountSearch, AccountsUsingNetworkSearch.entity().getId(), networkAccountSearch.entity().getAccountId(), JoinType.INNER); @@ -1944,6 +1945,55 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag } + @DB + public void shutdownNetwork(long networkId) { + Transaction txn = Transaction.currentTxn(); + txn.start(); + NetworkVO network = _networksDao.lockRow(networkId, true); + if (network == null) { + s_logger.debug("Unable to find network with id: " + networkId); + return; + } + if (network.getState() != Network.State.Implemented && network.getState() != Network.State.Destroying) { + s_logger.debug("Network is not implemented: " + network); + return; + } + network.setState(Network.State.Destroying); + _networksDao.update(network.getId(), network); + txn.commit(); + + boolean success = true; + for (NetworkElement element : _networkElements) { + try { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Sending network shutdown to " + element); + } + element.shutdown(network, null); + } catch (ResourceUnavailableException e) { + s_logger.warn("Unable to complete shutdown of the network due to element: " + element.getName(), e); + success = false; + } catch (ConcurrentOperationException e) { + s_logger.warn("Unable to complete shutdown of the network due to element: " + element.getName(), e); + success = false; + } catch (Exception e) { + s_logger.warn("Unable to complete shutdown of the network due to element: " + element.getName(), e); + success = false; + } + } + + if (success) { + NetworkGuru guru = _networkGurus.get(network.getGuruName()); + guru.destroy(network, _networkOfferingDao.findById(network.getNetworkOfferingId())); + network.setState(Network.State.Allocated); + _networksDao.update(network.getId(), network); + } else { + network.setState(Network.State.Implemented); + _networksDao.update(network.getId(), network); + } + + + } + @Override public boolean applyRules(Ip ip, List rules, boolean continueOnError) throws ResourceUnavailableException { if (rules.size() == 0) { @@ -1968,4 +2018,39 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag return success; } + + public class NetworkGarbageCollector implements Runnable { + + @Override + public void run() { + List shutdownList = new ArrayList(); + long currentTime = System.currentTimeMillis() >> 10; + HashMap stillFree = new HashMap(); + + List networkIds = _nicDao.listNetworksWithNoActiveNics(); + 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 + 600)) { + 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); + } + } + + } } diff --git a/server/src/com/cloud/vm/dao/NicDao.java b/server/src/com/cloud/vm/dao/NicDao.java index 4d68174be11..078d6a1c1d3 100644 --- a/server/src/com/cloud/vm/dao/NicDao.java +++ b/server/src/com/cloud/vm/dao/NicDao.java @@ -14,4 +14,6 @@ public interface NicDao extends GenericDao { List listIpAddressInNetworkConfiguration(long networkConfigId); List listByNetworkId(long networkId); + + List listNetworksWithNoActiveNics(); } diff --git a/server/src/com/cloud/vm/dao/NicDaoImpl.java b/server/src/com/cloud/vm/dao/NicDaoImpl.java index 3345e3fc30a..fe8d2a1376a 100644 --- a/server/src/com/cloud/vm/dao/NicDaoImpl.java +++ b/server/src/com/cloud/vm/dao/NicDaoImpl.java @@ -12,6 +12,7 @@ import com.cloud.utils.db.GenericSearchBuilder; import com.cloud.utils.db.SearchBuilder; import com.cloud.utils.db.SearchCriteria; import com.cloud.utils.db.SearchCriteria.Func; +import com.cloud.utils.db.SearchCriteria.Op; import com.cloud.vm.NicVO; @Local(value=NicDao.class) @@ -19,23 +20,30 @@ public class NicDaoImpl extends GenericDaoBase implements NicDao { private final SearchBuilder InstanceSearch; private final GenericSearchBuilder IpSearch; private final SearchBuilder NetworkSearch; + private final GenericSearchBuilder GarbageCollectSearch; protected NicDaoImpl() { super(); InstanceSearch = createSearchBuilder(); - InstanceSearch.and("instance", InstanceSearch.entity().getInstanceId(), SearchCriteria.Op.EQ); + InstanceSearch.and("instance", InstanceSearch.entity().getInstanceId(), Op.EQ); InstanceSearch.done(); IpSearch = createSearchBuilder(String.class); IpSearch.select(null, Func.DISTINCT, IpSearch.entity().getIp4Address()); - IpSearch.and("nc", IpSearch.entity().getNetworkId(), SearchCriteria.Op.EQ); - IpSearch.and("address", IpSearch.entity().getIp4Address(), SearchCriteria.Op.NNULL); + IpSearch.and("nc", IpSearch.entity().getNetworkId(), Op.EQ); + IpSearch.and("address", IpSearch.entity().getIp4Address(), Op.NNULL); IpSearch.done(); NetworkSearch = createSearchBuilder(); - NetworkSearch.and("networkId", NetworkSearch.entity().getNetworkId(), SearchCriteria.Op.EQ); + NetworkSearch.and("networkId", NetworkSearch.entity().getNetworkId(), Op.EQ); NetworkSearch.done(); + + GarbageCollectSearch = createSearchBuilder(Long.class); + GarbageCollectSearch.select(null, Func.DISTINCT, GarbageCollectSearch.entity().getNetworkId()); + GarbageCollectSearch.and("reservation", GarbageCollectSearch.entity().getReservationId(), Op.NULL); + GarbageCollectSearch.groupBy(GarbageCollectSearch.entity().getNetworkId()).having(Func.COUNT, GarbageCollectSearch.entity().getId(), Op.EQ, null); + GarbageCollectSearch.done(); } @Override @@ -58,4 +66,11 @@ public class NicDaoImpl extends GenericDaoBase implements NicDao { sc.setParameters("networkId", networkId); return listBy(sc); } + + @Override + public List listNetworksWithNoActiveNics() { + SearchCriteria sc = GarbageCollectSearch.create(); + + return customSearch(sc, null); + } } diff --git a/utils/src/com/cloud/utils/db/Attribute.java b/utils/src/com/cloud/utils/db/Attribute.java index 82a071adc40..aefb02dd139 100755 --- a/utils/src/com/cloud/utils/db/Attribute.java +++ b/utils/src/com/cloud/utils/db/Attribute.java @@ -221,4 +221,9 @@ public class Attribute { return columnName.equals(that.columnName) && table.equals(that.table); } + + @Override + public String toString() { + return table + "." + columnName; + } } diff --git a/utils/src/com/cloud/utils/db/GenericDaoBase.java b/utils/src/com/cloud/utils/db/GenericDaoBase.java index ff21e451611..c9b3dbc8e64 100755 --- a/utils/src/com/cloud/utils/db/GenericDaoBase.java +++ b/utils/src/com/cloud/utils/db/GenericDaoBase.java @@ -331,7 +331,7 @@ public abstract class GenericDaoBase implements Gene } } - addGroupBy(str, sc); + List groupByValues = addGroupBy(str, sc); addFilter(str, filter); final Transaction txn = Transaction.currentTxn(); @@ -356,6 +356,12 @@ public abstract class GenericDaoBase implements Gene if (joins != null) { i = addJoinAttributes(i, pstmt, joins); } + + if (groupByValues != null) { + for (Object value : groupByValues) { + pstmt.setObject(i++, value); + } + } if (s_logger.isDebugEnabled() && lock != null) { txn.registerLock(pstmt.toString()); @@ -392,7 +398,7 @@ public abstract class GenericDaoBase implements Gene } } - addGroupBy(str, sc); + List groupByValues = addGroupBy(str, sc); addFilter(str, filter); final String sql = str.toString(); @@ -412,6 +418,12 @@ public abstract class GenericDaoBase implements Gene i = addJoinAttributes(i, pstmt, joins); } + if (groupByValues != null) { + for (Object value : groupByValues) { + pstmt.setObject(i++, value); + } + } + ResultSet rs = pstmt.executeQuery(); SelectType st = sc.getSelectType(); ArrayList results = new ArrayList(); @@ -918,17 +930,13 @@ public abstract class GenericDaoBase implements Gene } @DB(txn=false) - protected void addGroupBy(final StringBuilder sql, SearchCriteria sc) { - List groupBys = sc.getGroupBy(); - if(groupBys != null) { - sql.append(" GROUP BY "); - for(int i = 0; i < groupBys.size(); i++) { - Attribute attr = groupBys.get(i); - sql.append(attr.table).append(".").append(attr.columnName); - if(i < groupBys.size() - 1) { - sql.append(", "); - } - } + protected List addGroupBy(final StringBuilder sql, SearchCriteria sc) { + Pair, List> groupBys = sc.getGroupBy(); + if (groupBys != null) { + groupBys.first().toSql(sql); + return groupBys.second(); + } else { + return null; } } diff --git a/utils/src/com/cloud/utils/db/GenericSearchBuilder.java b/utils/src/com/cloud/utils/db/GenericSearchBuilder.java index 60f3ca8c3be..5c10cbabc66 100644 --- a/utils/src/com/cloud/utils/db/GenericSearchBuilder.java +++ b/utils/src/com/cloud/utils/db/GenericSearchBuilder.java @@ -21,6 +21,7 @@ import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; import net.sf.cglib.proxy.Factory; @@ -48,7 +49,7 @@ public class GenericSearchBuilder implements MethodInterceptor { protected ArrayList _conditions; protected HashMap>> _joins; protected ArrayList _selects; - private final ArrayList _groupBys; + private final GroupBy _groupBy; + private final List _groupByValues; private final Class _resultType; private final SelectType _selectType; @@ -136,7 +137,12 @@ public class SearchCriteria { } } _selects = sb._selects; - _groupBys = sb._groupBys; + _groupBy = sb._groupBy; + if (_groupBy != null) { + _groupByValues = new ArrayList(); + } else { + _groupByValues = null; + } _resultType = sb._resultType; _selectType = sb._selectType; } @@ -204,12 +210,18 @@ public class SearchCriteria { join.getT().addOr(field, op, values); } - public SearchCriteria getJoin(String joinName) { + public SearchCriteria getJoin(String joinName) { return _joins.get(joinName).getT(); } - public List getGroupBy() { - return _groupBys; + public Pair, List> getGroupBy() { + return new Pair, List>(_groupBy, _groupByValues); + } + + public void setGroupByValues(Object... values) { + for (Object value : values) { + _groupByValues.add(value); + } } public Class getResultType() {