From 39aa86db70316419c7412eb725b1f27917661166 Mon Sep 17 00:00:00 2001 From: nnesic Date: Wed, 7 Oct 2015 10:46:41 +0000 Subject: [PATCH 1/7] Changed usage utils to lookup deleted accounts. This was causing problems when deleting accounts which had running resources. The resources are stopped and destroyed, but we never get a usage event indicating so. --- engine/components-api/src/com/cloud/event/UsageEventUtils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/engine/components-api/src/com/cloud/event/UsageEventUtils.java b/engine/components-api/src/com/cloud/event/UsageEventUtils.java index 69892d60b72e..76344158502b 100644 --- a/engine/components-api/src/com/cloud/event/UsageEventUtils.java +++ b/engine/components-api/src/com/cloud/event/UsageEventUtils.java @@ -177,7 +177,7 @@ private static void publishUsageEvent(String usageEventType, Long accountId, Lon return; // no provider is configured to provide events bus, so just return } - Account account = s_accountDao.findById(accountId); + Account account = s_accountDao.findByIdIncludingRemoved(accountId); DataCenterVO dc = s_dcDao.findById(zoneId); // if account has been deleted, this might be called during cleanup of resources and results in null pointer From fb5f15512a3e5da242a3041a66c87cc292a4aaec Mon Sep 17 00:00:00 2001 From: nnesic Date: Mon, 12 Oct 2015 13:15:30 +0000 Subject: [PATCH 2/7] Emit a VOLUME_DELETE usage event when account deletion destroys an instance. Currently the logic about volume deletion seems to be that an event should be emitted when the volume delete is requested, not when the deletion completes. The VolumeStateListener specifically ignores destroy events for ROOT volumes, assuming that the ROOT volume only gets deleted when the instance is destroyed and the UserVmManager should take care of it. When deleting an account, all of its resources get destroyed, but the instance expunging circumvents the UserVmManager, and thus we miss the VOLUME_DESTROY usage event. Added a check in the AccountManager to emit the deletion event for ROOT volumes belonging to instances which weren't destroyed prior to the account deletion. --- server/src/com/cloud/user/AccountManagerImpl.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/server/src/com/cloud/user/AccountManagerImpl.java b/server/src/com/cloud/user/AccountManagerImpl.java index da097378e16d..cb1c9c3d55b3 100644 --- a/server/src/com/cloud/user/AccountManagerImpl.java +++ b/server/src/com/cloud/user/AccountManagerImpl.java @@ -83,6 +83,7 @@ import com.cloud.event.ActionEventUtils; import com.cloud.event.ActionEvents; import com.cloud.event.EventTypes; +import com.cloud.event.UsageEventUtils; import com.cloud.exception.AgentUnavailableException; import com.cloud.exception.CloudAuthenticationException; import com.cloud.exception.ConcurrentOperationException; @@ -159,6 +160,7 @@ import com.cloud.vm.UserVmManager; import com.cloud.vm.UserVmVO; import com.cloud.vm.VMInstanceVO; +import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachineManager; import com.cloud.vm.dao.InstanceGroupDao; import com.cloud.vm.dao.UserVmDao; @@ -761,6 +763,19 @@ protected boolean cleanupAccount(AccountVO account, long callerUserId, Account c s_logger.error("Unable to expunge vm: " + vm.getId()); accountCleanupNeeded = true; } + else if (!vm.getState().equals(VirtualMachine.State.Destroyed)) { + // We have to emit the event here because the state listener is ignoring root volume deletions, + // assuming that the UserVMManager is responsible for emitting the usage event for them when + // the vm delete command is processed + List volumes = _volumeDao.findByInstance(vm.getId()); + for (VolumeVO volume : volumes) { + if (volume.getVolumeType().equals(Volume.Type.ROOT)) { + UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_DELETE, volume.getAccountId(), volume.getDataCenterId(), volume.getId(), volume.getName(), + Volume.class.getName(), volume.getUuid(), volume.isDisplayVolume()); + } + } + + } } // Mark the account's volumes as destroyed From 7f56a31e0b378728900b4831a4550895b3af8334 Mon Sep 17 00:00:00 2001 From: nnesic Date: Mon, 12 Oct 2015 13:28:58 +0000 Subject: [PATCH 3/7] Added the 'status' to volume event descriptions To allow distinguishing between pre- and post-stateTransition events --- server/src/com/cloud/storage/listener/VolumeStateListener.java | 1 + 1 file changed, 1 insertion(+) diff --git a/server/src/com/cloud/storage/listener/VolumeStateListener.java b/server/src/com/cloud/storage/listener/VolumeStateListener.java index 9a739ba2bc11..5c02894ecb85 100644 --- a/server/src/com/cloud/storage/listener/VolumeStateListener.java +++ b/server/src/com/cloud/storage/listener/VolumeStateListener.java @@ -115,6 +115,7 @@ private void pubishOnEventBus(String event, String status, Volume vo, State oldS eventDescription.put("id", vo.getUuid()); eventDescription.put("old-state", oldState.name()); eventDescription.put("new-state", newState.name()); + eventDescription.put("status", status); String eventDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z").format(new Date()); eventDescription.put("eventDateTime", eventDate); From 88dd464db415d5a2b53dda884338019bffa375be Mon Sep 17 00:00:00 2001 From: nnesic Date: Wed, 14 Oct 2015 17:20:56 +0000 Subject: [PATCH 4/7] Cleaner way of getting the root volume --- server/src/com/cloud/user/AccountManagerImpl.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/server/src/com/cloud/user/AccountManagerImpl.java b/server/src/com/cloud/user/AccountManagerImpl.java index cb1c9c3d55b3..7f09dcfe883b 100644 --- a/server/src/com/cloud/user/AccountManagerImpl.java +++ b/server/src/com/cloud/user/AccountManagerImpl.java @@ -767,12 +767,10 @@ else if (!vm.getState().equals(VirtualMachine.State.Destroyed)) { // We have to emit the event here because the state listener is ignoring root volume deletions, // assuming that the UserVMManager is responsible for emitting the usage event for them when // the vm delete command is processed - List volumes = _volumeDao.findByInstance(vm.getId()); + List volumes = _volumeDao.findByInstanceAndType(vm.getId(), Volume.Type.ROOT); for (VolumeVO volume : volumes) { - if (volume.getVolumeType().equals(Volume.Type.ROOT)) { UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_DELETE, volume.getAccountId(), volume.getDataCenterId(), volume.getId(), volume.getName(), Volume.class.getName(), volume.getUuid(), volume.isDisplayVolume()); - } } } From 1bcdc0659ab3bfb93531862f251200e38e1ff290 Mon Sep 17 00:00:00 2001 From: nnesic Date: Wed, 14 Oct 2015 17:21:36 +0000 Subject: [PATCH 5/7] Wrote unit test for emitting usage event for volumes on account delete. --- .../cloud/user/AccountManagerImplTest.java | 132 ++++++- .../com/cloud/user/MockUsageEventDao.java | 334 ++++++++++++++++++ 2 files changed, 453 insertions(+), 13 deletions(-) create mode 100644 server/test/com/cloud/user/MockUsageEventDao.java diff --git a/server/test/com/cloud/user/AccountManagerImplTest.java b/server/test/com/cloud/user/AccountManagerImplTest.java index a895ec27d778..8779503d6937 100644 --- a/server/test/com/cloud/user/AccountManagerImplTest.java +++ b/server/test/com/cloud/user/AccountManagerImplTest.java @@ -17,23 +17,21 @@ package com.cloud.user; import java.lang.reflect.Field; + import java.net.InetAddress; import java.net.UnknownHostException; -import java.util.Arrays; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import javax.inject.Inject; import com.cloud.server.auth.UserAuthenticator; import com.cloud.utils.Pair; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.mockito.runners.MockitoJUnitRunner; import org.apache.cloudstack.acl.ControlledEntity; import org.apache.cloudstack.acl.SecurityChecker; @@ -44,10 +42,14 @@ import org.apache.cloudstack.framework.config.dao.ConfigurationDao; import org.apache.cloudstack.framework.messagebus.MessageBus; import org.apache.cloudstack.region.gslb.GlobalLoadBalancerRuleDao; - -import com.cloud.vm.snapshot.VMSnapshotManager; -import com.cloud.vm.snapshot.VMSnapshotVO; -import com.cloud.vm.snapshot.dao.VMSnapshotDao; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.runners.MockitoJUnitRunner; import com.cloud.configuration.ConfigurationManager; import com.cloud.configuration.dao.ResourceCountDao; @@ -58,6 +60,8 @@ import com.cloud.domain.Domain; import com.cloud.domain.DomainVO; import com.cloud.domain.dao.DomainDao; +import com.cloud.event.UsageEventUtils; +import com.cloud.event.UsageEventVO; import com.cloud.exception.ConcurrentOperationException; import com.cloud.exception.ResourceUnavailableException; import com.cloud.network.as.AutoScaleManager; @@ -74,7 +78,9 @@ import com.cloud.projects.ProjectManager; import com.cloud.projects.dao.ProjectAccountDao; import com.cloud.projects.dao.ProjectDao; +import com.cloud.storage.Volume; import com.cloud.storage.VolumeApiService; +import com.cloud.storage.VolumeVO; import com.cloud.storage.dao.SnapshotDao; import com.cloud.storage.dao.VMTemplateDao; import com.cloud.storage.dao.VolumeDao; @@ -87,12 +93,16 @@ import com.cloud.vm.UserVmManager; import com.cloud.vm.UserVmVO; import com.cloud.vm.VMInstanceVO; +import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachineManager; import com.cloud.vm.dao.DomainRouterDao; import com.cloud.vm.dao.InstanceGroupDao; import com.cloud.vm.dao.UserVmDao; import com.cloud.vm.dao.VMInstanceDao; import org.springframework.test.util.ReflectionTestUtils; +import com.cloud.vm.snapshot.VMSnapshotManager; +import com.cloud.vm.snapshot.VMSnapshotVO; +import com.cloud.vm.snapshot.dao.VMSnapshotDao; @RunWith(MockitoJUnitRunner.class) public class AccountManagerImplTest { @@ -192,6 +202,9 @@ public class AccountManagerImplTest { @Mock VMSnapshotDao _vmSnapshotDao; + @Mock + MockUsageEventDao _usageEventDao; + @Mock User callingUser; @Mock @@ -353,6 +366,99 @@ public void testAuthenticateUser() throws UnknownHostException { Mockito.verify(userAuthenticator, Mockito.times(1)).authenticate("test", "fail", 1L, null); Mockito.verify(userAuthenticator, Mockito.never()).authenticate("test", null, 1L, null); Mockito.verify(userAuthenticator, Mockito.never()).authenticate("test", "", 1L, null); + } + + public UsageEventUtils setupUsageUtils() { + _usageEventDao = new MockUsageEventDao(); + UsageEventUtils utils = new UsageEventUtils(); + Map usageUtilsFields = new HashMap(); + usageUtilsFields.put("usageEventDao", "_usageEventDao"); + usageUtilsFields.put("accountDao", "_accountDao"); + usageUtilsFields.put("dcDao", "_dcDao"); + usageUtilsFields.put("configDao", "_configDao"); + for (String fieldName : usageUtilsFields.keySet()) { + try { + Field f = UsageEventUtils.class.getDeclaredField(fieldName); + f.setAccessible(true); + f.set(utils, + this.getClass() + .getDeclaredField( + usageUtilsFields.get(fieldName)) + .get(this)); + } catch (IllegalArgumentException | IllegalAccessException + | NoSuchFieldException | SecurityException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + } + try { + Method method = UsageEventUtils.class.getDeclaredMethod("init"); + method.setAccessible(true); + method.invoke(utils); + } catch (SecurityException | NoSuchMethodException + | IllegalAccessException | IllegalArgumentException + | InvocationTargetException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + return utils; + } + + public List deleteUserAccountRootVolumeUsageEvents(boolean vmDestroyedPrior) { + AccountVO account = new AccountVO(); + account.setId(42l); + DomainVO domain = new DomainVO(); + UserVmVO vm = Mockito.mock(UserVmVO.class); + VolumeVO vol = Mockito.mock(VolumeVO.class); + Mockito.when(_accountDao.findById(42l)).thenReturn(account); + Mockito.when( + securityChecker.checkAccess(Mockito.any(Account.class), + Mockito.any(ControlledEntity.class), Mockito.any(AccessType.class), + Mockito.anyString())) + .thenReturn(true); + Mockito.when(_accountDao.remove(42l)).thenReturn(true); + Mockito.when(_userVmDao.listByAccountId(42l)).thenReturn( + Arrays.asList(vm)); + Mockito.when(_userVmDao.findByUuid(Mockito.any(String.class))).thenReturn(vm); + Mockito.when( + _vmMgr.expunge(Mockito.any(UserVmVO.class), Mockito.anyLong(), + Mockito.any(Account.class))).thenReturn(true); + Mockito.when(vm.getState()).thenReturn( + vmDestroyedPrior + ? VirtualMachine.State.Destroyed + : VirtualMachine.State.Running); + Mockito.when( + _volumeDao.findByInstanceAndType(Mockito.any(Long.class), + Mockito.eq(Volume.Type.ROOT))).thenReturn( + Arrays.asList(vol)); + Mockito.when(vol.getAccountId()).thenReturn((long) 1); + Mockito.when(vol.getDataCenterId()).thenReturn((long) 1); + Mockito.when(vol.getId()).thenReturn((long) 1); + Mockito.when(vol.getName()).thenReturn("root volume"); + Mockito.when(vol.getUuid()).thenReturn("vol-111111"); + Mockito.when(vol.isDisplayVolume()).thenReturn(true); + + Mockito.when(_domainMgr.getDomain(Mockito.anyLong())) + .thenReturn(domain); + + accountManager.deleteUserAccount(42); + return _usageEventDao.listAll(); + } + + @Test + public void destroyedVMRootVolumeUsageEvent() { + UsageEventUtils utils = setupUsageUtils(); + List emittedEvents = deleteUserAccountRootVolumeUsageEvents(true); + Assert.assertEquals(0, emittedEvents.size()); + } + + @Test + public void runningVMRootVolumeUsageEvent() { + UsageEventUtils utils = setupUsageUtils(); + List emittedEvents = deleteUserAccountRootVolumeUsageEvents(false); + Assert.assertEquals(1, emittedEvents.size()); } } diff --git a/server/test/com/cloud/user/MockUsageEventDao.java b/server/test/com/cloud/user/MockUsageEventDao.java new file mode 100644 index 000000000000..63adc9416d2d --- /dev/null +++ b/server/test/com/cloud/user/MockUsageEventDao.java @@ -0,0 +1,334 @@ +package com.cloud.user; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Map; + +import javax.naming.ConfigurationException; + +import com.cloud.event.UsageEventVO; +import com.cloud.event.dao.UsageEventDao; +import com.cloud.utils.Pair; +import com.cloud.utils.db.Attribute; +import com.cloud.utils.db.Filter; +import com.cloud.utils.db.GenericSearchBuilder; +import com.cloud.utils.db.SearchBuilder; +import com.cloud.utils.db.SearchCriteria; + +public class MockUsageEventDao implements UsageEventDao{ + + List persistedItems; + + public MockUsageEventDao() { + persistedItems = new ArrayList(); + } + + @Override + public UsageEventVO findById(Long id) { + // TODO Auto-generated method stub + return null; + } + + @Override + public UsageEventVO findByIdIncludingRemoved(Long id) { + // TODO Auto-generated method stub + return null; + } + + @Override + public UsageEventVO findById(Long id, boolean fresh) { + // TODO Auto-generated method stub + return null; + } + + @Override + public UsageEventVO findByUuid(String uuid) { + // TODO Auto-generated method stub + return null; + } + + @Override + public UsageEventVO findByUuidIncludingRemoved(String uuid) { + // TODO Auto-generated method stub + return null; + } + + @Override + public UsageEventVO createForUpdate() { + // TODO Auto-generated method stub + return null; + } + + @Override + public SearchBuilder createSearchBuilder() { + // TODO Auto-generated method stub + return null; + } + + @Override + public GenericSearchBuilder createSearchBuilder( + Class clazz) { + // TODO Auto-generated method stub + return null; + } + + @Override + public UsageEventVO createForUpdate(Long id) { + // TODO Auto-generated method stub + return null; + } + + @Override + public SearchCriteria createSearchCriteria() { + // TODO Auto-generated method stub + return null; + } + + @Override + public List lockRows(SearchCriteria sc, + Filter filter, boolean exclusive) { + // TODO Auto-generated method stub + return null; + } + + @Override + public UsageEventVO lockOneRandomRow(SearchCriteria sc, + boolean exclusive) { + // TODO Auto-generated method stub + return null; + } + + @Override + public UsageEventVO lockRow(Long id, Boolean exclusive) { + // TODO Auto-generated method stub + return null; + } + + @Override + public UsageEventVO acquireInLockTable(Long id) { + // TODO Auto-generated method stub + return null; + } + + @Override + public UsageEventVO acquireInLockTable(Long id, int seconds) { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean releaseFromLockTable(Long id) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean update(Long id, UsageEventVO entity) { + // TODO Auto-generated method stub + return false; + } + + @Override + public int update(UsageEventVO entity, SearchCriteria sc) { + // TODO Auto-generated method stub + return 0; + } + + @Override + public List listAll() { + + return persistedItems; + } + + @Override + public List listAll(Filter filter) { + // TODO Auto-generated method stub + return null; + } + + @Override + public List search(SearchCriteria sc, + Filter filter) { + // TODO Auto-generated method stub + return null; + } + + @Override + public List search(SearchCriteria sc, + Filter filter, boolean enableQueryCache) { + // TODO Auto-generated method stub + return null; + } + + @Override + public List searchIncludingRemoved( + SearchCriteria sc, Filter filter, Boolean lock, + boolean cache) { + // TODO Auto-generated method stub + return null; + } + + @Override + public List searchIncludingRemoved( + SearchCriteria sc, Filter filter, Boolean lock, + boolean cache, boolean enableQueryCache) { + // TODO Auto-generated method stub + return null; + } + + @Override + public List customSearchIncludingRemoved(SearchCriteria sc, + Filter filter) { + // TODO Auto-generated method stub + return null; + } + + @Override + public List listAllIncludingRemoved() { + // TODO Auto-generated method stub + return null; + } + + @Override + public List listAllIncludingRemoved(Filter filter) { + // TODO Auto-generated method stub + return null; + } + + @Override + public UsageEventVO persist(UsageEventVO entity) { + persistedItems.add(entity); + return entity; + } + + @Override + public boolean remove(Long id) { + // TODO Auto-generated method stub + return false; + } + + @Override + public int remove(SearchCriteria sc) { + // TODO Auto-generated method stub + return 0; + } + + @Override + public boolean expunge(Long id) { + // TODO Auto-generated method stub + return false; + } + + @Override + public int expunge(SearchCriteria sc) { + // TODO Auto-generated method stub + return 0; + } + + @Override + public void expunge() { + // TODO Auto-generated method stub + + } + + @Override + public K getNextInSequence(Class clazz, String name) { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean configure(String name, Map params) + throws ConfigurationException { + // TODO Auto-generated method stub + return false; + } + + @Override + public List customSearch(SearchCriteria sc, Filter filter) { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean lockInLockTable(String id) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean lockInLockTable(String id, int seconds) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean unlockFromLockTable(String id) { + // TODO Auto-generated method stub + return false; + } + + @Override + public K getRandomlyIncreasingNextInSequence(Class clazz, String name) { + // TODO Auto-generated method stub + return null; + } + + @Override + public UsageEventVO findOneBy(SearchCriteria sc) { + // TODO Auto-generated method stub + return null; + } + + @Override + public Class getEntityBeanType() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Pair, Integer> searchAndCount( + SearchCriteria sc, Filter filter) { + // TODO Auto-generated method stub + return null; + } + + @Override + public Map getAllAttributes() { + // TODO Auto-generated method stub + return null; + } + + @Override + public List listLatestEvents(Date endDate) { + // TODO Auto-generated method stub + return null; + } + + @Override + public List getLatestEvent() { + // TODO Auto-generated method stub + return null; + } + + @Override + public List getRecentEvents(Date endDate) { + // TODO Auto-generated method stub + return null; + } + + @Override + public List listDirectIpEvents(Date startDate, Date endDate, + long zoneId) { + // TODO Auto-generated method stub + return null; + } + + @Override + public void saveDetails(long eventId, Map details) { + // TODO Auto-generated method stub + + } + +} From 428832e0de73e68abf1650e7ae2bbc4bcf872438 Mon Sep 17 00:00:00 2001 From: jeff Date: Thu, 19 Nov 2015 15:34:13 +0000 Subject: [PATCH 6/7] Restoring the UsageEventUtils static fields after unit test. --- .../cloud/user/AccountManagerImplTest.java | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/server/test/com/cloud/user/AccountManagerImplTest.java b/server/test/com/cloud/user/AccountManagerImplTest.java index 8779503d6937..e9a64f41d876 100644 --- a/server/test/com/cloud/user/AccountManagerImplTest.java +++ b/server/test/com/cloud/user/AccountManagerImplTest.java @@ -218,6 +218,11 @@ public class AccountManagerImplTest { @Mock private UserAuthenticator userAuthenticator; + //Maintain a list of old fields in the usage utils class... This + //is because of weirdness of how it uses static fields and an init + //method. + private Map oldFields = new HashMap<>(); + @Before public void setup() throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException { @@ -377,10 +382,15 @@ public UsageEventUtils setupUsageUtils() { usageUtilsFields.put("accountDao", "_accountDao"); usageUtilsFields.put("dcDao", "_dcDao"); usageUtilsFields.put("configDao", "_configDao"); + for (String fieldName : usageUtilsFields.keySet()) { try { Field f = UsageEventUtils.class.getDeclaredField(fieldName); f.setAccessible(true); + //Remember the old fields for cleanup later (see cleanupUsageUtils) + Field staticField = UsageEventUtils.class.getDeclaredField("s_" + fieldName); + staticField.setAccessible(true); + oldFields.put(f.getName(), staticField.get(null)); f.set(utils, this.getClass() .getDeclaredField( @@ -407,6 +417,33 @@ public UsageEventUtils setupUsageUtils() { return utils; } + public void cleanupUsageUtils() { + UsageEventUtils utils = new UsageEventUtils(); + + for (String fieldName : oldFields.keySet()) { + try { + Field f = UsageEventUtils.class.getDeclaredField(fieldName); + f.setAccessible(true); + f.set(utils, oldFields.get(fieldName)); + } catch (IllegalArgumentException | IllegalAccessException + | NoSuchFieldException | SecurityException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + } + try { + Method method = UsageEventUtils.class.getDeclaredMethod("init"); + method.setAccessible(true); + method.invoke(utils); + } catch (SecurityException | NoSuchMethodException + | IllegalAccessException | IllegalArgumentException + | InvocationTargetException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + public List deleteUserAccountRootVolumeUsageEvents(boolean vmDestroyedPrior) { AccountVO account = new AccountVO(); account.setId(42l); @@ -453,6 +490,7 @@ public void destroyedVMRootVolumeUsageEvent() { UsageEventUtils utils = setupUsageUtils(); List emittedEvents = deleteUserAccountRootVolumeUsageEvents(true); Assert.assertEquals(0, emittedEvents.size()); + cleanupUsageUtils(); } @Test @@ -460,5 +498,6 @@ public void runningVMRootVolumeUsageEvent() { UsageEventUtils utils = setupUsageUtils(); List emittedEvents = deleteUserAccountRootVolumeUsageEvents(false); Assert.assertEquals(1, emittedEvents.size()); + cleanupUsageUtils(); } } From fd45c9b3014ae1f19cbeb6a81be06c3d3dcee354 Mon Sep 17 00:00:00 2001 From: nnesic Date: Mon, 23 Nov 2015 11:43:48 +0000 Subject: [PATCH 7/7] Added the missing searchAndDistinctCount to MockUsageEventDao. --- server/test/com/cloud/user/MockUsageEventDao.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/server/test/com/cloud/user/MockUsageEventDao.java b/server/test/com/cloud/user/MockUsageEventDao.java index 63adc9416d2d..99e8d6fd0393 100644 --- a/server/test/com/cloud/user/MockUsageEventDao.java +++ b/server/test/com/cloud/user/MockUsageEventDao.java @@ -331,4 +331,10 @@ public void saveDetails(long eventId, Map details) { } + @Override + public Pair, Integer> searchAndDistinctCount(SearchCriteria sc, Filter filter) { + //TODO Auto-generated method stub + return null; + } + }