You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by da...@apache.org on 2020/10/16 07:19:59 UTC

[cloudstack] branch master updated: Handle with VM snapshot events (#4251)

This is an automated email from the ASF dual-hosted git repository.

dahn pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cloudstack.git


The following commit(s) were added to refs/heads/master by this push:
     new d676ffa  Handle with VM snapshot events (#4251)
d676ffa is described below

commit d676ffa0a02ee0aac083c9957e0b8f95277de5f4
Author: Rodrigo D. Lopez <ro...@hotmail.com>
AuthorDate: Fri Oct 16 04:19:44 2020 -0300

    Handle with VM snapshot events (#4251)
    
    Co-authored-by: Rodrigo <ro...@scclouds.com.br>
---
 .../java/com/cloud/usage/UsageManagerImpl.java     | 86 +++++++++++++++++++---
 .../java/com/cloud/usage/UsageManagerImplTest.java | 83 ++++++++++++++++++++-
 2 files changed, 156 insertions(+), 13 deletions(-)

diff --git a/usage/src/main/java/com/cloud/usage/UsageManagerImpl.java b/usage/src/main/java/com/cloud/usage/UsageManagerImpl.java
index efc4175..b47a9ca 100644
--- a/usage/src/main/java/com/cloud/usage/UsageManagerImpl.java
+++ b/usage/src/main/java/com/cloud/usage/UsageManagerImpl.java
@@ -997,7 +997,7 @@ public class UsageManagerImpl extends ManagerBase implements UsageManager, Runna
         } else if (isSecurityGroupEvent(eventType)) {
             createSecurityGroupEvent(event);
         } else if (isVmSnapshotEvent(eventType)) {
-            createVMSnapshotEvent(event);
+            handleVMSnapshotEvent(event);
         } else if (isVmSnapshotOnPrimaryEvent(eventType)) {
             createVmSnapshotOnPrimaryEvent(event);
         } else if (isBackupEvent(eventType)) {
@@ -1891,29 +1891,93 @@ public class UsageManagerImpl extends ManagerBase implements UsageManager, Runna
         }
     }
 
-    private void createVMSnapshotEvent(UsageEventVO event) {
-        Long vmId = event.getResourceId();
-        Long volumeId = event.getTemplateId();
+    /**
+     * Handles Vm Snapshot create and delete events:
+     * <ul>
+     *     <li>EventTypes#EVENT_VM_SNAPSHOT_CREATE</li>
+     *     <li>EventTypes#EVENT_VM_SNAPSHOT_DELETE</li>
+     * </ul>
+     * if the event received by this method is neither add nor remove, we ignore it.
+     */
+    protected void handleVMSnapshotEvent(UsageEventVO event) {
+        switch (event.getType()) {
+            case EventTypes.EVENT_VM_SNAPSHOT_CREATE:
+                createUsageVMSnapshot(event);
+                break;
+            case EventTypes.EVENT_VM_SNAPSHOT_DELETE:
+                deleteUsageVMSnapshot(event);
+                break;
+            default:
+                s_logger.debug(String.format("The event [type=%s, zoneId=%s, accountId=%s, resourceName=%s, diskOfferingId=%s, createDate=%s] is neither of type [%s] nor [%s]",
+                        event.getType(), event.getZoneId(), event.getAccountId(), event.getResourceName(), event.getOfferingId(), event.getCreateDate(), EventTypes.EVENT_VM_SNAPSHOT_CREATE, EventTypes.EVENT_VM_SNAPSHOT_DELETE));
+        }
+    }
+
+    /**
+     * Creates an entry for the Usage VM Snapshot.
+     */
+    protected void createUsageVMSnapshot(UsageEventVO event) {
+        long accountId = event.getAccountId();
+        Account acct = _accountDao.findByIdIncludingRemoved(event.getAccountId());
+        long domainId = acct.getDomainId();
         Long offeringId = event.getOfferingId();
-        Long zoneId = event.getZoneId();
-        Long accountId = event.getAccountId();
-        //Size could be null for VM snapshot delete events
-        long size = (event.getSize() == null) ? 0 : event.getSize();
+        long vmId = event.getResourceId();
+        long volumeId = event.getTemplateId();
+        long zoneId = event.getZoneId();
         Date created = event.getCreateDate();
-        Account acct = _accountDao.findByIdIncludingRemoved(event.getAccountId());
-        Long domainId = acct.getDomainId();
+        long size = (event.getSize() == null) ? 0 : event.getSize();
 
         UsageEventDetailsVO detailVO = _usageEventDetailsDao.findDetail(event.getId(), UsageEventVO.DynamicParameters.vmSnapshotId.name());
         Long vmSnapshotId = null;
         if (detailVO != null) {
             String snapId = detailVO.getValue();
-             vmSnapshotId = Long.valueOf(snapId);
+            vmSnapshotId = Long.valueOf(snapId);
         }
+        s_logger.debug(String.format("Creating usage VM Snapshot for VM id [%s] assigned to account [%s] domain [%s], zone [%s], and created at [%s]", vmId, accountId, domainId, zoneId,
+                event.getCreateDate()));
         UsageVMSnapshotVO vsVO = new UsageVMSnapshotVO(volumeId, zoneId, accountId, domainId, vmId, offeringId, size, created, null);
         vsVO.setVmSnapshotId(vmSnapshotId);
         _usageVMSnapshotDao.persist(vsVO);
     }
 
+    /**
+     * Find and delete, if exists, usage VM Snapshots entries
+     */
+    protected void deleteUsageVMSnapshot(UsageEventVO event) {
+        long accountId = event.getAccountId();
+        Account acct = _accountDao.findByIdIncludingRemoved(event.getAccountId());
+        Long domainId = acct.getDomainId();
+        Long diskOfferingId = event.getOfferingId();
+        long vmId = event.getResourceId();
+        long zoneId = event.getZoneId();
+        List<UsageVMSnapshotVO> usageVMSnapshots = findUsageVMSnapshots(accountId, zoneId, domainId, vmId, diskOfferingId);
+        if (CollectionUtils.isEmpty(usageVMSnapshots)){
+            s_logger.warn(String.format("No usage entry for VM snapshot for VM id [%s] assigned to account [%s] domain [%s] and zone [%s] was found.",
+                    vmId, accountId, domainId, zoneId));
+        }
+        if (usageVMSnapshots.size() > 1) {
+            s_logger.warn(String.format("More than one usage entry for VM snapshot for VM id [%s] assigned to account [%s] domain [%s] and zone [%s]; marking them all as deleted.", vmId,
+                    accountId, domainId, zoneId));
+        }
+        for (UsageVMSnapshotVO vmSnapshots : usageVMSnapshots) {
+            s_logger.debug(String.format("Deleting VM Snapshot for VM id [%s] assigned to account [%s] domain [%s] and zone [%s] that was created at [%s].", vmSnapshots.getVmId(),
+                    vmSnapshots.getAccountId(), vmSnapshots.getDomainId(), vmSnapshots.getZoneId(), vmSnapshots.getCreated()));
+            vmSnapshots.setProcessed(event.getCreateDate());
+            _usageVMSnapshotDao.update(vmSnapshots);
+        }
+    }
+
+    protected List<UsageVMSnapshotVO> findUsageVMSnapshots(long accountId, long zoneId, long domainId, long vmId, Long diskOfferingId) {
+        SearchCriteria<UsageVMSnapshotVO> sc = _usageVMSnapshotDao.createSearchCriteria();
+        sc.addAnd("zoneId", SearchCriteria.Op.EQ, zoneId);
+        sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
+        sc.addAnd("domainId", SearchCriteria.Op.EQ, domainId);
+        sc.addAnd("vmId", SearchCriteria.Op.EQ, vmId);
+        sc.addAnd("diskOfferingId", SearchCriteria.Op.EQ, diskOfferingId);
+        sc.addAnd("processed", SearchCriteria.Op.NULL);
+        return _usageVMSnapshotDao.search(sc, null);
+    }
+
     private void createVmSnapshotOnPrimaryEvent(UsageEventVO event) {
         Long vmId = event.getResourceId();
         String name = event.getResourceName();
diff --git a/usage/src/test/java/com/cloud/usage/UsageManagerImplTest.java b/usage/src/test/java/com/cloud/usage/UsageManagerImplTest.java
index 499d187..ab067b4 100644
--- a/usage/src/test/java/com/cloud/usage/UsageManagerImplTest.java
+++ b/usage/src/test/java/com/cloud/usage/UsageManagerImplTest.java
@@ -19,6 +19,8 @@ package com.cloud.usage;
 import java.util.ArrayList;
 import java.util.List;
 
+import com.cloud.event.dao.UsageEventDetailsDao;
+import com.cloud.usage.dao.UsageVMSnapshotDao;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -42,19 +44,28 @@ public class UsageManagerImplTest {
     private UsageManagerImpl usageManagerImpl;
 
     @Mock
+    private UsageEventDetailsDao usageEventDetailsDao;
+
+    @Mock
+    private UsageEventVO usageEventVOMock;
+
+    @Mock
     private UsageVPNUserDao usageVPNUserDaoMock;
 
     @Mock
+    private UsageVMSnapshotDao usageVMSnapshotDaoMock;
+
+    @Mock
     private AccountDao accountDaoMock;
 
     @Mock
     private UsageVPNUserVO vpnUserMock;
 
     @Mock
-    private AccountVO accountMock;
+    private UsageVMSnapshotVO vmSnapshotMock;
 
     @Mock
-    private UsageEventVO usageEventVOMock;
+    private AccountVO accountMock;
 
     private long accountMockId = 1l;
     private long acountDomainIdMock = 2l;
@@ -164,4 +175,72 @@ public class UsageManagerImplTest {
         Mockito.verify(usageManagerImpl, Mockito.never()).createUsageVpnUser(usageEventVOMock,accountMock);
         Mockito.verify(usageManagerImpl, Mockito.never()).deleteUsageVpnUser(usageEventVOMock, accountMock);
     }
+
+    @Test
+    public void createUsageVMSnapshotTest() {
+        Mockito.doReturn(vmSnapshotMock).when(usageVMSnapshotDaoMock).persist(Mockito.any(UsageVMSnapshotVO.class));
+        usageManagerImpl.createUsageVMSnapshot(Mockito.mock(UsageEventVO.class));
+        Mockito.verify(usageVMSnapshotDaoMock, Mockito.times(1)).persist(Mockito.any(UsageVMSnapshotVO.class));
+    }
+
+    @Test
+    public void deleteUsageVMSnapshotTest() {
+        List<UsageVMSnapshotVO> vmSnapshotsMock = new ArrayList<UsageVMSnapshotVO>();
+        vmSnapshotsMock.add(vmSnapshotMock);
+
+        Mockito.doReturn(vmSnapshotsMock).when(usageManagerImpl).findUsageVMSnapshots(Mockito.anyLong(), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyLong());
+        Mockito.doNothing().when(usageVMSnapshotDaoMock).update(Mockito.any(UsageVMSnapshotVO.class));
+
+        usageManagerImpl.deleteUsageVMSnapshot(usageEventVOMock);
+
+        Mockito.verify(usageVMSnapshotDaoMock, Mockito.times(1)).update(Mockito.any(UsageVMSnapshotVO.class));
+    }
+
+    @Test
+    public void deleteUsageVMSnapshotMultipleSnapshotsFoundTest() {
+        List<UsageVMSnapshotVO> vmSnapshotsMock = new ArrayList<UsageVMSnapshotVO>();
+        vmSnapshotsMock.add(vmSnapshotMock);
+        vmSnapshotsMock.add(Mockito.mock(UsageVMSnapshotVO.class));
+        vmSnapshotsMock.add(Mockito.mock(UsageVMSnapshotVO.class));
+
+
+        Mockito.doReturn(vmSnapshotsMock).when(usageManagerImpl).findUsageVMSnapshots(Mockito.anyLong(), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyLong());
+        Mockito.doNothing().when(usageVMSnapshotDaoMock).update(Mockito.any(UsageVMSnapshotVO.class));
+
+        usageManagerImpl.deleteUsageVMSnapshot(usageEventVOMock);
+
+        Mockito.verify(usageVMSnapshotDaoMock, Mockito.times(3)).update(Mockito.any(UsageVMSnapshotVO.class));
+    }
+
+    @Test
+    public void handleVMSnapshotEventTestCreateVMSnapshot() {
+        Mockito.when(usageEventVOMock.getType()).thenReturn(EventTypes.EVENT_VM_SNAPSHOT_CREATE);
+        Mockito.doNothing().when(this.usageManagerImpl).createUsageVMSnapshot(usageEventVOMock);
+
+        this.usageManagerImpl.handleVMSnapshotEvent(usageEventVOMock);
+
+        Mockito.verify(usageManagerImpl).createUsageVMSnapshot(usageEventVOMock);
+        Mockito.verify(usageManagerImpl, Mockito.never()).deleteUsageVMSnapshot(usageEventVOMock);
+    }
+
+    @Test
+    public void handleVMSnapshotEventTestDeleteVMSnapshot() {
+        Mockito.when(usageEventVOMock.getType()).thenReturn(EventTypes.EVENT_VM_SNAPSHOT_DELETE);
+        Mockito.doNothing().when(this.usageManagerImpl).deleteUsageVMSnapshot(usageEventVOMock);
+
+        this.usageManagerImpl.handleVMSnapshotEvent(usageEventVOMock);
+
+        Mockito.verify(usageManagerImpl).deleteUsageVMSnapshot(usageEventVOMock);
+        Mockito.verify(usageManagerImpl, Mockito.never()).createUsageVMSnapshot(usageEventVOMock);
+    }
+
+    @Test
+    public void handleVMSnapshotEventTestEventIsNeitherAddNorRemove() {
+        Mockito.when(this.usageEventVOMock.getType()).thenReturn("VPN.USER.UPDATE");
+
+        this.usageManagerImpl.handleVMSnapshotEvent(usageEventVOMock);
+
+        Mockito.verify(usageManagerImpl, Mockito.never()).createUsageVpnUser(usageEventVOMock,accountMock);
+        Mockito.verify(usageManagerImpl, Mockito.never()).deleteUsageVpnUser(usageEventVOMock, accountMock);
+    }
 }
\ No newline at end of file