network shutdown code

This commit is contained in:
Alex Huang 2010-12-09 20:57:32 -08:00
parent b24cf4715b
commit 2d4432d87e
9 changed files with 283 additions and 43 deletions

View File

@ -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;
}

View File

@ -191,6 +191,8 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
SearchBuilder<IPAddressVO> IpAddressSearch;
private Map<String, String> _configs;
HashMap<Long, Long> _lastNetworkIdsToFree = new HashMap<Long, Long>();
@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<NetworkAccountVO> 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<? extends FirewallRule> 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<Long> shutdownList = new ArrayList<Long>();
long currentTime = System.currentTimeMillis() >> 10;
HashMap<Long, Long> stillFree = new HashMap<Long, Long>();
List<Long> 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);
}
}
}
}

View File

@ -14,4 +14,6 @@ public interface NicDao extends GenericDao<NicVO, Long> {
List<String> listIpAddressInNetworkConfiguration(long networkConfigId);
List<NicVO> listByNetworkId(long networkId);
List<Long> listNetworksWithNoActiveNics();
}

View File

@ -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<NicVO, Long> implements NicDao {
private final SearchBuilder<NicVO> InstanceSearch;
private final GenericSearchBuilder<NicVO, String> IpSearch;
private final SearchBuilder<NicVO> NetworkSearch;
private final GenericSearchBuilder<NicVO, Long> 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<NicVO, Long> implements NicDao {
sc.setParameters("networkId", networkId);
return listBy(sc);
}
@Override
public List<Long> listNetworksWithNoActiveNics() {
SearchCriteria<Long> sc = GarbageCollectSearch.create();
return customSearch(sc, null);
}
}

View File

@ -221,4 +221,9 @@ public class Attribute {
return columnName.equals(that.columnName) && table.equals(that.table);
}
@Override
public String toString() {
return table + "." + columnName;
}
}

View File

