You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by al...@apache.org on 2012/07/24 01:37:40 UTC

[5/14] git commit: Modifying filter support in 3 EC2 Describe* API's(DescribeInstances, DescribeVolumes and DescribeSnapshots) to include tags. Component: AWSAPI.

Modifying filter support in 3 EC2 Describe* API's(DescribeInstances, DescribeVolumes and DescribeSnapshots) to include tags. Component: AWSAPI.

Tags support has been added to 3 EC2Describe* API's(DescribeInstances, DescribeVolumes and DescribeSnapshots). Hence for the same 3 EC2Describe* API's filter support has been modified to included 3 tag related filters: tag-key,
tag-value and tag:key.


Project: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/commit/59462cd8
Tree: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/tree/59462cd8
Diff: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/diff/59462cd8

Branch: refs/heads/vpc
Commit: 59462cd825e99d844d1d88ce92b134b3760745d6
Parents: aef09e1
Author: Likitha Shetty <li...@citrix.com>
Authored: Mon Jul 23 15:24:28 2012 -0700
Committer: prachi <pr...@cloud.com>
Committed: Mon Jul 23 15:24:41 2012 -0700

----------------------------------------------------------------------
 .../cloud/bridge/service/EC2SoapServiceImpl.java   |  196 ++++++++-------
 .../service/core/ec2/EC2DescribeInstances.java     |    9 +
 .../service/core/ec2/EC2DescribeSnapshots.java     |    9 +
 .../service/core/ec2/EC2DescribeVolumes.java       |    9 +
 .../cloud/bridge/service/core/ec2/EC2Engine.java   |   70 ++++--
 .../service/core/ec2/EC2InstanceFilterSet.java     |   45 +++-
 .../service/core/ec2/EC2SnapshotFilterSet.java     |   45 +++-
 .../service/core/ec2/EC2VolumeFilterSet.java       |   43 +++-
 awsapi/src/com/cloud/stack/CloudStackApi.java      |   15 +-
 9 files changed, 301 insertions(+), 140 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/59462cd8/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 aa048b2..38f80c8 100644
--- a/awsapi/src/com/cloud/bridge/service/EC2SoapServiceImpl.java
+++ b/awsapi/src/com/cloud/bridge/service/EC2SoapServiceImpl.java
@@ -413,11 +413,10 @@ public class EC2SoapServiceImpl implements AmazonEC2SkeletonInterface  {
 		if (null != items) {  // -> can be empty
 			for( int i=0; i < items.length; i++ ) request.addInstanceId( items[i].getInstanceId());
 		}
-		
-		if (null != fst) {
-			request.setFilterSet( toInstanceFilterSet( fst ));
-		}
-		
+
+        if (null != fst)
+            request = toInstanceFilterSet( request, fst );
+
 		return toDescribeInstancesResponse( engine.describeInstances( request ), engine );
 	}
 
