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]>'].