From aa570783e8ea108f49af664bd9982bcae2aa86d5 Mon Sep 17 00:00:00 2001 From: Alena Prokharchyk Date: Thu, 17 Oct 2013 14:56:55 -0700 Subject: [PATCH] Added resource tag support for Zone --- .../apache/cloudstack/api/ApiConstants.java | 2 +- .../offering/ListServiceOfferingsCmd.java | 4 +-- .../api/command/user/zone/ListZonesByCmd.java | 32 ++++++++++++++++--- .../api/response/ServiceOfferingResponse.java | 2 +- .../cloudstack/api/response/ZoneResponse.java | 15 +++++++++ .../com/cloud/api/query/QueryManagerImpl.java | 28 ++++++++++++++-- .../api/query/dao/DataCenterJoinDaoImpl.java | 20 ++++++++---- .../query/dao/ServiceOfferingJoinDaoImpl.java | 3 +- 8 files changed, 87 insertions(+), 19 deletions(-) diff --git a/api/src/org/apache/cloudstack/api/ApiConstants.java b/api/src/org/apache/cloudstack/api/ApiConstants.java index 62eed0908d4..e2f225d5fcc 100755 --- a/api/src/org/apache/cloudstack/api/ApiConstants.java +++ b/api/src/org/apache/cloudstack/api/ApiConstants.java @@ -518,7 +518,7 @@ public class ApiConstants { public static final String ROUTING = "isrouting"; public static final String MAX_CONNECTIONS = "maxconnections"; public static final String SERVICE_STATE = "servicestate"; - public static final String RESOURCE_TAG = "resourcetag"; + public static final String RESOURCE_TAGS = "resourcetags"; public enum HostDetails { all, capacity, events, stats, min; } diff --git a/api/src/org/apache/cloudstack/api/command/user/offering/ListServiceOfferingsCmd.java b/api/src/org/apache/cloudstack/api/command/user/offering/ListServiceOfferingsCmd.java index 06aad9d4732..2869d625cd2 100644 --- a/api/src/org/apache/cloudstack/api/command/user/offering/ListServiceOfferingsCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/offering/ListServiceOfferingsCmd.java @@ -25,12 +25,10 @@ import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseListCmd; import org.apache.cloudstack.api.Parameter; -import org.apache.cloudstack.api.BaseCmd.CommandType; import org.apache.cloudstack.api.response.DomainResponse; import org.apache.cloudstack.api.response.ListResponse; import org.apache.cloudstack.api.response.ServiceOfferingResponse; import org.apache.cloudstack.api.response.UserVmResponse; - import org.apache.log4j.Logger; import com.cloud.exception.InvalidParameterValueException; @@ -66,7 +64,7 @@ public class ListServiceOfferingsCmd extends BaseListCmd { @Parameter(name=ApiConstants.SYSTEM_VM_TYPE, type=CommandType.STRING, description="the system VM type. Possible types are \"consoleproxy\", \"secondarystoragevm\" or \"domainrouter\".") private String systemVmType; - @Parameter(name = ApiConstants.RESOURCE_TAG, type = CommandType.MAP, description = "List service offerings by resource tags (key/value pairs)", since="4.3") + @Parameter(name = ApiConstants.RESOURCE_TAGS, type = CommandType.MAP, description = "List service offerings by resource tags (key/value pairs)", since="4.3") private Map resourceTag; diff --git a/api/src/org/apache/cloudstack/api/command/user/zone/ListZonesByCmd.java b/api/src/org/apache/cloudstack/api/command/user/zone/ListZonesByCmd.java index 4cf3b58a0a8..2a98cfbe928 100644 --- a/api/src/org/apache/cloudstack/api/command/user/zone/ListZonesByCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/zone/ListZonesByCmd.java @@ -16,21 +16,21 @@ // under the License. package org.apache.cloudstack.api.command.user.zone; -import java.util.ArrayList; -import java.util.List; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseListCmd; import org.apache.cloudstack.api.Parameter; -import org.apache.cloudstack.api.BaseCmd.CommandType; import org.apache.cloudstack.api.response.DomainResponse; import org.apache.cloudstack.api.response.ListResponse; -import org.apache.cloudstack.api.response.ServiceOfferingResponse; import org.apache.cloudstack.api.response.ZoneResponse; import org.apache.log4j.Logger; -import com.cloud.dc.DataCenter; +import com.cloud.exception.InvalidParameterValueException; @APICommand(name = "listZones", description="Lists zones", responseObject=ZoneResponse.class) public class ListZonesByCmd extends BaseListCmd { @@ -62,6 +62,9 @@ public class ListZonesByCmd extends BaseListCmd { @Parameter(name=ApiConstants.SHOW_CAPACITIES, type=CommandType.BOOLEAN, description="flag to display the capacity of the zones") private Boolean showCapacities; + + @Parameter(name = ApiConstants.TAGS, type = CommandType.MAP, description = "List zones by resource tags (key/value pairs)", since="4.3") + private Map tags; ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// @@ -90,6 +93,25 @@ public class ListZonesByCmd extends BaseListCmd { public Boolean getShowCapacities() { return showCapacities; } + + public Map getTags() { + Map tagsMap = null; + if (tags != null && !tags.isEmpty()) { + tagsMap = new HashMap(); + Collection servicesCollection = tags.values(); + Iterator iter = servicesCollection.iterator(); + while (iter.hasNext()) { + HashMap services = (HashMap) iter.next(); + String key = services.get("key"); + String value = services.get("value"); + if (value == null) { + throw new InvalidParameterValueException("No value is passed in for key " + key); + } + tagsMap.put(key, value); + } + } + return tagsMap; + } ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// diff --git a/api/src/org/apache/cloudstack/api/response/ServiceOfferingResponse.java b/api/src/org/apache/cloudstack/api/response/ServiceOfferingResponse.java index d6838402b3c..204de3bc2b1 100644 --- a/api/src/org/apache/cloudstack/api/response/ServiceOfferingResponse.java +++ b/api/src/org/apache/cloudstack/api/response/ServiceOfferingResponse.java @@ -107,7 +107,7 @@ public class ServiceOfferingResponse extends BaseResponse { @Param(description = "additional key/value details tied with this service offering", since = "4.2.0") private Map details; - @SerializedName(ApiConstants.RESOURCE_TAG) @Param(description="the list of resource tags associated with service offering." + + @SerializedName(ApiConstants.RESOURCE_TAGS) @Param(description="the list of resource tags associated with service offering." + " The resource tags are not used for Volume/VM placement on the specific host.", responseObject = ResourceTagResponse.class, since="4.3") private Set resourceTags; diff --git a/api/src/org/apache/cloudstack/api/response/ZoneResponse.java b/api/src/org/apache/cloudstack/api/response/ZoneResponse.java index 2ebb15a1ecf..85f9ecfe474 100644 --- a/api/src/org/apache/cloudstack/api/response/ZoneResponse.java +++ b/api/src/org/apache/cloudstack/api/response/ZoneResponse.java @@ -16,7 +16,9 @@ // under the License. package org.apache.cloudstack.api.response; +import java.util.LinkedHashSet; import java.util.List; +import java.util.Set; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseResponse; @@ -98,6 +100,15 @@ public class ZoneResponse extends BaseResponse { @SerializedName(ApiConstants.LOCAL_STORAGE_ENABLED) @Param(description="true if local storage offering enabled, false otherwise") private boolean localStorageEnabled; + + @SerializedName(ApiConstants.TAGS) @Param(description="the list of resource tags associated with zone.", + responseObject = ResourceTagResponse.class, since="4.3") + private Set tags; + + + public ZoneResponse(){ + tags = new LinkedHashSet(); + } public void setId(String id) { this.id = id; @@ -198,4 +209,8 @@ public class ZoneResponse extends BaseResponse { public void setIp6Dns2(String ip6Dns2) { this.ip6Dns2 = ip6Dns2; } + + public void addTag(ResourceTagResponse tag){ + this.tags.add(tag); + } } diff --git a/server/src/com/cloud/api/query/QueryManagerImpl.java b/server/src/com/cloud/api/query/QueryManagerImpl.java index b464e9e5cdb..8edc2ebd1cf 100644 --- a/server/src/com/cloud/api/query/QueryManagerImpl.java +++ b/server/src/com/cloud/api/query/QueryManagerImpl.java @@ -2536,9 +2536,23 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { String keyword = cmd.getKeyword(); String name = cmd.getName(); String networkType = cmd.getNetworkType(); - + Map resourceTags = cmd.getTags(); + + SearchBuilder sb = _dcJoinDao.createSearchBuilder(); + if (resourceTags != null && !resourceTags.isEmpty()) { + SearchBuilder tagSearch = _resourceTagDao.createSearchBuilder(); + for (int count=0; count < resourceTags.size(); count++) { + tagSearch.or().op("key" + String.valueOf(count), tagSearch.entity().getKey(), SearchCriteria.Op.EQ); + tagSearch.and("value" + String.valueOf(count), tagSearch.entity().getValue(), SearchCriteria.Op.EQ); + tagSearch.cp(); + } + tagSearch.and("resourceType", tagSearch.entity().getResourceType(), SearchCriteria.Op.EQ); + sb.groupBy(sb.entity().getId()); + sb.join("tagSearch", tagSearch, sb.entity().getId(), tagSearch.entity().getResourceId(), JoinBuilder.JoinType.INNER); + } + Filter searchFilter = new Filter(DataCenterJoinVO.class, null, false, cmd.getStartIndex(), cmd.getPageSizeVal()); - SearchCriteria sc = _dcJoinDao.createSearchCriteria(); + SearchCriteria sc = sb.create(); if (networkType != null) { sc.addAnd("networkType", SearchCriteria.Op.EQ, networkType); @@ -2687,6 +2701,16 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { } } } + + if (resourceTags != null && !resourceTags.isEmpty()) { + int count = 0; + sc.setJoinParameters("tagSearch", "resourceType", TaggedResourceType.Zone.toString()); + for (String key : resourceTags.keySet()) { + sc.setJoinParameters("tagSearch", "key" + String.valueOf(count), key); + sc.setJoinParameters("tagSearch", "value" + String.valueOf(count), resourceTags.get(key)); + count++; + } + } return _dcJoinDao.searchAndCount(sc, searchFilter); } diff --git a/server/src/com/cloud/api/query/dao/DataCenterJoinDaoImpl.java b/server/src/com/cloud/api/query/dao/DataCenterJoinDaoImpl.java index edceb26666c..097824cb719 100644 --- a/server/src/com/cloud/api/query/dao/DataCenterJoinDaoImpl.java +++ b/server/src/com/cloud/api/query/dao/DataCenterJoinDaoImpl.java @@ -20,23 +20,23 @@ import java.util.List; import javax.ejb.Local; +import org.apache.cloudstack.api.response.ResourceTagResponse; +import org.apache.cloudstack.api.response.ZoneResponse; +import org.apache.cloudstack.context.CallContext; 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.DataCenterJoinVO; +import com.cloud.api.query.vo.ResourceTagJoinVO; import com.cloud.dc.DataCenter; - -import org.apache.cloudstack.api.response.ZoneResponse; -import org.apache.cloudstack.context.CallContext; - +import com.cloud.server.ResourceTag.TaggedResourceType; import com.cloud.user.Account; import com.cloud.utils.db.GenericDaoBase; import com.cloud.utils.db.SearchBuilder; import com.cloud.utils.db.SearchCriteria; -import org.springframework.stereotype.Component; - @Component @Local(value={DataCenterJoinDao.class}) public class DataCenterJoinDaoImpl extends GenericDaoBase implements DataCenterJoinDao { @@ -97,6 +97,14 @@ public class DataCenterJoinDaoImpl extends GenericDaoBase resourceTags = ApiDBUtils.listResourceTagViewByResourceUUID(dataCenter.getUuid(), TaggedResourceType.Zone); + for (ResourceTagJoinVO resourceTag : resourceTags) { + ResourceTagResponse tagResponse = ApiDBUtils.newResourceTagResponse(resourceTag, false); + zoneResponse.addTag(tagResponse); + } + zoneResponse.setObjectName("zone"); return zoneResponse; } diff --git a/server/src/com/cloud/api/query/dao/ServiceOfferingJoinDaoImpl.java b/server/src/com/cloud/api/query/dao/ServiceOfferingJoinDaoImpl.java index 8c32be3d13d..52c2e271a45 100644 --- a/server/src/com/cloud/api/query/dao/ServiceOfferingJoinDaoImpl.java +++ b/server/src/com/cloud/api/query/dao/ServiceOfferingJoinDaoImpl.java @@ -89,7 +89,8 @@ public class ServiceOfferingJoinDaoImpl extends GenericDaoBase resourceTags = ApiDBUtils.listResourceTagViewByResourceUUID(offering.getUuid(), TaggedResourceType.ServiceOffering); for (ResourceTagJoinVO resourceTag : resourceTags) { ResourceTagResponse tagResponse = ApiDBUtils.newResourceTagResponse(resourceTag, false); - offeringResponse.addTag(tagResponse); } + offeringResponse.addTag(tagResponse); + } return offeringResponse; }