@@ -518,7 +517,7 @@ public class EC2SoapServiceImpl implements AmazonEC2SkeletonInterface  {
 		{
 			String[] timeFilters = new String[1];
 			timeFilters[0] = new String( "start-time" );
-			request.setFilterSet( toSnapshotFilterSet( fst, timeFilters ));
+            request = toSnapshotFilterSet( request, fst, timeFilters );
 		}
 
 		return toDescribeSnapshotsResponse(engine.handleRequest(request));
@@ -557,7 +556,7 @@ public class EC2SoapServiceImpl implements AmazonEC2SkeletonInterface  {
 			String[] timeFilters = new String[2];
 			timeFilters[0] = new String( "attachment.attach-time" );
 			timeFilters[1] = new String( "create-time"            );
-			request.setFilterSet( toVolumeFilterSet( fst, timeFilters ));
+            request = toVolumeFilterSet( request, fst, timeFilters );
 		}
 		
 		return toDescribeVolumesResponse( engine.handleRequest( request ));
@@ -1045,8 +1044,7 @@ public class EC2SoapServiceImpl implements AmazonEC2SkeletonInterface  {
 		return vfs;
 	}
 
-	
-	private EC2VolumeFilterSet toVolumeFilterSet( FilterSetType fst, String[] timeStrs )
+    private EC2DescribeVolumes toVolumeFilterSet( EC2DescribeVolumes request, FilterSetType fst, String[] timeStrs )
 	{
 		EC2VolumeFilterSet vfs = new EC2VolumeFilterSet();
 		boolean timeFilter = false;
@@ -1057,73 +1055,94 @@ public class EC2SoapServiceImpl implements AmazonEC2SkeletonInterface  {
 			// -> each filter can have one or more values associated with it
 			for( int j=0; j < items.length; j++ )
 			{
-				EC2Filter oneFilter = new EC2Filter();
-				String filterName = items[j].getName();
-				oneFilter.setName( filterName );
-				
-				// -> is the filter one of the xsd:dateTime filters?
-				timeFilter = false;
-				for( int m=0; m < timeStrs.length; m++ )
-				{
-					 timeFilter = filterName.equalsIgnoreCase( timeStrs[m] );
-					 if (timeFilter) break;
-				}
-				
-				ValueSetType vst = items[j].getValueSet();
-				ValueType[] valueItems = vst.getItem();
-				for( int k=0; k < valueItems.length; k++ ) 
-				{
-					// -> time values are not encoded as regexes
-					if ( timeFilter )
-					     oneFilter.addValue( valueItems[k].getValue());
-					else oneFilter.addValueEncoded( valueItems[k].getValue());
-				}
-				vfs.addFilter( oneFilter );
-			}
-		}		
-		return vfs;
-	}
+                String filterName = items[j].getName();
+                ValueSetType vst = items[j].getValueSet();
+                ValueType[] valueItems = vst.getItem();
+
+                if (filterName.startsWith("tag:")) {
+                    String key= filterName.split(":")[1];
+                    for (ValueType valueItem : valueItems) {
+                        EC2TagKeyValue tag = new EC2TagKeyValue();
+                        tag.setKey(key);
+                        tag.setValue(valueItem.getValue());
+                        request.addResourceTag(tag);
+                    }
+                } else {
+                    EC2Filter oneFilter = new EC2Filter();
+                    oneFilter.setName( filterName );
+
+                    // -> is the filter one of the xsd:dateTime filters?
+                    timeFilter = false;
+                    for( int m=0; m < timeStrs.length; m++ ) {
+                        timeFilter = filterName.equalsIgnoreCase( timeStrs[m] );
+                        if (timeFilter) break;
+                    }
 
-	
-	private EC2SnapshotFilterSet toSnapshotFilterSet( FilterSetType fst, String[] timeStrs )
-	{
-		EC2SnapshotFilterSet vfs = new EC2SnapshotFilterSet();
+                    for( int k=0; k < valueItems.length; k++ ) {
+                        // -> time values are not encoded as regexes
+                        if ( timeFilter )
+                            oneFilter.addValue( valueItems[k].getValue());
+                        else
+                            oneFilter.addValueEncoded( valueItems[k].getValue());
+                    }
+                    vfs.addFilter( oneFilter );
+                }
+            }
+            request.setFilterSet(vfs);
+        }
+        return request;
+    }
+
+    private EC2DescribeSnapshots toSnapshotFilterSet( EC2DescribeSnapshots request, FilterSetType fst, String[] timeStrs )
+    {
+        EC2SnapshotFilterSet sfs = new EC2SnapshotFilterSet();
 		boolean timeFilter = false;
-		
+
 		FilterType[] items = fst.getItem();
 		if (null != items) 
 		{
 			// -> each filter can have one or more values associated with it
 			for( int j=0; j < items.length; j++ )
 			{
-				EC2Filter oneFilter = new EC2Filter();
-				String filterName = items[j].getName();
-				oneFilter.setName( filterName );
-				
-				// -> is the filter one of the xsd:dateTime filters?
-				timeFilter = false;
-				for( int m=0; m < timeStrs.length; m++ )
-				{
-					 timeFilter = filterName.equalsIgnoreCase( timeStrs[m] );
-					 if (timeFilter) break;
-				}
-				
-				ValueSetType vst = items[j].getValueSet();
-				ValueType[] valueItems = vst.getItem();
-				for( int k=0; k < valueItems.length; k++ ) 
-				{
-					// -> time values are not encoded as regexes
-					if ( timeFilter )
-					     oneFilter.addValue( valueItems[k].getValue());
-					else oneFilter.addValueEncoded( valueItems[k].getValue());
-				}
-				vfs.addFilter( oneFilter );
-			}
-		}		
-		return vfs;
-	}
+                String filterName = items[j].getName();
+                ValueSetType vst = items[j].getValueSet();
+                ValueType[] valueItems = vst.getItem();
+
+                if (filterName.startsWith("tag:")) {
+                    String key= filterName.split(":")[1];
+                    for (ValueType valueItem : valueItems) {
+                        EC2TagKeyValue tag = new EC2TagKeyValue();
+                        tag.setKey(key);
+                        tag.setValue(valueItem.getValue());
+                        request.addResourceTag(tag);
+                    }
+                }
+                else {
+                    EC2Filter oneFilter = new EC2Filter();
+                    oneFilter.setName( filterName );
+
+                    // -> is the filter one of the xsd:dateTime filters?
+                    timeFilter = false;
+                    for( int m=0; m < timeStrs.length; m++ ) {
+                        timeFilter = filterName.equalsIgnoreCase( timeStrs[m] );
+                        if (timeFilter) break;
+                    }
+
+                    for( int k=0; k < valueItems.length; k++ ) {
+                        // -> time values are not encoded as regexes
+                        if ( timeFilter )
+                            oneFilter.addValue( valueItems[k].getValue());
+                        else
+                            oneFilter.addValueEncoded( valueItems[k].getValue());
+                    }
+                    sfs.addFilter( oneFilter );
+                }
+            }
+            request.setFilterSet(sfs);
+        }
+        return request;
+    }
 
