From d989c5d8be1e0b8dc0d25d0402ada4039a695dc8 Mon Sep 17 00:00:00 2001 From: nnesic Date: Mon, 12 Oct 2015 13:15:30 +0000 Subject: [PATCH] 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. The account manager now attempts to propperly destroy the vm before expunging it. This way the destroy logic is respected, including the event emission. --- .../com/cloud/user/AccountManagerImpl.java | 12 +- .../cloud/user/AccountManagerImplTest.java | 220 +------------ ...countManagerImplVolumeDeleteEventTest.java | 209 ++++++++++++ .../user/AccountManagetImplTestBase.java | 242 ++++++++++++++ .../com/cloud/user/MockUsageEventDao.java | 307 ++++++++++++++++++ 5 files changed, 787 insertions(+), 203 deletions(-) create mode 100644 server/test/com/cloud/user/AccountManagerImplVolumeDeleteEventTest.java create mode 100644 server/test/com/cloud/user/AccountManagetImplTestBase.java create mode 100644 server/test/com/cloud/user/MockUsageEventDao.java diff --git a/server/src/com/cloud/user/AccountManagerImpl.java b/server/src/com/cloud/user/AccountManagerImpl.java index d3eb40c7db69..2d9cdb02d4ea 100644 --- a/server/src/com/cloud/user/AccountManagerImpl.java +++ b/server/src/com/cloud/user/AccountManagerImpl.java @@ -159,6 +159,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; @@ -755,8 +756,17 @@ protected boolean cleanupAccount(AccountVO account, long callerUserId, Account c s_logger.debug("Expunging # of vms (accountId=" + accountId + "): " + vms.size()); } - // no need to catch exception at this place as expunging vm should pass in order to perform further cleanup for (UserVmVO vm : vms) { + if (vm.getState() != VirtualMachine.State.Destroyed && vm.getState() != VirtualMachine.State.Expunging) { + try { + _vmMgr.destroyVm(vm.getId()); + } catch (Exception e) { + e.printStackTrace(); + s_logger.warn("Failed destroying instance " + vm.getUuid() + " as part of account deletion."); + } + } + // no need to catch exception at this place as expunging vm + // should pass in order to perform further cleanup if (!_vmMgr.expunge(vm, callerUserId, caller)) { s_logger.error("Unable to expunge vm: " + vm.getId()); accountCleanupNeeded = true; diff --git a/server/test/com/cloud/user/AccountManagerImplTest.java b/server/test/com/cloud/user/AccountManagerImplTest.java index a895ec27d778..278804962f8c 100644 --- a/server/test/com/cloud/user/AccountManagerImplTest.java +++ b/server/test/com/cloud/user/AccountManagerImplTest.java @@ -16,220 +16,35 @@ // under the License. package com.cloud.user; -import java.lang.reflect.Field; import java.net.InetAddress; import java.net.UnknownHostException; -import java.util.Arrays; import java.util.ArrayList; - -import javax.inject.Inject; - +import java.util.Arrays; 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; import org.apache.cloudstack.acl.SecurityChecker.AccessType; -import org.apache.cloudstack.affinity.dao.AffinityGroupDao; -import org.apache.cloudstack.context.CallContext; -import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService; -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 com.cloud.configuration.ConfigurationManager; -import com.cloud.configuration.dao.ResourceCountDao; -import com.cloud.configuration.dao.ResourceLimitDao; -import com.cloud.dc.dao.DataCenterDao; -import com.cloud.dc.dao.DataCenterVnetDao; -import com.cloud.dc.dao.DedicatedResourceDao; import com.cloud.domain.Domain; import com.cloud.domain.DomainVO; -import com.cloud.domain.dao.DomainDao; import com.cloud.exception.ConcurrentOperationException; import com.cloud.exception.ResourceUnavailableException; -import com.cloud.network.as.AutoScaleManager; -import com.cloud.network.dao.AccountGuestVlanMapDao; -import com.cloud.network.dao.IPAddressDao; -import com.cloud.network.dao.NetworkDao; -import com.cloud.network.dao.RemoteAccessVpnDao; -import com.cloud.network.dao.VpnUserDao; -import com.cloud.network.security.SecurityGroupManager; -import com.cloud.network.security.dao.SecurityGroupDao; -import com.cloud.network.vpc.VpcManager; -import com.cloud.network.vpn.RemoteAccessVpnService; -import com.cloud.network.vpn.Site2SiteVpnManager; -import com.cloud.projects.ProjectManager; -import com.cloud.projects.dao.ProjectAccountDao; -import com.cloud.projects.dao.ProjectDao; -import com.cloud.storage.VolumeApiService; -import com.cloud.storage.dao.SnapshotDao; -import com.cloud.storage.dao.VMTemplateDao; -import com.cloud.storage.dao.VolumeDao; -import com.cloud.storage.snapshot.SnapshotManager; -import com.cloud.template.TemplateManager; import com.cloud.user.Account.State; -import com.cloud.user.dao.AccountDao; -import com.cloud.user.dao.UserAccountDao; -import com.cloud.user.dao.UserDao; -import com.cloud.vm.UserVmManager; +import com.cloud.vm.UserVmManagerImpl; import com.cloud.vm.UserVmVO; import com.cloud.vm.VMInstanceVO; -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; -@RunWith(MockitoJUnitRunner.class) -public class AccountManagerImplTest { - @Mock - AccountDao _accountDao; - @Mock - ConfigurationDao _configDao; - @Mock - ResourceCountDao _resourceCountDao; - @Mock - UserDao _userDao; - @Mock - InstanceGroupDao _vmGroupDao; - @Mock - UserAccountDao _userAccountDao; - @Mock - VolumeDao _volumeDao; - @Mock - UserVmDao _userVmDao; - @Mock - VMTemplateDao _templateDao; - @Mock - NetworkDao _networkDao; - @Mock - SecurityGroupDao _securityGroupDao; - @Mock - VMInstanceDao _vmDao; - @Mock - protected SnapshotDao _snapshotDao; - @Mock - protected VMTemplateDao _vmTemplateDao; - @Mock - SecurityGroupManager _networkGroupMgr; - @Mock - NetworkOrchestrationService _networkMgr; - @Mock - SnapshotManager _snapMgr; - @Mock - UserVmManager _vmMgr; - @Mock - TemplateManager _tmpltMgr; - @Mock - ConfigurationManager _configMgr; - @Mock - VirtualMachineManager _itMgr; - @Mock - RemoteAccessVpnDao _remoteAccessVpnDao; - @Mock - RemoteAccessVpnService _remoteAccessVpnMgr; - @Mock - VpnUserDao _vpnUser; - @Mock - DataCenterDao _dcDao; - @Mock - DomainManager _domainMgr; - @Mock - ProjectManager _projectMgr; - @Mock - ProjectDao _projectDao; - @Mock - AccountDetailsDao _accountDetailsDao; - @Mock - DomainDao _domainDao; - @Mock - ProjectAccountDao _projectAccountDao; - @Mock - IPAddressDao _ipAddressDao; - @Mock - VpcManager _vpcMgr; - @Mock - DomainRouterDao _routerDao; - @Mock - Site2SiteVpnManager _vpnMgr; - @Mock - AutoScaleManager _autoscaleMgr; - @Mock - VolumeApiService volumeService; - @Mock - AffinityGroupDao _affinityGroupDao; - @Mock - AccountGuestVlanMapDao _accountGuestVlanMapDao; - @Mock - DataCenterVnetDao _dataCenterVnetDao; - @Mock - ResourceLimitService _resourceLimitMgr; - @Mock - ResourceLimitDao _resourceLimitDao; - @Mock - DedicatedResourceDao _dedicatedDao; - @Mock - GlobalLoadBalancerRuleDao _gslbRuleDao; - @Mock - MessageBus _messageBus; - @Mock - VMSnapshotManager _vmSnapshotMgr; - @Mock - VMSnapshotDao _vmSnapshotDao; +public class AccountManagerImplTest extends AccountManagetImplTestBase { - @Mock - User callingUser; - @Mock - Account callingAccount; - - AccountManagerImpl accountManager; - - @Mock - SecurityChecker securityChecker; @Mock - private UserAuthenticator userAuthenticator; - - @Before - public void setup() throws NoSuchFieldException, SecurityException, - IllegalArgumentException, IllegalAccessException { - accountManager = new AccountManagerImpl(); - for (Field field : AccountManagerImpl.class.getDeclaredFields()) { - if (field.getAnnotation(Inject.class) != null) { - field.setAccessible(true); - try { - Field mockField = this.getClass().getDeclaredField( - field.getName()); - field.set(accountManager, mockField.get(this)); - } catch (Exception e) { - // ignore missing fields - } - } - } - ReflectionTestUtils.setField(accountManager, "_userAuthenticators", Arrays.asList(userAuthenticator)); - accountManager.setSecurityCheckers(Arrays.asList(securityChecker)); - CallContext.register(callingUser, callingAccount); - } - - @After - public void cleanup() { - CallContext.unregister(); - } + UserVmManagerImpl _vmMgr; @Test public void disableAccountNotexisting() @@ -240,7 +55,7 @@ public void disableAccountNotexisting() @Test public void disableAccountDisabled() throws ConcurrentOperationException, - ResourceUnavailableException { + ResourceUnavailableException { AccountVO disabledAccount = new AccountVO(); disabledAccount.setState(State.disabled); Mockito.when(_accountDao.findById(42l)).thenReturn(disabledAccount); @@ -249,7 +64,7 @@ public void disableAccountDisabled() throws ConcurrentOperationException, @Test public void disableAccount() throws ConcurrentOperationException, - ResourceUnavailableException { + ResourceUnavailableException { AccountVO account = new AccountVO(); account.setState(State.enabled); Mockito.when(_accountDao.findById(42l)).thenReturn(account); @@ -272,17 +87,17 @@ public void deleteUserAccount() { 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.any(ControlledEntity.class), Mockito.any(AccessType.class), + Mockito.anyString())) + .thenReturn(true); Mockito.when(_accountDao.remove(42l)).thenReturn(true); Mockito.when(_configMgr.releaseAccountSpecificVirtualRanges(42l)) - .thenReturn(true); + .thenReturn(true); Mockito.when(_domainMgr.getDomain(Mockito.anyLong())).thenReturn(domain); Mockito.when( securityChecker.checkAccess(Mockito.any(Account.class), Mockito.any(Domain.class))) - .thenReturn(true); + .thenReturn(true); Mockito.when(_vmSnapshotDao.listByAccountId(Mockito.anyLong())).thenReturn(new ArrayList()); Assert.assertTrue(accountManager.deleteUserAccount(42)); @@ -301,10 +116,10 @@ public void deleteUserAccountCleanup() { securityChecker.checkAccess(Mockito.any(Account.class), Mockito.any(ControlledEntity.class), Mockito.any(AccessType.class), Mockito.anyString())) - .thenReturn(true); + .thenReturn(true); Mockito.when(_accountDao.remove(42l)).thenReturn(true); Mockito.when(_configMgr.releaseAccountSpecificVirtualRanges(42l)) - .thenReturn(true); + .thenReturn(true); Mockito.when(_userVmDao.listByAccountId(42l)).thenReturn( Arrays.asList(Mockito.mock(UserVmVO.class))); Mockito.when( @@ -314,7 +129,7 @@ public void deleteUserAccountCleanup() { Mockito.when( securityChecker.checkAccess(Mockito.any(Account.class), Mockito.any(Domain.class))) - .thenReturn(true); + .thenReturn(true); Assert.assertTrue(accountManager.deleteUserAccount(42)); // assert that this was NOT a clean delete @@ -327,7 +142,7 @@ public void deleteUserAccountCleanup() { public void testAuthenticateUser() throws UnknownHostException { Pair successAuthenticationPair = new Pair<>(true, null); Pair failureAuthenticationPair = new Pair<>(false, - UserAuthenticator.ActionOnFailedAuthentication.INCREMENT_INCORRECT_LOGIN_ATTEMPT_COUNT); + UserAuthenticator.ActionOnFailedAuthentication.INCREMENT_INCORRECT_LOGIN_ATTEMPT_COUNT); UserAccountVO userAccountVO = new UserAccountVO(); userAccountVO.setSource(User.Source.UNKNOWN); @@ -353,6 +168,7 @@ 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); - } + + } diff --git a/server/test/com/cloud/user/AccountManagerImplVolumeDeleteEventTest.java b/server/test/com/cloud/user/AccountManagerImplVolumeDeleteEventTest.java new file mode 100644 index 000000000000..43c8cfcacce7 --- /dev/null +++ b/server/test/com/cloud/user/AccountManagerImplVolumeDeleteEventTest.java @@ -0,0 +1,209 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package com.cloud.user; + +import static org.mockito.Mockito.when; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.anyLong; +import static org.mockito.Mockito.anyString; + +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.cloudstack.acl.ControlledEntity; +import org.apache.cloudstack.acl.SecurityChecker.AccessType; +import org.apache.cloudstack.engine.cloud.entity.api.VirtualMachineEntity; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.mockito.InjectMocks; +import org.mockito.Mockito; +import org.mockito.Spy; + +import com.cloud.domain.DomainVO; +import com.cloud.event.EventTypes; +import com.cloud.event.UsageEventUtils; +import com.cloud.event.UsageEventVO; +import com.cloud.exception.AgentUnavailableException; +import com.cloud.exception.CloudException; +import com.cloud.exception.ConcurrentOperationException; +import com.cloud.service.ServiceOfferingVO; +import com.cloud.storage.VolumeVO; +import com.cloud.storage.Volume.Type; +import com.cloud.vm.UserVmManagerImpl; +import com.cloud.vm.UserVmVO; +import com.cloud.vm.VirtualMachine; + + +public class AccountManagerImplVolumeDeleteEventTest extends AccountManagetImplTestBase { + + private static final Long ACCOUNT_ID = 1l; + private static final String VOLUME_UUID = "vol-111111"; + + @Spy + @InjectMocks + UserVmManagerImpl _vmMgr; + Map oldFields = new HashMap<>(); + UserVmVO vm = mock(UserVmVO.class); + + + // Configures the static fields of the UsageEventUtils class, Storing the + // previous values to be restored during the cleanup phase, to avoid + // interference with other unit tests. + protected UsageEventUtils setupUsageUtils() throws NoSuchMethodException, SecurityException, IllegalAccessException, + IllegalArgumentException, InvocationTargetException { + + _usageEventDao = new MockUsageEventDao(); + UsageEventUtils utils = new UsageEventUtils(); + + List usageUtilsFields = new ArrayList(); + usageUtilsFields.add("usageEventDao"); + usageUtilsFields.add("accountDao"); + usageUtilsFields.add("dcDao"); + usageUtilsFields.add("configDao"); + + for (String fieldName : usageUtilsFields) { + try { + Field f = UsageEventUtils.class.getDeclaredField(fieldName); + f.setAccessible(true); + Field staticField = UsageEventUtils.class.getDeclaredField("s_" + fieldName); + staticField.setAccessible(true); + oldFields.put(f.getName(), staticField.get(null)); + f.set(utils, + this.getClass().getSuperclass().getDeclaredField("_" + fieldName).get(this)); + } catch (IllegalArgumentException | IllegalAccessException | NoSuchFieldException | SecurityException e) { + e.printStackTrace(); + } + } + Method method; + method = UsageEventUtils.class.getDeclaredMethod("init"); + method.setAccessible(true); + method.invoke(utils); + return utils; + } + + + protected void defineMocksBehavior() + throws AgentUnavailableException, ConcurrentOperationException, CloudException { + + AccountVO account = new AccountVO(); + account.setId(ACCOUNT_ID); + when(_accountDao.remove(ACCOUNT_ID)).thenReturn(true); + when(_accountDao.findById(ACCOUNT_ID)).thenReturn(account); + + DomainVO domain = new DomainVO(); + VirtualMachineEntity vmEntity = mock(VirtualMachineEntity.class); + + when(_orchSrvc.getVirtualMachine(anyString())).thenReturn(vmEntity); + when(vmEntity.destroy(anyString())).thenReturn(true); + + Mockito.doReturn(vm).when(_vmDao).findById(anyLong()); + + VolumeVO vol = new VolumeVO(VOLUME_UUID, 1l, 1l, 1l, 1l, 1l, "folder", "path", null, 50, Type.ROOT); + vol.setDisplayVolume(true); + List volumes = new ArrayList<>(); + volumes.add(vol); + + when(securityChecker.checkAccess(any(Account.class), any(ControlledEntity.class), any(AccessType.class), + anyString())).thenReturn(true); + + when(_userVmDao.findById(anyLong())).thenReturn(vm); + when(_userVmDao.listByAccountId(ACCOUNT_ID)).thenReturn(Arrays.asList(vm)); + when(_userVmDao.findByUuid(any(String.class))).thenReturn(vm); + + when(_volumeDao.findByInstance(anyLong())).thenReturn(volumes); + + ServiceOfferingVO offering = mock(ServiceOfferingVO.class); + when(offering.getCpu()).thenReturn(500); + when(offering.getId()).thenReturn(1l); + when(offering.getCpu()).thenReturn(500); + when(offering.getRamSize()).thenReturn(500); + when(_serviceOfferingDao.findByIdIncludingRemoved(anyLong(), anyLong())) + .thenReturn(offering); + + when(_domainMgr.getDomain(anyLong())).thenReturn(domain); + + Mockito.doReturn(true).when(_vmMgr).expunge(any(UserVmVO.class), anyLong(), any(Account.class)); + + } + + @Before + public void init() + throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, + InvocationTargetException, AgentUnavailableException, ConcurrentOperationException, CloudException { + + setupUsageUtils(); + defineMocksBehavior(); + } + + @After + // Restores static fields of the UsageEventUtil class to previous values. + public void cleanupUsageUtils() throws ReflectiveOperationException, SecurityException { + + UsageEventUtils utils = new UsageEventUtils(); + for (String fieldName : oldFields.keySet()) { + Field f = UsageEventUtils.class.getDeclaredField(fieldName); + f.setAccessible(true); + f.set(utils, oldFields.get(fieldName)); + } + Method method = UsageEventUtils.class.getDeclaredMethod("init"); + method.setAccessible(true); + method.invoke(utils); + } + + @SuppressWarnings("unchecked") + protected List deleteUserAccountRootVolumeUsageEvents(boolean vmDestroyedPrior) + throws AgentUnavailableException, ConcurrentOperationException, CloudException { + + when(vm.getState()) + .thenReturn(vmDestroyedPrior ? VirtualMachine.State.Destroyed : VirtualMachine.State.Running); + when(vm.getRemoved()).thenReturn(vmDestroyedPrior ? new Date() : null); + accountManager.deleteUserAccount(ACCOUNT_ID); + + return _usageEventDao.listAll(); + } + + @Test + // If the VM is alerady destroyed, no events should get emitted + public void destroyedVMRootVolumeUsageEvent() throws SecurityException, IllegalArgumentException, + ReflectiveOperationException, AgentUnavailableException, ConcurrentOperationException, CloudException { + List emittedEvents = deleteUserAccountRootVolumeUsageEvents(true); + Assert.assertEquals(0, emittedEvents.size()); + } + + @Test + // If the VM is running, we should see one emitted event for the root + // volume. + public void runningVMRootVolumeUsageEvent() throws SecurityException, IllegalArgumentException, + ReflectiveOperationException, AgentUnavailableException, ConcurrentOperationException, CloudException { + List emittedEvents = deleteUserAccountRootVolumeUsageEvents(false); + Assert.assertEquals(1, emittedEvents.size()); + UsageEventVO event = emittedEvents.get(0); + Assert.assertEquals(EventTypes.EVENT_VOLUME_DELETE, event.getType()); + Assert.assertEquals(VOLUME_UUID, event.getResourceName()); + + } +} diff --git a/server/test/com/cloud/user/AccountManagetImplTestBase.java b/server/test/com/cloud/user/AccountManagetImplTestBase.java new file mode 100644 index 000000000000..5f1e8417c2bc --- /dev/null +++ b/server/test/com/cloud/user/AccountManagetImplTestBase.java @@ -0,0 +1,242 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package com.cloud.user; + +import java.lang.reflect.Field; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +import javax.inject.Inject; + +import org.apache.cloudstack.acl.SecurityChecker; +import org.apache.cloudstack.affinity.dao.AffinityGroupDao; +import org.apache.cloudstack.context.CallContext; +import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService; +import org.apache.cloudstack.engine.service.api.OrchestrationService; +import org.apache.cloudstack.framework.config.dao.ConfigurationDao; +import org.apache.cloudstack.framework.messagebus.MessageBus; +import org.apache.cloudstack.region.gslb.GlobalLoadBalancerRuleDao; +import org.junit.After; +import org.junit.Before; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; +import org.springframework.test.util.ReflectionTestUtils; + +import com.cloud.configuration.ConfigurationManager; +import com.cloud.configuration.dao.ResourceCountDao; +import com.cloud.configuration.dao.ResourceLimitDao; +import com.cloud.dc.dao.DataCenterDao; +import com.cloud.dc.dao.DataCenterVnetDao; +import com.cloud.dc.dao.DedicatedResourceDao; +import com.cloud.domain.dao.DomainDao; +import com.cloud.event.dao.UsageEventDao; +import com.cloud.network.as.AutoScaleManager; +import com.cloud.network.dao.AccountGuestVlanMapDao; +import com.cloud.network.dao.IPAddressDao; +import com.cloud.network.dao.NetworkDao; +import com.cloud.network.dao.RemoteAccessVpnDao; +import com.cloud.network.dao.VpnUserDao; +import com.cloud.network.security.SecurityGroupManager; +import com.cloud.network.security.dao.SecurityGroupDao; +import com.cloud.network.vpc.VpcManager; +import com.cloud.network.vpn.RemoteAccessVpnService; +import com.cloud.network.vpn.Site2SiteVpnManager; +import com.cloud.projects.ProjectManager; +import com.cloud.projects.dao.ProjectAccountDao; +import com.cloud.projects.dao.ProjectDao; +import com.cloud.server.auth.UserAuthenticator; +import com.cloud.service.dao.ServiceOfferingDao; +import com.cloud.storage.VolumeApiService; +import com.cloud.storage.dao.SnapshotDao; +import com.cloud.storage.dao.VMTemplateDao; +import com.cloud.storage.dao.VolumeDao; +import com.cloud.storage.snapshot.SnapshotManager; +import com.cloud.template.TemplateManager; +import com.cloud.user.dao.AccountDao; +import com.cloud.user.dao.UserAccountDao; +import com.cloud.user.dao.UserDao; +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 com.cloud.vm.snapshot.VMSnapshotManager; +import com.cloud.vm.snapshot.dao.VMSnapshotDao; + +@RunWith(MockitoJUnitRunner.class) +public class AccountManagetImplTestBase { + + @Mock + AccountDao _accountDao; + @Mock + ConfigurationDao _configDao; + @Mock + ResourceCountDao _resourceCountDao; + @Mock + UserDao _userDao; + @Mock + InstanceGroupDao _vmGroupDao; + @Mock + UserAccountDao _userAccountDao; + @Mock + VolumeDao _volumeDao; + @Mock + UserVmDao _userVmDao; + @Mock + VMTemplateDao _templateDao; + @Mock + NetworkDao _networkDao; + @Mock + SecurityGroupDao _securityGroupDao; + @Mock + VMInstanceDao _vmDao; + @Mock + protected SnapshotDao _snapshotDao; + @Mock + protected VMTemplateDao _vmTemplateDao; + @Mock + SecurityGroupManager _networkGroupMgr; + @Mock + NetworkOrchestrationService _networkMgr; + @Mock + SnapshotManager _snapMgr; + @Mock + TemplateManager _tmpltMgr; + @Mock + ConfigurationManager _configMgr; + @Mock + VirtualMachineManager _itMgr; + @Mock + RemoteAccessVpnDao _remoteAccessVpnDao; + @Mock + RemoteAccessVpnService _remoteAccessVpnMgr; + @Mock + VpnUserDao _vpnUser; + @Mock + DataCenterDao _dcDao; + @Mock + DomainManager _domainMgr; + @Mock + ProjectManager _projectMgr; + @Mock + ProjectDao _projectDao; + @Mock + AccountDetailsDao _accountDetailsDao; + @Mock + DomainDao _domainDao; + @Mock + ProjectAccountDao _projectAccountDao; + @Mock + IPAddressDao _ipAddressDao; + @Mock + VpcManager _vpcMgr; + @Mock + DomainRouterDao _routerDao; + @Mock + Site2SiteVpnManager _vpnMgr; + @Mock + AutoScaleManager _autoscaleMgr; + @Mock + VolumeApiService volumeService; + @Mock + AffinityGroupDao _affinityGroupDao; + @Mock + AccountGuestVlanMapDao _accountGuestVlanMapDao; + @Mock + DataCenterVnetDao _dataCenterVnetDao; + @Mock + ResourceLimitService _resourceLimitMgr; + @Mock + ResourceLimitDao _resourceLimitDao; + @Mock + DedicatedResourceDao _dedicatedDao; + @Mock + GlobalLoadBalancerRuleDao _gslbRuleDao; + @Mock + MessageBus _messageBus; + @Mock + VMSnapshotManager _vmSnapshotMgr; + @Mock + VMSnapshotDao _vmSnapshotDao; + @Mock + User callingUser; + @Mock + Account callingAccount; + + @Mock + SecurityChecker securityChecker; + @Mock + UserAuthenticator userAuthenticator; + @Mock + ServiceOfferingDao _serviceOfferingDao; + @Mock + ServiceOfferingDao _offeringDao; + @Mock + OrchestrationService _orchSrvc; + + + AccountManagerImpl accountManager; + + UsageEventDao _usageEventDao = new MockUsageEventDao(); + + @Before + public void setup() + throws NoSuchFieldException, SecurityException, + IllegalArgumentException, IllegalAccessException { + accountManager = new AccountManagerImpl(); + Map declaredFields = getInheritedFields(this.getClass()); + for (Field field : AccountManagerImpl.class.getDeclaredFields()) { + if (field.getAnnotation(Inject.class) != null) { + field.setAccessible(true); + if (declaredFields.containsKey(field.getName())) { + Field mockField = declaredFields.get(field.getName()); + field.set(accountManager, mockField.get(this)); + } + } + } + ReflectionTestUtils.setField(accountManager, "_userAuthenticators", Arrays.asList(userAuthenticator)); + accountManager.setSecurityCheckers(Arrays.asList(securityChecker)); + CallContext.register(callingUser, callingAccount); + } + + @After + public void cleanup() { + CallContext.unregister(); + } + + public static Map getInheritedFields(Class type) { + Map fields = new HashMap<>(); + for (Class c = type; c != null; c = c.getSuperclass()) { + for (Field f : c.getDeclaredFields()) { + fields.put(f.getName(), f); + } + } + return fields; + } + + public static Map, Field> getInheritedFieldsByClass(Class type) { + Map, Field> fields = new HashMap<>(); + for (Class c = type; c != null; c = c.getSuperclass()) { + for (Field f : c.getDeclaredFields()) { + fields.put(f.getType(), f); + } + } + return fields; + } +} diff --git a/server/test/com/cloud/user/MockUsageEventDao.java b/server/test/com/cloud/user/MockUsageEventDao.java new file mode 100644 index 000000000000..4959b83a4523 --- /dev/null +++ b/server/test/com/cloud/user/MockUsageEventDao.java @@ -0,0 +1,307 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +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) { + return null; + } + + @Override + public UsageEventVO findByIdIncludingRemoved(Long id) { + return null; + } + + @Override + public UsageEventVO findById(Long id, boolean fresh) { + return null; + } + + @Override + public UsageEventVO findByUuid(String uuid) { + return null; + } + + @Override + public UsageEventVO findByUuidIncludingRemoved(String uuid) { + return null; + } + + @Override + public UsageEventVO createForUpdate() { + return null; + } + + @Override + public SearchBuilder createSearchBuilder() { + return null; + } + + @Override + public GenericSearchBuilder createSearchBuilder( + Class clazz) { + return null; + } + + @Override + public UsageEventVO createForUpdate(Long id) { + return null; + } + + @Override + public SearchCriteria createSearchCriteria() { + return null; + } + + @Override + public List lockRows(SearchCriteria sc, + Filter filter, boolean exclusive) { + return null; + } + + @Override + public UsageEventVO lockOneRandomRow(SearchCriteria sc, + boolean exclusive) { + return null; + } + + @Override + public UsageEventVO lockRow(Long id, Boolean exclusive) { + return null; + } + + @Override + public UsageEventVO acquireInLockTable(Long id) { + return null; + } + + @Override + public UsageEventVO acquireInLockTable(Long id, int seconds) { + return null; + } + + @Override + public boolean releaseFromLockTable(Long id) { + return false; + } + + @Override + public boolean update(Long id, UsageEventVO entity) { + return false; + } + + @Override + public int update(UsageEventVO entity, SearchCriteria sc) { + return 0; + } + + @Override + public List listAll() { + return persistedItems; + } + + @Override + public List listAll(Filter filter) { + return null; + } + + @Override + public List search(SearchCriteria sc, + Filter filter) { + return null; + } + + @Override + public List search(SearchCriteria sc, + Filter filter, boolean enableQueryCache) { + return null; + } + + @Override + public List searchIncludingRemoved( + SearchCriteria sc, Filter filter, Boolean lock, + boolean cache) { + return null; + } + + @Override + public List searchIncludingRemoved( + SearchCriteria sc, Filter filter, Boolean lock, + boolean cache, boolean enableQueryCache) { + return null; + } + + @Override + public List customSearchIncludingRemoved(SearchCriteria sc, + Filter filter) { + return null; + } + + @Override + public List listAllIncludingRemoved() { + return null; + } + + @Override + public List listAllIncludingRemoved(Filter filter) { + return null; + } + + @Override + public UsageEventVO persist(UsageEventVO entity) { + persistedItems.add(entity); + return entity; + } + + @Override + public boolean remove(Long id) { + return false; + } + + @Override + public int remove(SearchCriteria sc) { + return 0; + } + + @Override + public boolean expunge(Long id) { + return false; + } + + @Override + public int expunge(SearchCriteria sc) { + return 0; + } + + @Override + public void expunge() { + + } + + @Override + public K getNextInSequence(Class clazz, String name) { + return null; + } + + @Override + public boolean configure(String name, Map params) + throws ConfigurationException { + return false; + } + + @Override + public List customSearch(SearchCriteria sc, Filter filter) { + return null; + } + + @Override + public boolean lockInLockTable(String id) { + return false; + } + + @Override + public boolean lockInLockTable(String id, int seconds) { + return false; + } + + @Override + public boolean unlockFromLockTable(String id) { + return false; + } + + @Override + public K getRandomlyIncreasingNextInSequence(Class clazz, String name) { + return null; + } + + @Override + public UsageEventVO findOneBy(SearchCriteria sc) { + return null; + } + + @Override + public Class getEntityBeanType() { + return null; + } + + @Override + public Pair, Integer> searchAndCount( + SearchCriteria sc, Filter filter) { + return null; + } + + @Override + public Pair, Integer> searchAndDistinctCount(SearchCriteria sc, Filter filter) { + return null; + } + + @Override + public Map getAllAttributes() { + return null; + } + + @Override + public List listLatestEvents(Date endDate) { + return null; + } + + @Override + public List getLatestEvent() { + return null; + } + + @Override + public List getRecentEvents(Date endDate) { + return null; + } + + @Override + public List listDirectIpEvents(Date startDate, Date endDate, + long zoneId) { + return null; + } + + @Override + public void saveDetails(long eventId, Map details) { + + } + +}