CLOUDSTACK-2599. Fix EC2 Rest to support tag related EC2 API's - CreateTags/DeleteTags/DescribeTags
Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/50339211 Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/50339211 Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/50339211 Branch: refs/heads/vmware-datamodel Commit: 503392119d515a81742e9c36d3f285afe2a960fb Parents: eb7c321 Author: Likitha Shetty <likitha.she...@citrix.com> Authored: Tue May 21 11:19:02 2013 +0530 Committer: Likitha Shetty <likitha.she...@citrix.com> Committed: Tue May 21 11:33:33 2013 +0530 ---------------------------------------------------------------------- .../com/cloud/bridge/service/EC2RestServlet.java | 91 ++++++++++ .../cloud/bridge/service/EC2SoapServiceImpl.java | 135 ++++++++------ 2 files changed, 168 insertions(+), 58 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cloudstack/blob/50339211/awsapi/src/com/cloud/bridge/service/EC2RestServlet.java ---------------------------------------------------------------------- diff --git a/awsapi/src/com/cloud/bridge/service/EC2RestServlet.java b/awsapi/src/com/cloud/bridge/service/EC2RestServlet.java index 6dd7a8c..6b634e8 100644 --- a/awsapi/src/com/cloud/bridge/service/EC2RestServlet.java +++ b/awsapi/src/com/cloud/bridge/service/EC2RestServlet.java @@ -35,8 +35,11 @@ import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.Enumeration; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Properties; +import java.util.Set; import java.util.UUID; import javax.inject.Inject; @@ -68,10 +71,12 @@ import com.amazon.ec2.CreateImageResponse; import com.amazon.ec2.CreateKeyPairResponse; import com.amazon.ec2.CreateSecurityGroupResponse; import com.amazon.ec2.CreateSnapshotResponse; +import com.amazon.ec2.CreateTagsResponse; import com.amazon.ec2.CreateVolumeResponse; import com.amazon.ec2.DeleteKeyPairResponse; import com.amazon.ec2.DeleteSecurityGroupResponse; import com.amazon.ec2.DeleteSnapshotResponse; +import com.amazon.ec2.DeleteTagsResponse; import com.amazon.ec2.DeleteVolumeResponse; import com.amazon.ec2.DeregisterImageResponse; import com.amazon.ec2.DescribeAvailabilityZonesResponse; @@ -82,6 +87,7 @@ import com.amazon.ec2.DescribeInstancesResponse; import com.amazon.ec2.DescribeKeyPairsResponse; import com.amazon.ec2.DescribeSecurityGroupsResponse; import com.amazon.ec2.DescribeSnapshotsResponse; +import com.amazon.ec2.DescribeTagsResponse; import com.amazon.ec2.DescribeVolumesResponse; import com.amazon.ec2.DetachVolumeResponse; import com.amazon.ec2.DisassociateAddressResponse; @@ -122,6 +128,7 @@ import com.cloud.bridge.service.core.ec2.EC2DescribeInstances; import com.cloud.bridge.service.core.ec2.EC2DescribeKeyPairs; import com.cloud.bridge.service.core.ec2.EC2DescribeSecurityGroups; import com.cloud.bridge.service.core.ec2.EC2DescribeSnapshots; +import com.cloud.bridge.service.core.ec2.EC2DescribeTags; import com.cloud.bridge.service.core.ec2.EC2DescribeVolumes; import com.cloud.bridge.service.core.ec2.EC2DisassociateAddress; import com.cloud.bridge.service.core.ec2.EC2Engine; @@ -143,6 +150,10 @@ import com.cloud.bridge.service.core.ec2.EC2SecurityGroup; import com.cloud.bridge.service.core.ec2.EC2SnapshotFilterSet; import com.cloud.bridge.service.core.ec2.EC2StartInstances; import com.cloud.bridge.service.core.ec2.EC2StopInstances; +import com.cloud.bridge.service.core.ec2.EC2TagKeyValue; +import com.cloud.bridge.service.core.ec2.EC2TagTypeId; +import com.cloud.bridge.service.core.ec2.EC2Tags; +import com.cloud.bridge.service.core.ec2.EC2TagsFilterSet; import com.cloud.bridge.service.core.ec2.EC2Volume; import com.cloud.bridge.service.core.ec2.EC2VolumeFilterSet; import com.cloud.bridge.service.exception.EC2ServiceException; @@ -294,6 +305,9 @@ public class EC2RestServlet extends HttpServlet { else if (action.equalsIgnoreCase( "ImportKeyPair" )) importKeyPair(request, response); else if (action.equalsIgnoreCase( "DeleteKeyPair" )) deleteKeyPair(request, response); else if (action.equalsIgnoreCase( "DescribeKeyPairs" )) describeKeyPairs(request, response); + else if (action.equalsIgnoreCase( "CreateTags" )) createTags(request, response); + else if (action.equalsIgnoreCase( "DeleteTags" )) deleteTags(request, response); + else if (action.equalsIgnoreCase( "DescribeTags" )) describeTags(request, response); else if (action.equalsIgnoreCase( "GetPasswordData" )) getPasswordData(request, response); else { logger.error("Unsupported action " + action); @@ -1824,6 +1838,83 @@ public class EC2RestServlet extends HttpServlet { serializeResponse(response, EC2Response); } + private void createTags(HttpServletRequest request, HttpServletResponse response) + throws ADBException, XMLStreamException, IOException { + EC2Tags ec2Request = createTagsRequest(request, response); + if (ec2Request == null) return; + CreateTagsResponse EC2Response = EC2SoapServiceImpl.toCreateTagsResponse( + ServiceProvider.getInstance().getEC2Engine().modifyTags( ec2Request, "create")); + serializeResponse(response, EC2Response); + } + + private void deleteTags(HttpServletRequest request, HttpServletResponse response) + throws ADBException, XMLStreamException, IOException { + EC2Tags ec2Request = createTagsRequest(request, response); + if (ec2Request == null) return; + DeleteTagsResponse EC2Response = EC2SoapServiceImpl.toDeleteTagsResponse( + ServiceProvider.getInstance().getEC2Engine().modifyTags( ec2Request, "delete")); + serializeResponse(response, EC2Response); + } + + private EC2Tags createTagsRequest(HttpServletRequest request, HttpServletResponse response) + throws IOException { + EC2Tags ec2Request = new EC2Tags(); + ArrayList<String> resourceIdList = new ArrayList<String>(); + Map<String, String> resourceTagList = new HashMap<String, String>(); + + int nCount = 1; + do { + String[] resourceIds = request.getParameterValues( "ResourceId." + nCount ); + if (resourceIds != null && resourceIds.length > 0) + resourceIdList.add(resourceIds[0]); + else break; + nCount++; + } while (true); + if ( resourceIdList.isEmpty() ) { + response.sendError(530, "At least one Resource is required" ); + return null; + } + ec2Request = EC2SoapServiceImpl.toResourceTypeAndIds(ec2Request, resourceIdList); + + nCount = 1; + do { + String[] tagKey = request.getParameterValues( "Tag." + nCount + ".Key" ); + if ( tagKey != null && tagKey.length > 0 ) { + String[] tagValue = request.getParameterValues( "Tag." + nCount + ".Value" ); + if ( tagValue != null && tagValue.length > 0 ) { + resourceTagList.put(tagKey[0], tagValue[0]); + } else + resourceTagList.put(tagKey[0], null); + } else break; + nCount++; + } while (true); + if ( resourceTagList.isEmpty() ) { + response.sendError(530, "At least one Tag is required" ); + return null; + } + ec2Request = EC2SoapServiceImpl.toResourceTag(ec2Request, resourceTagList); + + return ec2Request; + } + + private void describeTags(HttpServletRequest request, HttpServletResponse response) + throws ADBException, XMLStreamException, IOException { + EC2DescribeTags ec2Request = new EC2DescribeTags(); + + EC2Filter[] filterSet = extractFilters( request ); + if (null != filterSet) { + EC2TagsFilterSet tfs = new EC2TagsFilterSet(); + for( int i=0; i < filterSet.length; i++ ) + tfs.addFilter( filterSet[i] ); + ec2Request.setFilterSet( tfs ); + } + DescribeTagsResponse EC2Response = EC2SoapServiceImpl.toDescribeTagsResponse( + ServiceProvider.getInstance().getEC2Engine().describeTags( ec2Request)); + serializeResponse(response, EC2Response); + } + + + /** * This function implements the EC2 REST authentication algorithm. It uses the given * "AWSAccessKeyId" parameter to look up the Cloud.com account holder's secret key which is http://git-wip-us.apache.org/repos/asf/cloudstack/blob/50339211/awsapi/src/com/cloud/bridge/service/EC2SoapServiceImpl.java ---------------------------------------------------------------------- diff --git a/awsapi/src/com/cloud/bridge/service/EC2SoapServiceImpl.java b/awsapi/src/com/cloud/bridge/service/EC2SoapServiceImpl.java index cebac0b..9362b81 100644 --- a/awsapi/src/com/cloud/bridge/service/EC2SoapServiceImpl.java +++ b/awsapi/src/com/cloud/bridge/service/EC2SoapServiceImpl.java @@ -18,7 +18,10 @@ package com.cloud.bridge.service; import java.util.ArrayList; import java.util.Calendar; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.Set; import java.util.UUID; import org.apache.commons.codec.binary.Base64; @@ -210,88 +213,104 @@ public class EC2SoapServiceImpl implements AmazonEC2SkeletonInterface { public CreateTagsResponse createTags(CreateTags createTags) { EC2Tags request = new EC2Tags(); + ArrayList<String> resourceIdList = new ArrayList<String>(); + Map<String, String> resourceTagList = new HashMap<String, String>(); + CreateTagsType ctt = createTags.getCreateTags(); ResourceIdSetType resourceIds = ctt.getResourcesSet(); ResourceTagSetType resourceTags = ctt.getTagSet(); - request = toResourceTypeAndIds(resourceIds); + + ResourceIdSetItemType[] resourceIdItems = resourceIds.getItem(); + if (resourceIdItems != null) { + for( int i=0; i < resourceIdItems.length; i++ ) + resourceIdList.add(resourceIdItems[i].getResourceId()); + } + request = toResourceTypeAndIds(request, resourceIdList); + //add resource tag's to the request - if (resourceTags != null) { - ResourceTagSetItemType[] items = resourceTags.getItem(); - if (items != null) { - for( int i=0; i < items.length; i++ ) { - EC2TagKeyValue param1 = new EC2TagKeyValue(); - param1.setKey(items[i].getKey()); - param1.setValue(items[i].getValue()); - request.addResourceTag(param1); - } - } + ResourceTagSetItemType[] resourceTagItems = resourceTags.getItem(); + if (resourceTagItems != null) { + for( int i=0; i < resourceTagItems.length; i++ ) + resourceTagList.put(resourceTagItems[i].getKey(), resourceTagItems[i].getValue()); } + request = toResourceTag(request, resourceTagList); + return toCreateTagsResponse( engine.modifyTags( request, "create")); } public DeleteTagsResponse deleteTags(DeleteTags deleteTags) { EC2Tags request = new EC2Tags(); + ArrayList<String> resourceIdList = new ArrayList<String>(); + Map<String, String> resourceTagList = new HashMap<String, String>(); + DeleteTagsType dtt = deleteTags.getDeleteTags(); ResourceIdSetType resourceIds = dtt.getResourcesSet(); DeleteTagsSetType resourceTags = dtt.getTagSet(); - request = toResourceTypeAndIds(resourceIds); + + ResourceIdSetItemType[] resourceIdItems = resourceIds.getItem(); + + if (resourceIdItems != null) { + for( int i=0; i < resourceIdItems.length; i++ ) + resourceIdList.add(resourceIdItems[i].getResourceId()); + } + request = toResourceTypeAndIds(request, resourceIdList); + //add resource tag's to the request - if (resourceTags != null) { - DeleteTagsSetItemType[] items = resourceTags.getItem(); - if (items != null) { - for( int i=0; i < items.length; i++ ) { - EC2TagKeyValue param1 = new EC2TagKeyValue(); - param1.setKey(items[i].getKey()); - if (items[i].getValue() != null) - param1.setValue(items[i].getValue()); - request.addResourceTag(param1); - } - } + DeleteTagsSetItemType[] resourceTagItems = resourceTags.getItem(); + if (resourceTagItems != null) { + for( int i=0; i < resourceTagItems.length; i++ ) + resourceTagList.put(resourceTagItems[i].getKey(), resourceTagItems[i].getValue()); } + request = toResourceTag(request, resourceTagList); + return toDeleteTagsResponse( engine.modifyTags( request, "delete")); } - private EC2Tags toResourceTypeAndIds(ResourceIdSetType resourceIds) { - EC2Tags request = new EC2Tags(); - //add resource-type and resource-id's to the request - if (resourceIds != null) { - ResourceIdSetItemType[] items = resourceIds.getItem(); - List<String> resourceTypeList = new ArrayList<String>(); - if (items != null) { - for( int i=0; i < items.length; i++ ) { - if (!items[i].getResourceId().contains(":") || items[i].getResourceId().split(":").length != 2) { - throw new EC2ServiceException( ClientError.InvalidResourceId_Format, - "Invalid Format. ResourceId format is resource-type:resource-uuid"); - } - String resourceType = items[i].getResourceId().split(":")[0]; - if (resourceTypeList.isEmpty()) - resourceTypeList.add(resourceType); - else { - Boolean existsInList = false; - for (String addedResourceType : resourceTypeList) { - if (addedResourceType.equalsIgnoreCase(resourceType)) { - existsInList = true; - break; - } - } - if (!existsInList) - resourceTypeList.add(resourceType); - } - } - for (String resourceType : resourceTypeList){ - EC2TagTypeId param1 = new EC2TagTypeId(); - param1.setResourceType(resourceType); - for( int i=0; i < items.length; i++ ) { - String[] resourceTag = items[i].getResourceId().split(":"); - if (resourceType.equals(resourceTag[0])) - param1.addResourceId(resourceTag[1]); + public static EC2Tags toResourceTypeAndIds( EC2Tags request, ArrayList<String> resourceIdList ) { + List<String> resourceTypeList = new ArrayList<String>(); + for (String resourceId : resourceIdList) { + if (!resourceId.contains(":") || resourceId.split(":").length != 2) { + throw new EC2ServiceException( ClientError.InvalidResourceId_Format, + "Invalid Format. ResourceId format is resource-type:resource-uuid"); + } + String resourceType = resourceId.split(":")[0]; + if (resourceTypeList.isEmpty()) + resourceTypeList.add(resourceType); + else { + Boolean existsInList = false; + for (String addedResourceType : resourceTypeList) { + if (addedResourceType.equalsIgnoreCase(resourceType)) { + existsInList = true; + break; } - request.addResourceType(param1); } + if (!existsInList) + resourceTypeList.add(resourceType); } } + for (String resourceType : resourceTypeList) { + EC2TagTypeId param1 = new EC2TagTypeId(); + param1.setResourceType(resourceType); + for (String resourceId : resourceIdList) { + String[] resourceTag = resourceId.split(":"); + if (resourceType.equals(resourceTag[0])) + param1.addResourceId(resourceTag[1]); + } + request.addResourceType(param1); + } + return request; + } + + public static EC2Tags toResourceTag( EC2Tags request, Map<String, String> resourceTagList ) { + Set<String> resourceTagKeySet = resourceTagList.keySet(); + for (String resourceTagKey : resourceTagKeySet) { + EC2TagKeyValue param1 = new EC2TagKeyValue(); + param1.setKey(resourceTagKey); + param1.setValue(resourceTagList.get(resourceTagKey)); + request.addResourceTag(param1); + } return request; }