From 7efce2a0f625b7144d0c0514d493227ecdd1ee2b Mon Sep 17 00:00:00 2001 From: Boris Schrijver Date: Tue, 11 Aug 2015 19:01:38 +0200 Subject: [PATCH 1/2] CLOUDSTACK-8133 Added Virtualmachine count and ID's to listSecurityGroups response. See issue CLOUDSTACK-8133 for more information. Added null check by comment of Koushik Das. Added brackets by comment of Wido den Hollander. Removed a call to findById() by comment of Koushik Das. --- .../apache/cloudstack/api/ApiConstants.java | 1 + .../api/response/SecurityGroupResponse.java | 24 +++++++++++++++-- .../query/dao/SecurityGroupJoinDaoImpl.java | 27 +++++++++++++++---- 3 files changed, 45 insertions(+), 7 deletions(-) diff --git a/api/src/org/apache/cloudstack/api/ApiConstants.java b/api/src/org/apache/cloudstack/api/ApiConstants.java index 0e7ff88d68b6..e86e2d4a9952 100644 --- a/api/src/org/apache/cloudstack/api/ApiConstants.java +++ b/api/src/org/apache/cloudstack/api/ApiConstants.java @@ -271,6 +271,7 @@ public class ApiConstants { public static final String VIRTUAL_MACHINE_ID = "virtualmachineid"; public static final String VIRTUAL_MACHINE_IDS = "virtualmachineids"; public static final String VIRTUAL_MACHINE_ID_IP = "vmidipmap"; + public static final String VIRTUAL_MACHINE_COUNT = "virtualmachinecount"; public static final String USAGE_ID = "usageid"; public static final String VLAN = "vlan"; diff --git a/api/src/org/apache/cloudstack/api/response/SecurityGroupResponse.java b/api/src/org/apache/cloudstack/api/response/SecurityGroupResponse.java index 0be2ee137bee..c96421b0a400 100644 --- a/api/src/org/apache/cloudstack/api/response/SecurityGroupResponse.java +++ b/api/src/org/apache/cloudstack/api/response/SecurityGroupResponse.java @@ -19,14 +19,13 @@ import java.util.LinkedHashSet; import java.util.Set; -import com.google.gson.annotations.SerializedName; - import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseResponse; import org.apache.cloudstack.api.EntityReference; import com.cloud.network.security.SecurityGroup; import com.cloud.serializer.Param; +import com.google.gson.annotations.SerializedName; @SuppressWarnings("unused") @EntityReference(value = SecurityGroup.class) @@ -76,7 +75,16 @@ public class SecurityGroupResponse extends BaseResponse implements ControlledVie @Param(description = "the list of resource tags associated with the rule", responseObject = ResourceTagResponse.class) private Set tags; + @SerializedName(ApiConstants.VIRTUAL_MACHINE_COUNT) + @Param(description = "the number of virtualmachines associated with this securitygroup", since = "4.6.0") + private Integer virtualMachineCount; + + @SerializedName(ApiConstants.VIRTUAL_MACHINE_IDS) + @Param(description = "the list of virtualmachine ids associated with this securitygroup", since = "4.6.0") + private Set virtualMachineIds; + public SecurityGroupResponse() { + this.virtualMachineIds = new LinkedHashSet(); this.ingressRules = new LinkedHashSet(); this.egressRules = new LinkedHashSet(); this.tags = new LinkedHashSet(); @@ -176,4 +184,16 @@ public void setTags(Set tags) { public void addTag(ResourceTagResponse tag) { this.tags.add(tag); } + + public void setVirtualMachineCount(Integer virtualMachineCount) { + this.virtualMachineCount = virtualMachineCount; + } + + public void setVirtualMachineIds(Set virtualMachineIds) { + this.virtualMachineIds = virtualMachineIds; + } + + public void addVirtualMachineId(String virtualMachineId) { + this.virtualMachineIds.add(virtualMachineId); + } } diff --git a/server/src/com/cloud/api/query/dao/SecurityGroupJoinDaoImpl.java b/server/src/com/cloud/api/query/dao/SecurityGroupJoinDaoImpl.java index bb4df1dd556f..1c544276e2d4 100644 --- a/server/src/com/cloud/api/query/dao/SecurityGroupJoinDaoImpl.java +++ b/server/src/com/cloud/api/query/dao/SecurityGroupJoinDaoImpl.java @@ -24,25 +24,28 @@ import javax.ejb.Local; import javax.inject.Inject; -import com.cloud.server.ResourceTag; import org.apache.cloudstack.api.response.ResourceTagResponse; -import org.apache.log4j.Logger; -import org.springframework.stereotype.Component; - import org.apache.cloudstack.api.response.SecurityGroupResponse; import org.apache.cloudstack.api.response.SecurityGroupRuleResponse; import org.apache.cloudstack.framework.config.dao.ConfigurationDao; +import org.apache.log4j.Logger; +import org.springframework.stereotype.Component; import com.cloud.api.ApiDBUtils; import com.cloud.api.ApiResponseHelper; import com.cloud.api.query.vo.ResourceTagJoinVO; import com.cloud.api.query.vo.SecurityGroupJoinVO; import com.cloud.network.security.SecurityGroup; +import com.cloud.network.security.SecurityGroupVMMapVO; import com.cloud.network.security.SecurityRule.SecurityRuleType; +import com.cloud.network.security.dao.SecurityGroupVMMapDao; +import com.cloud.server.ResourceTag; import com.cloud.user.Account; import com.cloud.utils.db.GenericDaoBase; import com.cloud.utils.db.SearchBuilder; import com.cloud.utils.db.SearchCriteria; +import com.cloud.vm.UserVmVO; +import com.cloud.vm.dao.UserVmDao; @Component @Local(value = {SecurityGroupJoinDao.class}) @@ -51,9 +54,12 @@ public class SecurityGroupJoinDaoImpl extends GenericDaoBase sgSearch; @@ -125,6 +131,17 @@ public SecurityGroupResponse newSecurityGroupResponse(SecurityGroupJoinVO vsg, A } } + List securityGroupVmMap = _securityGroupVMMapDao.listBySecurityGroup(vsg.getId()); + s_logger.debug("newSecurityGroupResponse() -> virtualmachine count: " + securityGroupVmMap.size()); + sgResponse.setVirtualMachineCount(securityGroupVmMap.size()); + + for(SecurityGroupVMMapVO securityGroupVMMapVO : securityGroupVmMap) { + final UserVmVO userVmVO = _userVmDao.findById(securityGroupVMMapVO.getInstanceId()); + if (userVmVO != null) { + sgResponse.addVirtualMachineId(userVmVO.getUuid()); + } + } + // update tag information Long tag_id = vsg.getTagId(); if (tag_id != null && tag_id.longValue() > 0) { From 6977473391b34ce7f79425f67791d363959c3f52 Mon Sep 17 00:00:00 2001 From: Boris Schrijver Date: Wed, 12 Aug 2015 16:00:07 +0200 Subject: [PATCH 2/2] Added unit tests for CLOUDSTACK-8133 Tests will confirm the behaviour of the newly added response fields of listSecurityGroups. --- .../dao/SecurityGroupJoinDaoImplTest.java | 205 ++++++++++++++++++ 1 file changed, 205 insertions(+) create mode 100644 server/test/com/cloud/api/query/dao/SecurityGroupJoinDaoImplTest.java diff --git a/server/test/com/cloud/api/query/dao/SecurityGroupJoinDaoImplTest.java b/server/test/com/cloud/api/query/dao/SecurityGroupJoinDaoImplTest.java new file mode 100644 index 000000000000..112504d623ce --- /dev/null +++ b/server/test/com/cloud/api/query/dao/SecurityGroupJoinDaoImplTest.java @@ -0,0 +1,205 @@ +// 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.api.query.dao; + +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.when; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import org.apache.cloudstack.api.response.SecurityGroupResponse; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.mockito.runners.MockitoJUnitRunner; + +import com.cloud.api.query.vo.ResourceTagJoinVO; +import com.cloud.api.query.vo.SecurityGroupJoinVO; +import com.cloud.network.security.SecurityGroupVMMapVO; +import com.cloud.network.security.dao.SecurityGroupVMMapDao; +import com.cloud.server.ResourceTag.ResourceObjectType; +import com.cloud.user.Account; +import com.cloud.vm.UserVmVO; +import com.cloud.vm.dao.UserVmDao; + +import junit.framework.TestCase; + +@RunWith(MockitoJUnitRunner.class) +public class SecurityGroupJoinDaoImplTest extends TestCase { + + // Mock private variables. + @Mock (name = "_resourceTagJoinDao") + private ResourceTagJoinDao _resourceTagJoinDao; + @Mock (name = "_securityGroupVMMapDao") + private SecurityGroupVMMapDao _securityGroupVMMapDao; + @Mock (name = "_userVmDao") + private UserVmDao _userVmDao; + + // Inject mocks in class to be tested. + @InjectMocks + private SecurityGroupJoinDaoImpl _securityGroupJoinDaoImpl; + + // Mock a caller and a SecurityGroupJoinVO + @Mock + private Account caller; + @Mock + private SecurityGroupJoinVO vsg; + + // Mock securitygroups + @Mock + private SecurityGroupVMMapVO securityGroupVMMapVOone; + @Mock + private SecurityGroupVMMapVO securityGroupVMMapVOtwo; + + // Mock 2 UserVmVOs + @Mock + private UserVmVO userVmVOone; + @Mock + private UserVmVO userVmVOtwo; + + // Random generated UUIDs + private final String uuidOne = "463e022a-249d-4212-bdf4-726bc9047aa7"; + private final String uuidTwo = "d8714c5f-766f-4b14-bdf4-17571042b9c5"; + + @Before + public void setup() { + MockitoAnnotations.initMocks(this); + + // Security group without vms associated. + List securityGroupVmMap_empty = new ArrayList(); + + // Security group with one vm associated. + List securityGroupVmMap_one = new ArrayList(); + securityGroupVmMap_one.add(securityGroupVMMapVOone); + + // Security group with two or many vms associated + List securityGroupVmMap_two = new ArrayList(); + securityGroupVmMap_two.add(securityGroupVMMapVOone); + securityGroupVmMap_two.add(securityGroupVMMapVOtwo); + + // Mock the resource tags to return an empty list. + when(_resourceTagJoinDao.listBy(anyString(), any(ResourceObjectType.class))).thenReturn(new ArrayList()); + + // Mock the listBySecurityGroup method to return a specified list when being called. + when(_securityGroupVMMapDao.listBySecurityGroup(1L)).thenReturn(securityGroupVmMap_empty); + when(_securityGroupVMMapDao.listBySecurityGroup(2L)).thenReturn(securityGroupVmMap_one); + when(_securityGroupVMMapDao.listBySecurityGroup(3L)).thenReturn(securityGroupVmMap_two); + + // Mock the securityGroupVMMapVOs to return a specified instance id. + when(securityGroupVMMapVOone.getInstanceId()).thenReturn(1L); + when(securityGroupVMMapVOtwo.getInstanceId()).thenReturn(2L); + + // Mock _userVmDao to return a non null instance of UserVmVO. + when(_userVmDao.findById(1L)).thenReturn(userVmVOone); + when(_userVmDao.findById(2L)).thenReturn(userVmVOtwo); + + // Mock _userVmDao to return a non null instance of UserVmVO. + when(userVmVOone.getUuid()).thenReturn(uuidOne); + when(userVmVOtwo.getUuid()).thenReturn(uuidTwo); + } + + @Test + public void virtualMachineCountEmptyTest() throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException { + + when(vsg.getId()).thenReturn(1L); + + SecurityGroupResponse securityGroupResponse = _securityGroupJoinDaoImpl.newSecurityGroupResponse(vsg, caller); + + Field virtualMachineCount = securityGroupResponse.getClass().getDeclaredField("virtualMachineCount"); + virtualMachineCount.setAccessible(true); + assertEquals(0, ((Integer)virtualMachineCount.get(securityGroupResponse)).intValue()); + } + + @Test + public void virtualMachineCountOneTest() throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException { + + when(vsg.getId()).thenReturn(2L); + + SecurityGroupResponse securityGroupResponse = _securityGroupJoinDaoImpl.newSecurityGroupResponse(vsg, caller); + + Field virtualMachineCount = securityGroupResponse.getClass().getDeclaredField("virtualMachineCount"); + virtualMachineCount.setAccessible(true); + assertEquals(1, ((Integer)virtualMachineCount.get(securityGroupResponse)).intValue()); + } + + @Test + public void virtualMachineCountTwoTest() throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException { + + when(vsg.getId()).thenReturn(3L); + + SecurityGroupResponse securityGroupResponse = _securityGroupJoinDaoImpl.newSecurityGroupResponse(vsg, caller); + + Field virtualMachineCount = securityGroupResponse.getClass().getDeclaredField("virtualMachineCount"); + virtualMachineCount.setAccessible(true); + assertEquals(2, ((Integer)virtualMachineCount.get(securityGroupResponse)).intValue()); + } + + @Test + public void virtualMachineIDsEmptyTest() throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException { + + when(vsg.getId()).thenReturn(1L); + + SecurityGroupResponse securityGroupResponse = _securityGroupJoinDaoImpl.newSecurityGroupResponse(vsg, caller); + + Field fieldVirtualMachineIds = securityGroupResponse.getClass().getDeclaredField("virtualMachineIds"); + fieldVirtualMachineIds.setAccessible(true); + + Set virtualMachineIds = (Set)fieldVirtualMachineIds.get(securityGroupResponse); + + assertEquals(0, virtualMachineIds.size()); + } + + @Test + public void virtualMachineIDsOneTest() throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException { + + when(vsg.getId()).thenReturn(2L); + + SecurityGroupResponse securityGroupResponse = _securityGroupJoinDaoImpl.newSecurityGroupResponse(vsg, caller); + + Field fieldVirtualMachineIds = securityGroupResponse.getClass().getDeclaredField("virtualMachineIds"); + fieldVirtualMachineIds.setAccessible(true); + + Set virtualMachineIds = (Set)fieldVirtualMachineIds.get(securityGroupResponse); + + assertEquals(1, virtualMachineIds.size()); + assertTrue(virtualMachineIds.contains(uuidOne)); + } + + @Test + public void virtualMachineIDsTwoTest() throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException { + + when(vsg.getId()).thenReturn(3L); + + SecurityGroupResponse securityGroupResponse = _securityGroupJoinDaoImpl.newSecurityGroupResponse(vsg, caller); + + Field fieldVirtualMachineIds = securityGroupResponse.getClass().getDeclaredField("virtualMachineIds"); + fieldVirtualMachineIds.setAccessible(true); + + Set virtualMachineIds = (Set)fieldVirtualMachineIds.get(securityGroupResponse); + + assertEquals(2, virtualMachineIds.size()); + assertTrue(virtualMachineIds.contains(uuidOne)); + assertTrue(virtualMachineIds.contains(uuidTwo)); + } +} \ No newline at end of file