Skip to content

Commit 2d4432d

Browse files
author
Alex Huang
committed
network shutdown code
1 parent b24cf47 commit 2d4432d

9 files changed

Lines changed: 283 additions & 43 deletions

File tree

core/src/com/cloud/storage/VMTemplateVO.java

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323

2424
import javax.persistence.Column;
2525
import javax.persistence.Entity;
26+
import javax.persistence.EnumType;
27+
import javax.persistence.Enumerated;
2628
import javax.persistence.Id;
2729
import javax.persistence.Table;
2830
import javax.persistence.TableGenerator;
@@ -104,7 +106,8 @@ public class VMTemplateVO implements VirtualMachineTemplate {
104106
private boolean crossZones = false;
105107

106108
@Column(name="hypervisor_type")
107-
private String hypervisorType;
109+
@Enumerated(value=EnumType.STRING)
110+
private HypervisorType hypervisorType;
108111

109112
@Column(name="extractable")
110113
private boolean extractable = true;
@@ -145,7 +148,7 @@ public VMTemplateVO(Long id, String uniqueName, String name, ImageFormat format,
145148
this.created = created;
146149
this.guestOSId = guestOSId;
147150
this.bootable = bootable;
148-
this.hypervisorType = hyperType.toString();
151+
this.hypervisorType = hyperType;
149152
}
150153

151154
// Has an extra attribute - isExtractable
@@ -168,7 +171,7 @@ public VMTemplateVO(Long id, String uniqueName, String name, ImageFormat format,
168171
this.created = created;
169172
this.guestOSId = guestOSId;
170173
this.bootable = bootable;
171-
this.hypervisorType = hyperType.toString();
174+
this.hypervisorType = hyperType;
172175
}
173176

174177
@Override
@@ -217,7 +220,8 @@ public boolean requiresHvm() {
217220
return requiresHvm;
218221
}
219222

220-
public int getBits() {
223+
@Override
224+
public int getBits() {
221225
return bits;
222226
}
223227

@@ -247,6 +251,7 @@ public void setPublicTemplate(boolean publicTemplate) {
247251
this.publicTemplate = publicTemplate;
248252
}
249253

254+
@Override
250255
public boolean isFeatured() {
251256
return featured;
252257
}
@@ -332,11 +337,11 @@ public boolean isCrossZones() {
332337

333338
@Override
334339
public HypervisorType getHypervisorType() {
335-
return HypervisorType.getType(hypervisorType);
340+
return hypervisorType;
336341
}
337342

338343
public void setHypervisorType(HypervisorType hyperType) {
339-
hypervisorType = hyperType.toString();
344+
hypervisorType = hyperType;
340345
}
341346

342347
@Override
@@ -355,8 +360,9 @@ public long getDomainId() {
355360

356361
@Override
357362
public boolean equals(Object that) {
358-
if (this == that )
359-
return true;
363+
if (this == that ) {
364+
return true;
365+
}
360366
if (!(that instanceof VMTemplateVO)){
361367
return false;
362368
}

server/src/com/cloud/network/NetworkManagerImpl.java

Lines changed: 86 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,8 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
191191
SearchBuilder<IPAddressVO> IpAddressSearch;
192192

193193
private Map<String, String> _configs;
194+
195+
HashMap<Long, Long> _lastNetworkIdsToFree = new HashMap<Long, Long>();
194196

195197
@Override @DB
196198
public PublicIp fetchNewPublicIp(long dcId, VlanType vlanUse, Account owner, Long networkId, boolean sourceNat) throws InsufficientAddressCapacityException {
@@ -761,7 +763,6 @@ public boolean configure(final String name, final Map<String, Object> params) th
761763
NetworkOfferingVO defaultGuestDirectPodBasedNetworkOffering = new NetworkOfferingVO(NetworkOffering.DefaultDirectPodBasedNetworkOffering, "DirectPodBased", TrafficType.Public, GuestIpType.DirectPodBased, true, false, rateMbps, multicastRateMbps, null, true);
762764
defaultGuestNetworkOffering = _networkOfferingDao.persistDefaultNetworkOffering(defaultGuestDirectPodBasedNetworkOffering);
763765

764-
765766
AccountsUsingNetworkSearch = _accountDao.createSearchBuilder();
766767
SearchBuilder<NetworkAccountVO> networkAccountSearch = _networksDao.createSearchBuilderForAccount();
767768
AccountsUsingNetworkSearch.join("nc", networkAccountSearch, AccountsUsingNetworkSearch.entity().getId(), networkAccountSearch.entity().getAccountId(), JoinType.INNER);
@@ -1944,6 +1945,55 @@ public boolean deleteNetwork(DeleteNetworkCmd cmd) throws InvalidParameterValueE
19441945

19451946
}
19461947

1948+
@DB
1949+
public void shutdownNetwork(long networkId) {
1950+
Transaction txn = Transaction.currentTxn();
1951+
txn.start();
1952+
NetworkVO network = _networksDao.lockRow(networkId, true);
1953+
if (network == null) {
1954+
s_logger.debug("Unable to find network with id: " + networkId);
1955+
return;
1956+
}
1957+
if (network.getState() != Network.State.Implemented && network.getState() != Network.State.Destroying) {
1958+
s_logger.debug("Network is not implemented: " + network);
1959+
return;
1960+
}
1961+
network.setState(Network.State.Destroying);
1962+
_networksDao.update(network.getId(), network);
1963+
txn.commit();
1964+
1965+
boolean success = true;
1966+
for (NetworkElement element : _networkElements) {
1967+
try {
1968+
if (s_logger.isDebugEnabled()) {
1969+
s_logger.debug("Sending network shutdown to " + element);
1970+
}
1971+
element.shutdown(network, null);
1972+
} catch (ResourceUnavailableException e) {
1973+
s_logger.warn("Unable to complete shutdown of the network due to element: " + element.getName(), e);
1974+
success = false;
1975+
} catch (ConcurrentOperationException e) {
1976+
s_logger.warn("Unable to complete shutdown of the network due to element: " + element.getName(), e);
1977+
success = false;
1978+
} catch (Exception e) {
1979+
s_logger.warn("Unable to complete shutdown of the network due to element: " + element.getName(), e);
1980+
success = false;
1981+
}
1982+
}
1983+
1984+
if (success) {
1985+
NetworkGuru guru = _networkGurus.get(network.getGuruName());
1986+
guru.destroy(network, _networkOfferingDao.findById(network.getNetworkOfferingId()));
1987+
network.setState(Network.State.Allocated);
1988+
_networksDao.update(network.getId(), network);
1989+
} else {
1990+
network.setState(Network.State.Implemented);
1991+
_networksDao.update(network.getId(), network);
1992+
}
1993+
1994+
1995+
}
1996+
19471997
@Override
19481998
public boolean applyRules(Ip ip, List<? extends FirewallRule> rules, boolean continueOnError) throws ResourceUnavailableException {
19491999
if (rules.size() == 0) {
@@ -1968,4 +2018,39 @@ public boolean applyRules(Ip ip, List<? extends FirewallRule> rules, boolean con
19682018

19692019
return success;
19702020
}
2021+
2022+
public class NetworkGarbageCollector implements Runnable {
2023+
2024+
@Override
2025+
public void run() {
2026+
List<Long> shutdownList = new ArrayList<Long>();
2027+
long currentTime = System.currentTimeMillis() >> 10;
2028+
HashMap<Long, Long> stillFree = new HashMap<Long, Long>();
2029+
2030+
List<Long> networkIds = _nicDao.listNetworksWithNoActiveNics();
2031+
for (Long networkId : networkIds) {
2032+
Long time = _lastNetworkIdsToFree.remove(networkId);
2033+
if (time == null) {
2034+
if (s_logger.isDebugEnabled()) {
2035+
s_logger.debug("We found network " + networkId + " to be free for the first time. Adding it to the list: " + currentTime);
2036+
}
2037+
stillFree.put(networkId, currentTime);
2038+
} else if (time < (currentTime + 600)) {
2039+
if (s_logger.isDebugEnabled()) {
2040+
s_logger.debug("Network " + networkId + " is still free but it's not time to shutdown yet: " + time);
2041+
}
2042+
stillFree.put(networkId, time);
2043+
} else {
2044+
shutdownList.add(networkId);
2045+
}
2046+
}
2047+
2048+
_lastNetworkIdsToFree = stillFree;
2049+
2050+
for (Long networkId : shutdownList) {
2051+
shutdownNetwork(networkId);
2052+
}
2053+
}
2054+
2055+
}
19712056
}

server/src/com/cloud/vm/dao/NicDao.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,6 @@ public interface NicDao extends GenericDao<NicVO, Long> {
1414
List<String> listIpAddressInNetworkConfiguration(long networkConfigId);
1515

1616
List<NicVO> listByNetworkId(long networkId);
17+
18+
List<Long> listNetworksWithNoActiveNics();
1719
}

server/src/com/cloud/vm/dao/NicDaoImpl.java

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,30 +12,38 @@
1212
import com.cloud.utils.db.SearchBuilder;
1313
import com.cloud.utils.db.SearchCriteria;
1414
import com.cloud.utils.db.SearchCriteria.Func;
15+
import com.cloud.utils.db.SearchCriteria.Op;
1516
import com.cloud.vm.NicVO;
1617

1718
@Local(value=NicDao.class)
1819
public class NicDaoImpl extends GenericDaoBase<NicVO, Long> implements NicDao {
1920
private final SearchBuilder<NicVO> InstanceSearch;
2021
private final GenericSearchBuilder<NicVO, String> IpSearch;
2122
private final SearchBuilder<NicVO> NetworkSearch;
23+
private final GenericSearchBuilder<NicVO, Long> GarbageCollectSearch;
2224

2325
protected NicDaoImpl() {
2426
super();
2527

2628
InstanceSearch = createSearchBuilder();
27-
InstanceSearch.and("instance", InstanceSearch.entity().getInstanceId(), SearchCriteria.Op.EQ);
29+
InstanceSearch.and("instance", InstanceSearch.entity().getInstanceId(), Op.EQ);
2830
InstanceSearch.done();
2931

3032
IpSearch = createSearchBuilder(String.class);
3133
IpSearch.select(null, Func.DISTINCT, IpSearch.entity().getIp4Address());
32-
IpSearch.and("nc", IpSearch.entity().getNetworkId(), SearchCriteria.Op.EQ);
33-
IpSearch.and("address", IpSearch.entity().getIp4Address(), SearchCriteria.Op.NNULL);
34+
IpSearch.and("nc", IpSearch.entity().getNetworkId(), Op.EQ);
35+
IpSearch.and("address", IpSearch.entity().getIp4Address(), Op.NNULL);
3436
IpSearch.done();
3537

3638
NetworkSearch = createSearchBuilder();
37-
NetworkSearch.and("networkId", NetworkSearch.entity().getNetworkId(), SearchCriteria.Op.EQ);
39+
NetworkSearch.and("networkId", NetworkSearch.entity().getNetworkId(), Op.EQ);
3840
NetworkSearch.done();
41+
42+
GarbageCollectSearch = createSearchBuilder(Long.class);
43+
GarbageCollectSearch.select(null, Func.DISTINCT, GarbageCollectSearch.entity().getNetworkId());
44+
GarbageCollectSearch.and("reservation", GarbageCollectSearch.entity().getReservationId(), Op.NULL);
45+
GarbageCollectSearch.groupBy(GarbageCollectSearch.entity().getNetworkId()).having(Func.COUNT, GarbageCollectSearch.entity().getId(), Op.EQ, null);
46+
GarbageCollectSearch.done();
3947
}
4048

4149
@Override
@@ -58,4 +66,11 @@ public List<NicVO> listByNetworkId(long networkId) {
5866
sc.setParameters("networkId", networkId);
5967
return listBy(sc);
6068
}
69+
70+
@Override
71+
public List<Long> listNetworksWithNoActiveNics() {
72+
SearchCriteria<Long> sc = GarbageCollectSearch.create();
73+
74+
return customSearch(sc, null);
75+
}
6176
}

utils/src/com/cloud/utils/db/Attribute.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,4 +221,9 @@ public boolean equals(Object obj) {
221221

222222
return columnName.equals(that.columnName) && table.equals(that.table);
223223
}
224+
225+
@Override
226+
public String toString() {
227+
return table + "." + columnName;
228+
}
224229
}

utils/src/com/cloud/utils/db/GenericDaoBase.java

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,7 @@ public List<T> searchIncludingRemoved(SearchCriteria<T> sc, final Filter filter,
331331
}
332332
}
333333

334-
addGroupBy(str, sc);
334+
List<Object> groupByValues = addGroupBy(str, sc);
335335
addFilter(str, filter);
336336

337337
final Transaction txn = Transaction.currentTxn();
@@ -356,6 +356,12 @@ public List<T> searchIncludingRemoved(SearchCriteria<T> sc, final Filter filter,
356356
if (joins != null) {
357357
i = addJoinAttributes(i, pstmt, joins);
358358
}
359+
360+
if (groupByValues != null) {
361+
for (Object value : groupByValues) {
362+
pstmt.setObject(i++, value);
363+
}
364+
}
359365

360366
if (s_logger.isDebugEnabled() && lock != null) {
361367
txn.registerLock(pstmt.toString());
@@ -392,7 +398,7 @@ public <M> List<M> searchIncludingRemoved(SearchCriteria<M> sc, final Filter fil
392398
}
393399
}
394400

395-
addGroupBy(str, sc);
401+
List<Object> groupByValues = addGroupBy(str, sc);
396402
addFilter(str, filter);
397403

398404
final String sql = str.toString();
@@ -412,6 +418,12 @@ public <M> List<M> searchIncludingRemoved(SearchCriteria<M> sc, final Filter fil
412418
i = addJoinAttributes(i, pstmt, joins);
413419
}
414420

421+
if (groupByValues != null) {
422+
for (Object value : groupByValues) {
423+
pstmt.setObject(i++, value);
424+
}
425+
}
426+
415427
ResultSet rs = pstmt.executeQuery();
416428
SelectType st = sc.getSelectType();
417429
ArrayList<M> results = new ArrayList<M>();
@@ -918,17 +930,13 @@ public List<T> listAllIncludingRemoved() {
918930
}
919931

920932
@DB(txn=false)
921-
protected void addGroupBy(final StringBuilder sql, SearchCriteria<?> sc) {
922-
List<Attribute> groupBys = sc.getGroupBy();
923-
if(groupBys != null) {
924-
sql.append(" GROUP BY ");
925-
for(int i = 0; i < groupBys.size(); i++) {
926-
Attribute attr = groupBys.get(i);
927-
sql.append(attr.table).append(".").append(attr.columnName);
928-
if(i < groupBys.size() - 1) {
929-
sql.append(", ");
930-
}
931-
}
933+
protected List<Object> addGroupBy(final StringBuilder sql, SearchCriteria<?> sc) {
934+
Pair<GroupBy<?, ?>, List<Object>> groupBys = sc.getGroupBy();
935+
if (groupBys != null) {
936+
groupBys.first().toSql(sql);
937+
return groupBys.second();
938+
} else {
939+
return null;
932940
}
933941
}
934942

utils/src/com/cloud/utils/db/GenericSearchBuilder.java

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import java.lang.reflect.Method;
2222
import java.util.ArrayList;
2323
import java.util.HashMap;
24+
import java.util.List;
2425
import java.util.Map;
2526

2627
import net.sf.cglib.proxy.Factory;
@@ -48,7 +49,7 @@ public class GenericSearchBuilder<T, K> implements MethodInterceptor {
4849
protected ArrayList<Condition> _conditions;
4950
protected HashMap<String, JoinBuilder<GenericSearchBuilder<?, ?>>> _joins;
5051
protected ArrayList<Select> _selects;
51-
protected ArrayList<Attribute> _groupBys;
52+
protected GroupBy<T, K> _groupBy = null;
5253
protected Class<T> _entityBeanType;
5354
protected Class<K> _resultType;
5455
protected SelectType _selectType;
@@ -210,18 +211,15 @@ public GenericSearchBuilder<T, K> openParen(String name, Object useless, Op op)
210211
return left(name, useless, op);
211212
}
212213

213-
public GenericSearchBuilder<T, K> groupBy(Object... useless) {
214-
if(_groupBys == null) {
215-
_groupBys = new ArrayList<Attribute>();
216-
}
217-
218-
Attribute[] attrs = _specifiedAttrs.toArray(new Attribute[_specifiedAttrs.size()]);
219-
for(Attribute attr : attrs) {
220-
_groupBys.add(attr);
221-
}
214+
public GroupBy<T, K> groupBy(Object... useless) {
215+
assert _groupBy == null : "Can't do more than one group bys";
216+
_groupBy = new GroupBy<T, K>(this);
222217

223-
_specifiedAttrs.clear();
224-
return this;
218+
return _groupBy;
219+
}
220+
221+
protected List<Attribute> getSpecifiedAttributes() {
222+
return _specifiedAttrs;
225223
}
226224

227225
/**

0 commit comments

Comments
 (0)