You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jclouds.apache.org by ab...@apache.org on 2013/09/30 18:36:59 UTC

[3/3] git commit: Fix aws-ec2 live tests

Fix aws-ec2 live tests

Involves some non-trivial reworking of EC2 security group
translation/binding, but it was necessary.

Still problems with a number of tests:
- org.jclouds.aws.ec2.compute.AWSEC2TemplateBuilderLiveTest#testTemplateBuilderWithLessRegions
- org.jclouds.ec2.compute.EC2TemplateBuilderLiveTest#testTemplateBuilderCanUseImageIdWithoutFetchingAllImages

Those seem to be failing because there's caching going on that they're
not expecting, but I could be wrong.

Also failing:
- org.jclouds.aws.ec2.features.PlacementGroupApiLiveTest in general
- org.jclouds.aws.ec2.features.SpotInstanceApiLiveTest - a couple tests


Project: http://git-wip-us.apache.org/repos/asf/incubator-jclouds/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-jclouds/commit/0aa19a0c
Tree: http://git-wip-us.apache.org/repos/asf/incubator-jclouds/tree/0aa19a0c
Diff: http://git-wip-us.apache.org/repos/asf/incubator-jclouds/diff/0aa19a0c

Branch: refs/heads/master
Commit: 0aa19a0ceeea1dd09702e45d0c5f8cbbfa7b945c
Parents: 962f989
Author: Andrew Bayer <an...@gmail.com>
Authored: Fri Sep 27 16:21:19 2013 -0700
Committer: Andrew Bayer <an...@gmail.com>
Committed: Mon Sep 30 09:33:57 2013 -0700

----------------------------------------------------------------------
 .../extensions/EC2SecurityGroupExtension.java   |   7 +-
 .../EC2SecurityGroupToSecurityGroup.java        |   7 +-
 .../org/jclouds/ec2/util/IpPermissions.java     |   2 +-
 .../EC2SecurityGroupExtensionExpectTest.java    |   6 +-
 .../EC2SecurityGroupToSecurityGroupTest.java    |   4 +-
 .../org/jclouds/ec2/util/IpPermissionsTest.java |   2 +-
 .../extensions/NovaSecurityGroupExtension.java  |   5 +
 .../extensions/SecurityGroupExtension.java      |   6 +
 .../extensions/StubSecurityGroupExtension.java  |   7 +-
 .../BaseSecurityGroupExtensionLiveTest.java     |  32 ++---
 .../internal/BaseComputeServiceLiveTest.java    |   8 +-
 providers/aws-ec2/pom.xml                       |   5 +-
 .../AWSEC2ComputeServiceDependenciesModule.java |   4 +-
 .../AWSEC2SecurityGroupExtension.java           |  92 +++++++++---
 .../AWSEC2SecurityGroupToSecurityGroup.java     |  50 +++++++
 .../AWSEC2CreateSecurityGroupIfNeeded.java      |  12 +-
 .../strategy/AWSEC2ListNodesStrategy.java       |  10 +-
 .../aws/ec2/features/AWSSecurityGroupApi.java   |  14 +-
 ...C2DescribeSecurityGroupsResponseHandler.java | 125 ++++++++++++++++
 .../aws/ec2/xml/AWSEC2IpPermissionHandler.java  |  94 ++++++++++++
 .../aws/ec2/xml/AWSEC2SecurityGroupHandler.java | 142 +++++++++++++++++++
 .../compute/AWSEC2ComputeServiceLiveTest.java   |   2 -
 .../compute/AWSEC2TemplateBuilderLiveTest.java  |  14 +-
 .../AWSEC2SecurityGroupExtensionExpectTest.java |  28 ++--
 .../AWSEC2SecurityGroupToSecurityGroupTest.java |  83 +++++++++++
 .../BaseAWSEC2ComputeServiceExpectTest.java     |  24 +++-
 .../AWSEC2CreateSecurityGroupIfNeededTest.java  |   4 +-
 .../aws/ec2/features/AWSKeyPairApiLiveTest.java |   1 -
 .../features/AWSSecurityGroupApiLiveTest.java   |  44 +++++-
 .../ec2/features/AWSSecurityGroupApiTest.java   |   6 +-
 .../ec2/features/PlacementGroupApiLiveTest.java |   6 +-
 .../ec2/features/SpotInstanceApiLiveTest.java   |   3 +-
 32 files changed, 743 insertions(+), 106 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/0aa19a0c/apis/ec2/src/main/java/org/jclouds/ec2/compute/extensions/EC2SecurityGroupExtension.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/compute/extensions/EC2SecurityGroupExtension.java b/apis/ec2/src/main/java/org/jclouds/ec2/compute/extensions/EC2SecurityGroupExtension.java
index fe0201c..ca71620 100644
--- a/apis/ec2/src/main/java/org/jclouds/ec2/compute/extensions/EC2SecurityGroupExtension.java
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/compute/extensions/EC2SecurityGroupExtension.java
@@ -221,7 +221,7 @@ public class EC2SecurityGroupExtension implements SecurityGroupExtension {
             }
          }
       }
-      System.out.println("group: " + group);
+
       return getSecurityGroupById(new RegionAndName(region, group.getName()).slashEncode());
    }
 
@@ -330,6 +330,11 @@ public class EC2SecurityGroupExtension implements SecurityGroupExtension {
    }
 
    @Override
+   public boolean supportsTenantIdGroupIdPairs() {
+      return false;
+   }
+
+   @Override
    public boolean supportsGroupIds() {
       return false;
    }

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/0aa19a0c/apis/ec2/src/main/java/org/jclouds/ec2/compute/functions/EC2SecurityGroupToSecurityGroup.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/compute/functions/EC2SecurityGroupToSecurityGroup.java b/apis/ec2/src/main/java/org/jclouds/ec2/compute/functions/EC2SecurityGroupToSecurityGroup.java
index c46ca68..ffa5443 100644
--- a/apis/ec2/src/main/java/org/jclouds/ec2/compute/functions/EC2SecurityGroupToSecurityGroup.java
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/compute/functions/EC2SecurityGroupToSecurityGroup.java
@@ -31,7 +31,6 @@ import org.jclouds.compute.domain.SecurityGroupBuilder;
 import org.jclouds.compute.reference.ComputeServiceConstants;
 import org.jclouds.domain.Location;
 import org.jclouds.logging.Logger;
-import org.jclouds.net.domain.IpPermission;
 
 import com.google.common.base.Function;
 import com.google.common.base.Predicate;
@@ -64,7 +63,7 @@ public class EC2SecurityGroupToSecurityGroup implements Function<org.jclouds.ec2
       SecurityGroupBuilder builder = new SecurityGroupBuilder();
       Location location = findLocationWithId(group.getRegion());
       builder.location(location);
-      builder.id(group.getName());
+      builder.id(group.getRegion() + "/" + idOrName(group));
       builder.providerId(group.getId());
       builder.name(group.getName());
       builder.ipPermissions(group);
@@ -73,6 +72,10 @@ public class EC2SecurityGroupToSecurityGroup implements Function<org.jclouds.ec2
       return builder.build();
    }
 
