Skip to content

Commit 696bc50

Browse files
authored
Backport #9888 to 4.19: Fix Usage inconsistencies (#10712)
1 parent f0838cd commit 696bc50

File tree

5 files changed

+128
-33
lines changed

5 files changed

+128
-33
lines changed

engine/schema/src/main/java/com/cloud/usage/dao/UsageNetworksDao.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,6 @@ public interface UsageNetworksDao extends GenericDao<UsageNetworksVO, Long> {
2828
void remove(long networkId, Date removed);
2929

3030
List<UsageNetworksVO> getUsageRecords(Long accountId, Date startDate, Date endDate);
31+
32+
List<UsageNetworksVO> listAll(long networkId);
3133
}

engine/schema/src/main/java/com/cloud/usage/dao/UsageNetworksDaoImpl.java

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,16 @@
1616
// under the License.
1717
package com.cloud.usage.dao;
1818

19-
import com.cloud.network.Network;
2019
import com.cloud.usage.UsageNetworksVO;
2120
import com.cloud.utils.DateUtil;
2221
import com.cloud.utils.db.GenericDaoBase;
22+
import com.cloud.utils.db.SearchBuilder;
2323
import com.cloud.utils.db.SearchCriteria;
2424
import com.cloud.utils.db.TransactionLegacy;
2525
import org.apache.log4j.Logger;
2626
import org.springframework.stereotype.Component;
2727

28+
import javax.annotation.PostConstruct;
2829
import java.sql.PreparedStatement;
2930
import java.sql.ResultSet;
3031
import java.util.ArrayList;
@@ -39,6 +40,14 @@ public class UsageNetworksDaoImpl extends GenericDaoBase<UsageNetworksVO, Long>
3940
" account_id = ? AND ((removed IS NULL AND created <= ?) OR (created BETWEEN ? AND ?) OR (removed BETWEEN ? AND ?) " +
4041
" OR ((created <= ?) AND (removed >= ?)))";
4142

43+
private SearchBuilder<UsageNetworksVO> usageNetworksSearch;
44+
45+
@PostConstruct
46+
public void init() {
47+
usageNetworksSearch = createSearchBuilder();
48+
usageNetworksSearch.and("networkId", usageNetworksSearch.entity().getNetworkId(), SearchCriteria.Op.EQ);
49+
usageNetworksSearch.done();
50+
}
4251

