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

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


The following commit(s) were added to refs/heads/master by this push:
     new 32807cb  CLOUDSTACK-9958: Include tags of resources in 
listUsageRecords API (#2242)
32807cb is described below

commit 32807cb88797572eadd885b3109d365b1a43b755
Author: mrunalinikankariya <[email protected]>
AuthorDate: Tue Nov 7 09:52:00 2017 +0530

    CLOUDSTACK-9958: Include tags of resources in listUsageRecords API (#2242)
    
    Tags field to be included in the listusagerecords response such that it can 
be used in billing report. E.g.
    "tags":[
    
{"key":"city","value":"Toronto","resourcetype":"UserVm","resourceid":"a0cca906-f985-4b56-ad11-f33e59c4c733","account":"admin","domainid":"dec39eb8-4f81-11e7-8315-067fa0000031","domain":"ROOT"}
    ,
    
{"key":"region","value":"canada","resourcetype":"UserVm","resourceid":"a0cca906-f985-4b56-ad11-f33e59c4c733","account":"admin","domainid":"dec39eb8-4f81-11e7-8315-067fa0000031","domain":"ROOT"}
---
 .../org/apache/cloudstack/api/ApiConstants.java    |  1 +
 .../apache/cloudstack/api/ResponseGenerator.java   |  5 ++
 .../command/admin/usage/GetUsageRecordsCmd.java    | 18 ++++++-
 .../api/response/UsageRecordResponse.java          | 15 +++++-
 .../src/com/cloud/tags/dao/ResourceTagDao.java     |  5 ++
 .../com/cloud/tags/dao/ResourceTagsDaoImpl.java    | 28 ++++++++++-
 server/src/com/cloud/api/ApiResponseHelper.java    | 57 ++++++++++++++++++++--
 7 files changed, 121 insertions(+), 8 deletions(-)

diff --git a/api/src/org/apache/cloudstack/api/ApiConstants.java 
b/api/src/org/apache/cloudstack/api/ApiConstants.java
index 2a2d686..2d5fe77 100644
--- a/api/src/org/apache/cloudstack/api/ApiConstants.java
+++ b/api/src/org/apache/cloudstack/api/ApiConstants.java
@@ -302,6 +302,7 @@ public class ApiConstants {
     public static final String VIRTUAL_MACHINE_COUNT = "virtualmachinecount";
     public static final String USAGE_ID = "usageid";
     public static final String USAGE_TYPE = "usagetype";
+    public static final String INCLUDE_TAGS = "includetags";
 
     public static final String VLAN = "vlan";
     public static final String VLAN_RANGE = "vlanrange";
diff --git a/api/src/org/apache/cloudstack/api/ResponseGenerator.java 
b/api/src/org/apache/cloudstack/api/ResponseGenerator.java
index 9fd4d84..7b33ebb 100644
--- a/api/src/org/apache/cloudstack/api/ResponseGenerator.java
+++ b/api/src/org/apache/cloudstack/api/ResponseGenerator.java
@@ -20,6 +20,7 @@ import java.text.DecimalFormat;
 import java.util.EnumSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 import org.apache.cloudstack.affinity.AffinityGroup;
 import org.apache.cloudstack.affinity.AffinityGroupResponse;
@@ -430,6 +431,10 @@ public interface ResponseGenerator {
 
     UsageRecordResponse createUsageResponse(Usage usageRecord);
 
+    UsageRecordResponse createUsageResponse(Usage usageRecord, Map<String, 
Set<ResourceTagResponse>> resourceTagResponseMap);
+
+    public Map<String, Set<ResourceTagResponse>> getUsageResourceTags();
+
     TrafficMonitorResponse createTrafficMonitorResponse(Host trafficMonitor);
 
     VMSnapshotResponse createVMSnapshotResponse(VMSnapshot vmSnapshot);
diff --git 
a/api/src/org/apache/cloudstack/api/command/admin/usage/GetUsageRecordsCmd.java 
b/api/src/org/apache/cloudstack/api/command/admin/usage/GetUsageRecordsCmd.java
index 4cceb3b..90bc4f2 100644
--- 
a/api/src/org/apache/cloudstack/api/command/admin/usage/GetUsageRecordsCmd.java
+++ 
b/api/src/org/apache/cloudstack/api/command/admin/usage/GetUsageRecordsCmd.java
@@ -19,6 +19,8 @@ package org.apache.cloudstack.api.command.admin.usage;
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
+import java.util.Map;
+import java.util.Set;
 
 import org.apache.log4j.Logger;
 
@@ -31,6 +33,7 @@ import org.apache.cloudstack.api.response.DomainResponse;
 import org.apache.cloudstack.api.response.ListResponse;
 import org.apache.cloudstack.api.response.ProjectResponse;
 import org.apache.cloudstack.api.response.UsageRecordResponse;
+import org.apache.cloudstack.api.response.ResourceTagResponse;
 import org.apache.cloudstack.usage.Usage;
 
 import com.cloud.utils.Pair;
@@ -76,6 +79,9 @@ public class GetUsageRecordsCmd extends BaseListCmd {
     @Parameter(name = ApiConstants.USAGE_ID, type = CommandType.STRING, 
description = "List usage records for the specified usage UUID. Can be used 
only together with TYPE parameter.")
     private String usageId;
 
+    @Parameter(name = ApiConstants.INCLUDE_TAGS, type = CommandType.BOOLEAN, 
description = "Flag to enable display of Tags for a resource")
+    private Boolean includeTags;
+
     /////////////////////////////////////////////////////
     /////////////////// Accessors ///////////////////////
     /////////////////////////////////////////////////////
@@ -115,6 +121,10 @@ public class GetUsageRecordsCmd extends BaseListCmd {
         this.accountName = accountName;
     }
 
+    public Boolean getIncludeTags() {
+        return includeTags;
+    }
+
     public void setDomainId(Long domainId) {
         this.domainId = domainId;
     }
@@ -150,12 +160,18 @@ public class GetUsageRecordsCmd extends BaseListCmd {
         Pair<List<? extends Usage>, Integer> usageRecords = 
_usageService.getUsageRecords(this);
         ListResponse<UsageRecordResponse> response = new 
ListResponse<UsageRecordResponse>();
         List<UsageRecordResponse> usageResponses = new 
ArrayList<UsageRecordResponse>();
+        Map<String, Set<ResourceTagResponse>> resourceTagResponseMap = null;
         if (usageRecords != null) {
+            //read the resource tags details for all the resources in usage 
data and store in Map
+            if(null != includeTags && includeTags) {
+                resourceTagResponseMap =  
_responseGenerator.getUsageResourceTags();
+            }
             for (Usage usageRecord : usageRecords.first()) {
-                UsageRecordResponse usageResponse = 
_responseGenerator.createUsageResponse(usageRecord);
+                UsageRecordResponse usageResponse = 
_responseGenerator.createUsageResponse(usageRecord, resourceTagResponseMap);
                 usageResponse.setObjectName("usagerecord");
                 usageResponses.add(usageResponse);
             }
+
             response.setResponses(usageResponses, usageRecords.second());
         }
 
diff --git 
a/api/src/org/apache/cloudstack/api/response/UsageRecordResponse.java 
b/api/src/org/apache/cloudstack/api/response/UsageRecordResponse.java
index e51475b..c53f2b9 100644
--- a/api/src/org/apache/cloudstack/api/response/UsageRecordResponse.java
+++ b/api/src/org/apache/cloudstack/api/response/UsageRecordResponse.java
@@ -19,12 +19,15 @@ package org.apache.cloudstack.api.response;
 import com.google.gson.annotations.SerializedName;
 
 import org.apache.cloudstack.api.ApiConstants;
-import org.apache.cloudstack.api.BaseResponse;
 
 import com.cloud.serializer.Param;
+import org.apache.cloudstack.api.BaseResponseWithTagInformation;
+
+import java.util.LinkedHashSet;
+import java.util.Set;
 
 @SuppressWarnings("unused")
-public class UsageRecordResponse extends BaseResponse implements 
ControlledEntityResponse {
+public class UsageRecordResponse extends BaseResponseWithTagInformation 
implements ControlledEntityResponse {
     @SerializedName(ApiConstants.ACCOUNT)
     @Param(description = "the user account name")
     private String accountName;
@@ -137,6 +140,14 @@ public class UsageRecordResponse extends BaseResponse 
implements ControlledEntit
     @Param(description = "True if the resource is default")
     private Boolean isDefault;
 
+    public UsageRecordResponse() {
+        tags = new LinkedHashSet<ResourceTagResponse>();
+    }
+
+    public void setTags(Set<ResourceTagResponse> tags) {
+        this.tags = tags;
+    }
+
     @Override
     public void setAccountName(String accountName) {
         this.accountName = accountName;
diff --git a/engine/schema/src/com/cloud/tags/dao/ResourceTagDao.java 
b/engine/schema/src/com/cloud/tags/dao/ResourceTagDao.java
index 87662ef..b788434 100644
--- a/engine/schema/src/com/cloud/tags/dao/ResourceTagDao.java
+++ b/engine/schema/src/com/cloud/tags/dao/ResourceTagDao.java
@@ -17,11 +17,14 @@
 package com.cloud.tags.dao;
 
 import java.util.List;
+import java.util.Map;
+import java.util.Set;
 
 import com.cloud.server.ResourceTag;
 import com.cloud.server.ResourceTag.ResourceObjectType;
 import com.cloud.tags.ResourceTagVO;
 import com.cloud.utils.db.GenericDao;
+import org.apache.cloudstack.api.response.ResourceTagResponse;
 
 public interface ResourceTagDao extends GenericDao<ResourceTagVO, Long> {
 
@@ -35,4 +38,6 @@ public interface ResourceTagDao extends 
GenericDao<ResourceTagVO, Long> {
     List<? extends ResourceTag> listBy(long resourceId, ResourceObjectType 
resourceType);
 
     void updateResourceId(long srcId, long destId, ResourceObjectType 
resourceType);
+
+    Map<String, Set<ResourceTagResponse>> listTags();
 }
diff --git a/engine/schema/src/com/cloud/tags/dao/ResourceTagsDaoImpl.java 
b/engine/schema/src/com/cloud/tags/dao/ResourceTagsDaoImpl.java
index 0e23eff..d5578a8 100644
--- a/engine/schema/src/com/cloud/tags/dao/ResourceTagsDaoImpl.java
+++ b/engine/schema/src/com/cloud/tags/dao/ResourceTagsDaoImpl.java
@@ -17,8 +17,12 @@
 package com.cloud.tags.dao;
 
 import java.util.List;
+import java.util.Set;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.HashSet;
 
-
+import org.apache.cloudstack.api.response.ResourceTagResponse;
 import org.springframework.stereotype.Component;
 
 import com.cloud.server.ResourceTag;
@@ -67,4 +71,26 @@ public class ResourceTagsDaoImpl extends 
GenericDaoBase<ResourceTagVO, Long> imp
             update(tag.getId(), tag);
         }
     }
+
+    @Override
+    public Map<String, Set<ResourceTagResponse>> listTags() {
+        SearchCriteria<ResourceTagVO> sc = AllFieldsSearch.create();
+        List<ResourceTagVO> resourceTagList = listBy(sc);
+        Map<String, Set<ResourceTagResponse>> resourceTagMap = new HashMap();
+        String resourceKey = null;
+        ResourceTagResponse resourceTagResponse = null;
+        for (ResourceTagVO resourceTagVO : resourceTagList) {
+            resourceTagResponse = new ResourceTagResponse();
+            resourceTagResponse.setKey(resourceTagVO.getKey());
+            resourceTagResponse.setValue(resourceTagVO.getValue());
+            Set<ResourceTagResponse> resourceTagSet = new HashSet();
+            resourceKey = resourceTagVO.getResourceId() + ":" + 
resourceTagVO.getResourceType();
+            if(resourceTagMap.get(resourceKey) != null) {
+                resourceTagSet = resourceTagMap.get(resourceKey);
+            }
+            resourceTagSet.add(resourceTagResponse);
+            resourceTagMap.put(resourceKey, resourceTagSet);
+        }
+        return resourceTagMap;
+    }
 }
diff --git a/server/src/com/cloud/api/ApiResponseHelper.java 
b/server/src/com/cloud/api/ApiResponseHelper.java
index 82f9397..99f1b47 100644
--- a/server/src/com/cloud/api/ApiResponseHelper.java
+++ b/server/src/com/cloud/api/ApiResponseHelper.java
@@ -17,6 +17,7 @@
 package com.cloud.api;
 
 import com.cloud.utils.crypt.DBEncryptionUtil;
+import com.cloud.tags.dao.ResourceTagDao;
 import com.cloud.agent.api.VgpuTypesInfo;
 import com.cloud.api.query.ViewResponseHelper;
 import com.cloud.api.query.vo.AccountJoinVO;
@@ -346,6 +347,8 @@ public class ApiResponseHelper implements ResponseGenerator 
{
     private PrimaryDataStoreDao _storagePoolDao;
     @Inject
     private ClusterDetailsDao _clusterDetailsDao;
+    @Inject
+    private ResourceTagDao _resourceTagDao;
 
     @Override
     public UserResponse createUserResponse(User user) {
@@ -3193,9 +3196,24 @@ public class ApiResponseHelper implements 
ResponseGenerator {
     }
 
     @Override
+    public Map<String, Set<ResourceTagResponse>> getUsageResourceTags()
+    {
+        try {
+            return _resourceTagDao.listTags();
+        } catch(Exception ex) {
+            s_logger.warn("Failed to get resource details for Usage data due 
to exception : ", ex);
+        }
+        return null;
+    }
+
+    @Override
     public UsageRecordResponse createUsageResponse(Usage usageRecord) {
-        UsageRecordResponse usageRecResponse = new UsageRecordResponse();
+        return createUsageResponse(usageRecord, null);
+    }
 
+    @Override
+    public UsageRecordResponse createUsageResponse(Usage usageRecord, 
Map<String, Set<ResourceTagResponse>> resourceTagResponseMap) {
+        UsageRecordResponse usageRecResponse = new UsageRecordResponse();
         Account account = 
ApiDBUtils.findAccountById(usageRecord.getAccountId());
         if (account.getType() == Account.ACCOUNT_TYPE_PROJECT) {
             //find the project
@@ -3238,14 +3256,20 @@ public class ApiResponseHelper implements 
ResponseGenerator {
             }
         }
 
+        ResourceTag.ResourceObjectType resourceType = null;
+        Long resourceId = null;
         if (usageRecord.getUsageType() == UsageTypes.RUNNING_VM || 
usageRecord.getUsageType() == UsageTypes.ALLOCATED_VM) {
             ServiceOfferingVO svcOffering = 
_entityMgr.findByIdIncludingRemoved(ServiceOfferingVO.class, 
usageRecord.getOfferingId().toString());
             //Service Offering Id
-            usageRecResponse.setOfferingId(svcOffering.getUuid());
+            if(svcOffering != null) {
+                usageRecResponse.setOfferingId(svcOffering.getUuid());
+            }
             //VM Instance ID
             VMInstanceVO vm = 
_entityMgr.findByIdIncludingRemoved(VMInstanceVO.class, 
usageRecord.getUsageId().toString());
             if (vm != null) {
+                resourceType = ResourceTag.ResourceObjectType.UserVm;
                 usageRecResponse.setUsageId(vm.getUuid());
+                resourceId = vm.getId();
             }
             //Hypervisor Type
             usageRecResponse.setType(usageRecord.getType());
@@ -3274,16 +3298,20 @@ public class ApiResponseHelper implements 
ResponseGenerator {
             //IP Address ID
             IPAddressVO ip = 
_entityMgr.findByIdIncludingRemoved(IPAddressVO.class, 
usageRecord.getUsageId().toString());
             if (ip != null) {
+                resourceType = ResourceObjectType.PublicIpAddress;
+                resourceId = ip.getId();
                 usageRecResponse.setUsageId(ip.getUuid());
             }
 
         } else if (usageRecord.getUsageType() == UsageTypes.NETWORK_BYTES_SENT 
|| usageRecord.getUsageType() == UsageTypes.NETWORK_BYTES_RECEIVED) {
             //Device Type
+            resourceType = ResourceObjectType.UserVm;
             usageRecResponse.setType(usageRecord.getType());
             if (usageRecord.getType().equals("DomainRouter") || 
usageRecord.getType().equals("UserVm")) {
                 //Domain Router Id
                 VMInstanceVO vm = 
_entityMgr.findByIdIncludingRemoved(VMInstanceVO.class, 
usageRecord.getUsageId().toString());
                 if (vm != null) {
+                    resourceId = vm.getId();
                     usageRecResponse.setUsageId(vm.getUuid());
                 }
             } else {
@@ -3297,14 +3325,16 @@ public class ApiResponseHelper implements 
ResponseGenerator {
             if((usageRecord.getNetworkId() != null) && 
(usageRecord.getNetworkId() != 0)) {
                 NetworkVO network = 
_entityMgr.findByIdIncludingRemoved(NetworkVO.class, 
usageRecord.getNetworkId().toString());
                 if (network != null) {
+                    resourceType = ResourceObjectType.Network;
+                    resourceId = network.getId();
                     usageRecResponse.setNetworkId(network.getUuid());
                 }
             }
-
         } else if (usageRecord.getUsageType() == UsageTypes.VM_DISK_IO_READ || 
usageRecord.getUsageType() == UsageTypes.VM_DISK_IO_WRITE
                 || usageRecord.getUsageType() == UsageTypes.VM_DISK_BYTES_READ 
|| usageRecord.getUsageType() == UsageTypes.VM_DISK_BYTES_WRITE) {
             //Device Type
             usageRecResponse.setType(usageRecord.getType());
+            resourceType = ResourceObjectType.Volume;
             //VM Instance Id
             VMInstanceVO vm = 
_entityMgr.findByIdIncludingRemoved(VMInstanceVO.class, 
usageRecord.getVmInstanceId().toString());
             if (vm != null) {
@@ -3314,13 +3344,16 @@ public class ApiResponseHelper implements 
ResponseGenerator {
             VolumeVO volume = 
_entityMgr.findByIdIncludingRemoved(VolumeVO.class, 
usageRecord.getUsageId().toString());
             if (volume != null) {
                 usageRecResponse.setUsageId(volume.getUuid());
+                resourceId = volume.getId();
             }
 
         } else if (usageRecord.getUsageType() == UsageTypes.VOLUME) {
             //Volume ID
             VolumeVO volume = 
_entityMgr.findByIdIncludingRemoved(VolumeVO.class, 
usageRecord.getUsageId().toString());
+            resourceType = ResourceObjectType.Volume;
             if (volume != null) {
                 usageRecResponse.setUsageId(volume.getUuid());
+                resourceId = volume.getId();
             }
             //Volume Size
             usageRecResponse.setSize(usageRecord.getSize());
@@ -3335,20 +3368,25 @@ public class ApiResponseHelper implements 
ResponseGenerator {
             VMTemplateVO tmpl = 
_entityMgr.findByIdIncludingRemoved(VMTemplateVO.class, 
usageRecord.getUsageId().toString());
             if (tmpl != null) {
                 usageRecResponse.setUsageId(tmpl.getUuid());
+                resourceId = tmpl.getId();
             }
             //Template/ISO Size
             usageRecResponse.setSize(usageRecord.getSize());
             if (usageRecord.getUsageType() == UsageTypes.ISO) {
                 usageRecResponse.setVirtualSize(usageRecord.getSize());
+                resourceType = ResourceObjectType.ISO;
             } else {
                 usageRecResponse.setVirtualSize(usageRecord.getVirtualSize());
+                resourceType = ResourceObjectType.Template;
             }
 
         } else if (usageRecord.getUsageType() == UsageTypes.SNAPSHOT) {
             //Snapshot ID
             SnapshotVO snap = 
_entityMgr.findByIdIncludingRemoved(SnapshotVO.class, 
usageRecord.getUsageId().toString());
+            resourceType = ResourceObjectType.Snapshot;
             if (snap != null) {
                 usageRecResponse.setUsageId(snap.getUuid());
+                resourceId = snap.getId();
             }
             //Snapshot Size
             usageRecResponse.setSize(usageRecord.getSize());
@@ -3356,14 +3394,18 @@ public class ApiResponseHelper implements 
ResponseGenerator {
         } else if (usageRecord.getUsageType() == 
UsageTypes.LOAD_BALANCER_POLICY) {
             //Load Balancer Policy ID
             LoadBalancerVO lb = 
_entityMgr.findByIdIncludingRemoved(LoadBalancerVO.class, 
usageRecord.getUsageId().toString());
+            resourceType = ResourceObjectType.LoadBalancer;
             if (lb != null) {
                 usageRecResponse.setUsageId(lb.getUuid());
+                resourceId = lb.getId();
             }
         } else if (usageRecord.getUsageType() == 
UsageTypes.PORT_FORWARDING_RULE) {
             //Port Forwarding Rule ID
             PortForwardingRuleVO pf = 
_entityMgr.findByIdIncludingRemoved(PortForwardingRuleVO.class, 
usageRecord.getUsageId().toString());
+            resourceType = ResourceObjectType.PortForwardingRule;
             if (pf != null) {
                 usageRecResponse.setUsageId(pf.getUuid());
+                resourceId = pf.getId();
             }
 
         } else if (usageRecord.getUsageType() == UsageTypes.NETWORK_OFFERING) {
@@ -3379,16 +3421,19 @@ public class ApiResponseHelper implements 
ResponseGenerator {
             if (vpnUser != null) {
                 usageRecResponse.setUsageId(vpnUser.getUuid());
             }
-
         } else if (usageRecord.getUsageType() == UsageTypes.SECURITY_GROUP) {
             //Security Group Id
             SecurityGroupVO sg = 
_entityMgr.findByIdIncludingRemoved(SecurityGroupVO.class, 
usageRecord.getUsageId().toString());
+            resourceType = ResourceObjectType.SecurityGroup;
             if (sg != null) {
+                resourceId = sg.getId();
                 usageRecResponse.setUsageId(sg.getUuid());
             }
         } else if (usageRecord.getUsageType() == UsageTypes.VM_SNAPSHOT) {
             VMInstanceVO vm = 
_entityMgr.findByIdIncludingRemoved(VMInstanceVO.class, 
usageRecord.getVmInstanceId().toString());
+            resourceType = ResourceObjectType.UserVm;
             if (vm != null) {
+                resourceId = vm.getId();
                 usageRecResponse.setVmName(vm.getInstanceName());
                 usageRecResponse.setUsageId(vm.getUuid());
             }
@@ -3398,6 +3443,10 @@ public class ApiResponseHelper implements 
ResponseGenerator {
             }
         }
 
+        if(resourceTagResponseMap != null && 
resourceTagResponseMap.get(resourceId + ":" + resourceType) != null) {
+             usageRecResponse.setTags(resourceTagResponseMap.get(resourceId + 
":" + resourceType));
+        }
+
         if (usageRecord.getRawUsage() != null) {
             DecimalFormat decimalFormat = new 
DecimalFormat("###########.######");
             
usageRecResponse.setRawUsage(decimalFormat.format(usageRecord.getRawUsage()));

-- 
To stop receiving notification emails like this one, please contact
['"[email protected]" <[email protected]>'].

Reply via email to