@ -331,7 +331,7 @@ public abstract class GenericDaoBase<T, ID extends Serializable> implements Gene
}
}
addGroupBy(str, sc);
List<Object> groupByValues = addGroupBy(str, sc);
addFilter(str, filter);
final Transaction txn = Transaction.currentTxn();
@ -356,6 +356,12 @@ public abstract class GenericDaoBase<T, ID extends Serializable> 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<T, ID extends Serializable> implements Gene
}
}
addGroupBy(str, sc);
List<Object> groupByValues = addGroupBy(str, sc);
addFilter(str, filter);
final String sql = str.toString();
@ -412,6 +418,12 @@ public abstract class GenericDaoBase<T, ID extends Serializable> 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<M> results = new ArrayList<M>();
@ -918,17 +930,13 @@ public abstract class GenericDaoBase<T, ID extends Serializable> implements Gene
}
@DB(txn=false)
protected void addGroupBy(final StringBuilder sql, SearchCriteria<?> sc) {
List<Attribute> 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<Object> addGroupBy(final StringBuilder sql, SearchCriteria<?> sc) {
Pair<GroupBy<?, ?>, List<Object>> groupBys = sc.getGroupBy();
if (groupBys != null) {
groupBys.first().toSql(sql);
return groupBys.second();
} else {
return null;
}
}

View File

@ -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<T, K> implements MethodInterceptor {
protected ArrayList<Condition> _conditions;
protected HashMap<String, JoinBuilder<GenericSearchBuilder<?, ?>>> _joins;
protected ArrayList<Select> _selects;
protected ArrayList<Attribute> _groupBys;
protected GroupBy<T, K> _groupBy = null;
protected Class<T> _entityBeanType;
protected Class<K> _resultType;
protected SelectType _selectType;
@ -210,18 +211,15 @@ public class GenericSearchBuilder<T, K> implements MethodInterceptor {
return left(name, useless, op);
}
public GenericSearchBuilder<T, K> groupBy(Object... useless) {
if(_groupBys == null) {
_groupBys = new ArrayList<Attribute>();
}
public GroupBy<T, K> groupBy(Object... useless) {
assert _groupBy == null : "Can't do more than one group bys";
_groupBy = new GroupBy<T, K>(this);
Attribute[] attrs = _specifiedAttrs.toArray(new Attribute[_specifiedAttrs.size()]);
for(Attribute attr : attrs) {
_groupBys.add(attr);
}
_specifiedAttrs.clear();
return this;
return _groupBy;
}
protected List<Attribute> getSpecifiedAttributes() {
return _specifiedAttrs;
}
/**

View File

@ -0,0 +1,109 @@
/**
* Copyright (C) 2010 Cloud.com, Inc. All rights reserved.
*
* This software is licensed under the GNU General Public License v3 or later.
*
* It is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.cloud.utils.db;
import java.util.ArrayList;
import java.util.List;
import com.cloud.utils.Pair;
import com.cloud.utils.db.SearchCriteria.Func;
import com.cloud.utils.db.SearchCriteria.Op;
public class GroupBy<T, R> {
GenericSearchBuilder<T, R> _builder;
List<Pair<Func, Attribute>> _groupBys;
Having _having;
public GroupBy(GenericSearchBuilder<T, R> builder) {
_builder = builder;
_groupBys = new ArrayList<Pair<Func, Attribute>>();
_having = null;
for (Attribute attr : _builder.getSpecifiedAttributes()) {
_groupBys.add(new Pair<Func, Attribute>(null, attr));
}
_builder.getSpecifiedAttributes().clear();
}
public GroupBy<T, R> group(Object useless) {
_groupBys.add(new Pair<Func, Attribute>(null, _builder.getSpecifiedAttributes().get(0)));
_builder.getSpecifiedAttributes().clear();
return this;
}
public GroupBy<T, R> group(Func func, Object useless) {
_groupBys.add(new Pair<Func, Attribute>(func, _builder.getSpecifiedAttributes().get(0)));
_builder.getSpecifiedAttributes().clear();
return this;
}
public GenericSearchBuilder<T, R> having(Func func, Object obj, Op op, Object value) {
assert(_having == null) : "You can only specify one having in a group by";
List<Attribute> attrs = _builder.getSpecifiedAttributes();
assert attrs.size() == 1 : "You didn't specified an attribute";
_having = new Having(func, attrs.get(0), op, value);
_builder.getSpecifiedAttributes().clear();
return _builder;
}
public void toSql(StringBuilder builder) {
builder.append(" GROUP BY ");
for (Pair<Func, Attribute> groupBy : _groupBys) {
if (groupBy.first() != null) {
String func = groupBy.first().toString();
func.replaceFirst("@", groupBy.second().table + "." + groupBy.second().columnName);
builder.append(func);
} else {
builder.append(groupBy.second().table + "." + groupBy.second().columnName);
}
builder.append(", ");
}
builder.delete(builder.length() - 2, builder.length());
if (_having != null) {
_having.toSql(builder);
}
}
protected class Having {
public Func func;
public Attribute attr;
public Op op;
public Object value;
public Having(Func func, Attribute attr, Op op, Object value) {
this.func = func;
this.attr = attr;
this.op = op;
this.value = value;
}
public void toSql(StringBuilder builder) {
if (func != null) {
String f = func.toString();
f.replaceFirst("@", attr.toString());
builder.append(func);
} else {
builder.append(attr.toString());
}
builder.append(op.toString());
}
}
}

View File

@ -118,7 +118,8 @@ public class SearchCriteria<K> {
private int _counter;
private HashMap<String, JoinBuilder<SearchCriteria<?>>> _joins;
private final ArrayList<Select> _selects;
private final ArrayList<Attribute> _groupBys;
private final GroupBy<?, K> _groupBy;
private final List<Object> _groupByValues;
private final Class<K> _resultType;
private final SelectType _selectType;
@ -136,7 +137,12 @@ public class SearchCriteria<K> {
}
}
_selects = sb._selects;
_groupBys = sb._groupBys;
_groupBy = sb._groupBy;
if (_groupBy != null) {
_groupByValues = new ArrayList<Object>();
} else {
_groupByValues = null;
}
_resultType = sb._resultType;
_selectType = sb._selectType;
}
@ -204,12 +210,18 @@ public class SearchCriteria<K> {
join.getT().addOr(field, op, values);
}
public SearchCriteria getJoin(String joinName) {
public SearchCriteria<?> getJoin(String joinName) {
return _joins.get(joinName).getT();
}
public List<Attribute> getGroupBy() {
return _groupBys;
public Pair<GroupBy<?, ?>, List<Object>> getGroupBy() {
return new Pair<GroupBy<?, ?>, List<Object>>(_groupBy, _groupByValues);
}
public void setGroupByValues(Object... values) {
for (Object value : values) {
_groupByValues.add(value);
}
}
public Class<K> getResultType() {