+   protected String idOrName(org.jclouds.ec2.domain.SecurityGroup group) {
+      return group.getName();
+   }
+
    private Location findLocationWithId(final String locationId) {
       if (locationId == null)
          return null;

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/0aa19a0c/apis/ec2/src/main/java/org/jclouds/ec2/util/IpPermissions.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/util/IpPermissions.java b/apis/ec2/src/main/java/org/jclouds/ec2/util/IpPermissions.java
index 9c938f0..cc2b68a 100644
--- a/apis/ec2/src/main/java/org/jclouds/ec2/util/IpPermissions.java
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/util/IpPermissions.java
@@ -71,7 +71,7 @@ public class IpPermissions extends IpPermission {
       for (Entry<String, String> tenantIdGroupNamePair : checkNotNull(permission.getTenantIdGroupNamePairs(),
             "tenantIdGroupNamePairs").entries()) {
          headers.put(prefix + i + ".UserId", tenantIdGroupNamePair.getKey());
-         headers.put(prefix + i + ".GroupName", tenantIdGroupNamePair.getValue());
+         headers.put(prefix + i + ".GroupId", tenantIdGroupNamePair.getValue());
          i++;
       }
       prefix = "IpPermissions.%d.IpRanges.";

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/0aa19a0c/apis/ec2/src/test/java/org/jclouds/ec2/compute/extensions/EC2SecurityGroupExtensionExpectTest.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/compute/extensions/EC2SecurityGroupExtensionExpectTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/compute/extensions/EC2SecurityGroupExtensionExpectTest.java
index 89e54f2..496026c 100644
--- a/apis/ec2/src/test/java/org/jclouds/ec2/compute/extensions/EC2SecurityGroupExtensionExpectTest.java
+++ b/apis/ec2/src/test/java/org/jclouds/ec2/compute/extensions/EC2SecurityGroupExtensionExpectTest.java
@@ -27,7 +27,6 @@ import javax.ws.rs.core.MediaType;
 import org.jclouds.compute.domain.SecurityGroup;
 import org.jclouds.compute.domain.SecurityGroupBuilder;
 import org.jclouds.compute.extensions.SecurityGroupExtension;
-import org.jclouds.domain.Location;
 import org.jclouds.domain.LocationBuilder;
 import org.jclouds.domain.LocationScope;
 import org.jclouds.ec2.compute.domain.RegionAndName;
@@ -46,7 +45,6 @@ import com.google.common.collect.Iterables;
 import com.google.common.collect.LinkedHashMultimap;
 import com.google.common.collect.Multimap;
 import com.google.common.collect.Sets;
-import com.google.common.util.concurrent.Futures;
 
 /**
  * 
@@ -189,7 +187,7 @@ public class EC2SecurityGroupExtensionExpectTest extends BaseEC2ComputeServiceEx
       
       SecurityGroup group = extension.getSecurityGroupById(new RegionAndName(region, "jclouds#some-group").slashEncode());
       assertEquals("sg-3c6ef654", group.getProviderId());
-      assertEquals("jclouds#some-group", group.getId());
+      assertEquals(region + "/jclouds#some-group", group.getId());
    }
 
    public void testCreateSecurityGroup() {
@@ -236,7 +234,7 @@ public class EC2SecurityGroupExtensionExpectTest extends BaseEC2ComputeServiceEx
                                                           .build());
       
       assertEquals("sg-3c6ef654", group.getProviderId());
-      assertEquals("jclouds#some-group", group.getId());
+      assertEquals(region + "/jclouds#some-group", group.getId());
    }
 
    public void testRemoveSecurityGroup() {

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/0aa19a0c/apis/ec2/src/test/java/org/jclouds/ec2/compute/functions/EC2SecurityGroupToSecurityGroupTest.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/compute/functions/EC2SecurityGroupToSecurityGroupTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/compute/functions/EC2SecurityGroupToSecurityGroupTest.java
index 9c7d3b1..61eff5b 100644
--- a/apis/ec2/src/test/java/org/jclouds/ec2/compute/functions/EC2SecurityGroupToSecurityGroupTest.java
+++ b/apis/ec2/src/test/java/org/jclouds/ec2/compute/functions/EC2SecurityGroupToSecurityGroupTest.java
@@ -17,12 +17,10 @@
 package org.jclouds.ec2.compute.functions;
 
 import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertTrue;
 
 import java.util.Set;
 
 import org.jclouds.compute.domain.SecurityGroup;
-import org.jclouds.compute.reference.ComputeServiceConstants;
 import org.jclouds.domain.Location;
 import org.jclouds.domain.LocationBuilder;
 import org.jclouds.domain.LocationScope;
@@ -60,7 +58,7 @@ public class EC2SecurityGroupToSecurityGroupTest {
       SecurityGroup group = parser.apply(origGroup);
       
       assertEquals(group.getLocation(), provider);
-      assertEquals(group.getId(), origGroup.getName());
+      assertEquals(group.getId(), provider.getId() + "/" + origGroup.getName());
       assertEquals(group.getProviderId(), origGroup.getId());
       assertEquals(group.getName(), origGroup.getName());
       assertEquals(group.getIpPermissions(), (Set<IpPermission>)origGroup);

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/0aa19a0c/apis/ec2/src/test/java/org/jclouds/ec2/util/IpPermissionsTest.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/util/IpPermissionsTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/util/IpPermissionsTest.java
index 03a2549..242bf59 100644
--- a/apis/ec2/src/test/java/org/jclouds/ec2/util/IpPermissionsTest.java
+++ b/apis/ec2/src/test/java/org/jclouds/ec2/util/IpPermissionsTest.java
@@ -101,6 +101,6 @@ public class IpPermissionsTest {
             "groupId");
       assertEquals(
             IpPermissions.buildFormParametersForIndex(0, authorization).toString(),
-            "{IpPermissions.0.IpProtocol=[icmp], IpPermissions.0.FromPort=[-1], IpPermissions.0.ToPort=[-1], IpPermissions.0.Groups.0.UserId=[userId], IpPermissions.0.Groups.0.GroupName=[groupId]}");
+            "{IpPermissions.0.IpProtocol=[icmp], IpPermissions.0.FromPort=[-1], IpPermissions.0.ToPort=[-1], IpPermissions.0.Groups.0.UserId=[userId], IpPermissions.0.Groups.0.GroupId=[groupId]}");
    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/0aa19a0c/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/extensions/NovaSecurityGroupExtension.java
----------------------------------------------------------------------
diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/extensions/NovaSecurityGroupExtension.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/extensions/NovaSecurityGroupExtension.java
index 416e3a9..71d3032 100644
--- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/extensions/NovaSecurityGroupExtension.java
+++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/extensions/NovaSecurityGroupExtension.java
@@ -372,6 +372,11 @@ public class NovaSecurityGroupExtension implements SecurityGroupExtension {
    }
 
    @Override
+   public boolean supportsTenantIdGroupIdPairs() {
+      return false;
+   }
+
+   @Override
    public boolean supportsGroupIds() {
       return true;
    }

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/0aa19a0c/compute/src/main/java/org/jclouds/compute/extensions/SecurityGroupExtension.java
----------------------------------------------------------------------
diff --git a/compute/src/main/java/org/jclouds/compute/extensions/SecurityGroupExtension.java b/compute/src/main/java/org/jclouds/compute/extensions/SecurityGroupExtension.java
index f07e72d..19a6f37 100644
--- a/compute/src/main/java/org/jclouds/compute/extensions/SecurityGroupExtension.java
+++ b/compute/src/main/java/org/jclouds/compute/extensions/SecurityGroupExtension.java
@@ -168,6 +168,12 @@ public interface SecurityGroupExtension {
    boolean supportsTenantIdGroupNamePairs();
 
    /**
+    * Returns true if this SecurityGroupExtension supports tenant ID + group ID pairs.
+    */
+   boolean supportsTenantIdGroupIdPairs();
+
+
+   /**
     * Returns true if this SecurityGroupExtension supports group IDs.
     */
    boolean supportsGroupIds();

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/0aa19a0c/compute/src/main/java/org/jclouds/compute/stub/extensions/StubSecurityGroupExtension.java
----------------------------------------------------------------------
diff --git a/compute/src/main/java/org/jclouds/compute/stub/extensions/StubSecurityGroupExtension.java b/compute/src/main/java/org/jclouds/compute/stub/extensions/StubSecurityGroupExtension.java
index 5e8fdd9..1825287 100644
--- a/compute/src/main/java/org/jclouds/compute/stub/extensions/StubSecurityGroupExtension.java
+++ b/compute/src/main/java/org/jclouds/compute/stub/extensions/StubSecurityGroupExtension.java
@@ -42,8 +42,6 @@ import com.google.common.base.Supplier;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Multimap;
-import com.google.common.collect.Sets;
-import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.ListeningExecutorService;
 
 /**
@@ -245,6 +243,11 @@ public class StubSecurityGroupExtension implements SecurityGroupExtension {
    }
 
    @Override
+   public boolean supportsTenantIdGroupIdPairs() {
+      return false;
+   }
+
+   @Override
    public boolean supportsGroupIds() {
       return true;
    }

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/0aa19a0c/compute/src/test/java/org/jclouds/compute/extensions/internal/BaseSecurityGroupExtensionLiveTest.java
----------------------------------------------------------------------
diff --git a/compute/src/test/java/org/jclouds/compute/extensions/internal/BaseSecurityGroupExtensionLiveTest.java b/compute/src/test/java/org/jclouds/compute/extensions/internal/BaseSecurityGroupExtensionLiveTest.java
index 9a63763..3f775d2 100644
--- a/compute/src/test/java/org/jclouds/compute/extensions/internal/BaseSecurityGroupExtensionLiveTest.java
+++ b/compute/src/test/java/org/jclouds/compute/extensions/internal/BaseSecurityGroupExtensionLiveTest.java
@@ -16,8 +16,6 @@
  */
 package org.jclouds.compute.extensions.internal;
 
-import static com.google.common.collect.Iterables.filter;
-import static org.jclouds.compute.predicates.NodePredicates.inGroup;
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertTrue;
 
@@ -234,7 +232,8 @@ public abstract class BaseSecurityGroupExtensionLiveTest extends BaseComputeServ
          assertTrue(secondNewGroup.getIpPermissions().contains(secondPerm)); 
       }
 
-      if (securityGroupExtension.get().supportsTenantIdGroupNamePairs()) {
+      if (securityGroupExtension.get().supportsTenantIdGroupNamePairs()
+              || securityGroupExtension.get().supportsTenantIdGroupIdPairs()) {
          IpPermission.Builder thirdBuilder = IpPermission.builder();
 
          int fromPort;
@@ -250,8 +249,12 @@ public abstract class BaseSecurityGroupExtensionLiveTest extends BaseComputeServ
          thirdBuilder.ipProtocol(IpProtocol.TCP);
          thirdBuilder.fromPort(fromPort);
          thirdBuilder.toPort(toPort);
-         thirdBuilder.tenantIdGroupNamePair(group.getOwnerId(), group.getId());
-         
+         if (securityGroupExtension.get().supportsTenantIdGroupIdPairs()) {
+            thirdBuilder.tenantIdGroupNamePair(group.getOwnerId(), group.getProviderId());
+         } else if (securityGroupExtension.get().supportsTenantIdGroupNamePairs()) {
+            thirdBuilder.tenantIdGroupNamePair(group.getOwnerId(), group.getName());
+         }
+
          IpPermission thirdPerm = thirdBuilder.build();
 
          SecurityGroup thirdNewGroup = securityGroupExtension.get().addIpPermission(IpProtocol.TCP,
@@ -262,7 +265,7 @@ public abstract class BaseSecurityGroupExtensionLiveTest extends BaseComputeServ
                                                                                     emptyStringSet(),
                                                                                     newGroup);
 
-         assertTrue(thirdNewGroup.getIpPermissions().contains(thirdPerm)); 
+         assertTrue(thirdNewGroup.getIpPermissions().contains(thirdPerm));
       }
    }
 
@@ -316,7 +319,6 @@ public abstract class BaseSecurityGroupExtensionLiveTest extends BaseComputeServ
       assertTrue(optGroup.isPresent());
 
       SecurityGroup group = optGroup.get();
-
       assertTrue(securityGroupExtension.get().removeSecurityGroup(group.getId()));
    }
    
@@ -346,16 +348,10 @@ public abstract class BaseSecurityGroupExtensionLiveTest extends BaseComputeServ
       Optional<SecurityGroupExtension> securityGroupExtension = computeService.getSecurityGroupExtension();
 
       if (securityGroupExtension.isPresent()) {
-         SecurityGroup group = Iterables.getFirst(filter(securityGroupExtension.get().listSecurityGroups(),
-                 new Predicate<SecurityGroup>() {
-                    @Override
-                    public boolean apply(SecurityGroup input) {
-                       return secGroupName.equals(input.getName());
-                    }
-                 }), null);
-
-         if (group != null) {
-            securityGroupExtension.get().removeSecurityGroup(group.getId());
+         Optional<SecurityGroup> group = getGroup(securityGroupExtension.get());
+
+         if (group.isPresent()) {
+            securityGroupExtension.get().removeSecurityGroup(group.get().getId());
          }
       }
    }
