diff --git a/usage/pom.xml b/usage/pom.xml
index 119f47d9d0b..1e78bc178f6 100644
--- a/usage/pom.xml
+++ b/usage/pom.xml
@@ -75,11 +75,6 @@
org.apache.maven.plugins
maven-surefire-plugin
-
-
- com/cloud/usage/UsageManagerTest.java
-
-
org.apache.maven.plugins
diff --git a/usage/src/main/java/com/cloud/usage/UsageManagerImpl.java b/usage/src/main/java/com/cloud/usage/UsageManagerImpl.java
index 98b94e4c86e..9514ac04f2c 100644
--- a/usage/src/main/java/com/cloud/usage/UsageManagerImpl.java
+++ b/usage/src/main/java/com/cloud/usage/UsageManagerImpl.java
@@ -37,6 +37,7 @@ import org.apache.cloudstack.quota.QuotaAlertManager;
import org.apache.cloudstack.quota.QuotaManager;
import org.apache.cloudstack.quota.QuotaStatement;
import org.apache.cloudstack.utils.usage.UsageUtils;
+import org.apache.commons.collections.CollectionUtils;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
@@ -990,7 +991,7 @@ public class UsageManagerImpl extends ManagerBase implements UsageManager, Runna
} else if (isNetworkOfferingEvent(eventType)) {
createNetworkOfferingEvent(event);
} else if (isVPNUserEvent(eventType)) {
- createVPNUserEvent(event);
+ handleVpnUserEvent(event);
} else if (isSecurityGroupEvent(eventType)) {
createSecurityGroupEvent(event);
} else if (isVmSnapshotEvent(eventType)) {
@@ -1766,39 +1767,92 @@ public class UsageManagerImpl extends ManagerBase implements UsageManager, Runna
}
}
- private void createVPNUserEvent(UsageEventVO event) {
-
- long zoneId = 0L;
-
+ /**
+ * Handles VPN user create and remove events:
+ *
+ * - EventTypes#EVENT_VPN_USER_ADD
+ * - EventTypes#EVENT_VPN_USER_ADD
+ *
+ * if the event received by this method is neither add nor remove, we ignore it.
+ */
+ protected void handleVpnUserEvent(UsageEventVO event) {
+ long accountId = event.getAccountId();
+ Account account = _accountDao.findByIdIncludingRemoved(accountId);
+ long zoneId = event.getZoneId();
long userId = event.getResourceId();
- if (EventTypes.EVENT_VPN_USER_ADD.equals(event.getType())) {
- if (s_logger.isDebugEnabled()) {
- s_logger.debug("Creating VPN user: " + userId + " for account: " + event.getAccountId());
- }
- Account acct = _accountDao.findByIdIncludingRemoved(event.getAccountId());
- String userName = event.getResourceName();
- UsageVPNUserVO vpnUser = new UsageVPNUserVO(zoneId, event.getAccountId(), acct.getDomainId(), userId, userName, event.getCreateDate(), null);
- _usageVPNUserDao.persist(vpnUser);
- } else if (EventTypes.EVENT_VPN_USER_REMOVE.equals(event.getType())) {
- SearchCriteria sc = _usageVPNUserDao.createSearchCriteria();
- sc.addAnd("accountId", SearchCriteria.Op.EQ, event.getAccountId());
- sc.addAnd("userId", SearchCriteria.Op.EQ, userId);
- sc.addAnd("deleted", SearchCriteria.Op.NULL);
- List vuVOs = _usageVPNUserDao.search(sc, null);
- if (vuVOs.size() > 1) {
- s_logger.warn("More that one usage entry for vpn user: " + userId + " assigned to account: " + event.getAccountId() + "; marking them all as deleted...");
- }
- for (UsageVPNUserVO vuVO : vuVOs) {
- if (s_logger.isDebugEnabled()) {
- s_logger.debug("deleting vpn user: " + vuVO.getUserId());
- }
- vuVO.setDeleted(event.getCreateDate()); // there really shouldn't be more than one
- _usageVPNUserDao.update(vuVO);
- }
+ switch (event.getType()) {
+ case EventTypes.EVENT_VPN_USER_ADD:
+ createUsageVpnUser(event, account);
+ break;
+ case EventTypes.EVENT_VPN_USER_REMOVE:
+ deleteUsageVpnUser(event, account);
+ break;
+ default:
+ s_logger.debug(String.format("The event [type=%s, zoneId=%s, accountId=%s, userId=%s, resourceName=%s, createDate=%s] is neither of type [%s] nor [%s]",
+ event.getType(), zoneId, accountId, userId, event.getResourceName(), event.getCreateDate(), EventTypes.EVENT_VPN_USER_ADD, EventTypes.EVENT_VPN_USER_REMOVE));
}
}
+ /**
+ * Find and delete, if exists, usage VPN user entries
+ */
+ protected void deleteUsageVpnUser(UsageEventVO event, Account account) {
+ long accountId = account.getId();
+ long userId = event.getResourceId();
+ long zoneId = event.getZoneId();
+ long domainId = account.getDomainId();
+
+ List usageVpnUsers = findUsageVpnUsers(accountId, zoneId, userId, domainId);
+
+ if (CollectionUtils.isEmpty(usageVpnUsers)) {
+ s_logger.warn(String.format("No usage entry for vpn user [%s] assigned to account [%s] domain [%s] and zone [%s] was found.",
+ userId, accountId, domainId, zoneId));
+ }
+ if (usageVpnUsers.size() > 1) {
+ s_logger.warn(String.format("More than one usage entry for vpn user [%s] assigned to account [%s] domain [%s] and zone [%s]; marking them all as deleted.", userId,
+ accountId, domainId, zoneId));
+ }
+ for (UsageVPNUserVO vpnUser : usageVpnUsers) {
+ s_logger.debug(String.format("Deleting vpn user [%s] assigned to account [%s] domain [%s] and zone [%s] that was created at [%s].", vpnUser.getUserId(),
+ vpnUser.getAccountId(), vpnUser.getDomainId(), vpnUser.getZoneId(), vpnUser.getCreated()));
+ vpnUser.setDeleted(new Date());
+ _usageVPNUserDao.update(vpnUser);
+ }
+ }
+
+ /**
+ * Creates an entry for the Usage VPN User.
+ * If there is already an entry in the database with the same accountId, domainId, userId and zoneId, we do not persist a new entry.
+ */
+ protected void createUsageVpnUser(UsageEventVO event, Account account) {
+ long accountId = account.getId();
+ long userId = event.getResourceId();
+ long zoneId = event.getZoneId();
+ long domainId = account.getDomainId();
+
+ List usageVpnUsers = findUsageVpnUsers(accountId, zoneId, userId, domainId);
+
+ if (usageVpnUsers.size() > 0) {
+ s_logger.debug(String.format("We do not need to create the usage VPN user [%s] assigned to account [%s] because it already exists.", userId, accountId));
+ } else {
+ s_logger.debug(String.format("Creating VPN user user [%s] assigned to account [%s] domain [%s], zone [%s], and created at [%s]", userId, accountId, domainId, zoneId,
+ event.getCreateDate()));
+ UsageVPNUserVO vpnUser = new UsageVPNUserVO(zoneId, accountId, domainId, userId, event.getResourceName(), event.getCreateDate(), null);
+ _usageVPNUserDao.persist(vpnUser);
+ }
+ }
+
+ protected List findUsageVpnUsers(long accountId, long zoneId, long userId, long domainId) {
+ SearchCriteria sc = _usageVPNUserDao.createSearchCriteria();
+ sc.addAnd("zoneId", SearchCriteria.Op.EQ, zoneId);
+ sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
+ sc.addAnd("domainId", SearchCriteria.Op.EQ, domainId);
+ sc.addAnd("userId", SearchCriteria.Op.EQ, userId);
+ sc.addAnd("deleted", SearchCriteria.Op.NULL);
+ return _usageVPNUserDao.search(sc, null);
+ }
+
private void createSecurityGroupEvent(UsageEventVO event) {
long zoneId = -1L;
diff --git a/usage/src/test/java/com/cloud/usage/UsageManagerImplTest.java b/usage/src/test/java/com/cloud/usage/UsageManagerImplTest.java
new file mode 100644
index 00000000000..499d187e4ef
--- /dev/null
+++ b/usage/src/test/java/com/cloud/usage/UsageManagerImplTest.java
@@ -0,0 +1,167 @@
+// 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.usage;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.Spy;
+
+import com.cloud.event.EventTypes;
+import com.cloud.event.UsageEventVO;
+import com.cloud.usage.dao.UsageVPNUserDao;
+import com.cloud.user.AccountVO;
+import com.cloud.user.dao.AccountDao;
+import org.mockito.junit.MockitoJUnitRunner;
+
+@RunWith(MockitoJUnitRunner.class)
+public class UsageManagerImplTest {
+
+ @Spy
+ @InjectMocks
+ private UsageManagerImpl usageManagerImpl;
+
+ @Mock
+ private UsageVPNUserDao usageVPNUserDaoMock;
+
+ @Mock
+ private AccountDao accountDaoMock;
+
+ @Mock
+ private UsageVPNUserVO vpnUserMock;
+
+ @Mock
+ private AccountVO accountMock;
+
+ @Mock
+ private UsageEventVO usageEventVOMock;
+
+ private long accountMockId = 1l;
+ private long acountDomainIdMock = 2l;
+
+ @Before
+ public void before() {
+ Mockito.when(accountMock.getId()).thenReturn(accountMockId);
+ Mockito.when(accountMock.getDomainId()).thenReturn(acountDomainIdMock);
+
+ Mockito.doReturn(accountMock).when(accountDaoMock).findByIdIncludingRemoved(Mockito.anyLong());
+
+ }
+
+ @Test
+ public void createUsageVpnUserTestUserExits() {
+ List vpnUsersMock = new ArrayList();
+ vpnUsersMock.add(vpnUserMock);
+
+ Mockito.doReturn(vpnUsersMock).when(usageManagerImpl).findUsageVpnUsers(Mockito.anyLong(), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyLong());
+
+ usageManagerImpl.createUsageVpnUser(usageEventVOMock, accountMock);
+
+ Mockito.verify(usageVPNUserDaoMock, Mockito.never()).persist(Mockito.any(UsageVPNUserVO.class));
+
+ }
+
+ @Test
+ public void createUsageVpnUserTestUserDoesNotExits() {
+ List vpnUsersMock = new ArrayList();
+
+ Mockito.doReturn(vpnUsersMock).when(usageManagerImpl).findUsageVpnUsers(Mockito.anyLong(), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyLong());
+ Mockito.doReturn(vpnUserMock).when(usageVPNUserDaoMock).persist(Mockito.any(UsageVPNUserVO.class));
+
+ usageManagerImpl.createUsageVpnUser(usageEventVOMock, accountMock);
+
+ Mockito.verify(usageVPNUserDaoMock, Mockito.times(1)).persist(Mockito.any(UsageVPNUserVO.class));
+
+ }
+
+ @Test
+ public void deleteUsageVpnUserNoUserFound() {
+ List vpnUsersMock = new ArrayList();
+
+ Mockito.doReturn(vpnUsersMock).when(usageManagerImpl).findUsageVpnUsers(Mockito.anyLong(), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyLong());
+
+ usageManagerImpl.deleteUsageVpnUser(usageEventVOMock, accountMock);
+
+ Mockito.verify(usageVPNUserDaoMock, Mockito.never()).update(Mockito.any(UsageVPNUserVO.class));
+ }
+
+ @Test
+ public void deleteUsageVpnUserOneUserFound() {
+ List vpnUsersMock = new ArrayList();
+ vpnUsersMock.add(vpnUserMock);
+
+ Mockito.doReturn(vpnUsersMock).when(usageManagerImpl).findUsageVpnUsers(Mockito.anyLong(), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyLong());
+ Mockito.doNothing().when(usageVPNUserDaoMock).update(Mockito.any(UsageVPNUserVO.class));
+
+ usageManagerImpl.deleteUsageVpnUser(usageEventVOMock, accountMock);
+
+ Mockito.verify(usageVPNUserDaoMock, Mockito.times(1)).update(Mockito.any(UsageVPNUserVO.class));
+ }
+
+ @Test
+ public void deleteUsageVpnUserMultipleUsersFound() {
+ List vpnUsersMock = new ArrayList();
+ vpnUsersMock.add(vpnUserMock);
+ vpnUsersMock.add(Mockito.mock(UsageVPNUserVO.class));
+ vpnUsersMock.add(Mockito.mock(UsageVPNUserVO.class));
+
+ Mockito.doReturn(vpnUsersMock).when(usageManagerImpl).findUsageVpnUsers(Mockito.anyLong(), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyLong());
+ Mockito.doNothing().when(usageVPNUserDaoMock).update(Mockito.any(UsageVPNUserVO.class));
+
+ usageManagerImpl.deleteUsageVpnUser(usageEventVOMock, accountMock);
+
+ Mockito.verify(usageVPNUserDaoMock, Mockito.times(3)).update(Mockito.any(UsageVPNUserVO.class));
+ }
+
+ @Test
+ public void handleVpnUserEventTestAddUser() {
+ Mockito.when(this.usageEventVOMock.getType()).thenReturn(EventTypes.EVENT_VPN_USER_ADD);
+ Mockito.doNothing().when(this.usageManagerImpl).createUsageVpnUser(usageEventVOMock, accountMock);
+
+ this.usageManagerImpl.handleVpnUserEvent(usageEventVOMock);
+
+ Mockito.verify(usageManagerImpl).createUsageVpnUser(usageEventVOMock, accountMock);
+ Mockito.verify(usageManagerImpl, Mockito.never()).deleteUsageVpnUser(usageEventVOMock, accountMock);
+ }
+
+ @Test
+ public void handleVpnUserEventTestRemoveUser() {
+ Mockito.when(this.usageEventVOMock.getType()).thenReturn(EventTypes.EVENT_VPN_USER_REMOVE);
+ Mockito.doNothing().when(this.usageManagerImpl).deleteUsageVpnUser(usageEventVOMock, accountMock);
+
+ this.usageManagerImpl.handleVpnUserEvent(usageEventVOMock);
+
+ Mockito.verify(usageManagerImpl, Mockito.never()).createUsageVpnUser(usageEventVOMock, accountMock);
+ Mockito.verify(usageManagerImpl).deleteUsageVpnUser(usageEventVOMock, accountMock);
+ }
+
+ @Test
+ public void handleVpnUserEventTestEventIsNeitherAddNorRemove() {
+ Mockito.when(this.usageEventVOMock.getType()).thenReturn("VPN.USER.UPDATE");
+
+ this.usageManagerImpl.handleVpnUserEvent(usageEventVOMock);
+
+ Mockito.verify(usageManagerImpl, Mockito.never()).createUsageVpnUser(usageEventVOMock,accountMock);
+ Mockito.verify(usageManagerImpl, Mockito.never()).deleteUsageVpnUser(usageEventVOMock, accountMock);
+ }
+}
\ No newline at end of file
diff --git a/usage/src/test/java/com/cloud/usage/UsageManagerTest.java b/usage/src/test/java/com/cloud/usage/UsageManagerTest.java
deleted file mode 100644
index 139b65d42db..00000000000
--- a/usage/src/test/java/com/cloud/usage/UsageManagerTest.java
+++ /dev/null
@@ -1,113 +0,0 @@
-// 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.usage;
-
-import java.util.Date;
-
-import javax.inject.Inject;
-import javax.naming.ConfigurationException;
-
-import junit.framework.TestCase;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.springframework.test.context.ContextConfiguration;
-import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
-
-import com.cloud.usage.parser.IPAddressUsageParser;
-import com.cloud.usage.parser.LoadBalancerUsageParser;
-import com.cloud.usage.parser.NetworkOfferingUsageParser;
-import com.cloud.usage.parser.NetworkUsageParser;
-import com.cloud.usage.parser.PortForwardingUsageParser;
-import com.cloud.usage.parser.SecurityGroupUsageParser;
-import com.cloud.usage.parser.StorageUsageParser;
-import com.cloud.usage.parser.VMInstanceUsageParser;
-import com.cloud.usage.parser.VPNUserUsageParser;
-import com.cloud.usage.parser.VmDiskUsageParser;
-import com.cloud.usage.parser.VolumeUsageParser;
-import com.cloud.user.AccountVO;
-import com.cloud.utils.component.ComponentContext;
-
-@RunWith(SpringJUnit4ClassRunner.class)
-@ContextConfiguration(locations = "classpath:/UsageManagerTestContext.xml")
-public class UsageManagerTest extends TestCase {
- @Inject
- UsageManagerImpl _usageMgr = null;
- @Inject
- VMInstanceUsageParser vmParser = null;
- @Inject
- IPAddressUsageParser ipParser = null;
- @Inject
- LoadBalancerUsageParser lbParser = null;
- @Inject
- NetworkOfferingUsageParser noParser = null;
- @Inject
- NetworkUsageParser netParser = null;
- @Inject
- VmDiskUsageParser vmdiskParser = null;
- @Inject
- PortForwardingUsageParser pfParser = null;
- @Inject
- SecurityGroupUsageParser sgParser = null;
- @Inject
- StorageUsageParser stParser = null;
- @Inject
- VolumeUsageParser volParser = null;
- @Inject
- VPNUserUsageParser vpnParser = null;
-
- Date startDate = null;
- Date endDate = null;
-
- @Before
- public void setup() throws Exception {
- System.setProperty("pid", "5678");
- ComponentContext.initComponentsLifeCycle();
- startDate = new Date();
- endDate = new Date(100000L + System.currentTimeMillis());
- }
-
- @Test
- public void testParse() throws ConfigurationException {
- UsageJobVO job = new UsageJobVO();
- _usageMgr.parse(job, System.currentTimeMillis(), 100000L + System.currentTimeMillis());
- }
-
- @Test
- public void testSchedule() throws ConfigurationException {
- _usageMgr.scheduleParse();
- }
-
- @Test
- public void testParsers() throws ConfigurationException {
- AccountVO account = new AccountVO();
- account.setId(2L);
- VMInstanceUsageParser.parse(account, startDate, endDate);
- IPAddressUsageParser.parse(account, startDate, endDate);
- LoadBalancerUsageParser.parse(account, startDate, endDate);
- NetworkOfferingUsageParser.parse(account, startDate, endDate);
- NetworkUsageParser.parse(account, startDate, endDate);
- VmDiskUsageParser.parse(account, startDate, endDate);
- PortForwardingUsageParser.parse(account, startDate, endDate);
- SecurityGroupUsageParser.parse(account, startDate, endDate);
- StorageUsageParser.parse(account, startDate, endDate);
- VolumeUsageParser.parse(account, startDate, endDate);
- VPNUserUsageParser.parse(account, startDate, endDate);
- }
-
-}