4352
@Override
4453
public void update(long networkId, long newNetworkOffering, String state) {
@@ -68,11 +77,10 @@ public void remove(long networkId, Date removed) {
6877
SearchCriteria<UsageNetworksVO> sc = this.createSearchCriteria();
6978
sc.addAnd("networkId", SearchCriteria.Op.EQ, networkId);
7079
sc.addAnd("removed", SearchCriteria.Op.NULL);
71-
UsageNetworksVO vo = findOneBy(sc);
72-
if (vo != null) {
73-
vo.setRemoved(removed);
74-
vo.setState(Network.State.Destroy.name());
75-
update(vo.getId(), vo);
80+
List<UsageNetworksVO> usageNetworksVOs = listBy(sc);
81+
for (UsageNetworksVO entry : usageNetworksVOs) {
82+
entry.setRemoved(removed);
83+
update(entry.getId(), entry);
7684
}
7785
} catch (final Exception e) {
7886
txn.rollback();
@@ -131,4 +139,11 @@ public List<UsageNetworksVO> getUsageRecords(Long accountId, Date startDate, Dat
131139

132140
return usageRecords;
133141
}
142+
143+
@Override
144+
public List<UsageNetworksVO> listAll(long networkId) {
145+
SearchCriteria<UsageNetworksVO> sc = usageNetworksSearch.create();
146+
sc.setParameters("networkId", networkId);
147+
return listBy(sc);
148+
}
134149
}

engine/schema/src/main/java/com/cloud/usage/dao/UsageVpcDao.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@
2424

2525
public interface UsageVpcDao extends GenericDao<UsageVpcVO, Long> {
2626
void update(UsageVpcVO usage);
27+
2728
void remove(long vpcId, Date removed);
29+
2830
List<UsageVpcVO> getUsageRecords(Long accountId, Date startDate, Date endDate);
31+
32+
List<UsageVpcVO> listAll(long vpcId);
2933
}

engine/schema/src/main/java/com/cloud/usage/dao/UsageVpcDaoImpl.java

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,16 @@
1616
// under the License.
1717
package com.cloud.usage.dao;
1818

19-
import com.cloud.network.vpc.Vpc;
2019
import com.cloud.usage.UsageVpcVO;
2120
import com.cloud.utils.DateUtil;
2221
import com.cloud.utils.db.GenericDaoBase;
22+
import com.cloud.utils.db.SearchBuilder;
2323
import com.cloud.utils.db.SearchCriteria;
2424
import com.cloud.utils.db.TransactionLegacy;
2525
import org.apache.log4j.Logger;
2626
import org.springframework.stereotype.Component;
2727

28+
import javax.annotation.PostConstruct;
2829
import java.sql.PreparedStatement;
2930
import java.sql.ResultSet;
3031
import java.util.ArrayList;
@@ -39,6 +40,15 @@ public class UsageVpcDaoImpl extends GenericDaoBase<UsageVpcVO, Long> implements
3940
" account_id = ? AND ((removed IS NULL AND created <= ?) OR (created BETWEEN ? AND ?) OR (removed BETWEEN ? AND ?) " +
4041
" OR ((created <= ?) AND (removed >= ?)))";
4142

43+
private SearchBuilder<UsageVpcVO> usageVpcSearch;
44+
45+
@PostConstruct
46+
public void init() {
47+
usageVpcSearch = createSearchBuilder();
48+
usageVpcSearch.and("vpcId", usageVpcSearch.entity().getVpcId(), SearchCriteria.Op.EQ);
49+
usageVpcSearch.done();
50+
}
51+
4252
@Override
4353
public void update(UsageVpcVO usage) {
4454
TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.USAGE_DB);
@@ -66,11 +76,10 @@ public void remove(long vpcId, Date removed) {
6676
SearchCriteria<UsageVpcVO> sc = this.createSearchCriteria();
6777
sc.addAnd("vpcId", SearchCriteria.Op.EQ, vpcId);
6878
sc.addAnd("removed", SearchCriteria.Op.NULL);
69-
UsageVpcVO vo = findOneBy(sc);
70-
if (vo != null) {
71-
vo.setRemoved(removed);
72-
vo.setState(Vpc.State.Inactive.name());
73-
update(vo.getId(), vo);
79+
List<UsageVpcVO> usageVpcVOs = listBy(sc);
80+
for (UsageVpcVO entry : usageVpcVOs) {
81+
entry.setRemoved(removed);
82+
update(entry.getId(), entry);
7483
}
7584
} catch (final Exception e) {
7685
txn.rollback();
@@ -128,4 +137,11 @@ public List<UsageVpcVO> getUsageRecords(Long accountId, Date startDate, Date end
128137

129138
return usageRecords;
130139
}
140+
141+
@Override
142+
public List<UsageVpcVO> listAll(long vpcId) {
143+
SearchCriteria<UsageVpcVO> sc = usageVpcSearch.create();
144+
sc.setParameters("vpcId", vpcId);
145+
return listBy(sc);
146+
}
131147
}

usage/src/main/java/com/cloud/usage/UsageManagerImpl.java

Lines changed: 79 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1540,7 +1540,7 @@ private void createVolumeHelperEvent(UsageEventVO event) {
15401540
//For volumes which are 'attached' successfully, set the 'deleted' column in the usage_storage table,
15411541
//so that the secondary storage should stop accounting and only primary will be accounted.
15421542
SearchCriteria<UsageStorageVO> sc = _usageStorageDao.createSearchCriteria();
1543-
sc.addAnd("id", SearchCriteria.Op.EQ, volId);
1543+
sc.addAnd("entityId", SearchCriteria.Op.EQ, volId);
15441544
sc.addAnd("storageType", SearchCriteria.Op.EQ, StorageTypes.VOLUME);
15451545
List<UsageStorageVO> volumesVOs = _usageStorageDao.search(sc, null);
15461546
if (volumesVOs != null) {
@@ -1595,7 +1595,8 @@ private void createVolumeHelperEvent(UsageEventVO event) {
15951595
//For Upload event add an entry to the usage_storage table.
15961596
SearchCriteria<UsageStorageVO> sc = _usageStorageDao.createSearchCriteria();
15971597
sc.addAnd("accountId", SearchCriteria.Op.EQ, event.getAccountId());
1598-
sc.addAnd("id", SearchCriteria.Op.EQ, volId);
1598+
sc.addAnd("entityId", SearchCriteria.Op.EQ, volId);
1599+
sc.addAnd("storageType", SearchCriteria.Op.EQ, StorageTypes.VOLUME);
15991600
sc.addAnd("deleted", SearchCriteria.Op.NULL);
16001601
List<UsageStorageVO> volumesVOs = _usageStorageDao.search(sc, null);
16011602

@@ -1772,7 +1773,7 @@ private void createLoadBalancerHelperEvent(UsageEventVO event) {
17721773
} else if (EventTypes.EVENT_LOAD_BALANCER_DELETE.equals(event.getType())) {
17731774
SearchCriteria<UsageLoadBalancerPolicyVO> sc = _usageLoadBalancerPolicyDao.createSearchCriteria();
17741775
sc.addAnd("accountId", SearchCriteria.Op.EQ, event.getAccountId());
1775-
sc.addAnd("id", SearchCriteria.Op.EQ, id);
1776+
sc.addAnd("lbId", SearchCriteria.Op.EQ, id);
17761777
sc.addAnd("deleted", SearchCriteria.Op.NULL);
17771778
List<UsageLoadBalancerPolicyVO> lbVOs = _usageLoadBalancerPolicyDao.search(sc, null);
17781779
if (lbVOs.size() > 1) {
@@ -1806,7 +1807,7 @@ private void createPortForwardingHelperEvent(UsageEventVO event) {
18061807
} else if (EventTypes.EVENT_NET_RULE_DELETE.equals(event.getType())) {
18071808
SearchCriteria<UsagePortForwardingRuleVO> sc = _usagePortForwardingRuleDao.createSearchCriteria();
18081809
sc.addAnd("accountId", SearchCriteria.Op.EQ, event.getAccountId());
1809-
sc.addAnd("id", SearchCriteria.Op.EQ, id);
1810+
sc.addAnd("pfId", SearchCriteria.Op.EQ, id);
18101811
sc.addAnd("deleted", SearchCriteria.Op.NULL);
18111812
List<UsagePortForwardingRuleVO> pfVOs = _usagePortForwardingRuleDao.search(sc, null);
18121813
if (pfVOs.size() > 1) {
@@ -2104,7 +2105,7 @@ private void createVmSnapshotOnPrimaryEvent(UsageEventVO event) {
21042105
} else if (EventTypes.EVENT_VM_SNAPSHOT_OFF_PRIMARY.equals(event.getType())) {
21052106
QueryBuilder<UsageSnapshotOnPrimaryVO> sc = QueryBuilder.create(UsageSnapshotOnPrimaryVO.class);
21062107
sc.and(sc.entity().getAccountId(), SearchCriteria.Op.EQ, event.getAccountId());
2107-
sc.and(sc.entity().getId(), SearchCriteria.Op.EQ, vmId);
2108+
sc.and(sc.entity().getVmId(), SearchCriteria.Op.EQ, vmId);
21082109
sc.and(sc.entity().getName(), SearchCriteria.Op.EQ, name);
21092110
sc.and(sc.entity().getDeleted(), SearchCriteria.Op.NULL);
21102111
List<UsageSnapshotOnPrimaryVO> vmsnaps = sc.list();
@@ -2142,33 +2143,90 @@ private void createBackupEvent(final UsageEventVO event) {
21422143
}
21432144

21442145
private void handleNetworkEvent(UsageEventVO event) {
2146+
String eventType = event.getType();
2147+
if (EventTypes.EVENT_NETWORK_DELETE.equals(eventType)) {
2148+
removeNetworkHelperEntry(event);
2149+
} else if (EventTypes.EVENT_NETWORK_CREATE.equals(eventType)) {
2150+
createNetworkHelperEntry(event);
2151+
} else if (EventTypes.EVENT_NETWORK_UPDATE.equals(eventType)) {
2152+
updateNetworkHelperEntry(event);
2153+
} else {
2154+
s_logger.error(String.format("Unknown event type [%s] in Networks event parser. Skipping it.", eventType));
2155+
}
2156+
}
2157+
2158+
private void removeNetworkHelperEntry(UsageEventVO event) {
2159+
long networkId = event.getResourceId();
2160+
s_logger.debug(String.format("Removing helper entries of network [%s].", networkId));
2161+
usageNetworksDao.remove(networkId, event.getCreateDate());
2162+
}
2163+
2164+
private void createNetworkHelperEntry(UsageEventVO event) {
2165+
long networkId = event.getResourceId();
21452166
Account account = _accountDao.findByIdIncludingRemoved(event.getAccountId());
21462167
long domainId = account.getDomainId();
2147-
if (EventTypes.EVENT_NETWORK_DELETE.equals(event.getType())) {
2148-
usageNetworksDao.remove(event.getResourceId(), event.getCreateDate());
2149-
} else if (EventTypes.EVENT_NETWORK_CREATE.equals(event.getType())) {
2150-
UsageNetworksVO usageNetworksVO = new UsageNetworksVO(event.getResourceId(), event.getOfferingId(), event.getZoneId(), event.getAccountId(), domainId, Network.State.Allocated.name(), event.getCreateDate(), null);
2151-
usageNetworksDao.persist(usageNetworksVO);
2152-
} else if (EventTypes.EVENT_NETWORK_UPDATE.equals(event.getType())) {
2153-
usageNetworksDao.update(event.getResourceId(), event.getOfferingId(), event.getResourceType());
2154-
} else {
2155-
s_logger.error(String.format("Unknown event type [%s] in Networks event parser. Skipping it.", event.getType()));
2168+
2169+
List<UsageNetworksVO> entries = usageNetworksDao.listAll(networkId);
2170+
if (!entries.isEmpty()) {
2171+
s_logger.warn(String.format("Received a NETWORK.CREATE event for a network [%s] that already has helper entries; " +
2172+
"therefore, we will not create a new one.", networkId));
2173+
return;
21562174
}
2175+
2176+
s_logger.debug(String.format("Creating a helper entry for network [%s].", networkId));
2177+
UsageNetworksVO usageNetworksVO = new UsageNetworksVO(networkId, event.getOfferingId(), event.getZoneId(),
2178+
event.getAccountId(), domainId, Network.State.Allocated.name(), event.getCreateDate(), null);
2179+
usageNetworksDao.persist(usageNetworksVO);
21572180
}
21582181

2159-
private void handleVpcEvent(UsageEventVO event) {
2182+
private void updateNetworkHelperEntry(UsageEventVO event) {
2183+
long networkId = event.getResourceId();
21602184
Account account = _accountDao.findByIdIncludingRemoved(event.getAccountId());
21612185
long domainId = account.getDomainId();
2162-
if (EventTypes.EVENT_VPC_DELETE.equals(event.getType())) {
2163-
usageVpcDao.remove(event.getResourceId(), event.getCreateDate());
2164-
} else if (EventTypes.EVENT_VPC_CREATE.equals(event.getType())) {
2165-
UsageVpcVO usageVPCVO = new UsageVpcVO(event.getResourceId(), event.getZoneId(), event.getAccountId(), domainId, Vpc.State.Enabled.name(), event.getCreateDate(), null);
2166-
usageVpcDao.persist(usageVPCVO);
2186+
2187+
s_logger.debug(String.format("Marking previous helper entries of network [%s] as removed.", networkId));
2188+
usageNetworksDao.remove(networkId, event.getCreateDate());
2189+
2190+
s_logger.debug(String.format("Creating an updated helper entry for network [%s].", networkId));
2191+
UsageNetworksVO usageNetworksVO = new UsageNetworksVO(networkId, event.getOfferingId(), event.getZoneId(),
2192+
event.getAccountId(), domainId, event.getResourceType(), event.getCreateDate(), null);
2193+
usageNetworksDao.persist(usageNetworksVO);
2194+
}
2195+
2196+
private void handleVpcEvent(UsageEventVO event) {
2197+
String eventType = event.getType();
2198+
if (EventTypes.EVENT_VPC_DELETE.equals(eventType)) {
2199+
removeVpcHelperEntry(event);
2200+
} else if (EventTypes.EVENT_VPC_CREATE.equals(eventType)) {
2201+
createVpcHelperEntry(event);
21672202
} else {
2168-
s_logger.error(String.format("Unknown event type [%s] in VPC event parser. Skipping it.", event.getType()));
2203+
s_logger.error(String.format("Unknown event type [%s] in VPC event parser. Skipping it.", eventType));
21692204
}
21702205
}
21712206

2207+
private void removeVpcHelperEntry(UsageEventVO event) {
2208+
long vpcId = event.getResourceId();
2209+
s_logger.debug(String.format("Removing helper entries of VPC [%s].", vpcId));
2210+
usageVpcDao.remove(vpcId, event.getCreateDate());
2211+
}
2212+
2213+
private void createVpcHelperEntry(UsageEventVO event) {
2214+
long vpcId = event.getResourceId();
2215+
Account account = _accountDao.findByIdIncludingRemoved(event.getAccountId());
2216+
long domainId = account.getDomainId();
2217+
2218+
List<UsageVpcVO> entries = usageVpcDao.listAll(vpcId);
2219+
if (!entries.isEmpty()) {
2220+
s_logger.warn(String.format("Active helper entries already exist for VPC [%s]; therefore, we will not create a new one.",
2221+
vpcId));
2222+
return;
2223+
}
2224+
2225+
s_logger.debug(String.format("Creating a helper entry for VPC [%s].", vpcId));
2226+
UsageVpcVO usageVPCVO = new UsageVpcVO(vpcId, event.getZoneId(), event.getAccountId(), domainId, Vpc.State.Enabled.name(), event.getCreateDate(), null);
2227+
usageVpcDao.persist(usageVPCVO);
2228+
}
2229+
21722230
private class Heartbeat extends ManagedContextRunnable {
21732231
@Override
21742232
protected void runInContext() {

0 commit comments

Comments
 (0)