@@ -365,8 +361,6 @@ public abstract class BaseSecurityGroupExtensionLiveTest extends BaseComputeServ
    @Override
    protected void tearDownContext() {
       try {
-         view.getComputeService().destroyNodesMatching(inGroup(nodeGroup));
-
          cleanup();
       } catch (Exception e) {
 

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/0aa19a0c/compute/src/test/java/org/jclouds/compute/internal/BaseComputeServiceLiveTest.java
----------------------------------------------------------------------
diff --git a/compute/src/test/java/org/jclouds/compute/internal/BaseComputeServiceLiveTest.java b/compute/src/test/java/org/jclouds/compute/internal/BaseComputeServiceLiveTest.java
index 435173f..ca5102e 100644
--- a/compute/src/test/java/org/jclouds/compute/internal/BaseComputeServiceLiveTest.java
+++ b/compute/src/test/java/org/jclouds/compute/internal/BaseComputeServiceLiveTest.java
@@ -45,6 +45,7 @@ import static org.jclouds.compute.util.ComputeServiceUtils.getCores;
 import static org.jclouds.util.Predicates2.retry;
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
 import static org.testng.Assert.fail;
 
 import java.io.IOException;
@@ -102,6 +103,7 @@ import com.google.common.base.Predicates;
 import com.google.common.base.Stopwatch;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.ImmutableSortedSet;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
@@ -573,9 +575,11 @@ public abstract class BaseComputeServiceLiveTest extends BaseComputeServiceConte
             }
             
          }));
-      
+
+      SortedSet<NodeMetadata> listedNodes = ImmutableSortedSet.copyOf(client.listNodesByIds(nodeIds));
       // newTreeSet is here because elementsEqual cares about ordering.
-      assert Iterables.elementsEqual(nodes, newTreeSet(client.listNodesByIds(nodeIds))); 
+      assertTrue(Iterables.elementsEqual(nodes, listedNodes),
+              "nodes and listNodesByIds should be identical: was " + listedNodes + " but should be " + nodes);
    }
 
    @Test(enabled = true, dependsOnMethods = "testSuspendResume")

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/0aa19a0c/providers/aws-ec2/pom.xml
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/pom.xml b/providers/aws-ec2/pom.xml
index 8d05c15..4ae25b1 100644
--- a/providers/aws-ec2/pom.xml
+++ b/providers/aws-ec2/pom.xml
@@ -37,9 +37,10 @@
     <test.aws-ec2.build-version />
     <test.aws-ec2.identity>${test.aws.identity}</test.aws-ec2.identity>
     <test.aws-ec2.credential>${test.aws.credential}</test.aws-ec2.credential>
+
     <test.aws-ec2.template />
