diff --git a/engine/schema/src/main/java/com/cloud/usage/dao/UsageNetworksDao.java b/engine/schema/src/main/java/com/cloud/usage/dao/UsageNetworksDao.java index 9be4c49b55e0..4d84caaad44f 100644 --- a/engine/schema/src/main/java/com/cloud/usage/dao/UsageNetworksDao.java +++ b/engine/schema/src/main/java/com/cloud/usage/dao/UsageNetworksDao.java @@ -28,4 +28,6 @@ public interface UsageNetworksDao extends GenericDao { void remove(long networkId, Date removed); List getUsageRecords(Long accountId, Date startDate, Date endDate); + + List listAll(long networkId); } diff --git a/engine/schema/src/main/java/com/cloud/usage/dao/UsageNetworksDaoImpl.java b/engine/schema/src/main/java/com/cloud/usage/dao/UsageNetworksDaoImpl.java index 8829414f3f26..6b1322289858 100644 --- a/engine/schema/src/main/java/com/cloud/usage/dao/UsageNetworksDaoImpl.java +++ b/engine/schema/src/main/java/com/cloud/usage/dao/UsageNetworksDaoImpl.java @@ -16,15 +16,16 @@ // under the License. package com.cloud.usage.dao; -import com.cloud.network.Network; import com.cloud.usage.UsageNetworksVO; import com.cloud.utils.DateUtil; import com.cloud.utils.db.GenericDaoBase; +import com.cloud.utils.db.SearchBuilder; import com.cloud.utils.db.SearchCriteria; import com.cloud.utils.db.TransactionLegacy; import org.apache.log4j.Logger; import org.springframework.stereotype.Component; +import javax.annotation.PostConstruct; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.util.ArrayList; @@ -39,6 +40,14 @@ public class UsageNetworksDaoImpl extends GenericDaoBase " account_id = ? AND ((removed IS NULL AND created <= ?) OR (created BETWEEN ? AND ?) OR (removed BETWEEN ? AND ?) " + " OR ((created <= ?) AND (removed >= ?)))"; + private SearchBuilder usageNetworksSearch; + + @PostConstruct + public void init() { + usageNetworksSearch = createSearchBuilder(); + usageNetworksSearch.and("networkId", usageNetworksSearch.entity().getNetworkId(), SearchCriteria.Op.EQ); + usageNetworksSearch.done(); + } @Override public void update(long networkId, long newNetworkOffering, String state) { @@ -68,11 +77,10 @@ public void remove(long networkId, Date removed) { SearchCriteria sc = this.createSearchCriteria(); sc.addAnd("networkId", SearchCriteria.Op.EQ, networkId); sc.addAnd("removed", SearchCriteria.Op.NULL); - UsageNetworksVO vo = findOneBy(sc); - if (vo != null) { - vo.setRemoved(removed); - vo.setState(Network.State.Destroy.name()); - update(vo.getId(), vo); + List usageNetworksVOs = listBy(sc); + for (UsageNetworksVO entry : usageNetworksVOs) { + entry.setRemoved(removed); + update(entry.getId(), entry); } } catch (final Exception e) { txn.rollback(); @@ -131,4 +139,11 @@ public List getUsageRecords(Long accountId, Date startDate, Dat return usageRecords; } + + @Override + public List listAll(long networkId) { + SearchCriteria sc = usageNetworksSearch.create(); + sc.setParameters("networkId", networkId); + return listBy(sc); + } } diff --git a/engine/schema/src/main/java/com/cloud/usage/dao/UsageVpcDao.java b/engine/schema/src/main/java/com/cloud/usage/dao/UsageVpcDao.java index a1514aba4cad..5167bf88c485 100644 --- a/engine/schema/src/main/java/com/cloud/usage/dao/UsageVpcDao.java +++ b/engine/schema/src/main/java/com/cloud/usage/dao/UsageVpcDao.java @@ -24,6 +24,10 @@ public interface UsageVpcDao extends GenericDao { void update(UsageVpcVO usage); + void remove(long vpcId, Date removed); + List getUsageRecords(Long accountId, Date startDate, Date endDate); + + List listAll(long vpcId); } diff --git a/engine/schema/src/main/java/com/cloud/usage/dao/UsageVpcDaoImpl.java b/engine/schema/src/main/java/com/cloud/usage/dao/UsageVpcDaoImpl.java index a42b96486a54..e7ebf706cf3a 100644 --- a/engine/schema/src/main/java/com/cloud/usage/dao/UsageVpcDaoImpl.java +++ b/engine/schema/src/main/java/com/cloud/usage/dao/UsageVpcDaoImpl.java @@ -16,15 +16,16 @@ // under the License. package com.cloud.usage.dao; -import com.cloud.network.vpc.Vpc; import com.cloud.usage.UsageVpcVO; import com.cloud.utils.DateUtil; import com.cloud.utils.db.GenericDaoBase; +import com.cloud.utils.db.SearchBuilder; import com.cloud.utils.db.SearchCriteria; import com.cloud.utils.db.TransactionLegacy; import org.apache.log4j.Logger; import org.springframework.stereotype.Component; +import javax.annotation.PostConstruct; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.util.ArrayList; @@ -39,6 +40,15 @@ public class UsageVpcDaoImpl extends GenericDaoBase implements " account_id = ? AND ((removed IS NULL AND created <= ?) OR (created BETWEEN ? AND ?) OR (removed BETWEEN ? AND ?) " + " OR ((created <= ?) AND (removed >= ?)))"; + private SearchBuilder usageVpcSearch; + + @PostConstruct + public void init() { + usageVpcSearch = createSearchBuilder(); + usageVpcSearch.and("vpcId", usageVpcSearch.entity().getVpcId(), SearchCriteria.Op.EQ); + usageVpcSearch.done(); + } + @Override public void update(UsageVpcVO usage) { TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.USAGE_DB); @@ -66,11 +76,10 @@ public void remove(long vpcId, Date removed) { SearchCriteria sc = this.createSearchCriteria(); sc.addAnd("vpcId", SearchCriteria.Op.EQ, vpcId); sc.addAnd("removed", SearchCriteria.Op.NULL); - UsageVpcVO vo = findOneBy(sc); - if (vo != null) { - vo.setRemoved(removed); - vo.setState(Vpc.State.Inactive.name()); - update(vo.getId(), vo); + List usageVpcVOs = listBy(sc); + for (UsageVpcVO entry : usageVpcVOs) { + entry.setRemoved(removed); + update(entry.getId(), entry); } } catch (final Exception e) { txn.rollback(); @@ -128,4 +137,11 @@ public List getUsageRecords(Long accountId, Date startDate, Date end return usageRecords; } + + @Override + public List listAll(long vpcId) { + SearchCriteria sc = usageVpcSearch.create(); + sc.setParameters("vpcId", vpcId); + return listBy(sc); + } } diff --git a/usage/src/main/java/com/cloud/usage/UsageManagerImpl.java b/usage/src/main/java/com/cloud/usage/UsageManagerImpl.java index 63624cdc3c07..cc129a9ec5e4 100644 --- a/usage/src/main/java/com/cloud/usage/UsageManagerImpl.java +++ b/usage/src/main/java/com/cloud/usage/UsageManagerImpl.java @@ -1540,7 +1540,7 @@ private void createVolumeHelperEvent(UsageEventVO event) { //For volumes which are 'attached' successfully, set the 'deleted' column in the usage_storage table, //so that the secondary storage should stop accounting and only primary will be accounted. SearchCriteria sc = _usageStorageDao.createSearchCriteria(); - sc.addAnd("id", SearchCriteria.Op.EQ, volId); + sc.addAnd("entityId", SearchCriteria.Op.EQ, volId); sc.addAnd("storageType", SearchCriteria.Op.EQ, StorageTypes.VOLUME); List volumesVOs = _usageStorageDao.search(sc, null); if (volumesVOs != null) { @@ -1595,7 +1595,8 @@ private void createVolumeHelperEvent(UsageEventVO event) { //For Upload event add an entry to the usage_storage table. SearchCriteria sc = _usageStorageDao.createSearchCriteria(); sc.addAnd("accountId", SearchCriteria.Op.EQ, event.getAccountId()); - sc.addAnd("id", SearchCriteria.Op.EQ, volId); + sc.addAnd("entityId", SearchCriteria.Op.EQ, volId); + sc.addAnd("storageType", SearchCriteria.Op.EQ, StorageTypes.VOLUME); sc.addAnd("deleted", SearchCriteria.Op.NULL); List volumesVOs = _usageStorageDao.search(sc, null); @@ -1772,7 +1773,7 @@ private void createLoadBalancerHelperEvent(UsageEventVO event) { } else if (EventTypes.EVENT_LOAD_BALANCER_DELETE.equals(event.getType())) { SearchCriteria sc = _usageLoadBalancerPolicyDao.createSearchCriteria(); sc.addAnd("accountId", SearchCriteria.Op.EQ, event.getAccountId()); - sc.addAnd("id", SearchCriteria.Op.EQ, id); + sc.addAnd("lbId", SearchCriteria.Op.EQ, id); sc.addAnd("deleted", SearchCriteria.Op.NULL); List lbVOs = _usageLoadBalancerPolicyDao.search(sc, null); if (lbVOs.size() > 1) { @@ -1806,7 +1807,7 @@ private void createPortForwardingHelperEvent(UsageEventVO event) { } else if (EventTypes.EVENT_NET_RULE_DELETE.equals(event.getType())) { SearchCriteria sc = _usagePortForwardingRuleDao.createSearchCriteria(); sc.addAnd("accountId", SearchCriteria.Op.EQ, event.getAccountId()); - sc.addAnd("id", SearchCriteria.Op.EQ, id); + sc.addAnd("pfId", SearchCriteria.Op.EQ, id); sc.addAnd("deleted", SearchCriteria.Op.NULL); List pfVOs = _usagePortForwardingRuleDao.search(sc, null); if (pfVOs.size() > 1) { @@ -2104,7 +2105,7 @@ private void createVmSnapshotOnPrimaryEvent(UsageEventVO event) { } else if (EventTypes.EVENT_VM_SNAPSHOT_OFF_PRIMARY.equals(event.getType())) { QueryBuilder sc = QueryBuilder.create(UsageSnapshotOnPrimaryVO.class); sc.and(sc.entity().getAccountId(), SearchCriteria.Op.EQ, event.getAccountId()); - sc.and(sc.entity().getId(), SearchCriteria.Op.EQ, vmId); + sc.and(sc.entity().getVmId(), SearchCriteria.Op.EQ, vmId); sc.and(sc.entity().getName(), SearchCriteria.Op.EQ, name); sc.and(sc.entity().getDeleted(), SearchCriteria.Op.NULL); List vmsnaps = sc.list(); @@ -2142,33 +2143,90 @@ private void createBackupEvent(final UsageEventVO event) { } private void handleNetworkEvent(UsageEventVO event) { + String eventType = event.getType(); + if (EventTypes.EVENT_NETWORK_DELETE.equals(eventType)) { + removeNetworkHelperEntry(event); + } else if (EventTypes.EVENT_NETWORK_CREATE.equals(eventType)) { + createNetworkHelperEntry(event); + } else if (EventTypes.EVENT_NETWORK_UPDATE.equals(eventType)) { + updateNetworkHelperEntry(event); + } else { + s_logger.error(String.format("Unknown event type [%s] in Networks event parser. Skipping it.", eventType)); + } + } + + private void removeNetworkHelperEntry(UsageEventVO event) { + long networkId = event.getResourceId(); + s_logger.debug(String.format("Removing helper entries of network [%s].", networkId)); + usageNetworksDao.remove(networkId, event.getCreateDate()); + } + + private void createNetworkHelperEntry(UsageEventVO event) { + long networkId = event.getResourceId(); Account account = _accountDao.findByIdIncludingRemoved(event.getAccountId()); long domainId = account.getDomainId(); - if (EventTypes.EVENT_NETWORK_DELETE.equals(event.getType())) { - usageNetworksDao.remove(event.getResourceId(), event.getCreateDate()); - } else if (EventTypes.EVENT_NETWORK_CREATE.equals(event.getType())) { - UsageNetworksVO usageNetworksVO = new UsageNetworksVO(event.getResourceId(), event.getOfferingId(), event.getZoneId(), event.getAccountId(), domainId, Network.State.Allocated.name(), event.getCreateDate(), null); - usageNetworksDao.persist(usageNetworksVO); - } else if (EventTypes.EVENT_NETWORK_UPDATE.equals(event.getType())) { - usageNetworksDao.update(event.getResourceId(), event.getOfferingId(), event.getResourceType()); - } else { - s_logger.error(String.format("Unknown event type [%s] in Networks event parser. Skipping it.", event.getType())); + + List entries = usageNetworksDao.listAll(networkId); + if (!entries.isEmpty()) { + s_logger.warn(String.format("Received a NETWORK.CREATE event for a network [%s] that already has helper entries; " + + "therefore, we will not create a new one.", networkId)); + return; } + + s_logger.debug(String.format("Creating a helper entry for network [%s].", networkId)); + UsageNetworksVO usageNetworksVO = new UsageNetworksVO(networkId, event.getOfferingId(), event.getZoneId(), + event.getAccountId(), domainId, Network.State.Allocated.name(), event.getCreateDate(), null); + usageNetworksDao.persist(usageNetworksVO); } - private void handleVpcEvent(UsageEventVO event) { + private void updateNetworkHelperEntry(UsageEventVO event) { + long networkId = event.getResourceId(); Account account = _accountDao.findByIdIncludingRemoved(event.getAccountId()); long domainId = account.getDomainId(); - if (EventTypes.EVENT_VPC_DELETE.equals(event.getType())) { - usageVpcDao.remove(event.getResourceId(), event.getCreateDate()); - } else if (EventTypes.EVENT_VPC_CREATE.equals(event.getType())) { - UsageVpcVO usageVPCVO = new UsageVpcVO(event.getResourceId(), event.getZoneId(), event.getAccountId(), domainId, Vpc.State.Enabled.name(), event.getCreateDate(), null); - usageVpcDao.persist(usageVPCVO); + + s_logger.debug(String.format("Marking previous helper entries of network [%s] as removed.", networkId)); + usageNetworksDao.remove(networkId, event.getCreateDate()); + + s_logger.debug(String.format("Creating an updated helper entry for network [%s].", networkId)); + UsageNetworksVO usageNetworksVO = new UsageNetworksVO(networkId, event.getOfferingId(), event.getZoneId(), + event.getAccountId(), domainId, event.getResourceType(), event.getCreateDate(), null); + usageNetworksDao.persist(usageNetworksVO); + } + + private void handleVpcEvent(UsageEventVO event) { + String eventType = event.getType(); + if (EventTypes.EVENT_VPC_DELETE.equals(eventType)) { + removeVpcHelperEntry(event); + } else if (EventTypes.EVENT_VPC_CREATE.equals(eventType)) { + createVpcHelperEntry(event); } else { - s_logger.error(String.format("Unknown event type [%s] in VPC event parser. Skipping it.", event.getType())); + s_logger.error(String.format("Unknown event type [%s] in VPC event parser. Skipping it.", eventType)); } } + private void removeVpcHelperEntry(UsageEventVO event) { + long vpcId = event.getResourceId(); + s_logger.debug(String.format("Removing helper entries of VPC [%s].", vpcId)); + usageVpcDao.remove(vpcId, event.getCreateDate()); + } + + private void createVpcHelperEntry(UsageEventVO event) { + long vpcId = event.getResourceId(); + Account account = _accountDao.findByIdIncludingRemoved(event.getAccountId()); + long domainId = account.getDomainId(); + + List entries = usageVpcDao.listAll(vpcId); + if (!entries.isEmpty()) { + s_logger.warn(String.format("Active helper entries already exist for VPC [%s]; therefore, we will not create a new one.", + vpcId)); + return; + } + + s_logger.debug(String.format("Creating a helper entry for VPC [%s].", vpcId)); + UsageVpcVO usageVPCVO = new UsageVpcVO(vpcId, event.getZoneId(), event.getAccountId(), domainId, Vpc.State.Enabled.name(), event.getCreateDate(), null); + usageVpcDao.persist(usageVPCVO); + } + private class Heartbeat extends ManagedContextRunnable { @Override protected void runInContext() {