-	
 	// TODO make these filter set functions use generics 
 	private EC2GroupFilterSet toGroupFilterSet( FilterSetType fst )
 	{
@@ -1151,8 +1170,7 @@ public class EC2SoapServiceImpl implements AmazonEC2SkeletonInterface  {
 		return gfs;
 	}
 
-	
-	private EC2InstanceFilterSet toInstanceFilterSet( FilterSetType fst )
+    private EC2DescribeInstances toInstanceFilterSet( EC2DescribeInstances request, FilterSetType fst )
 	{
 		EC2InstanceFilterSet ifs = new EC2InstanceFilterSet();
 		
@@ -1162,22 +1180,30 @@ public class EC2SoapServiceImpl implements AmazonEC2SkeletonInterface  {
 			// -> each filter can have one or more values associated with it
 			for( int j=0; j < items.length; j++ )
 			{
-				EC2Filter oneFilter = new EC2Filter();
-				String filterName = items[j].getName();
-				oneFilter.setName( filterName );
-				
-				ValueSetType vst = items[j].getValueSet();
-				ValueType[] valueItems = vst.getItem();
-				for( int k=0; k < valueItems.length; k++ ) 
-				{
-					oneFilter.addValueEncoded( valueItems[k].getValue());
-				}
-				ifs.addFilter( oneFilter );
-			}
-		}		
-		return ifs;
-	}
-
+                String filterName = items[j].getName();
+                ValueSetType vst = items[j].getValueSet();
+                ValueType[] valueItems = vst.getItem();
+
+                if (filterName.startsWith("tag:")) {
+                    String key= filterName.split(":")[1];
+                    for (ValueType valueItem : valueItems) {
+                        EC2TagKeyValue tag = new EC2TagKeyValue();
+                        tag.setKey(key);
+                        tag.setValue(valueItem.getValue());
+                        request.addResourceTag(tag);
+                    }
+                } else {
+                    EC2Filter oneFilter = new EC2Filter();
+                    oneFilter.setName( filterName );
+                    for( int k=0; k < valueItems.length; k++ )
+                        oneFilter.addValueEncoded( valueItems[k].getValue());
+                    ifs.addFilter( oneFilter );
+                }
+            }
+            request.setFilterSet(ifs);
+        }
+        return request;
+    }
 
     private EC2AvailabilityZonesFilterSet toAvailabiltyZonesFilterSet( FilterSetType fst )	{
         EC2AvailabilityZonesFilterSet azfs = new EC2AvailabilityZonesFilterSet();

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/59462cd8/awsapi/src/com/cloud/bridge/service/core/ec2/EC2DescribeInstances.java
----------------------------------------------------------------------
diff --git a/awsapi/src/com/cloud/bridge/service/core/ec2/EC2DescribeInstances.java b/awsapi/src/com/cloud/bridge/service/core/ec2/EC2DescribeInstances.java
index e79cd9d..145342f 100644
--- a/awsapi/src/com/cloud/bridge/service/core/ec2/EC2DescribeInstances.java
+++ b/awsapi/src/com/cloud/bridge/service/core/ec2/EC2DescribeInstances.java
@@ -23,6 +23,7 @@ public class EC2DescribeInstances {
 
 	private List<String> instancesSet = new ArrayList<String>();    // a list of strings identifying instances
 	private EC2InstanceFilterSet ifs = null;
+    private List<EC2TagKeyValue> resourceTagSet = new ArrayList<EC2TagKeyValue>();
 
 	public EC2DescribeInstances() {
 	}
@@ -42,4 +43,12 @@ public class EC2DescribeInstances {
 	public void setFilterSet( EC2InstanceFilterSet param ) {
 		ifs = param;
 	}
+
+    public void addResourceTag( EC2TagKeyValue param ) {
+        resourceTagSet.add( param );
+    }
+
+    public EC2TagKeyValue[] getResourceTagSet() {
+        return resourceTagSet.toArray(new EC2TagKeyValue[0]);
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/59462cd8/awsapi/src/com/cloud/bridge/service/core/ec2/EC2DescribeSnapshots.java
----------------------------------------------------------------------
diff --git a/awsapi/src/com/cloud/bridge/service/core/ec2/EC2DescribeSnapshots.java b/awsapi/src/com/cloud/bridge/service/core/ec2/EC2DescribeSnapshots.java
index 1bf6e37..cd77fde 100644
--- a/awsapi/src/com/cloud/bridge/service/core/ec2/EC2DescribeSnapshots.java
+++ b/awsapi/src/com/cloud/bridge/service/core/ec2/EC2DescribeSnapshots.java
@@ -23,6 +23,7 @@ public class EC2DescribeSnapshots {
 
 	private List<String> snapshotSet = new ArrayList<String>();    // a list of strings identifying snapshots
 	private EC2SnapshotFilterSet sfs = null;
+    private List<EC2TagKeyValue> resourceTagSet = new ArrayList<EC2TagKeyValue>();
 
 	public EC2DescribeSnapshots() {
 	}
@@ -42,4 +43,12 @@ public class EC2DescribeSnapshots {
 	public void setFilterSet( EC2SnapshotFilterSet param ) {
 		sfs = param;
 	}
+
+    public void addResourceTag( EC2TagKeyValue param ) {
+        resourceTagSet.add( param );
+    }
+
+    public EC2TagKeyValue[] getResourceTagSet() {
+        return resourceTagSet.toArray(new EC2TagKeyValue[0]);
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/59462cd8/awsapi/src/com/cloud/bridge/service/core/ec2/EC2DescribeVolumes.java
----------------------------------------------------------------------
diff --git a/awsapi/src/com/cloud/bridge/service/core/ec2/EC2DescribeVolumes.java b/awsapi/src/com/cloud/bridge/service/core/ec2/EC2DescribeVolumes.java
index 04145fa..3bfd2a4 100644
--- a/awsapi/src/com/cloud/bridge/service/core/ec2/EC2DescribeVolumes.java
+++ b/awsapi/src/com/cloud/bridge/service/core/ec2/EC2DescribeVolumes.java
@@ -23,6 +23,7 @@ public class EC2DescribeVolumes {
 
 	private List<String> volumeSet = new ArrayList<String>();    // a list of strings identifying volume ids
 	private EC2VolumeFilterSet vfs = null;
+    private List<EC2TagKeyValue> resourceTagSet = new ArrayList<EC2TagKeyValue>();
 
 	public EC2DescribeVolumes() {
 	}
@@ -42,4 +43,12 @@ public class EC2DescribeVolumes {
 	public void setFilterSet( EC2VolumeFilterSet param ) {
 		vfs = param;
 	}
+
+    public void addResourceTag( EC2TagKeyValue param ) {
+        resourceTagSet.add( param );
+    }
+
+    public EC2TagKeyValue[] getResourceTagSet() {
+        return resourceTagSet.toArray(new EC2TagKeyValue[0]);
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/59462cd8/awsapi/src/com/cloud/bridge/service/core/ec2/EC2Engine.java
----------------------------------------------------------------------
diff --git a/awsapi/src/com/cloud/bridge/service/core/ec2/EC2Engine.java b/awsapi/src/com/cloud/bridge/service/core/ec2/EC2Engine.java
index 2906093..c64a073 100644
--- a/awsapi/src/com/cloud/bridge/service/core/ec2/EC2Engine.java
+++ b/awsapi/src/com/cloud/bridge/service/core/ec2/EC2Engine.java
@@ -418,20 +418,22 @@ public class EC2Engine {
 	 * @param request
 	 * @return
 	 */
-	public EC2DescribeSnapshotsResponse handleRequest( EC2DescribeSnapshots request ) 
+    public EC2DescribeSnapshotsResponse handleRequest( EC2DescribeSnapshots request ) 
 	{
 		EC2DescribeVolumesResponse volumes = new EC2DescribeVolumesResponse();
 		EC2SnapshotFilterSet sfs = request.getFilterSet();
+        EC2TagKeyValue[] tagKeyValueSet = request.getResourceTagSet();
 
 		try { 
 			// -> query to get the volume size for each snapshot
-			EC2DescribeSnapshotsResponse response = listSnapshots( request.getSnapshotSet());
+            EC2DescribeSnapshotsResponse response = listSnapshots( request.getSnapshotSet(),
+                    getResourceTags(tagKeyValueSet));
 			if (response == null) {
 				return new EC2DescribeSnapshotsResponse();
 			}
 			EC2Snapshot[] snapshots = response.getSnapshotSet();
 			for (EC2Snapshot snap : snapshots) {
-				volumes = listVolumes(snap.getVolumeId(), null, volumes);
+				volumes = listVolumes(snap.getVolumeId(), null, volumes, null);
 				EC2Volume[] volSet = volumes.getVolumeSet();
 				if (0 < volSet.length) snap.setVolumeSize(volSet[0].getSize());
 				volumes.reset();
@@ -473,7 +475,7 @@ public class EC2Engine {
 			ec2Snapshot.setCreated(snap.getCreated());
 			ec2Snapshot.setVolumeId(snap.getVolumeId());
 			
-			List<CloudStackVolume> vols = getApi().listVolumes(null, null, null, snap.getVolumeId(), null, null, null, null, null, null, null);
+			List<CloudStackVolume> vols = getApi().listVolumes(null, null, null, snap.getVolumeId(), null, null, null, null, null, null, null, null);
 
 			if(vols.size() > 0) {
 				assert(vols.get(0).getSize() != null);
@@ -630,17 +632,18 @@ public class EC2Engine {
 	 * 
 	 * @param interestedShots - can be null, should be a subset of all snapshots
 	 */
-	private EC2DescribeSnapshotsResponse listSnapshots( String[] interestedShots ) throws Exception {
+    private EC2DescribeSnapshotsResponse listSnapshots( String[] interestedShots, List<CloudStackKeyValue> resourceTagSet ) throws Exception {
 		EC2DescribeSnapshotsResponse snapshots = new EC2DescribeSnapshotsResponse();
 
 		List<CloudStackSnapshot> cloudSnaps;
 		if (interestedShots == null || interestedShots.length == 0) {
-			cloudSnaps = getApi().listSnapshots(null, null, null, null, null, null, null, null, null);
+            cloudSnaps = getApi().listSnapshots(null, null, null, null, null, null, null, null, null, resourceTagSet);
 		} else {
 			cloudSnaps = new ArrayList<CloudStackSnapshot>();
 
 			for(String id : interestedShots) {
-				List<CloudStackSnapshot> tmpList = getApi().listSnapshots(null, null, id, null, null, null, null, null, null);
+                List<CloudStackSnapshot> tmpList = getApi().listSnapshots(null, null, id, null, null, null, null,
+                    null, null, resourceTagSet);
 				cloudSnaps.addAll(tmpList);
 			}
 		}
@@ -880,7 +883,7 @@ public class EC2Engine {
 	public boolean associateAddress( EC2AssociateAddress request ) {
 		try {
 			CloudStackIpAddress cloudIp = getApi().listPublicIpAddresses(null, null, null, null, null, request.getPublicIp(), null, null, null).get(0);
-	        CloudStackUserVm cloudVm = getApi().listVirtualMachines(null, null, true, null, null, null, null, request.getInstanceId(), null, null, null, null, null, null, null, null).get(0);
+	        CloudStackUserVm cloudVm = getApi().listVirtualMachines(null, null, true, null, null, null, null, request.getInstanceId(), null, null, null, null, null, null, null, null, null).get(0);
 
 			CloudStackInfoResponse resp = getApi().enableStaticNat(cloudIp.getId(), cloudVm.getId());
 			if (resp != null) {
@@ -1005,7 +1008,7 @@ public class EC2Engine {
 			// [A] Creating a template from a VM volume should be from the ROOT volume
 			//     Also for this to work the VM must be in a Stopped state so we 'reboot' it if its not
 			EC2DescribeVolumesResponse volumes = new EC2DescribeVolumesResponse();
-			volumes = listVolumes( null, request.getInstanceId(), volumes );
+			volumes = listVolumes( null, request.getInstanceId(), volumes, null );
 			EC2Volume[] volSet = volumes.getVolumeSet();
 			for (EC2Volume vol : volSet) {
 				if (vol.getType().equalsIgnoreCase( "ROOT" )) {
@@ -1022,7 +1025,7 @@ public class EC2Engine {
 
 			// [B] The parameters must be in sorted order for proper signature generation
 			EC2DescribeInstancesResponse instances = new EC2DescribeInstancesResponse();
-			instances = lookupInstances( request.getInstanceId(), instances );
+			instances = lookupInstances( request.getInstanceId(), instances, null );
 			EC2Instance[] instanceSet = instances.getInstanceSet();
 			String templateId = instanceSet[0].getTemplateId();
 
@@ -1116,7 +1119,9 @@ public class EC2Engine {
 	 */
 	public EC2DescribeInstancesResponse describeInstances(EC2DescribeInstances request ) {
 		try {
-			return listVirtualMachines( request.getInstancesSet(), request.getFilterSet()); 
+            EC2TagKeyValue[] tagKeyValueSet = request.getResourceTagSet();
+            return listVirtualMachines( request.getInstancesSet(), request.getFilterSet(),
+                    getResourceTags(tagKeyValueSet));
 		} catch( Exception e ) {
 			logger.error( "EC2 DescribeInstances - " ,e);
 			throw new EC2ServiceException(ServerError.InternalError, e.getMessage() != null ? e.getMessage() : "An unexpected error occurred.");
@@ -1160,14 +1165,14 @@ public class EC2Engine {
 	public EC2DescribeVolumesResponse handleRequest( EC2DescribeVolumes request ) {
 		EC2DescribeVolumesResponse volumes = new EC2DescribeVolumesResponse();
 		EC2VolumeFilterSet vfs = request.getFilterSet();
-
+        EC2TagKeyValue[] tagKeyValueSet = request.getResourceTagSet();
 		try {   
 			String[] volumeIds = request.getVolumeSet();
 			if ( 0 == volumeIds.length ){
-				volumes = listVolumes( null, null, volumes );
+                volumes = listVolumes( null, null, volumes, getResourceTags(tagKeyValueSet) );
 			} else {     
 				for (String s : volumeIds) 
-					volumes = listVolumes(s, null, volumes );
+                    volumes = listVolumes(s, null, volumes, getResourceTags(tagKeyValueSet) );
 			}
 
 			if ( null == vfs )
@@ -1408,7 +1413,7 @@ public class EC2Engine {
 		// -> reboot is not allowed on destroyed (i.e., terminated) instances
 		try {   
 			String[] instanceSet = request.getInstancesSet();
-			EC2DescribeInstancesResponse previousState = listVirtualMachines( instanceSet, null );
+			EC2DescribeInstancesResponse previousState = listVirtualMachines( instanceSet, null, null );
 			vms = previousState.getInstanceSet();
 
 			// -> send reboot requests for each found VM
@@ -1545,7 +1550,7 @@ public class EC2Engine {
 
 		// -> first determine the current state of each VM (becomes it previous state)
 		try {
-			EC2DescribeInstancesResponse previousState = listVirtualMachines( request.getInstancesSet(), null );
+			EC2DescribeInstancesResponse previousState = listVirtualMachines( request.getInstancesSet(), null, null );
 			vms = previousState.getInstanceSet();
 
 			// -> send start requests for each item 
@@ -1587,7 +1592,7 @@ public class EC2Engine {
 		try {   
 			String[] instanceSet = request.getInstancesSet();
 
-			EC2DescribeInstancesResponse previousState = listVirtualMachines( instanceSet, null );
+			EC2DescribeInstancesResponse previousState = listVirtualMachines( instanceSet, null, null );
 			virtualMachines = previousState.getInstanceSet();
 
 			// -> send stop requests for each item 
@@ -1654,7 +1659,7 @@ public class EC2Engine {
 			if (maxAllowed == -1) 
 				return -1;   // no limit
 
-			EC2DescribeInstancesResponse existingVMS = listVirtualMachines( null, null );
+			EC2DescribeInstancesResponse existingVMS = listVirtualMachines( null, null, null );
 			EC2Instance[] vmsList = existingVMS.getInstanceSet();
 			return (maxAllowed - vmsList.length);
 		} else {
@@ -1668,15 +1673,16 @@ public class EC2Engine {
 	 * @param virtualMachineIds - an array of instances we are interested in getting information on
 	 * @param ifs - filter out unwanted instances
 	 */
-	private EC2DescribeInstancesResponse listVirtualMachines( String[] virtualMachineIds, EC2InstanceFilterSet ifs ) throws Exception 
+	private EC2DescribeInstancesResponse listVirtualMachines( String[] virtualMachineIds, EC2InstanceFilterSet ifs,
+            List<CloudStackKeyValue> resourceTags ) throws Exception 
 	{
 		EC2DescribeInstancesResponse instances = new EC2DescribeInstancesResponse();
 
 		if (null == virtualMachineIds || 0 == virtualMachineIds.length) {
-			instances = lookupInstances( null, instances );
+            instances = lookupInstances( null, instances, resourceTags );
 		} else {
 			for( int i=0; i <  virtualMachineIds.length; i++ ) {
-				instances = lookupInstances( virtualMachineIds[i], instances );
+                instances = lookupInstances( virtualMachineIds[i], instances, resourceTags );
 			}
 		}
 
@@ -1691,9 +1697,11 @@ public class EC2Engine {
 	 * @param volumeId   - if interested in one specific volume, null if want to list all volumes
 	 * @param instanceId - if interested in volumes for a specific instance, null if instance is not important
 	 */
-	private EC2DescribeVolumesResponse listVolumes(String volumeId, String instanceId, EC2DescribeVolumesResponse volumes)throws Exception {
+	private EC2DescribeVolumesResponse listVolumes(String volumeId, String instanceId, EC2DescribeVolumesResponse volumes,
+            List<CloudStackKeyValue> resourceTagSet)throws Exception {
 
-		List<CloudStackVolume> vols = getApi().listVolumes(null, null, null, volumeId, null, null, null, null, null, instanceId, null);
+        List<CloudStackVolume> vols = getApi().listVolumes(null, null, null, volumeId, null, null, null, null, null,
+                instanceId, null, resourceTagSet);
 		if(vols != null && vols.size() > 0) {
 			for(CloudStackVolume vol : vols) {
 				EC2Volume ec2Vol = new EC2Volume();
@@ -1872,12 +1880,13 @@ public class EC2Engine {
 	 * @return the same object passed in as the "instances" parameter modified with one or more
 	 *         EC2Instance objects loaded.
 	 */
-	private EC2DescribeInstancesResponse lookupInstances( String instanceId, EC2DescribeInstancesResponse instances ) 
+	private EC2DescribeInstancesResponse lookupInstances( String instanceId, EC2DescribeInstancesResponse instances,
+            List<CloudStackKeyValue> resourceTagSet )
 			throws Exception {
 
 		String instId = instanceId != null ? instanceId : null;
         List<CloudStackUserVm> vms = getApi().listVirtualMachines(null, null, true, null, null, null, null,
-				instId, null, null, null, null, null, null, null, null);
+            instId, null, null, null, null, null, null, null, null, resourceTagSet);
 		
 		if(vms != null && vms.size() > 0) {
     		for(CloudStackUserVm cloudVm : vms) {
@@ -2439,4 +2448,15 @@ public class EC2Engine {
         }
         return elementList.toString();
     }
+
+    private List<CloudStackKeyValue> getResourceTags(EC2TagKeyValue[] tagKeyValueSet) {
+        List<CloudStackKeyValue> resourceTags = new ArrayList<CloudStackKeyValue>();
+        for (EC2TagKeyValue tagKeyValue : tagKeyValueSet) {
+            CloudStackKeyValue resourceTag = new CloudStackKeyValue();
+            resourceTag.setKeyValue(tagKeyValue.getKey(), tagKeyValue.getValue());
+            resourceTags.add(resourceTag);
+        }
+        return resourceTags;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/59462cd8/awsapi/src/com/cloud/bridge/service/core/ec2/EC2InstanceFilterSet.java
----------------------------------------------------------------------
diff --git a/awsapi/src/com/cloud/bridge/service/core/ec2/EC2InstanceFilterSet.java b/awsapi/src/com/cloud/bridge/service/core/ec2/EC2InstanceFilterSet.java
index 6d5255a..449d89e 100644
--- a/awsapi/src/com/cloud/bridge/service/core/ec2/EC2InstanceFilterSet.java
+++ b/awsapi/src/com/cloud/bridge/service/core/ec2/EC2InstanceFilterSet.java
@@ -48,20 +48,21 @@ public class EC2InstanceFilterSet {
 		filterTypes.put( "root-device-name",     "string"  );
 		filterTypes.put( "private-ip-address",   "string"  );
         filterTypes.put( "group-id",             "string"  );
+        filterTypes.put( "tag-key",              "string"  );
+        filterTypes.put( "tag-value",            "string"  );
 	}
 	
 	
 	public void addFilter( EC2Filter param ) 
 	{	
 		String filterName = param.getName();
-		String value = (String) filterTypes.get( filterName );
-		
-		if (null == value)
-			throw new EC2ServiceException( "Unsupported filter [" + filterName + "]", 501 );
-		
-		if (null != value && value.equalsIgnoreCase( "null" ))
-			throw new EC2ServiceException( "Unsupported filter [" + filterName + "]", 501 );
+        String value = (String) filterTypes.get( filterName );
 
+        if (null == value)
+            throw new EC2ServiceException( "Unsupported filter [" + filterName + "]", 501 );
+
+        if (null != value && value.equalsIgnoreCase( "null" ))
+            throw new EC2ServiceException( "Unsupported filter [" + filterName + "]", 501 );
 		// ToDo we could add checks to make sure the type of a filters value is correct (e.g., an integer)
 		filterSet.add( param );
 	}
@@ -163,6 +164,26 @@ public class EC2InstanceFilterSet {
                 if (containsString(group, valueSet)) return true;
             return false;
         }
+        else if (filterName.equalsIgnoreCase("tag-key"))
+        {
+            EC2TagKeyValue[] tagSet = vm.getResourceTags();
+            for (EC2TagKeyValue tag : tagSet)
+                if (containsString(tag.getKey(), valueSet)) return true;
+            return false;
+        }
+        else if (filterName.equalsIgnoreCase("tag-value"))
+        {
+            EC2TagKeyValue[] tagSet = vm.getResourceTags();
+            for (EC2TagKeyValue tag : tagSet) {
+                if (tag.getValue() == null) {
+                    if (containsEmptyValue(valueSet)) return true;
+                }
+                else {
+                    if (containsString(tag.getValue(), valueSet)) return true;
+                }
+            }
+            return false;
+        }
 	    else return false;
 	}
 	
@@ -178,8 +199,14 @@ public class EC2InstanceFilterSet {
 	    }
 	    return false;
 	}
-	
-	
+
+    private boolean containsEmptyValue( String[] set )
+    {
+        for( int i=0; i < set.length; i++ )
+            if (set[i].isEmpty()) return true;
+        return false;
+    }
+
 	private boolean containsInteger( int lookingFor, String[] set )
 	{
         for( int i=0; i < set.length; i++ )

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/59462cd8/awsapi/src/com/cloud/bridge/service/core/ec2/EC2SnapshotFilterSet.java
----------------------------------------------------------------------
diff --git a/awsapi/src/com/cloud/bridge/service/core/ec2/EC2SnapshotFilterSet.java b/awsapi/src/com/cloud/bridge/service/core/ec2/EC2SnapshotFilterSet.java
index 1c428f0..c2bed3c 100644
--- a/awsapi/src/com/cloud/bridge/service/core/ec2/EC2SnapshotFilterSet.java
+++ b/awsapi/src/com/cloud/bridge/service/core/ec2/EC2SnapshotFilterSet.java
@@ -46,20 +46,23 @@ public class EC2SnapshotFilterSet {
 		filterTypes.put( "status",      "string"  );
 		filterTypes.put( "volume-id",   "string"  ); 
 		filterTypes.put( "volume-size", "string"  );
+        filterTypes.put( "tag-key",     "string"  );
+        filterTypes.put( "tag-value",   "string"  );
 	}
 	
 	
 	public void addFilter( EC2Filter param ) 
 	{	
 		String filterName = param.getName();
-		String value = (String) filterTypes.get( filterName );
-		
-		if (null == value)
-			throw new EC2ServiceException( "Unsupported filter [" + filterName + "] - 1", 501 );
-		
-		if (null != value && value.equalsIgnoreCase( "null" ))
-			throw new EC2ServiceException( "Unsupported filter [" + filterName + "] - 2", 501 );
+        if (!filterName.startsWith("tag:")) {
+            String value = (String) filterTypes.get( filterName );
 
+            if (null == value)
+                throw new EC2ServiceException( "Unsupported filter [" + filterName + "] - 1", 501 );
+
+            if (null != value && value.equalsIgnoreCase( "null" ))
+                throw new EC2ServiceException( "Unsupported filter [" + filterName + "] - 2", 501 );
+        }
 		// ToDo we could add checks to make sure the type of a filters value is correct (e.g., an integer)
 		filterSet.add( param );
 	}
@@ -140,6 +143,26 @@ public class EC2SnapshotFilterSet {
 	    {
 	    	 return containsLong( snap.getVolumeSize(), valueSet );		
 	    }
+        else if (filterName.equalsIgnoreCase("tag-key"))
+        {
+            EC2TagKeyValue[] tagSet = snap.getResourceTags();
+            for (EC2TagKeyValue tag : tagSet)
+                if (containsString(tag.getKey(), valueSet)) return true;
+            return false;
+        }
+        else if (filterName.equalsIgnoreCase("tag-value"))
+        {
+            EC2TagKeyValue[] tagSet = snap.getResourceTags();
+            for (EC2TagKeyValue tag : tagSet){
+                if (tag.getValue() == null) {
+                    if (containsEmptyValue(valueSet)) return true;
+                }
+                else {
+                    if (containsString(tag.getValue(), valueSet)) return true;
+                }
+            }
+            return false;
+        }
 	    else return false;
 	}
 	
@@ -155,7 +178,13 @@ public class EC2SnapshotFilterSet {
 	    return false;
 	}
 
-	
+    private boolean containsEmptyValue( String[] set )
+    {
+        for( int i=0; i < set.length; i++ )
+            if (set[i].isEmpty()) return true;
+        return false;
+    }
+
 	private boolean containsLong( long lookingFor, String[] set )
 	{
 		for (String s : set) {

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/59462cd8/awsapi/src/com/cloud/bridge/service/core/ec2/EC2VolumeFilterSet.java
----------------------------------------------------------------------
diff --git a/awsapi/src/com/cloud/bridge/service/core/ec2/EC2VolumeFilterSet.java b/awsapi/src/com/cloud/bridge/service/core/ec2/EC2VolumeFilterSet.java
index 95d306f..0594231 100644
--- a/awsapi/src/com/cloud/bridge/service/core/ec2/EC2VolumeFilterSet.java
+++ b/awsapi/src/com/cloud/bridge/service/core/ec2/EC2VolumeFilterSet.java
@@ -49,8 +49,8 @@ public class EC2VolumeFilterSet {
 		filterTypes.put( "size",                             "integer"      );
 		filterTypes.put( "snapshot-id",                      "string"       );
 		filterTypes.put( "status",                           "set:creating|available|in-use|deleting|deleted|error" );
-		filterTypes.put( "tag-key",                          "null"         );
-		filterTypes.put( "tag-value",                        "null"         );
+		filterTypes.put( "tag-key",                          "string"         );
+		filterTypes.put( "tag-value",                        "string"         );
 		filterTypes.put( "volume-id",                        "string"       );	
 		//		filterTypes.put( "tag:*",                            "null" );
 	}
@@ -59,14 +59,13 @@ public class EC2VolumeFilterSet {
 	public void addFilter( EC2Filter param ) 
 	{	
 		String filterName = param.getName();
-		String value = (String) filterTypes.get( filterName );
+        String value = (String) filterTypes.get( filterName );
 
-		if (null == value)
-			throw new EC2ServiceException( "Unsupported filter [" + filterName + "] - 1", 501 );
-
-		if (null != value && value.equalsIgnoreCase( "null" ))
-			throw new EC2ServiceException( "Unsupported filter [" + filterName + "] - 2", 501 );
+        if (null == value)
+            throw new EC2ServiceException( "Unsupported filter [" + filterName + "] - 1", 501 );
 
+        if (null != value && value.equalsIgnoreCase( "null" ))
+            throw new EC2ServiceException( "Unsupported filter [" + filterName + "] - 2", 501 );
 		// ToDo we could add checks to make sure the type of a filters value is correct (e.g., an integer)
 		filterSet.add( param );
 	}
@@ -136,7 +135,27 @@ public class EC2VolumeFilterSet {
 		else if (filterName.equalsIgnoreCase( "attachment.device" )) 
 			return containsDevice(vol.getDeviceId(), valueSet );	
 		else if (filterName.equalsIgnoreCase( "attachment.instance-id" )) 
-			return containsString(String.valueOf(vol.getInstanceId()), valueSet );		
+			return containsString(String.valueOf(vol.getInstanceId()), valueSet );
+        else if (filterName.equalsIgnoreCase("tag-key"))
+        {
+            EC2TagKeyValue[] tagSet = vol.getResourceTags();
+            for (EC2TagKeyValue tag : tagSet)
+                if (containsString(tag.getKey(), valueSet)) return true;
+            return false;
+        }
+        else if (filterName.equalsIgnoreCase("tag-value"))
+        {
+            EC2TagKeyValue[] tagSet = vol.getResourceTags();
+            for (EC2TagKeyValue tag : tagSet){
+                if (tag.getValue() == null) {
+                    if (containsEmptyValue(valueSet)) return true;
+                }
+                else {
+                    if (containsString(tag.getValue(), valueSet)) return true;
+                }
+            }
+            return false;
+        }
 		else return false;
 	}
 
@@ -150,6 +169,12 @@ public class EC2VolumeFilterSet {
 		return false;
 	}
 
+    private boolean containsEmptyValue( String[] set )
+    {
+        for( int i=0; i < set.length; i++ )
+            if (set[i].isEmpty()) return true;
+        return false;
+    }
 
 	private boolean containsLong( long lookingFor, String[] set )
 	{

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/59462cd8/awsapi/src/com/cloud/stack/CloudStackApi.java
----------------------------------------------------------------------
diff --git a/awsapi/src/com/cloud/stack/CloudStackApi.java b/awsapi/src/com/cloud/stack/CloudStackApi.java
index 50b2b25..52c2459 100644
--- a/awsapi/src/com/cloud/stack/CloudStackApi.java
+++ b/awsapi/src/com/cloud/stack/CloudStackApi.java
@@ -314,7 +314,7 @@ public class CloudStackApi {
 	 */
     public List<CloudStackUserVm> listVirtualMachines(String account, String accountId, Boolean listAll, Boolean forVirtualNetwork, String groupId, String hostId,
 			String hypervisor, String id, Boolean isRecursive, String keyWord, String name, String networkId, String podId, String state, String storageId, 
-			String zoneId) throws Exception {
+            String zoneId, List<CloudStackKeyValue> resourceTags) throws Exception {
 		CloudStackCommand cmd = new CloudStackCommand(ApiConstants.LIST_VIRTUAL_MACHINES);
 		if (cmd != null) {
 			if (account != null) cmd.setParam(ApiConstants.ACCOUNT, account);
@@ -333,6 +333,8 @@ public class CloudStackApi {
 			if (state != null) cmd.setParam(ApiConstants.STATE, state);
 			if (storageId != null) cmd.setParam(ApiConstants.STORAGE_ID, storageId);
 			if (zoneId != null) cmd.setParam(ApiConstants.ZONE_ID, zoneId);
+            if (resourceTags != null && resourceTags.size() > 0)
+                cmd = setParams(cmd, null, null, resourceTags);
 		}
 		return _client.listCall(cmd, apiKey, secretKey, ApiConstants.LIST_VIRTUAL_MACHINES_RESPONSE, ApiConstants.VIRTUAL_MACHINE, 
 				new TypeToken<List<CloudStackUserVm>>() {}.getType());
@@ -935,7 +937,7 @@ public class CloudStackApi {
 	 * @throws Exception
 	 */
 	public List<CloudStackVolume> listVolumes(String account, String domainId, String hostId, String id, Boolean isRecursive, String keyWord, String name,
-			String podId, String type, String virtualMachineId, String zoneId) throws Exception {
+            String podId, String type, String virtualMachineId, String zoneId, List<CloudStackKeyValue> resourceTags) throws Exception {
 		CloudStackCommand cmd = new CloudStackCommand(ApiConstants.LIST_VOLUMES);
 		if (cmd != null) {
 			if (account != null) cmd.setParam(ApiConstants.ACCOUNT, account);
@@ -949,6 +951,8 @@ public class CloudStackApi {
 			if (type != null) cmd.setParam(ApiConstants.TYPE, type);
 			if (virtualMachineId != null) cmd.setParam(ApiConstants.VIRTUAL_MACHINE_ID, virtualMachineId);
 			if (zoneId != null) cmd.setParam(ApiConstants.ZONE_ID, zoneId);
+            if (resourceTags != null && resourceTags.size() > 0)
+                cmd = setParams(cmd, null, null, resourceTags);
 		}
 		return _client.listCall(cmd, apiKey, secretKey, ApiConstants.LIST_VOLUMES_RESPONSE, ApiConstants.VOLUME, 
 				new TypeToken<List<CloudStackVolume>>() {}.getType());
@@ -1029,7 +1033,8 @@ public class CloudStackApi {
     private CloudStackCommand setParams(CloudStackCommand cmd, String resourceType, List<String>resourceIds,
             List<CloudStackKeyValue> resourceTags) {
         if (cmd != null) {
-            cmd.setParam(ApiConstants.RESOURCE_TYPE, resourceType);
+            if (resourceType != null)
+                cmd.setParam(ApiConstants.RESOURCE_TYPE, resourceType);
             if (resourceIds != null && resourceIds.size() > 0) {
                 String resourceIdList = resourceIds.get(0);
                 for (int i=1 ; i<resourceIds.size(); i++)
@@ -1243,7 +1248,7 @@ public class CloudStackApi {
 	 * @throws Exception
 	 */
 	public List<CloudStackSnapshot> listSnapshots(String account, String domainId, String id, String intervalType, Boolean isRecursive,
-			String keyWord, String name, String snapshotType, String volumeId) throws Exception {
+			String keyWord, String name, String snapshotType, String volumeId, List<CloudStackKeyValue> resourceTags) throws Exception {
 		CloudStackCommand cmd = new CloudStackCommand(ApiConstants.LIST_SNAPSHOTS);
 		if (cmd != null) {
 			if (account != null) cmd.setParam(ApiConstants.ACCOUNT, account);
@@ -1255,6 +1260,8 @@ public class CloudStackApi {
 			if (name != null) cmd.setParam(ApiConstants.NAME, name);
 			if (snapshotType != null) cmd.setParam(ApiConstants.SNAPSHOT_TYPE, snapshotType);
 			if (volumeId != null) cmd.setParam(ApiConstants.VOLUME_ID, volumeId);
+			if (resourceTags != null && resourceTags.size() > 0)
+				cmd = setParams(cmd, null, null, resourceTags);			
 		}
 		return _client.listCall(cmd, apiKey, secretKey, ApiConstants.LIST_SNAPSHOTS_RESPONSE, ApiConstants.SNAPSHOT, 
 				new TypeToken<List<CloudStackSnapshot>>() {}.getType());