-    <!-- https://aws.amazon.com/amazon-linux-ami/ EBS-Backed 32-bit Oregon -->
-    <test.aws-ec2.ebs-template>hardwareId=m1.small,imageId=us-west-2/ami-2231bf12</test.aws-ec2.ebs-template>
+    <!-- Active EBS template as of 9/25/2013 -->
+    <test.aws-ec2.ebs-template>hardwareId=m1.small,imageId=us-east-1/ami-53b1ff3a</test.aws-ec2.ebs-template>
     <!-- Windows_Server-2008-R2 with WinRM enabled (setup instructions at http://www.frontiertown.co.uk/2011/12/overthere-control-windows-from-java/) -->
     <test.aws-ec2.windows-template>hardwareId=m1.small,imageId=us-east-1/ami-0cb76d65</test.aws-ec2.windows-template>
     <jclouds.osgi.export>org.jclouds.aws.ec2*;version="${project.version}"</jclouds.osgi.export>

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/0aa19a0c/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/config/AWSEC2ComputeServiceDependenciesModule.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/config/AWSEC2ComputeServiceDependenciesModule.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/config/AWSEC2ComputeServiceDependenciesModule.java
index 6abac69..466deb1 100644
--- a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/config/AWSEC2ComputeServiceDependenciesModule.java
+++ b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/config/AWSEC2ComputeServiceDependenciesModule.java
@@ -32,6 +32,7 @@ import javax.inject.Singleton;
 import org.jclouds.aws.ec2.compute.AWSEC2ComputeService;
 import org.jclouds.aws.ec2.compute.AWSEC2TemplateOptions;
 import org.jclouds.aws.ec2.compute.extensions.AWSEC2SecurityGroupExtension;
+import org.jclouds.aws.ec2.compute.functions.AWSEC2SecurityGroupToSecurityGroup;
 import org.jclouds.aws.ec2.compute.loaders.AWSEC2CreateSecurityGroupIfNeeded;
 import org.jclouds.aws.ec2.compute.suppliers.CallForImages;
 import org.jclouds.aws.ec2.domain.PlacementGroup;
@@ -57,7 +58,6 @@ import org.jclouds.ec2.compute.functions.CreateUniqueKeyPair;
 import org.jclouds.ec2.compute.functions.CredentialsForInstance;
 import org.jclouds.ec2.compute.functions.EC2ImageParser;
 import org.jclouds.ec2.compute.functions.EC2SecurityGroupIdFromName;
-import org.jclouds.ec2.compute.functions.EC2SecurityGroupToSecurityGroup;
 import org.jclouds.ec2.compute.functions.PasswordCredentialsFromWindowsInstance;
 import org.jclouds.ec2.compute.functions.WindowsLoginCredentialsFromEncryptedData;
 import org.jclouds.ec2.compute.internal.EC2TemplateBuilderImpl;
@@ -113,7 +113,7 @@ public class AWSEC2ComputeServiceDependenciesModule extends EC2ComputeServiceDep
       bind(new TypeLiteral<Function<org.jclouds.ec2.domain.Image, Image>>() {
       }).to(EC2ImageParser.class);
       bind(new TypeLiteral<Function<org.jclouds.ec2.domain.SecurityGroup, SecurityGroup>>() {
-      }).to(EC2SecurityGroupToSecurityGroup.class);
+      }).to(AWSEC2SecurityGroupToSecurityGroup.class);
       bind(new TypeLiteral<ImageExtension>() {
       }).to(EC2ImageExtension.class);
       bind(new TypeLiteral<SecurityGroupExtension>() {

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/0aa19a0c/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/extensions/AWSEC2SecurityGroupExtension.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/extensions/AWSEC2SecurityGroupExtension.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/extensions/AWSEC2SecurityGroupExtension.java
index fff36d9..3b04335 100644
--- a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/extensions/AWSEC2SecurityGroupExtension.java
+++ b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/extensions/AWSEC2SecurityGroupExtension.java
@@ -17,6 +17,10 @@
 package org.jclouds.aws.ec2.compute.extensions;
 
 import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Predicates.notNull;
+import static com.google.common.collect.Iterables.filter;
+import static com.google.common.collect.Iterables.getOnlyElement;
+import static com.google.common.collect.Iterables.transform;
 
 import java.util.Set;
 
@@ -31,6 +35,7 @@ import org.jclouds.compute.domain.SecurityGroup;
 import org.jclouds.compute.functions.GroupNamingConvention;
 import org.jclouds.domain.Location;
 import org.jclouds.ec2.compute.domain.RegionAndName;
+import org.jclouds.ec2.compute.domain.RegionNameAndIngressRules;
 import org.jclouds.ec2.compute.extensions.EC2SecurityGroupExtension;
 import org.jclouds.location.Region;
 import org.jclouds.net.domain.IpPermission;
@@ -67,16 +72,59 @@ public class AWSEC2SecurityGroupExtension extends EC2SecurityGroupExtension {
       this.groupNameToId = checkNotNull(groupNameToId, "groupNameToId");
    }
 
+   @Override
+   public SecurityGroup createSecurityGroup(String name, String region) {
+      String markerGroup = namingConvention.create().sharedNameForGroup(name);
+      RegionNameAndIngressRules regionAndName = new RegionNameAndIngressRules(region, markerGroup, new int[] {},
+              false);
+
+      groupCreator.getUnchecked(regionAndName);
+      String groupId = groupNameToId.apply(markerGroup);
+      return getSecurityGroupById(regionAndName.getRegion() + "/" + groupId);
+   }
+
+   @Override
+   public SecurityGroup getSecurityGroupById(String id) {
+      checkNotNull(id, "id");
+      String[] parts = AWSUtils.parseHandle(id);
+      String region = parts[0];
+      String groupId = parts[1];
+
+      Set<? extends org.jclouds.ec2.domain.SecurityGroup> rawGroups =
+              client.getSecurityGroupApi().get().describeSecurityGroupsInRegionById(region, groupId);
+
+      return getOnlyElement(transform(filter(rawGroups, notNull()), groupConverter));
+   }
+
+   @Override
+   public boolean removeSecurityGroup(String id) {
+      checkNotNull(id, "id");
+      String[] parts = AWSUtils.parseHandle(id);
+      String region = parts[0];
+      String groupId = parts[1];
+
+      org.jclouds.ec2.domain.SecurityGroup group = Iterables.getFirst(
+              client.getSecurityGroupApi().get().describeSecurityGroupsInRegionById(region, groupId),
+              null);
+
+      if (group != null) {
+         client.getSecurityGroupApi().get().deleteSecurityGroupInRegionById(region, groupId);
+         // TODO: test this clear happens
+         groupCreator.invalidate(new RegionNameAndIngressRules(region, group.getName(), null, false));
+         return true;
+      }
+
+      return false;
+   }
 
    @Override
    public SecurityGroup addIpPermission(IpPermission ipPermission, SecurityGroup group) {
       String region = AWSUtils.getRegionFromLocationOrNull(group.getLocation());
-      String name = group.getName();
-      String id = groupNameToId.apply(new RegionAndName(region, name).slashEncode());
+      String id = group.getProviderId();
 
       client.getSecurityGroupApi().get().authorizeSecurityGroupIngressInRegion(region, id, ipPermission);
 
-      return getSecurityGroupById(new RegionAndName(region, group.getName()).slashEncode());
+      return getSecurityGroupById(group.getId());
    }
 
    @Override
@@ -85,8 +133,7 @@ public class AWSEC2SecurityGroupExtension extends EC2SecurityGroupExtension {
                                         Iterable<String> ipRanges,
                                         Iterable<String> groupIds, SecurityGroup group) {
       String region = AWSUtils.getRegionFromLocationOrNull(group.getLocation());
-      String name = group.getName();
-      String id = groupNameToId.apply(new RegionAndName(region, name).slashEncode());
+      String id = group.getProviderId();
 
       IpPermission.Builder builder = IpPermission.builder();
 
@@ -102,26 +149,27 @@ public class AWSEC2SecurityGroupExtension extends EC2SecurityGroupExtension {
 
       if (tenantIdGroupNamePairs.size() > 0) {
          for (String userId : tenantIdGroupNamePairs.keySet()) {
-            for (String groupName : tenantIdGroupNamePairs.get(userId)) {
-               builder.tenantIdGroupNamePair(userId, groupName);
+            for (String groupString : tenantIdGroupNamePairs.get(userId)) {
+               String[] parts = AWSUtils.parseHandle(groupString);
+               String groupId = parts[1];
+               builder.tenantIdGroupNamePair(userId, groupId);
             }
          }
       }
 
       client.getSecurityGroupApi().get().authorizeSecurityGroupIngressInRegion(region, id, builder.build());
 
-      return getSecurityGroupById(new RegionAndName(region, group.getName()).slashEncode());
+      return getSecurityGroupById(group.getId());
    }
       
    @Override
    public SecurityGroup removeIpPermission(IpPermission ipPermission, SecurityGroup group) {
       String region = AWSUtils.getRegionFromLocationOrNull(group.getLocation());
-      String name = group.getName();
-      String id = groupNameToId.apply(new RegionAndName(region, name).slashEncode());
+      String id = group.getProviderId();
 
       client.getSecurityGroupApi().get().revokeSecurityGroupIngressInRegion(region, id, ipPermission);
 
-      return getSecurityGroupById(new RegionAndName(region, group.getName()).slashEncode());
+      return getSecurityGroupById(group.getId());
    }
 
    @Override
@@ -130,8 +178,7 @@ public class AWSEC2SecurityGroupExtension extends EC2SecurityGroupExtension {
                                            Iterable<String> ipRanges,
                                            Iterable<String> groupIds, SecurityGroup group) {
       String region = AWSUtils.getRegionFromLocationOrNull(group.getLocation());
-      String name = group.getName();
-      String id = groupNameToId.apply(new RegionAndName(region, name).slashEncode());
+      String id = group.getProviderId();
 
       IpPermission.Builder builder = IpPermission.builder();
 
@@ -147,14 +194,27 @@ public class AWSEC2SecurityGroupExtension extends EC2SecurityGroupExtension {
 
       if (tenantIdGroupNamePairs.size() > 0) {
          for (String userId : tenantIdGroupNamePairs.keySet()) {
-            for (String groupName : tenantIdGroupNamePairs.get(userId)) {
-               builder.tenantIdGroupNamePair(userId, groupName);
+            for (String groupString : tenantIdGroupNamePairs.get(userId)) {
+               String[] parts = AWSUtils.parseHandle(groupString);
+               String groupId = parts[1];
+               builder.tenantIdGroupNamePair(userId, groupId);
             }
          }
       }
 
       client.getSecurityGroupApi().get().revokeSecurityGroupIngressInRegion(region, id, builder.build());
 
-      return getSecurityGroupById(new RegionAndName(region, group.getName()).slashEncode());
+      return getSecurityGroupById(group.getId());
+   }
+
+   @Override
+   public boolean supportsTenantIdGroupNamePairs() {
+      return false;
    }
+
+   @Override
+   public boolean supportsTenantIdGroupIdPairs() {
+      return true;
+   }
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/0aa19a0c/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/functions/AWSEC2SecurityGroupToSecurityGroup.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/functions/AWSEC2SecurityGroupToSecurityGroup.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/functions/AWSEC2SecurityGroupToSecurityGroup.java
new file mode 100644
index 0000000..b0c3cd3
--- /dev/null
+++ b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/functions/AWSEC2SecurityGroupToSecurityGroup.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.aws.ec2.compute.functions;
+
+import java.util.Set;
+
+import javax.inject.Singleton;
+
+import org.jclouds.collect.Memoized;
+import org.jclouds.domain.Location;
+import org.jclouds.ec2.compute.functions.EC2SecurityGroupToSecurityGroup;
+
+import com.google.common.base.Supplier;
+import com.google.inject.Inject;
+
+
+/**
+ * A function for transforming an EC2-specific SecurityGroup into a generic
+ * SecurityGroup object.
+ * 
+ * @author Andrew Bayer
+ */
+@Singleton
+public class AWSEC2SecurityGroupToSecurityGroup extends EC2SecurityGroupToSecurityGroup {
+
+   @Inject
+   public AWSEC2SecurityGroupToSecurityGroup(@Memoized Supplier<Set<? extends Location>> locations) {
+      super(locations);
+   }
+
+   @Override
+   protected String idOrName(org.jclouds.ec2.domain.SecurityGroup group) {
+      return group.getId();
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/0aa19a0c/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/loaders/AWSEC2CreateSecurityGroupIfNeeded.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/loaders/AWSEC2CreateSecurityGroupIfNeeded.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/loaders/AWSEC2CreateSecurityGroupIfNeeded.java
index 26a2ded..a9c1391 100644
--- a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/loaders/AWSEC2CreateSecurityGroupIfNeeded.java
+++ b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/loaders/AWSEC2CreateSecurityGroupIfNeeded.java
@@ -82,6 +82,7 @@ public class AWSEC2CreateSecurityGroupIfNeeded extends CacheLoader<RegionAndName
       checkNotNull(region, "region");
       checkNotNull(name, "name");
       logger.debug(">> creating securityGroup region(%s) name(%s)", region, name);
+
       try {
          securityApi.createSecurityGroupInRegion(region, name, name);
          boolean created = securityGroupEventualConsistencyDelay.apply(new RegionAndName(region, name));
@@ -91,6 +92,12 @@ public class AWSEC2CreateSecurityGroupIfNeeded extends CacheLoader<RegionAndName
          logger.debug("<< created securityGroup(%s)", name);
 
          ImmutableSet.Builder<IpPermission> permissions = ImmutableSet.builder();
+         String id;
+         if (name.startsWith("sg-")) {
+            id = name;
+         } else {
+            id = groupNameToId.apply(new RegionAndName(region, name).slashEncode());
+         }
 
          if (ports.length > 0) {
             for (Map.Entry<Integer, Integer> range : getPortRangesFromList(ports).entrySet()) {
@@ -107,20 +114,19 @@ public class AWSEC2CreateSecurityGroupIfNeeded extends CacheLoader<RegionAndName
                             .fromPort(0)
                             .toPort(65535)
                             .ipProtocol(IpProtocol.TCP)
-                            .tenantIdGroupNamePair(myOwnerId, name)
+                            .tenantIdGroupNamePair(myOwnerId, id)
                             .build());
             permissions.add(IpPermission.builder()
                             .fromPort(0)
                             .toPort(65535)
                             .ipProtocol(IpProtocol.UDP)
-                            .tenantIdGroupNamePair(myOwnerId, name)
+                            .tenantIdGroupNamePair(myOwnerId, id)
                             .build());
          }
 
          Set<IpPermission> perms = permissions.build();
 
          if (perms.size() > 0) {
-            String id = groupNameToId.apply(new RegionAndName(region, name).slashEncode());
             logger.debug(">> authorizing securityGroup region(%s) name(%s) IpPermissions(%s)", region, name, perms);
             securityApi.authorizeSecurityGroupIngressInRegion(region, id, perms);
             logger.debug("<< authorized securityGroup(%s)", name);

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/0aa19a0c/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/strategy/AWSEC2ListNodesStrategy.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/strategy/AWSEC2ListNodesStrategy.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/strategy/AWSEC2ListNodesStrategy.java
index 0d3b034..91b5c45 100644
--- a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/strategy/AWSEC2ListNodesStrategy.java
+++ b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/strategy/AWSEC2ListNodesStrategy.java
@@ -22,9 +22,7 @@ import static com.google.common.collect.Iterables.concat;
 import static com.google.common.collect.Iterables.filter;
 import static com.google.common.collect.Iterables.toArray;
 import static com.google.common.collect.Iterables.transform;
-import static org.jclouds.concurrent.FutureIterables.transformParallel;
 
-import java.util.Map.Entry;
 import java.util.Set;
 
 import javax.inject.Named;
@@ -42,9 +40,7 @@ import org.jclouds.location.Region;
 
 import com.google.common.base.Function;
 import com.google.common.base.Supplier;
-import com.google.common.collect.Iterables;
 import com.google.common.collect.Multimap;
-import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.ListeningExecutorService;
 import com.google.inject.Inject;
 
@@ -83,8 +79,10 @@ public class AWSEC2ListNodesStrategy extends EC2ListNodesStrategy {
                                                                                        spotInstancesByIdInRegion(idsByRegions))),
 
                                                                       spotConverter), notNull());
-
-      return concat(super.pollRunningInstancesByRegionsAndIds(idsByRegions), spots);
+      System.err.println("spots: " + spots);
+      Iterable<? extends RunningInstance> superInsts = super.pollRunningInstancesByRegionsAndIds(idsByRegions);
+      System.err.println("superInsts: " + superInsts);
+      return concat(superInsts, spots);
    }
 
    protected Function<String, Set<SpotInstanceRequest>> allSpotInstancesInRegion() {

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/0aa19a0c/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/features/AWSSecurityGroupApi.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/features/AWSSecurityGroupApi.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/features/AWSSecurityGroupApi.java
index d71d544..6f0f761 100644
--- a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/features/AWSSecurityGroupApi.java
+++ b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/features/AWSSecurityGroupApi.java
@@ -28,14 +28,15 @@ import javax.ws.rs.Path;
 import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
 import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
 import org.jclouds.aws.ec2.options.CreateSecurityGroupOptions;
+import org.jclouds.aws.ec2.xml.AWSEC2DescribeSecurityGroupsResponseHandler;
 import org.jclouds.aws.ec2.xml.CreateSecurityGroupResponseHandler;
 import org.jclouds.aws.filters.FormSigner;
 import org.jclouds.ec2.binders.BindGroupIdsToIndexedFormParams;
+import org.jclouds.ec2.binders.BindGroupNamesToIndexedFormParams;
 import org.jclouds.ec2.binders.BindIpPermissionToIndexedFormParams;
 import org.jclouds.ec2.binders.BindIpPermissionsToIndexedFormParams;
 import org.jclouds.ec2.domain.SecurityGroup;
 import org.jclouds.ec2.features.SecurityGroupApi;
-import org.jclouds.ec2.xml.DescribeSecurityGroupsResponseHandler;
 import org.jclouds.javax.annotation.Nullable;
 import org.jclouds.location.functions.RegionToEndpointOrProviderIfNull;
 import org.jclouds.net.domain.IpPermission;
@@ -116,10 +117,19 @@ public interface AWSSecurityGroupApi extends SecurityGroupApi {
    @POST
    @Path("/")
    @FormParams(keys = ACTION, values = "DescribeSecurityGroups")
-   @XMLResponseParser(DescribeSecurityGroupsResponseHandler.class)
+   @XMLResponseParser(AWSEC2DescribeSecurityGroupsResponseHandler.class)
    @Fallback(EmptySetOnNotFoundOr404.class)
    Set<SecurityGroup> describeSecurityGroupsInRegionById(
             @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
             @BinderParam(BindGroupIdsToIndexedFormParams.class) String... securityGroupNames);
 
+   @Named("DescribeSecurityGroups")
+   @POST
+   @Path("/")
+   @FormParams(keys = ACTION, values = "DescribeSecurityGroups")
+   @XMLResponseParser(AWSEC2DescribeSecurityGroupsResponseHandler.class)
+   @Fallback(EmptySetOnNotFoundOr404.class)
+   Set<SecurityGroup> describeSecurityGroupsInRegion(
+           @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+           @BinderParam(BindGroupNamesToIndexedFormParams.class) String... securityGroupNames);
 }

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/0aa19a0c/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/xml/AWSEC2DescribeSecurityGroupsResponseHandler.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/xml/AWSEC2DescribeSecurityGroupsResponseHandler.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/xml/AWSEC2DescribeSecurityGroupsResponseHandler.java
new file mode 100644
index 0000000..4c25f3e
--- /dev/null
+++ b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/xml/AWSEC2DescribeSecurityGroupsResponseHandler.java
@@ -0,0 +1,125 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.aws.ec2.xml;
+
+import static org.jclouds.util.SaxUtils.equalsOrSuffix;
+
+import java.util.Set;
+
+import javax.inject.Inject;
+
+import org.jclouds.ec2.domain.SecurityGroup;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.functions.ParseSax.HandlerForGeneratedRequestWithResult;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.ImmutableSet.Builder;
+
+/**
+ * Parses: DescribeSecurityGroupsResponse
+ * xmlns="http://ec2.amazonaws.com/doc/2010-06-15/"
+ *
+ * @see <a href=
+ *      "http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/index.html?ApiReference-query-DescribesecurityGroupInfo.html"
+ *      />
+ * @author Adrian Cole
+ */
+public class AWSEC2DescribeSecurityGroupsResponseHandler extends
+      HandlerForGeneratedRequestWithResult<Set<SecurityGroup>> {
+
+   private final AWSEC2SecurityGroupHandler securityGroupHandler;
+
+   private StringBuilder currentText = new StringBuilder();
+   private Builder<SecurityGroup> securityGroups = ImmutableSet.<SecurityGroup> builder();
+   private boolean inSecurityGroupInfo;
+
+   protected int itemDepth;
+
+   @Inject
+   public AWSEC2DescribeSecurityGroupsResponseHandler(AWSEC2SecurityGroupHandler securityGroupHandler) {
+      this.securityGroupHandler = securityGroupHandler;
+   }
+
+   @Override
+   public HandlerForGeneratedRequestWithResult<Set<SecurityGroup>> setContext(HttpRequest request) {
+      securityGroupHandler.setContext(request);
+      return super.setContext(request);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public Set<SecurityGroup> getResult() {
+      return securityGroups.build();
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public void startElement(String url, String name, String qName, Attributes attributes) throws SAXException {
+      if (equalsOrSuffix(qName, "item")) {
+         itemDepth++;
+      } else if (equalsOrSuffix(qName, "securityGroupInfo")) {
+         inSecurityGroupInfo = true;
+      }
+      if (inSecurityGroupInfo) {
+         securityGroupHandler.startElement(url, name, qName, attributes);
+      }
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public void endElement(String uri, String name, String qName) throws SAXException {
+      if (equalsOrSuffix(qName, "item")) {
+         endItem(uri, name, qName);
+         itemDepth--;
+      } else if (equalsOrSuffix(qName, "securityGroupInfo")) {
+         inSecurityGroupInfo = false;
+      } else if (inSecurityGroupInfo) {
+         securityGroupHandler.endElement(uri, name, qName);
+      }
+      currentText = new StringBuilder();
+   }
+
+   protected void endItem(String uri, String name, String qName) throws SAXException {
+      if (inSecurityGroupInfo) {
+         if (itemDepth == 1)
+            securityGroups.add(securityGroupHandler.getResult());
+         else
+            securityGroupHandler.endElement(uri, name, qName);
+      }
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public void characters(char ch[], int start, int length) {
+      if (inSecurityGroupInfo) {
+         securityGroupHandler.characters(ch, start, length);
+      } else {
+         currentText.append(ch, start, length);
+      }
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/0aa19a0c/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/xml/AWSEC2IpPermissionHandler.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/xml/AWSEC2IpPermissionHandler.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/xml/AWSEC2IpPermissionHandler.java
new file mode 100644
index 0000000..392fb5f
--- /dev/null
+++ b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/xml/AWSEC2IpPermissionHandler.java
@@ -0,0 +1,94 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.aws.ec2.xml;
+
+import static org.jclouds.util.SaxUtils.currentOrNull;
+import static org.jclouds.util.SaxUtils.equalsOrSuffix;
+
+import org.jclouds.http.functions.ParseSax;
+import org.jclouds.net.domain.IpPermission;
+import org.jclouds.net.domain.IpProtocol;
+import org.xml.sax.SAXException;
+
+/**
+ *
+ * @author Adrian Cole
+ */
+public class AWSEC2IpPermissionHandler extends ParseSax.HandlerForGeneratedRequestWithResult<IpPermission> {
+
+   private StringBuilder currentText = new StringBuilder();
+   private IpPermission.Builder builder = IpPermission.builder();
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public IpPermission getResult() {
+      try {
+         return builder.build();
+      } finally {
+         builder = IpPermission.builder();
+      }
+   }
+
+   private String userId;
+   private String groupId;
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public void endElement(String uri, String name, String qName) throws SAXException {
+      if (equalsOrSuffix(qName, "ipProtocol")) {
+         // Algorete: ipProtocol can be an empty tag on EC2 clone (e.g.
+         // OpenStack EC2)
+         builder.ipProtocol(IpProtocol.fromValue(currentOrNegative(currentText)));
+      } else if (equalsOrSuffix(qName, "fromPort")) {
+         // Algorete: fromPort can be an empty tag on EC2 clone (e.g. OpenStack
+         // EC2)
+         builder.fromPort(Integer.parseInt(currentOrNegative(currentText)));
+      } else if (equalsOrSuffix(qName, "toPort")) {
+         // Algorete: toPort can be an empty tag on EC2 clone (e.g. OpenStack
+         // EC2)
+         builder.toPort(Integer.parseInt(currentOrNegative(currentText)));
+      } else if (equalsOrSuffix(qName, "cidrIp")) {
+         builder.cidrBlock(currentOrNull(currentText));
+      } else if (equalsOrSuffix(qName, "userId")) {
+         this.userId = currentOrNull(currentText);
+      } else if (equalsOrSuffix(qName, "groupId")) {
+         this.groupId = currentOrNull(currentText);
+      } else if (equalsOrSuffix(qName, "item")) {
+         if (userId != null && groupId != null)
+            builder.tenantIdGroupNamePair(userId, groupId);
+         userId = groupId = null;
+      }
+      currentText = new StringBuilder();
+   }
+
+   private static String currentOrNegative(StringBuilder currentText) {
+      String returnVal = currentText.toString().trim();
+      return returnVal.equals("") ? "-1" : returnVal;
+   }
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public void characters(char ch[], int start, int length) {
+      currentText.append(ch, start, length);
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/0aa19a0c/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/xml/AWSEC2SecurityGroupHandler.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/xml/AWSEC2SecurityGroupHandler.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/xml/AWSEC2SecurityGroupHandler.java
new file mode 100644
index 0000000..552303b
--- /dev/null
+++ b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/xml/AWSEC2SecurityGroupHandler.java
@@ -0,0 +1,142 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.aws.ec2.xml;
+
+import static org.jclouds.util.SaxUtils.currentOrNull;
+import static org.jclouds.util.SaxUtils.equalsOrSuffix;
+
+import org.jclouds.aws.util.AWSUtils;
+import org.jclouds.ec2.domain.SecurityGroup;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.functions.ParseSax.HandlerForGeneratedRequestWithResult;
+import org.jclouds.location.Region;
+import org.jclouds.rest.internal.GeneratedHttpRequest;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+
+import com.google.common.base.Supplier;
+import com.google.inject.Inject;
+
+/**
+ * @author Adrian Cole
+ */
+public class AWSEC2SecurityGroupHandler extends HandlerForGeneratedRequestWithResult<SecurityGroup> {
+
+   protected final AWSEC2IpPermissionHandler ipPermissionHandler;
+   protected final Supplier<String> defaultRegion;
+
+   protected StringBuilder currentText = new StringBuilder();
+   protected SecurityGroup.Builder<?> builder;
+   protected boolean inIpPermissions;
+
+   protected int itemDepth;
+
+   protected String region;
+
+   @Inject
+   public AWSEC2SecurityGroupHandler(AWSEC2IpPermissionHandler ipPermissionHandler, @Region Supplier<String> defaultRegion) {
+      this.ipPermissionHandler = ipPermissionHandler;
+      this.defaultRegion = defaultRegion;
+   }
+
+   protected SecurityGroup.Builder<?> builder() {
+      return SecurityGroup.builder().region(region);
+   }
+
+   @Override
+   public HandlerForGeneratedRequestWithResult<SecurityGroup> setContext(HttpRequest request) {
+      region = AWSUtils.findRegionInArgsOrNull(GeneratedHttpRequest.class.cast(request));
+      if (region == null)
+         region = defaultRegion.get();
+      builder = builder();
+      return super.setContext(request);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public SecurityGroup getResult() {
+      try {
+         return builder.build();
+      } finally {
+         builder = builder();
+      }
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public void startElement(String url, String name, String qName, Attributes attributes) throws SAXException {
+      if (equalsOrSuffix(qName, "item")) {
+         itemDepth++;
+      } else if (equalsOrSuffix(qName, "ipPermissions")) {
+         inIpPermissions = true;
+      }
+      if (inIpPermissions) {
+         ipPermissionHandler.startElement(url, name, qName, attributes);
+      }
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public void endElement(String uri, String name, String qName) throws SAXException {
+      if (equalsOrSuffix(qName, "item")) {
+         endItem(uri, name, qName);
+         itemDepth--;
+      } else if (equalsOrSuffix(qName, "ipPermissions")) {
+         inIpPermissions = false;
+         itemDepth = 0;
+      } else if (inIpPermissions) {
+         ipPermissionHandler.endElement(uri, name, qName);
+      } else if (equalsOrSuffix(qName, "groupName")) {
+         builder.name(currentOrNull(currentText));
+      } else if (equalsOrSuffix(qName, "groupId")) {
+         builder.id(currentOrNull(currentText));
+      } else if (equalsOrSuffix(qName, "ownerId")) {
+         builder.ownerId(currentOrNull(currentText));
+      } else if (equalsOrSuffix(qName, "groupDescription")) {
+         builder.description(currentOrNull(currentText));
+      }
+      currentText = new StringBuilder();
+   }
+
+   protected void endItem(String uri, String name, String qName) throws SAXException {
+      if (inIpPermissions) {
+         if (itemDepth == 2)
+            builder.ipPermission(ipPermissionHandler.getResult());
+         else
+            ipPermissionHandler.endElement(uri, name, qName);
+      }
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public void characters(char ch[], int start, int length) {
+      if (inIpPermissions) {
+         ipPermissionHandler.characters(ch, start, length);
+      } else {
+         currentText.append(ch, start, length);
+      }
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/0aa19a0c/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/AWSEC2ComputeServiceLiveTest.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/AWSEC2ComputeServiceLiveTest.java b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/AWSEC2ComputeServiceLiveTest.java
index 235e596..68d9bf8 100644
--- a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/AWSEC2ComputeServiceLiveTest.java
+++ b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/AWSEC2ComputeServiceLiveTest.java
@@ -29,7 +29,6 @@ import java.util.concurrent.TimeUnit;
 
 import org.jclouds.ContextBuilder;
 import org.jclouds.aws.cloudwatch.AWSCloudWatchProviderMetadata;
-import org.jclouds.aws.ec2.AWSEC2ApiMetadata;
 import org.jclouds.aws.ec2.AWSEC2Api;
 import org.jclouds.aws.ec2.domain.AWSRunningInstance;
 import org.jclouds.aws.ec2.domain.MonitoringState;
@@ -46,7 +45,6 @@ import org.jclouds.compute.domain.NodeMetadata;
 import org.jclouds.compute.domain.Template;
 import org.jclouds.compute.predicates.NodePredicates;
 import org.jclouds.domain.LoginCredentials;
-import org.jclouds.ec2.EC2Api;
 import org.jclouds.ec2.compute.EC2ComputeServiceLiveTest;
 import org.jclouds.ec2.domain.KeyPair;
 import org.jclouds.ec2.domain.SecurityGroup;

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/0aa19a0c/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/AWSEC2TemplateBuilderLiveTest.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/AWSEC2TemplateBuilderLiveTest.java b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/AWSEC2TemplateBuilderLiveTest.java
index ca94b70..e22f611 100644
--- a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/AWSEC2TemplateBuilderLiveTest.java
+++ b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/AWSEC2TemplateBuilderLiveTest.java
@@ -19,6 +19,7 @@ package org.jclouds.aws.ec2.compute;
 import static org.jclouds.compute.util.ComputeServiceUtils.getCores;
 import static org.jclouds.http.internal.TrackingJavaUrlHttpCommandExecutorService.getInvokerOfRequestAtIndex;
 import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
 
 import java.io.IOException;
 import java.util.List;
@@ -27,22 +28,20 @@ import java.util.Set;
 
 import org.jclouds.aws.domain.Region;
 import org.jclouds.aws.ec2.AWSEC2Api;
-import org.jclouds.aws.ec2.AWSEC2ApiMetadata;
 import org.jclouds.aws.ec2.reference.AWSEC2Constants;
 import org.jclouds.compute.ComputeServiceContext;
 import org.jclouds.compute.domain.OsFamily;
 import org.jclouds.compute.domain.OsFamilyVersion64Bit;
 import org.jclouds.compute.domain.Template;
 import org.jclouds.ec2.EC2Api;
-import org.jclouds.ec2.EC2ApiMetadata;
 import org.jclouds.ec2.compute.EC2TemplateBuilderLiveTest;
 import org.jclouds.ec2.compute.predicates.EC2ImagePredicates;
 import org.jclouds.ec2.domain.InstanceType;
 import org.jclouds.ec2.domain.RootDeviceType;
+import org.jclouds.ec2.features.AvailabilityZoneAndRegionApi;
 import org.jclouds.ec2.options.DescribeAvailabilityZonesOptions;
 import org.jclouds.ec2.options.DescribeRegionsOptions;
 import org.jclouds.ec2.reference.EC2Constants;
-import org.jclouds.ec2.features.AvailabilityZoneAndRegionApi;
 import org.jclouds.http.HttpCommand;
 import org.jclouds.http.internal.TrackingJavaUrlHttpCommandExecutorService;
 import org.jclouds.location.reference.LocationConstants;
@@ -151,7 +150,6 @@ public class AWSEC2TemplateBuilderLiveTest extends EC2TemplateBuilderLiveTest {
       Template template = view.getComputeService().templateBuilder().imageId("us-east-1/ami-ccb35ea5")
             .hardwareId(InstanceType.M2_2XLARGE).locationId("us-east-1a").build();
 
-      System.out.println(template.getHardware());
       assert (template.getImage().getProviderId().startsWith("ami-")) : template;
       assertEquals(template.getImage().getOperatingSystem().getVersion(), "5.4");
       assertEquals(template.getImage().getOperatingSystem().is64Bit(), true);
@@ -169,7 +167,9 @@ public class AWSEC2TemplateBuilderLiveTest extends EC2TemplateBuilderLiveTest {
    public void testDefaultTemplateBuilder() throws IOException {
       Template defaultTemplate = view.getComputeService().templateBuilder().build();
       assert (defaultTemplate.getImage().getProviderId().startsWith("ami-")) : defaultTemplate;
-      assertEquals(defaultTemplate.getImage().getOperatingSystem().getVersion(), "pv-2012.09.rc-1");
+      assertTrue(defaultTemplate.getImage().getOperatingSystem().getVersion().contains("pv-201"),
+              "Default template version should include 'pv-201' but is "
+                      + defaultTemplate.getImage().getOperatingSystem().getVersion());
       assertEquals(defaultTemplate.getImage().getOperatingSystem().is64Bit(), true);
       assertEquals(defaultTemplate.getImage().getOperatingSystem().getFamily(), OsFamily.AMZN_LINUX);
       assertEquals(defaultTemplate.getImage().getUserMetadata().get("rootDeviceType"), "ebs");
@@ -184,7 +184,7 @@ public class AWSEC2TemplateBuilderLiveTest extends EC2TemplateBuilderLiveTest {
       Template defaultTemplate = view.getComputeService().templateBuilder().osFamily(OsFamily.AMZN_LINUX)
             .imageMatches(EC2ImagePredicates.rootDeviceType(RootDeviceType.INSTANCE_STORE)).build();
       assert (defaultTemplate.getImage().getProviderId().startsWith("ami-")) : defaultTemplate;
-      assertEquals(defaultTemplate.getImage().getOperatingSystem().getVersion(), "pv-2012.09.rc-1");
+      assertEquals(defaultTemplate.getImage().getOperatingSystem().getVersion(), "pv-2013.09.rc-1");
       assertEquals(defaultTemplate.getImage().getOperatingSystem().is64Bit(), true);
       assertEquals(defaultTemplate.getImage().getOperatingSystem().getFamily(), OsFamily.AMZN_LINUX);
       assertEquals(defaultTemplate.getImage().getUserMetadata().get("rootDeviceType"), "instance-store");
@@ -238,7 +238,6 @@ public class AWSEC2TemplateBuilderLiveTest extends EC2TemplateBuilderLiveTest {
          assertEquals(context.getComputeService().listImages().size(), 0);
 
          Template template = context.getComputeService().templateBuilder().imageId("us-east-1/ami-ccb35ea5").build();
-         System.out.println(template.getHardware());
          assert (template.getImage().getProviderId().startsWith("ami-")) : template;
          assertEquals(template.getImage().getOperatingSystem().getVersion(), "5.4");
          assertEquals(template.getImage().getOperatingSystem().is64Bit(), true);
@@ -272,7 +271,6 @@ public class AWSEC2TemplateBuilderLiveTest extends EC2TemplateBuilderLiveTest {
          assertEquals(context.getComputeService().listImages().size(), 0);
 
          Template template = context.getComputeService().templateBuilder().imageId("us-east-1/ami-ccb35ea5").build();
-         System.out.println(template.getHardware());
          assert (template.getImage().getProviderId().startsWith("ami-")) : template;
          assertEquals(template.getImage().getOperatingSystem().getVersion(), "5.4");
          assertEquals(template.getImage().getOperatingSystem().is64Bit(), true);

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/0aa19a0c/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/extensions/AWSEC2SecurityGroupExtensionExpectTest.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/extensions/AWSEC2SecurityGroupExtensionExpectTest.java b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/extensions/AWSEC2SecurityGroupExtensionExpectTest.java
index cec22ee..f13737a 100644
--- a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/extensions/AWSEC2SecurityGroupExtensionExpectTest.java
+++ b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/extensions/AWSEC2SecurityGroupExtensionExpectTest.java
@@ -59,7 +59,7 @@ public class AWSEC2SecurityGroupExtensionExpectTest extends BaseAWSEC2ComputeSer
                            .endpoint("https://ec2." + region + ".amazonaws.com/")
                            .addHeader("Host", "ec2." + region + ".amazonaws.com")
                            .addFormParam("Action", "DescribeSecurityGroups")
-                           .addFormParam("GroupName.1", "jclouds#some-group").build());
+                           .addFormParam("GroupId.1", "sg-3c6ef654").build());
       
       HttpResponse describeSecurityGroupsSingleResponse = 
          HttpResponse.builder().statusCode(200)
@@ -101,7 +101,7 @@ public class AWSEC2SecurityGroupExtensionExpectTest extends BaseAWSEC2ComputeSer
       SecurityGroupExtension extension = requestsSendResponses(requestResponseMap.build()).getSecurityGroupExtension().get();
 
       SecurityGroupBuilder groupBuilder = new SecurityGroupBuilder();
-      groupBuilder.id("jclouds#some-group");
+      groupBuilder.id("us-east-1/sg-3c6ef654");
       groupBuilder.providerId("sg-3c6ef654");
       groupBuilder.name("jclouds#some-group");
       groupBuilder.location(new LocationBuilder()
@@ -133,7 +133,7 @@ public class AWSEC2SecurityGroupExtensionExpectTest extends BaseAWSEC2ComputeSer
                            .endpoint("https://ec2." + region + ".amazonaws.com/")
                            .addHeader("Host", "ec2." + region + ".amazonaws.com")
                            .addFormParam("Action", "DescribeSecurityGroups")
-                           .addFormParam("GroupName.1", "jclouds#some-group").build());
+                           .addFormParam("GroupId.1", "sg-3c6ef654").build());
       
       HttpResponse describeSecurityGroupsSingleResponse = 
          HttpResponse.builder().statusCode(200)
@@ -166,7 +166,7 @@ public class AWSEC2SecurityGroupExtensionExpectTest extends BaseAWSEC2ComputeSer
       SecurityGroupExtension extension = requestsSendResponses(requestResponseMap.build()).getSecurityGroupExtension().get();
 
       SecurityGroupBuilder groupBuilder = new SecurityGroupBuilder();
-      groupBuilder.id("jclouds#some-group");
+      groupBuilder.id("us-east-1/sg-3c6ef654");
       groupBuilder.providerId("sg-3c6ef654");
       groupBuilder.name("jclouds#some-group");
       groupBuilder.location(new LocationBuilder()
@@ -204,7 +204,7 @@ public class AWSEC2SecurityGroupExtensionExpectTest extends BaseAWSEC2ComputeSer
                            .endpoint("https://ec2." + region + ".amazonaws.com/")
                            .addHeader("Host", "ec2." + region + ".amazonaws.com")
                            .addFormParam("Action", "DescribeSecurityGroups")
-                           .addFormParam("GroupName.1", "jclouds#some-group").build());
+                           .addFormParam("GroupId.1", "sg-3c6ef654").build());
       
       HttpResponse describeSecurityGroupsSingleResponse = 
          HttpResponse.builder().statusCode(200)
@@ -220,7 +220,7 @@ public class AWSEC2SecurityGroupExtensionExpectTest extends BaseAWSEC2ComputeSer
                                  .addFormParam("Action", "AuthorizeSecurityGroupIngress")
                                  .addFormParam("GroupId", "sg-3c6ef654")
                                  .addFormParam("IpPermissions.0.FromPort", "22")
-                                 .addFormParam("IpPermissions.0.Groups.0.GroupName", "jclouds#some-group")
+                                 .addFormParam("IpPermissions.0.Groups.0.GroupId", "sg-3c6ef654")
                                  .addFormParam("IpPermissions.0.Groups.0.UserId", "993194456877")
                                  .addFormParam("IpPermissions.0.IpProtocol", "tcp")
                                  .addFormParam("IpPermissions.0.ToPort", "40")
@@ -240,14 +240,14 @@ public class AWSEC2SecurityGroupExtensionExpectTest extends BaseAWSEC2ComputeSer
       builder.ipProtocol(IpProtocol.TCP);
       builder.fromPort(22);
       builder.toPort(40);
-      builder.tenantIdGroupNamePair("993194456877", "jclouds#some-group");
+      builder.tenantIdGroupNamePair("993194456877", "sg-3c6ef654");
 
       IpPermission perm = builder.build();
 
       SecurityGroupExtension extension = requestsSendResponses(requestResponseMap.build()).getSecurityGroupExtension().get();
 
       SecurityGroupBuilder groupBuilder = new SecurityGroupBuilder();
-      groupBuilder.id("jclouds#some-group");
+      groupBuilder.id("us-east-1/sg-3c6ef654");
       groupBuilder.providerId("sg-3c6ef654");
       groupBuilder.name("jclouds#some-group");
       groupBuilder.location(new LocationBuilder()
@@ -272,7 +272,7 @@ public class AWSEC2SecurityGroupExtensionExpectTest extends BaseAWSEC2ComputeSer
       assertEquals(0, newPerm.getCidrBlocks().size());
       assertEquals(1, newPerm.getTenantIdGroupNamePairs().size());
       assertTrue(newPerm.getTenantIdGroupNamePairs().keySet().contains(origGroup.getOwnerId()));
-      assertTrue(newPerm.getTenantIdGroupNamePairs().values().contains(origGroup.getName()));
+      assertTrue(newPerm.getTenantIdGroupNamePairs().values().contains(origGroup.getProviderId()));
    }
 
 
@@ -283,7 +283,7 @@ public class AWSEC2SecurityGroupExtensionExpectTest extends BaseAWSEC2ComputeSer
                            .endpoint("https://ec2." + region + ".amazonaws.com/")
                            .addHeader("Host", "ec2." + region + ".amazonaws.com")
                            .addFormParam("Action", "DescribeSecurityGroups")
-                           .addFormParam("GroupName.1", "jclouds#some-group").build());
+                           .addFormParam("GroupId.1", "sg-3c6ef654").build());
       
       HttpResponse describeSecurityGroupsSingleResponse = 
          HttpResponse.builder().statusCode(200)
@@ -299,7 +299,7 @@ public class AWSEC2SecurityGroupExtensionExpectTest extends BaseAWSEC2ComputeSer
                                  .addFormParam("Action", "AuthorizeSecurityGroupIngress")
                                  .addFormParam("GroupId", "sg-3c6ef654")
                                  .addFormParam("IpPermissions.0.FromPort", "22")
-                                 .addFormParam("IpPermissions.0.Groups.0.GroupName", "jclouds#some-group")
+                                 .addFormParam("IpPermissions.0.Groups.0.GroupId", "sg-3c6ef654")
                                  .addFormParam("IpPermissions.0.Groups.0.UserId", "993194456877")
                                  .addFormParam("IpPermissions.0.IpProtocol", "tcp")
                                  .addFormParam("IpPermissions.0.ToPort", "40")
@@ -317,7 +317,7 @@ public class AWSEC2SecurityGroupExtensionExpectTest extends BaseAWSEC2ComputeSer
       SecurityGroupExtension extension = requestsSendResponses(requestResponseMap.build()).getSecurityGroupExtension().get();
 
       SecurityGroupBuilder groupBuilder = new SecurityGroupBuilder();
-      groupBuilder.id("jclouds#some-group");
+      groupBuilder.id("us-east-1/sg-3c6ef654");
       groupBuilder.providerId("sg-3c6ef654");
       groupBuilder.name("jclouds#some-group");
       groupBuilder.ownerId("993194456877");
@@ -330,7 +330,7 @@ public class AWSEC2SecurityGroupExtensionExpectTest extends BaseAWSEC2ComputeSer
       SecurityGroup origGroup = groupBuilder.build();
 
       ImmutableMultimap.Builder<String, String> permBuilder = ImmutableMultimap.builder();
-      permBuilder.put(origGroup.getOwnerId(), origGroup.getName());
+      permBuilder.put(origGroup.getOwnerId(), origGroup.getId());
       
       SecurityGroup newGroup = extension.addIpPermission(IpProtocol.TCP,
                                                          22,
@@ -351,7 +351,7 @@ public class AWSEC2SecurityGroupExtensionExpectTest extends BaseAWSEC2ComputeSer
       assertEquals(0, newPerm.getCidrBlocks().size());
       assertEquals(1, newPerm.getTenantIdGroupNamePairs().size());
       assertTrue(newPerm.getTenantIdGroupNamePairs().keySet().contains(origGroup.getOwnerId()));
-      assertTrue(newPerm.getTenantIdGroupNamePairs().values().contains(origGroup.getName()));
+      assertTrue(newPerm.getTenantIdGroupNamePairs().values().contains(origGroup.getProviderId()));
    }
 
    private Multimap<String, String> emptyMultimap() {

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/0aa19a0c/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/functions/AWSEC2SecurityGroupToSecurityGroupTest.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/functions/AWSEC2SecurityGroupToSecurityGroupTest.java b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/functions/AWSEC2SecurityGroupToSecurityGroupTest.java
new file mode 100644
index 0000000..8c0bc44
--- /dev/null
+++ b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/functions/AWSEC2SecurityGroupToSecurityGroupTest.java
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.aws.ec2.compute.functions;
+
+import static org.testng.Assert.assertEquals;
+
+import java.util.Set;
+
+import org.jclouds.compute.domain.SecurityGroup;
+import org.jclouds.domain.Location;
+import org.jclouds.domain.LocationBuilder;
+import org.jclouds.domain.LocationScope;
+import org.jclouds.ec2.util.IpPermissions;
+import org.jclouds.net.domain.IpPermission;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Supplier;
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * @author Andrew Bayer
+ */
+@Test(groups = "unit", testName = "AWSEC2SecurityGroupToSecurityGroupTest")
+public class AWSEC2SecurityGroupToSecurityGroupTest {
+
+   static Location provider = new LocationBuilder().scope(LocationScope.REGION).id("us-east-1")
+         .description("us-east-1").build();
+
+   @Test
+   public void testApply() {
+      IpPermissions authorization = IpPermissions.permitAnyProtocol();
+
+      org.jclouds.ec2.domain.SecurityGroup origGroup = org.jclouds.ec2.domain.SecurityGroup.builder()
+         .region("us-east-1")
+         .id("some-id")
+         .name("some-group")
+         .ownerId("some-owner")
+         .description("some-description")
+         .ipPermission(authorization)
+         .build();
+
+      AWSEC2SecurityGroupToSecurityGroup parser = createGroupParser(ImmutableSet.of(provider));
+
+      SecurityGroup group = parser.apply(origGroup);
+      
+      assertEquals(group.getLocation(), provider);
+      assertEquals(group.getId(), provider.getId() + "/" + origGroup.getId());
+      assertEquals(group.getProviderId(), origGroup.getId());
+      assertEquals(group.getName(), origGroup.getName());
+      assertEquals(group.getIpPermissions(), (Set<IpPermission>)origGroup);
+      assertEquals(group.getOwnerId(), origGroup.getOwnerId());
+   }
+
+   private AWSEC2SecurityGroupToSecurityGroup createGroupParser(final ImmutableSet<Location> locations) {
+      Supplier<Set<? extends Location>> locationSupplier = new Supplier<Set<? extends Location>>() {
+
+         @Override
+         public Set<? extends Location> get() {
+            return locations;
+         }
+
+      };
+
+      AWSEC2SecurityGroupToSecurityGroup parser = new AWSEC2SecurityGroupToSecurityGroup(locationSupplier);
+
+      return parser;
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/0aa19a0c/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/internal/BaseAWSEC2ComputeServiceExpectTest.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/internal/BaseAWSEC2ComputeServiceExpectTest.java b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/internal/BaseAWSEC2ComputeServiceExpectTest.java
index 5423a50..c5f9838 100644
--- a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/internal/BaseAWSEC2ComputeServiceExpectTest.java
+++ b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/internal/BaseAWSEC2ComputeServiceExpectTest.java
@@ -41,6 +41,8 @@ import com.google.inject.TypeLiteral;
  */
 public abstract class BaseAWSEC2ComputeServiceExpectTest extends BaseEC2ComputeServiceExpectTest {
 
+   protected HttpRequest describeSecurityGroupByIdRequest;
+
    public BaseAWSEC2ComputeServiceExpectTest() {
       provider = "aws-ec2";
    }
@@ -59,6 +61,24 @@ public abstract class BaseAWSEC2ComputeServiceExpectTest extends BaseEC2ComputeS
    protected void setupDefaultRequests() {
       super.setupDefaultRequests();
 
+      describeSecurityGroupByIdRequest =
+              formSigner.filter(HttpRequest.builder()
+                      .method("POST")
+                      .endpoint("https://ec2." + region + ".amazonaws.com/")
+                      .addHeader("Host", "ec2." + region + ".amazonaws.com")
+                      .addFormParam("Action", "DescribeSecurityGroups")
+                      .addFormParam("GroupId.1", "sg-3c6ef654").build());
+
+      authorizeSecurityGroupIngressRequestGroup =
+              formSigner.filter(HttpRequest.builder()
+                      .method("POST")
+                      .endpoint("https://ec2." + region + ".amazonaws.com/")
+                      .addHeader("Host", "ec2." + region + ".amazonaws.com")
+                      .addFormParam("Action", "AuthorizeSecurityGroupIngress")
+                      .addFormParam("SourceSecurityGroupId", "sg-3c6ef654")
+                      .addFormParam("SourceSecurityGroupOwnerId", "993194456877")
+                      .addFormParam("GroupName", "jclouds#test").build());
+
       authorizeSecurityGroupIngressRequest22 = 
          formSigner.filter(HttpRequest.builder()
                            .method("POST")
@@ -72,12 +92,12 @@ public abstract class BaseAWSEC2ComputeServiceExpectTest extends BaseEC2ComputeS
                            .addFormParam("IpPermissions.0.IpProtocol", "tcp")
                            .addFormParam("IpPermissions.1.FromPort", "0")
                            .addFormParam("IpPermissions.1.ToPort", "65535")
-                           .addFormParam("IpPermissions.1.Groups.0.GroupName", "jclouds#test")
+                           .addFormParam("IpPermissions.1.Groups.0.GroupId", "sg-3c6ef654")
                            .addFormParam("IpPermissions.1.Groups.0.UserId", "993194456877")
                            .addFormParam("IpPermissions.1.IpProtocol", "tcp")
                            .addFormParam("IpPermissions.2.FromPort", "0")
                            .addFormParam("IpPermissions.2.ToPort", "65535")
-                           .addFormParam("IpPermissions.2.Groups.0.GroupName", "jclouds#test")
+                           .addFormParam("IpPermissions.2.Groups.0.GroupId", "sg-3c6ef654")
                            .addFormParam("IpPermissions.2.Groups.0.UserId", "993194456877")
                            .addFormParam("IpPermissions.2.IpProtocol", "udp")
                            .build());

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/0aa19a0c/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/loaders/AWSEC2CreateSecurityGroupIfNeededTest.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/loaders/AWSEC2CreateSecurityGroupIfNeededTest.java b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/loaders/AWSEC2CreateSecurityGroupIfNeededTest.java
index 0ac9aea..60f86f5 100644
--- a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/loaders/AWSEC2CreateSecurityGroupIfNeededTest.java
+++ b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/loaders/AWSEC2CreateSecurityGroupIfNeededTest.java
@@ -71,13 +71,13 @@ public class AWSEC2CreateSecurityGroupIfNeededTest {
                       .fromPort(0)
                       .toPort(65535)
                       .ipProtocol(IpProtocol.TCP)
-                      .tenantIdGroupNamePair("ownerId", "group")
+                      .tenantIdGroupNamePair("ownerId", "sg-123456")
                       .build());
       permissions.add(IpPermission.builder()
                       .fromPort(0)
                       .toPort(65535)
                       .ipProtocol(IpProtocol.UDP)
-                      .tenantIdGroupNamePair("ownerId", "group")
+                      .tenantIdGroupNamePair("ownerId", "sg-123456")
                       .build());
       
       client.createSecurityGroupInRegion("region", "group", "group");

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/0aa19a0c/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/AWSKeyPairApiLiveTest.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/AWSKeyPairApiLiveTest.java b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/AWSKeyPairApiLiveTest.java
index e629e7f..c2ddc8a 100644
--- a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/AWSKeyPairApiLiveTest.java
+++ b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/AWSKeyPairApiLiveTest.java
@@ -34,7 +34,6 @@ import java.util.Set;
 import java.util.SortedSet;
 
 import org.jclouds.aws.domain.Region;
-import org.jclouds.aws.ec2.AWSEC2ApiMetadata;
 import org.jclouds.aws.ec2.AWSEC2Api;
 import org.jclouds.aws.ec2.compute.AWSEC2TemplateOptions;
 import org.jclouds.aws.ec2.domain.AWSRunningInstance;

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/0aa19a0c/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/AWSSecurityGroupApiLiveTest.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/AWSSecurityGroupApiLiveTest.java b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/AWSSecurityGroupApiLiveTest.java
index 731c703..7766d17 100644
--- a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/AWSSecurityGroupApiLiveTest.java
+++ b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/AWSSecurityGroupApiLiveTest.java
@@ -22,6 +22,7 @@ import static org.testng.Assert.assertNotNull;
 import java.util.Set;
 
 import org.jclouds.ec2.domain.SecurityGroup;
+import org.jclouds.ec2.domain.UserIdGroupPair;
 import org.jclouds.ec2.features.SecurityGroupApiLiveTest;
 import org.jclouds.ec2.util.IpPermissions;
 import org.jclouds.net.domain.IpPermission;
@@ -42,15 +43,52 @@ public class AWSSecurityGroupApiLiveTest extends SecurityGroupApiLiveTest {
    }
 
    @Test
+   void testAuthorizeSecurityGroupIngressSourceGroup() {
+      final String group1Name = PREFIX + "ingress1";
+      String group2Name = PREFIX + "ingress2";
+      cleanupAndSleep(group2Name);
+      cleanupAndSleep(group1Name);
+      try {
+         final String group1Id = AWSSecurityGroupApi.class.cast(client).createSecurityGroupInRegionAndReturnId(null,
+                 group1Name, group1Name);
+         String group2Id = AWSSecurityGroupApi.class.cast(client).createSecurityGroupInRegionAndReturnId(null,
+                 group2Name, group2Name);
+         ensureGroupsExist(group1Name, group2Name);
+         client.authorizeSecurityGroupIngressInRegion(null, group1Name, IpProtocol.TCP, 80, 80, "0.0.0.0/0");
+         assertEventually(new GroupHasPermission(client, group1Name, new TCPPort80AllIPs()));
+         Set<SecurityGroup> oneResult = client.describeSecurityGroupsInRegion(null, group1Name);
+         assertNotNull(oneResult);
+         assertEquals(oneResult.size(), 1);
+         final SecurityGroup group = oneResult.iterator().next();
+         assertEquals(group.getName(), group1Name);
+         final UserIdGroupPair to = new UserIdGroupPair(group.getOwnerId(), group1Name);
+         client.authorizeSecurityGroupIngressInRegion(null, group2Name, to);
+         assertEventually(new GroupHasPermission(client, group2Name, new Predicate<IpPermission>() {
+            @Override
+            public boolean apply(IpPermission arg0) {
+               return arg0.getTenantIdGroupNamePairs().equals(ImmutableMultimap.of(group.getOwnerId(), group1Id));
+            }
+         }));
+
+         client.revokeSecurityGroupIngressInRegion(null, group2Name,
+                 new UserIdGroupPair(group.getOwnerId(), group1Name));
+         assertEventually(new GroupHasNoPermissions(client, group2Name));
+      } finally {
+         client.deleteSecurityGroupInRegion(null, group2Name);
+         client.deleteSecurityGroupInRegion(null, group1Name);
+      }
+   }
+
+   @Test
    void testAuthorizeSecurityGroupIngressIpPermission() throws InterruptedException {
       final String group1Name = PREFIX + "ingress11";
       String group2Name = PREFIX + "ingress12";
       cleanupAndSleep(group2Name);
       cleanupAndSleep(group1Name);
       try {
-         String group1Id = AWSSecurityGroupApi.class.cast(client).createSecurityGroupInRegionAndReturnId(null,
+         final String group1Id = AWSSecurityGroupApi.class.cast(client).createSecurityGroupInRegionAndReturnId(null,
                group1Name, group1Name);
-         String group2Id = AWSSecurityGroupApi.class.cast(client).createSecurityGroupInRegionAndReturnId(null,
+         final String group2Id = AWSSecurityGroupApi.class.cast(client).createSecurityGroupInRegionAndReturnId(null,
                group2Name, group2Name);
          Thread.sleep(100);// eventual consistent
          ensureGroupsExist(group1Name, group2Name);
@@ -69,7 +107,7 @@ public class AWSSecurityGroupApiLiveTest extends SecurityGroupApiLiveTest {
          assertEventually(new GroupHasPermission(client, group2Name, new Predicate<IpPermission>() {
             @Override
             public boolean apply(IpPermission arg0) {
-               return arg0.getTenantIdGroupNamePairs().equals(ImmutableMultimap.of(group.getOwnerId(), group1Name))
+               return arg0.getTenantIdGroupNamePairs().equals(ImmutableMultimap.of(group.getOwnerId(), group1Id))
                      && arg0.getFromPort() == 80 && arg0.getToPort() == 80 && arg0.getIpProtocol() == IpProtocol.TCP;
             }
          }));