You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jclouds.apache.org by za...@apache.org on 2013/08/30 19:19:55 UTC

[1/3] Adds Otter (Rackspace Autoscale) to labs https://issues.apache.org/jira/browse/JCLOUDS-215

Updated Branches:
  refs/heads/master 9f440d6bc -> 46f493ac8


http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/46f493ac/rackspace-autoscale/src/test/java/org/jclouds/rackspace/autoscale/v1/internal/BaseAutoscaleExpectTest.java
----------------------------------------------------------------------
diff --git a/rackspace-autoscale/src/test/java/org/jclouds/rackspace/autoscale/v1/internal/BaseAutoscaleExpectTest.java b/rackspace-autoscale/src/test/java/org/jclouds/rackspace/autoscale/v1/internal/BaseAutoscaleExpectTest.java
new file mode 100644
index 0000000..4e5668d
--- /dev/null
+++ b/rackspace-autoscale/src/test/java/org/jclouds/rackspace/autoscale/v1/internal/BaseAutoscaleExpectTest.java
@@ -0,0 +1,82 @@
+/*
+ * 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.rackspace.autoscale.v1.internal;
+
+import javax.ws.rs.core.MediaType;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.HttpResponse;
+import org.jclouds.openstack.keystone.v2_0.internal.KeystoneFixture;
+import org.jclouds.rest.internal.BaseRestApiExpectTest;
+
+/**
+ * Base class for writing Autoscale Expect tests
+ * 
+ * @author Adrian Cole
+ * @author Zack Shoylev
+ */
+public class BaseAutoscaleExpectTest<T> extends BaseRestApiExpectTest<T> {
+   protected HttpRequest keystoneAuthWithUsernameAndPassword;
+   protected HttpRequest keystoneAuthWithUsernameAndPasswordAndTenantName;
+   protected HttpRequest keystoneAuthWithAccessKeyAndSecretKeyAndTenantName;
+   protected String authToken;
+   protected HttpResponse responseWithKeystoneAccess;
+   protected HttpRequest extensionsOfNovaRequest;
+   protected HttpResponse extensionsOfNovaResponse;
+   protected HttpResponse unmatchedExtensionsOfNovaResponse;
+   protected HttpRequest keystoneAuthWithAccessKeyAndSecretKeyAndTenantId;
+   protected String identityWithTenantId;
+
+   public BaseAutoscaleExpectTest() {
+      provider = "rackspace-autoscale";
+      keystoneAuthWithUsernameAndPassword = KeystoneFixture.INSTANCE.initialAuthWithUsernameAndPassword(identity,
+            credential);
+      keystoneAuthWithUsernameAndPasswordAndTenantName = KeystoneFixture.INSTANCE.initialAuthWithUsernameAndPasswordAndTenantName(identity,
+            credential);
+      keystoneAuthWithAccessKeyAndSecretKeyAndTenantName = KeystoneFixture.INSTANCE.initialAuthWithAccessKeyAndSecretKeyAndTenantName(identity,
+            credential);
+      keystoneAuthWithAccessKeyAndSecretKeyAndTenantId = KeystoneFixture.INSTANCE.initialAuthWithAccessKeyAndSecretKeyAndTenantId(identity,
+            credential);
+
+      authToken = "bb03a23aa8271291a7aaa9aaa2aaaaaa";
+      responseWithKeystoneAccess = HttpResponse.builder()
+            .statusCode(200)
+            .payload(payloadFromResourceWithContentType("/access_rax.json", "application/json"))
+            .build();
+      // now, createContext arg will need tenant prefix
+      identityWithTenantId = KeystoneFixture.INSTANCE.getTenantId() + ":" + identity;
+      identity = KeystoneFixture.INSTANCE.getTenantName() + ":" + identity;
+   }
+
+   @Override
+   protected HttpRequestComparisonType compareHttpRequestAsType(HttpRequest input) {
+      return HttpRequestComparisonType.JSON;
+   }
+
+   protected HttpRequest.Builder<?> authenticatedGET() {
+      return HttpRequest.builder()
+            .method("GET")
+            .addHeader("Accept", MediaType.APPLICATION_JSON)
+            .addHeader("X-Auth-Token", authToken);
+   }
+
+   protected HttpRequest.Builder<?> authenticatedPOST() {
+      return HttpRequest.builder()
+            .method("POST")
+            .addHeader("Accept", MediaType.APPLICATION_JSON)
+            .addHeader("X-Auth-Token", authToken);
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/46f493ac/rackspace-autoscale/src/test/resources/access_rax.json
----------------------------------------------------------------------
diff --git a/rackspace-autoscale/src/test/resources/access_rax.json b/rackspace-autoscale/src/test/resources/access_rax.json
new file mode 100644
index 0000000..2fba05d
--- /dev/null
+++ b/rackspace-autoscale/src/test/resources/access_rax.json
@@ -0,0 +1,249 @@
+{
+    "access":{
+        "token":{
+            "id":"bb03a23aa8271291a7aaa9aaa2aaaaaa",
+            "expires":"2013-08-02T16:55:24.229-05:00",
+            "tenant":{
+                "id":"888888",
+                "name":"888888"
+            },
+            "RAX-AUTH:authenticatedBy":[
+                "PASSWORD"
+            ]
+        },
+        "serviceCatalog":[
+            {
+                "name":"cloudFilesCDN",
+                "endpoints":[
+                    {
+                        "region":"ORD",
+                        "tenantId":"MossoCloudFS_0d629063-aa0f-4bf9-9e04-62e1fd6aaa2c",
+                        "publicURL":"https:\/\/cdn2.clouddrive.com\/v1\/MossoCloudFS_0d629063-aa0f-4bf9-9e04-62e1fd6aaa2c"
+                    },
+                    {
+                        "region":"DFW",
+                        "tenantId":"MossoCloudFS_0d629063-aa0f-4bf9-9e04-62e1fd6aaa2c",
+                        "publicURL":"https:\/\/cdn1.clouddrive.com\/v1\/MossoCloudFS_0d629063-aa0f-4bf9-9e04-62e1fd6aaa2c"
+                    },
+                    {
+                        "region":"SYD",
+                        "tenantId":"MossoCloudFS_0d629063-aa0f-4bf9-9e04-62e1fd6aaa2c",
+                        "publicURL":"https:\/\/cdn4.clouddrive.com\/v1\/MossoCloudFS_0d629063-aa0f-4bf9-9e04-62e1fd6aaa2c"
+                    }
+                ],
+                "type":"rax:object-cdn"
+            },
+            {
+                "name":"cloudFiles",
+                "endpoints":[
+                    {
+                        "region":"ORD",
+                        "tenantId":"MossoCloudFS_0d629063-aa0f-4bf9-9e04-62e1fd6aaa2c",
+                        "publicURL":"https:\/\/storage101.ord1.clouddrive.com\/v1\/MossoCloudFS_0d629063-aa0f-4bf9-9e04-62e1fd6aaa2c",
+                        "internalURL":"https:\/\/snet-storage101.ord1.clouddrive.com\/v1\/MossoCloudFS_0d629063-aa0f-4bf9-9e04-62e1fd6aaa2c"
+                    },
+                    {
+                        "region":"DFW",
+                        "tenantId":"MossoCloudFS_0d629063-aa0f-4bf9-9e04-62e1fd6aaa2c",
+                        "publicURL":"https:\/\/storage101.dfw1.clouddrive.com\/v1\/MossoCloudFS_0d629063-aa0f-4bf9-9e04-62e1fd6aaa2c",
+                        "internalURL":"https:\/\/snet-storage101.dfw1.clouddrive.com\/v1\/MossoCloudFS_0d629063-aa0f-4bf9-9e04-62e1fd6aaa2c"
+                    },
+                    {
+                        "region":"SYD",
+                        "tenantId":"MossoCloudFS_0d629063-aa0f-4bf9-9e04-62e1fd6aaa2c",
+                        "publicURL":"https:\/\/storage101.syd2.clouddrive.com\/v1\/MossoCloudFS_0d629063-aa0f-4bf9-9e04-62e1fd6aaa2c",
+                        "internalURL":"https:\/\/snet-storage101.syd2.clouddrive.com\/v1\/MossoCloudFS_0d629063-aa0f-4bf9-9e04-62e1fd6aaa2c"
+                    }
+                ],
+                "type":"object-store"
+            },
+            {
+                "name":"cloudLoadBalancers",
+                "endpoints":[
+                    {
+                        "region":"SYD",
+                        "tenantId":"888888",
+                        "publicURL":"https:\/\/syd.loadbalancers.api.rackspacecloud.com\/v1.0\/888888"
+                    },
+                    {
+                        "region":"DFW",
+                        "tenantId":"888888",
+                        "publicURL":"https:\/\/dfw.loadbalancers.api.rackspacecloud.com\/v1.0\/888888"
+                    },
+                    {
+                        "region":"ORD",
+                        "tenantId":"888888",
+                        "publicURL":"https:\/\/ord.loadbalancers.api.rackspacecloud.com\/v1.0\/888888"
+                    }
+                ],
+                "type":"rax:load-balancer"
+            },
+            {
+                "name":"cloudDatabases",
+                "endpoints":[
+                    {
+                        "region":"SYD",
+                        "tenantId":"888888",
+                        "publicURL":"https:\/\/syd.databases.api.rackspacecloud.com\/v1.0\/888888"
+                    },
+                    {
+                        "region":"DFW",
+                        "tenantId":"888888",
+                        "publicURL":"https:\/\/dfw.databases.api.rackspacecloud.com\/v1.0\/888888"
+                    },
+                    {
+                        "region":"ORD",
+                        "tenantId":"888888",
+                        "publicURL":"https:\/\/ord.databases.api.rackspacecloud.com\/v1.0\/888888"
+                    }
+                ],
+                "type":"rax:database"
+            },
+            {
+                "name":"cloudBlockStorage",
+                "endpoints":[
+                    {
+                        "region":"SYD",
+                        "tenantId":"888888",
+                        "publicURL":"https:\/\/syd.blockstorage.api.rackspacecloud.com\/v1\/888888"
+                    },
+                    {
+                        "region":"DFW",
+                        "tenantId":"888888",
+                        "publicURL":"https:\/\/dfw.blockstorage.api.rackspacecloud.com\/v1\/888888"
+                    },
+                    {
+                        "region":"ORD",
+                        "tenantId":"888888",
+                        "publicURL":"https:\/\/ord.blockstorage.api.rackspacecloud.com\/v1\/888888"
+                    }
+                ],
+                "type":"volume"
+            },
+            {
+                "name":"cloudServersOpenStack",
+                "endpoints":[
+                    {
+                        "region":"SYD",
+                        "tenantId":"888888",
+                        "publicURL":"https:\/\/syd.servers.api.rackspacecloud.com\/v2\/888888",
+                        "versionInfo":"https:\/\/syd.servers.api.rackspacecloud.com\/v2",
+                        "versionList":"https:\/\/syd.servers.api.rackspacecloud.com\/",
+                        "versionId":"2"
+                    },
+                    {
+                        "region":"DFW",
+                        "tenantId":"888888",
+                        "publicURL":"https:\/\/dfw.servers.api.rackspacecloud.com\/v2\/888888",
+                        "versionInfo":"https:\/\/dfw.servers.api.rackspacecloud.com\/v2",
+                        "versionList":"https:\/\/dfw.servers.api.rackspacecloud.com\/",
+                        "versionId":"2"
+                    },
+                    {
+                        "region":"ORD",
+                        "tenantId":"888888",
+                        "publicURL":"https:\/\/ord.servers.api.rackspacecloud.com\/v2\/888888",
+                        "versionInfo":"https:\/\/ord.servers.api.rackspacecloud.com\/v2",
+                        "versionList":"https:\/\/ord.servers.api.rackspacecloud.com\/",
+                        "versionId":"2"
+                    }
+                ],
+                "type":"compute"
+            },
+            {
+                "name":"autoscale",
+                "endpoints":[
+                    {
+                        "region":"ORD",
+                        "tenantId":"888888",
+                        "publicURL":"https:\/\/ord.autoscale.api.rackspacecloud.com\/v1.0\/888888",
+                        "versionInfo":null,
+                        "versionList":null,
+                        "versionId":"1.0"
+                    },
+                    {
+                        "region":"DFW",
+                        "tenantId":"888888",
+                        "publicURL":"https:\/\/dfw.autoscale.api.rackspacecloud.com\/v1.0\/888888",
+                        "versionInfo":null,
+                        "versionList":null,
+                        "versionId":"1.0"
+                    }
+                ],
+                "type":"rax:autoscale"
+            },
+            {
+                "name":"cloudMonitoring",
+                "endpoints":[
+                    {
+                        "tenantId":"888888",
+                        "publicURL":"https:\/\/monitoring.api.rackspacecloud.com\/v1.0\/888888"
+                    }
+                ],
+                "type":"rax:monitor"
+            },
+            {
+                "name":"cloudBackup",
+                "endpoints":[
+                    {
+                        "tenantId":"888888",
+                        "publicURL":"https:\/\/backup.api.rackspacecloud.com\/v1.0\/888888"
+                    }
+                ],
+                "type":"rax:backup"
+            },
+            {
+                "name":"cloudServers",
+                "endpoints":[
+                    {
+                        "tenantId":"888888",
+                        "publicURL":"https:\/\/servers.api.rackspacecloud.com\/v1.0\/888888",
+                        "versionInfo":"https:\/\/servers.api.rackspacecloud.com\/v1.0",
+                        "versionList":"https:\/\/servers.api.rackspacecloud.com\/",
+                        "versionId":"1.0"
+                    }
+                ],
+                "type":"compute"
+            },
+            {
+                "name":"cloudDNS",
+                "endpoints":[
+                    {
+                        "tenantId":"888888",
+                        "publicURL":"https:\/\/dns.api.rackspacecloud.com\/v1.0\/888888"
+                    }
+                ],
+                "type":"rax:dns"
+            }
+        ],
+        "user":{
+            "id":"335853",
+            "roles":[
+                {
+                    "id":"10000150",
+                    "description":"Checkmate Access role",
+                    "name":"checkmate"
+                },
+                {
+                    "tenantId":"MossoCloudFS_0d629063-aa0f-4bf9-9e04-62e1fd6aaa2c",
+                    "id":"5",
+                    "description":"A Role that allows a user access to keystone Service methods",
+                    "name":"object-store:default"
+                },
+                {
+                    "tenantId":"888888",
+                    "id":"6",
+                    "description":"A Role that allows a user access to keystone Service methods",
+                    "name":"compute:default"
+                },
+                {
+                    "id":"3",
+                    "description":"User Admin Role.",
+                    "name":"identity:user-admin"
+                }
+            ],
+            "name":"test",
+            "RAX-AUTH:defaultRegion":"ORD"
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/46f493ac/rackspace-autoscale/src/test/resources/autoscale_groups_create_request.json
----------------------------------------------------------------------
diff --git a/rackspace-autoscale/src/test/resources/autoscale_groups_create_request.json b/rackspace-autoscale/src/test/resources/autoscale_groups_create_request.json
new file mode 100644
index 0000000..4480ff0
--- /dev/null
+++ b/rackspace-autoscale/src/test/resources/autoscale_groups_create_request.json
@@ -0,0 +1,56 @@
+{
+  "launchConfiguration": {
+    "args": {
+      "loadBalancers": [
+        {
+          "port": 8080,
+          "loadBalancerId": 9099
+        }
+      ],
+      "server": {
+        "name": "autoscale_server",
+        "imageRef": "0d589460-f177-4b0f-81c1-8ab8903ac7d8",
+        "flavorRef": "2",
+        "OS-DCF:diskConfig": "AUTO",
+        "metadata": {
+          "build_config": "core",
+          "meta_key_1": "meta_value_1",
+          "meta_key_2": "meta_value_2"
+        },
+        "networks": [
+          {
+            "uuid": "11111111-1111-1111-1111-111111111111"
+          },
+          {
+            "uuid": "00000000-0000-0000-0000-000000000000"
+          }
+        ],
+        "personality": [
+          {
+            "path": "/root/.csivh",
+            "contents": "VGhpcyBpcyBhIHRlc3QgZmlsZS4="
+          }
+        ]
+      }
+    },
+    "type": "launch_server"
+  },
+  "groupConfiguration": {
+    "maxEntities": 10,
+    "cooldown": 360,
+    "name": "testscalinggroup198547",
+    "minEntities": 0,
+    "metadata": {
+      "gc_meta_key_2": "gc_meta_value_2",
+      "gc_meta_key_1": "gc_meta_value_1"
+    }
+  },
+  "scalingPolicies": [
+    {
+      "cooldown": 0,
+      "type": "webhook",
+      "name": "scale up by 1",
+      "change": 1
+    }
+  ]
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/46f493ac/rackspace-autoscale/src/test/resources/autoscale_groups_create_response.json
----------------------------------------------------------------------
diff --git a/rackspace-autoscale/src/test/resources/autoscale_groups_create_response.json b/rackspace-autoscale/src/test/resources/autoscale_groups_create_response.json
new file mode 100644
index 0000000..21622f9
--- /dev/null
+++ b/rackspace-autoscale/src/test/resources/autoscale_groups_create_response.json
@@ -0,0 +1,72 @@
+{
+  "group": {
+    "launchConfiguration": {
+      "args": {
+        "loadBalancers": [
+          {
+            "port": 8080,
+            "loadBalancerId": 9099
+          }
+        ],
+        "server": {
+          "name": "autoscale_server",
+          "imageRef": "0d589460-f177-4b0f-81c1-8ab8903ac7d8",
+          "flavorRef": "2",
+          "OS-DCF:diskConfig": "AUTO",
+          "personality": [
+            {
+              "path": "/root/.csivh",
+              "contents": "VGhpcyBpcyBhIHRlc3QgZmlsZS4="
+            }
+          ],
+          "networks": [
+            {
+              "uuid": "11111111-1111-1111-1111-111111111111"
+            },
+            {
+              "uuid": "00000000-0000-0000-0000-000000000000"
+            }
+          ],
+          "metadata": {
+            "build_config": "core",
+            "meta_key_1": "meta_value_1",
+            "meta_key_2": "meta_value_2"
+          }
+        }
+      },
+      "type": "launch_server"
+    },
+    "groupConfiguration": {
+      "maxEntities": 10,
+      "cooldown": 360,
+      "name": "testscalinggroup198547",
+      "minEntities": 0,
+      "metadata": {
+        "gc_meta_key_2": "gc_meta_value_2",
+        "gc_meta_key_1": "gc_meta_value_1"
+      }
+    },
+    "scalingPolicies": [
+      {
+        "name": "scale up by 1",
+        "links": [
+          {
+            "href": "https://ord.autoscale.api.rackspacecloud.com/v1.0/829409/groups/6791761b-821a-4d07-820d-0b2afc7dd7f6/policies/dceb14ac-b2b3-4f06-aac9-a5b6cd5d40e1/",
+            "rel": "self"
+          }
+        ],
+        "cooldown": 0,
+        "type": "webhook",
+        "id": "dceb14ac-b2b3-4f06-aac9-a5b6cd5d40e1",
+        "change": 1
+      }
+    ],
+    "links": [
+      {
+        "href": "https://ord.autoscale.api.rackspacecloud.com/v1.0/829409/groups/6791761b-821a-4d07-820d-0b2afc7dd7f6/",
+        "rel": "self"
+      }
+    ],
+    "id": "6791761b-821a-4d07-820d-0b2afc7dd7f6"
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/46f493ac/rackspace-autoscale/src/test/resources/autoscale_groups_get_response.json
----------------------------------------------------------------------
diff --git a/rackspace-autoscale/src/test/resources/autoscale_groups_get_response.json b/rackspace-autoscale/src/test/resources/autoscale_groups_get_response.json
new file mode 100644
index 0000000..ccf1ec0
--- /dev/null
+++ b/rackspace-autoscale/src/test/resources/autoscale_groups_get_response.json
@@ -0,0 +1,93 @@
+{
+    "group": {
+        "id": "1234567890",
+        "links": [
+          {
+            "href": "https://rackspace/v1.0/010101/groups/1234567890",
+            "rel": "self"
+          }
+        ],
+        "groupConfiguration": {
+            "name": "workers",
+            "cooldown": 60,
+            "minEntities": 5,
+            "maxEntities": 100,
+            "metadata": {
+                "firstkey": "this is a string",
+                "secondkey": "1"
+            }
+        },
+        "launchConfiguration": {
+            "type": "launch_server",
+            "args": {
+                "server": {
+                    "flavorRef": "3",
+                    "name": "webhead",
+                    "imageRef": "0d589460-f177-4b0f-81c1-8ab8903ac7d8",
+                    "OS-DCF:diskConfig": "AUTO",
+                    "metadata": {
+                        "mykey": "myvalue"
+                    },
+                    "personality": [
+                        {
+                            "path": "/root/.ssh/authorized_keys",
+                            "contents": "ssh-rsa AAAAB3Nza...LiPk== user@example.net"
+                        }
+                    ],
+                    "networks": [
+                        {
+                            "uuid": "11111111-1111-1111-1111-111111111111"
+                        }
+                    ]
+                },
+                "loadBalancers": [
+                    {
+                        "loadBalancerId": 2200,
+                        "port": 8081
+                    }
+                ]
+            }
+        },
+        "scalingPolicies": [
+            {
+                "id": "policyId1",
+                "links": [
+                  {
+                    "href": "https://rackspace/v1.0/010101/groups/1234567890/policies/policyId1",
+                    "rel": "self"
+                  }
+                ],
+                "name": "scale up by 10",
+                "change": 10,
+                "cooldown": 5,
+                "type": "webhook"
+            },
+            {
+                "id": "policyId2",
+                "links": [
+                  {
+                    "href": "https://rackspace/v1.0/010101/groups/1234567890/policies/policyId2",
+                    "rel": "self"
+                  }
+                ],
+                "name": "scale down by 5.5 percent",
+                "changePercent": -5.5,
+                "cooldown": 6,
+                "type": "webhook"
+            },
+            {
+                "id": "policyId3",
+                "links": [
+                  {
+                    "href": "https://rackspace/v1.0/010101/groups/groupId/policies/policyId3",
+                    "rel": "self"
+                  }
+                ],
+                "name": "set number of servers to 10",
+                "desiredCapacity": 10,
+                "cooldown": 3,
+                "type": "webhook"
+            }
+        ]
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/46f493ac/rackspace-autoscale/src/test/resources/autoscale_groups_list_response.json
----------------------------------------------------------------------
diff --git a/rackspace-autoscale/src/test/resources/autoscale_groups_list_response.json b/rackspace-autoscale/src/test/resources/autoscale_groups_list_response.json
new file mode 100644
index 0000000..82aa4dc
--- /dev/null
+++ b/rackspace-autoscale/src/test/resources/autoscale_groups_list_response.json
@@ -0,0 +1,33 @@
+{
+    "groups": [
+        {
+            "active": [],
+            "activeCapacity": 0,
+            "desiredCapacity": 0,
+            "id": "e41380ae-173c-4b40-848a-25c16d7fa83d",
+            "links": [
+                {
+                    "href": "https://dfw.autoscale.api.rackspacecloud.com/v1.0/676873/groups/e41380ae-173c-4b40-848a-25c16d7fa83d/",
+                    "rel": "self"
+                }
+            ],
+            "paused": false,
+            "pendingCapacity": 0
+        },
+        {
+            "active": [],
+            "activeCapacity": 0,
+            "desiredCapacity": 0,
+            "id": "f82bb000-f451-40c8-9dc3-6919097d2f7e",
+            "links": [
+                {
+                    "href": "https://dfw.autoscale.api.rackspacecloud.com/v1.0/676873/groups/f82bb000-f451-40c8-9dc3-6919097d2f7e/",
+                    "rel": "self"
+                }
+            ],
+            "paused": false,
+            "pendingCapacity": 0
+        }
+    ],
+    "groups_links": []
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/46f493ac/rackspace-autoscale/src/test/resources/autoscale_groups_state_response.json
----------------------------------------------------------------------
diff --git a/rackspace-autoscale/src/test/resources/autoscale_groups_state_response.json b/rackspace-autoscale/src/test/resources/autoscale_groups_state_response.json
new file mode 100644
index 0000000..f55d08a
--- /dev/null
+++ b/rackspace-autoscale/src/test/resources/autoscale_groups_state_response.json
@@ -0,0 +1,35 @@
+{
+    "group": {
+        "id": "1234567890",
+        "links": [
+            {
+                "href": "https://dfw.servers.api.rackspacecloud.com/v1.0/010101/groups/1234567890",
+                "rel": "self"
+            }
+        ],
+        "active": [
+            {
+                "id": "444444",
+                "links": [
+                    {
+                        "href": "https://dfw.servers.api.rackspacecloud.com/v2/010101/servers/444444",
+                        "rel": "self"
+                    }
+                ]
+            },
+            {
+                "id": "555555555",
+                "links": [
+                    {
+                        "href": "https://dfw.servers.api.rackspacecloud.com/v2/010101/servers/555555555",
+                        "rel": "self"
+                    }
+                ]
+            }
+        ],
+        "activeCapacity": 2,
+        "pendingCapacity": 2,
+        "desiredCapacity": 4,
+        "paused": false
+    }
+}


[2/3] Adds Otter (Rackspace Autoscale) to labs https://issues.apache.org/jira/browse/JCLOUDS-215

Posted by za...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/46f493ac/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/domain/LaunchConfiguration.java
----------------------------------------------------------------------
diff --git a/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/domain/LaunchConfiguration.java b/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/domain/LaunchConfiguration.java
new file mode 100644
index 0000000..a6690ef
--- /dev/null
+++ b/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/domain/LaunchConfiguration.java
@@ -0,0 +1,341 @@
+/*
+ * 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.rackspace.autoscale.v1.domain;
+
+import java.beans.ConstructorProperties;
+import java.util.EnumSet;
+import java.util.List;
+import java.util.Map;
+
+import org.jclouds.rackspace.autoscale.v1.features.GroupApi;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+
+/**
+ * Autoscale LaunchConfiguration.
+ * 
+ * @see GroupApi#create(GroupConfiguration, LaunchConfiguration, List)
+ * @author Zack Shoylev
+ */
+public class LaunchConfiguration implements Comparable<LaunchConfiguration>{
+   private final ImmutableList<LoadBalancer> loadBalancers;
+   private final LaunchConfigurationType type;
+   private final ImmutableList<String> networks;
+   private final ImmutableList<Personality> personalities;
+
+   private final String serverName;
+   private final String serverImageRef;
+   private final String serverFlavorRef;
+   private final String serverDiskConfig;
+   private final ImmutableMap<String, String> serverMetadata;
+
+   @ConstructorProperties({
+      "loadBalancers", "type", "networks", "personalities", "serverName", "serverImageRef", "serverFlavorRef", "serverDiskConfig", "serverMetadata"
+   })
+   protected LaunchConfiguration(List<LoadBalancer> loadBalancers, LaunchConfigurationType type, List<String> networks, List<Personality> personalities, String serverName, String serverImageRef, String serverFlavorRef, String serverDiskConfig, Map<String, String> serverMetadata) {
+      this.loadBalancers = ImmutableList.copyOf(loadBalancers);
+      this.type = type;
+      this.networks = ImmutableList.copyOf(networks);
+      this.personalities = ImmutableList.copyOf(personalities);
+      this.serverName = serverName;
+      this.serverImageRef = serverImageRef;
+      this.serverFlavorRef = serverFlavorRef;
+      this.serverDiskConfig = serverDiskConfig;
+      this.serverMetadata = ImmutableMap.copyOf(serverMetadata);
+   }
+
+   /**
+    * @return the list of load balancers of this LaunchConfiguration.
+    * @see LaunchConfiguration.Builder#loadBalancers(List)
+    */
+   public List<LoadBalancer> getLoadBalancers() {
+      return this.loadBalancers;
+   }
+
+   /**
+    * @return the type for this LaunchConfiguration.
+    * @see LaunchConfigurationType
+    * @see LaunchConfiguration.Builder#type(LaunchConfigurationType)
+    */
+   public LaunchConfigurationType getType() {
+      return this.type;
+   }
+
+   /**
+    * @return the networks for this LaunchConfiguration.
+    * @see LaunchConfiguration#getNetworks()
+    * @see LaunchConfiguration.Builder#networks(List)
+    */
+   public List<String> getNetworks() {
+      return this.networks;
+   }
+
+   /**
+    * @return the personalities for this LaunchConfiguration.
+    * @see Personality
+    * @see LaunchConfiguration.Builder#personalities(List)
+    */
+   public List<Personality> getPersonalities() {
+      return this.personalities;
+   }
+
+   /**
+    * @return the server name for this LaunchConfiguration.
+    * @see LaunchConfiguration.Builder#serverName(String)
+    */
+   public String getServerName() {
+      return this.serverName;
+   }
+
+   /**
+    * @return the server image ref for this LaunchConfiguration.
+    * @see LaunchConfiguration.Builder#serverImageRef(String)
+    */
+   public String getServerImageRef() {
+      return this.serverImageRef;
+   }
+
+   /**
+    * @return the server flavor ref for this LaunchConfiguration.
+    * @see LaunchConfiguration.Builder#serverFlavorRef(String)
+    */
+   public String getServerFlavorRef() {
+      return this.serverFlavorRef;
+   }
+
+   /**
+    * @return the server disk config for this LaunchConfiguration, ex. "AUTO"
+    * @see LaunchConfiguration.Builder#serverDiskConfig(String)
+    */
+   public String getServerDiskConfig() {
+      return this.serverDiskConfig;
+   }
+
+   /**
+    * @return the server metadata for this LaunchConfiguration.
+    * @see LaunchConfiguration.Builder#serverMetadata(ImmutableMap)
+    */
+   public ImmutableMap<String, String> getServerMetadata() {
+      return this.serverMetadata;
+   }
+
+   @Override
+   public int hashCode() {
+      return Objects.hashCode(loadBalancers, type, networks, personalities, serverName, serverImageRef, serverFlavorRef, serverDiskConfig, serverMetadata);
+   }
+
+   @Override
+   public boolean equals(Object obj) {
+      if (this == obj) return true;
+      if (obj == null || getClass() != obj.getClass()) return false;
+      LaunchConfiguration that = LaunchConfiguration.class.cast(obj);
+      return Objects.equal(this.loadBalancers, that.loadBalancers) && 
+            Objects.equal(this.type, that.type) &&
+            Objects.equal(this.networks, that.networks) &&
+            Objects.equal(this.personalities, that.personalities) &&
+            Objects.equal(this.serverName, that.serverName) &&      
+            Objects.equal(this.serverImageRef, that.serverImageRef) &&
+            Objects.equal(this.serverFlavorRef, that.serverFlavorRef) &&
+            Objects.equal(this.serverDiskConfig, that.serverDiskConfig) &&
+            Objects.equal(this.serverMetadata, that.serverMetadata);
+   }
+
+   protected ToStringHelper string() {
+      return Objects.toStringHelper(this)
+            .add("loadBalancers", loadBalancers)
+            .add("type", type)
+            .add("networks", networks)
+            .add("personalities", personalities)
+            .add("serverName", serverName)
+            .add("serverImageRef", serverImageRef)
+            .add("serverFlavorRef", serverFlavorRef)
+            .add("serverDiskConfig", serverDiskConfig)
+            .add("serverMetadata", serverMetadata);
+   }
+
+   @Override
+   public String toString() {
+      return string().toString();
+   }
+
+   public static Builder builder() { 
+      return new Builder();
+   }
+
+   public Builder toBuilder() { 
+      return new Builder().fromLaunchConfiguration(this);
+   }
+
+   public static class Builder {
+      protected List<LoadBalancer> loadBalancers;
+      protected LaunchConfigurationType type;
+      protected List<String> networks;
+      protected List<Personality> personalities;
+
+      protected String serverName;
+      protected String serverImageRef;
+      protected String serverFlavorRef;
+      protected String serverDiskConfig;
+      protected ImmutableMap<String, String> serverMetadata;
+
+      /** 
+       * @param loadBalancers The load balancers of this LaunchConfiguration.
+       * @return The builder object.
+       * @see LaunchConfiguration#getLoadBalancers()
+       */
+      public Builder loadBalancers(List<LoadBalancer> loadBalancers) {
+         this.loadBalancers = loadBalancers;
+         return this;
+      }
+
+      /** 
+       * @param type The type for this LaunchConfiguration.
+       * @return The builder object.
+       * @see LaunchConfiguration#getType()
+       */
+      public Builder type(LaunchConfigurationType type) {
+         this.type = type;
+         return this;
+      }
+
+      /** 
+       * @param networks The networks of this LaunchConfiguration.
+       * @return The builder object.
+       * @see LaunchConfiguration#getNetworks()
+       */
+      public Builder networks(List<String> networks) {
+         this.networks = networks;
+         return this;
+      }
+
+      /** 
+       * @param personalities The personalities of this LaunchConfiguration.
+       * @return The builder object.
+       * @see Personality
+       * @see LaunchConfiguration#getPersonalities()
+       */
+      public Builder personalities(List<Personality> personalities) {
+         this.personalities = personalities;
+         return this;
+      }
+
+      /** 
+       * @param serverName The serverName of this LaunchConfiguration.
+       * @return The builder object.
+       * @see LaunchConfiguration#getServerName()
+       */
+      public Builder serverName(String serverName) {
+         this.serverName = serverName;
+         return this;
+      }
+
+      /** 
+       * @param serverImageRef The serverImageRef of this LaunchConfiguration.
+       * @return The builder object.
+       * @see LaunchConfiguration#getServerImageRef()
+       */
+      public Builder serverImageRef(String serverImageRef) {
+         this.serverImageRef = serverImageRef;
+         return this;
+      }
+
+      /** 
+       * @param serverFlavorRef The serverFlavorRef of this LaunchConfiguration.
+       * @return The builder object.
+       * @see LaunchConfiguration#getServerFlavorRef()
+       */
+      public Builder serverFlavorRef(String serverFlavorRef) {
+         this.serverFlavorRef = serverFlavorRef;
+         return this;
+      }
+
+      /** 
+       * @param serverDiskConfig The serverDiskConfig of this LaunchConfiguration.
+       * @return The builder object.
+       * @see LaunchConfiguration#getServerDiskConfig()
+       */
+      public Builder serverDiskConfig(String serverDiskConfig) {
+         this.serverDiskConfig = serverDiskConfig;
+         return this;
+      }
+
+      /** 
+       * @param serverMetadata The serverMetadata of this LaunchConfiguration.
+       * @return The builder object.
+       * @see LaunchConfiguration#getServerMetadata()
+       */
+      public Builder serverMetadata(Map<String, String> serverMetadata) {
+         this.serverMetadata = ImmutableMap.copyOf(serverMetadata);
+         return this;
+      }
+
+      /**
+       * @return A new LaunchConfiguration object.
+       */
+      public LaunchConfiguration build() {
+         return new LaunchConfiguration(loadBalancers, type, networks, personalities, serverName, serverImageRef, serverFlavorRef, serverDiskConfig, serverMetadata);
+      }
+
+      public Builder fromLaunchConfiguration(LaunchConfiguration in) {
+         return this
+               .loadBalancers(in.getLoadBalancers())
+               .type(in.getType())
+               .networks(in.getNetworks())
+               .personalities(in.getPersonalities())
+               .serverName(in.getServerName())
+               .serverImageRef(in.getServerImageRef())
+               .serverFlavorRef(in.getServerFlavorRef())
+               .serverDiskConfig(in.getServerDiskConfig())
+               .serverMetadata(in.getServerMetadata());
+      }        
+   }
+
+   @Override
+   public int compareTo(LaunchConfiguration that) {
+      return this.getServerName().compareTo(that.getServerName());
+   }
+
+   /**
+    * Enumerates launch configuration types
+    */
+   public static enum LaunchConfigurationType {
+      LAUNCH_SERVER("launch_server");
+
+      private final String name;
+
+      private LaunchConfigurationType(String name) {
+         this.name = name;
+      }
+
+      public String toString() {
+         return name;
+      }
+
+      public static Optional<LaunchConfigurationType> getByValue(String value){
+         for (final LaunchConfigurationType element : EnumSet.allOf(LaunchConfigurationType.class)) {
+            if (element.toString().equals(value)) {
+               return Optional.of(element);
+            }
+         }
+         return Optional.absent();
+      }
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/46f493ac/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/domain/LoadBalancer.java
----------------------------------------------------------------------
diff --git a/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/domain/LoadBalancer.java b/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/domain/LoadBalancer.java
new file mode 100644
index 0000000..004bb97
--- /dev/null
+++ b/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/domain/LoadBalancer.java
@@ -0,0 +1,129 @@
+/*
+ * 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.rackspace.autoscale.v1.domain;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+import java.beans.ConstructorProperties;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.gson.annotations.SerializedName;
+
+/**
+ * Autoscale LoadBalancer. Part of the launch configuration.
+ * 
+ * @see LaunchConfiguration#getLoadBalancers()
+ * @author Zack Shoylev
+ */
+public class LoadBalancer { 
+   private final int port;
+   @SerializedName("loadBalancerId")
+   private final int id;
+
+   @ConstructorProperties({ "port", "loadBalancerId" })
+   protected LoadBalancer(int port, int id) {
+      checkArgument(port >= 0, "port should be non-negative");
+      this.port = port;
+      checkArgument(id >= 0, "id should be non-negative");
+      this.id = id;
+   }
+
+   /**
+    * @return the socket port number of this LoadBalancer.
+    * @see LoadBalancer.Builder#port(int)
+    */
+   public int getPort() {
+      return this.port;
+   }
+
+   /**
+    * @return the id for this LoadBalancer.
+    * @see LoadBalancer.Builder#id(int)
+    */
+   public int getId() {
+      return this.id;
+   }
+
+   @Override
+   public int hashCode() {
+      return Objects.hashCode(port, id);
+   }
+
+   @Override
+   public boolean equals(Object obj) {
+      if (this == obj)
+         return true;
+      if (obj == null || getClass() != obj.getClass())
+         return false;
+      LoadBalancer that = LoadBalancer.class.cast(obj);
+      return Objects.equal(this.port, that.port) && Objects.equal(this.id, that.id);
+   }
+
+   protected ToStringHelper string() {
+      return Objects.toStringHelper(this).add("port", port).add("id", id);
+   }
+
+   @Override
+   public String toString() {
+      return string().toString();
+   }
+
+   public static Builder builder() {
+      return new Builder();
+   }
+
+   public Builder toBuilder() {
+      return new Builder().fromLoadBalancer(this);
+   }
+
+   public static class Builder {
+      protected int port;
+      protected int id;
+
+      /**
+       * @param port The port of this LoadBalancer.
+       * @return The builder object.
+       * @see LoadBalancer#getPort()
+       */
+      public Builder port(int port) {
+         this.port = port;
+         return this;
+      }
+
+      /**
+       * @param id The id of this LoadBalancer.
+       * @return The builder object.
+       * @see LoadBalancer#getId()
+       */
+      public Builder id(int id) {
+         this.id = id;
+         return this;
+      }
+
+      /**
+       * @return A new LoadBalancer object.
+       */
+      public LoadBalancer build() {
+         return new LoadBalancer(port, id);
+      }
+
+      public Builder fromLoadBalancer(LoadBalancer in) {
+         return this.port(in.getPort()).id(in.getId());
+      }
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/46f493ac/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/domain/Personality.java
----------------------------------------------------------------------
diff --git a/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/domain/Personality.java b/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/domain/Personality.java
new file mode 100644
index 0000000..4b2400f
--- /dev/null
+++ b/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/domain/Personality.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.rackspace.autoscale.v1.domain;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.beans.ConstructorProperties;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Autoscale Personality. Part of the launch configuration.
+ * 
+ * @see LaunchConfiguration#getPersonalities()
+ * @author Zack Shoylev
+ */
+public class Personality {
+   private final String path;
+   private final String contents;
+
+   @ConstructorProperties({ "path", "contents" })
+   protected Personality(String path, String contents) {
+      this.path = checkNotNull(path, "path should not be null");
+      this.contents = checkNotNull(contents, "contents should not be null");
+   }
+
+   /**
+    * @return the path of this Personality.
+    * @see Personality.Builder#path(String)
+    */
+   public String getPath() {
+      return this.path;
+   }
+
+   /**
+    * @return the contents for this Personality.
+    * @see Personality.Builder#contents(String)
+    */
+   public String getContents() {
+      return this.contents;
+   }
+
+   @Override
+   public int hashCode() {
+      return Objects.hashCode(path, contents);
+   }
+
+   @Override
+   public boolean equals(Object obj) {
+      if (this == obj)
+         return true;
+      if (obj == null || getClass() != obj.getClass())
+         return false;
+      Personality that = Personality.class.cast(obj);
+      return Objects.equal(this.path, that.path) && Objects.equal(this.contents, that.contents);
+   }
+
+   protected ToStringHelper string() {
+      return Objects.toStringHelper(this).add("path", path).add("contents", contents);
+   }
+
+   @Override
+   public String toString() {
+      return string().toString();
+   }
+
+   public static Builder builder() {
+      return new Builder();
+   }
+
+   public Builder toBuilder() {
+      return new Builder().fromPersonality(this);
+   }
+
+   public static class Builder {
+      protected String path;
+      protected String contents;
+
+      /**
+       * @param path The path of this Personality.
+       * @return The builder object.
+       * @see Personality#getPath()
+       */
+      public Builder path(String path) {
+         this.path = path;
+         return this;
+      }
+
+      /**
+       * @param contents The contents of this Personality.
+       * @return The builder object.
+       * @see Personality#getContents()
+       */
+      public Builder contents(String contents) {
+         this.contents = contents;
+         return this;
+      }
+
+      /**
+       * @return A new Personality object.
+       */
+      public Personality build() {
+         return new Personality(path, contents);
+      }
+
+      public Builder fromPersonality(Personality in) {
+         return this.path(in.getPath()).contents(in.getContents());
+      }
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/46f493ac/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/domain/ScalingPolicy.java
----------------------------------------------------------------------
diff --git a/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/domain/ScalingPolicy.java b/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/domain/ScalingPolicy.java
new file mode 100644
index 0000000..0cefb05
--- /dev/null
+++ b/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/domain/ScalingPolicy.java
@@ -0,0 +1,275 @@
+/*
+ * 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.rackspace.autoscale.v1.domain;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.beans.ConstructorProperties;
+import java.util.EnumSet;
+
+import org.jclouds.rackspace.autoscale.v1.features.GroupApi;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.base.Optional;
+
+/**
+ * Autoscale ScalingPolicy. This class is used for requests.
+ * 
+ * @see GroupApi#create(GroupConfiguration, LaunchConfiguration, java.util.List)
+ * @see Group#getScalingPolicies()
+ * @see ScalingPolicyResponse
+ * @author Zack Shoylev
+ */
+public class ScalingPolicy implements Comparable<ScalingPolicy>{
+   private final String name;
+   private final ScalingPolicyType type;
+   private final int cooldown;
+   private final int target;
+   private final ScalingPolicyTargetType targetType;
+
+   @ConstructorProperties({
+      "name", "type", "cooldown", "target", "targetType"
+   })
+   protected ScalingPolicy(String name, ScalingPolicyType type, int cooldown, int target, ScalingPolicyTargetType targetType) {
+
+      this.name = checkNotNull(name, "name required");
+      this.type = type;
+      checkArgument(cooldown >= 0, "cooldown should be non-negative");
+      this.cooldown = cooldown;
+      this.target = target;
+      this.targetType = targetType;
+   }
+
+   /**
+    * @return the name of this ScalingPolicy.
+    * @see ScalingPolicy.Builder#name(String)
+    */
+   public String getName() {
+      return this.name;
+   }   
+
+   /**
+    * @return the type for this ScalingPolicy.
+    * @see ScalingPolicyType
+    * @see ScalingPolicy.Builder#type(String)
+    */
+   public ScalingPolicyType getType() {
+      return this.type;
+   }
+
+   /**
+    * @return the cooldown for this ScalingPolicy.
+    * @see ScalingPolicy.Builder#cooldown(int)
+    */
+   public int getCooldown() {
+      return this.cooldown;
+   }
+
+   /**
+    * @return the target for this ScalingPolicy. This is a numeric value, but could represent a 0-100% for some target types. Scale-down policies might have negative values.
+    * 
+    * @see ScalingPolicy.Builder#target(int)
+    */
+   public int getTarget() {
+      return this.target;
+   }
+
+   /**
+    * @return the target type for this ScalingPolicy.
+    * @see ScalingPolicyTargetType
+    * @see ScalingPolicy.Builder#targetType(int)
+    */
+   public ScalingPolicyTargetType getTargetType() {
+      return this.targetType;
+   }
+
+   @Override
+   public int hashCode() {
+      return Objects.hashCode(name, type, cooldown, target, targetType);
+   }
+
+   @Override
+   public boolean equals(Object obj) {
+      if (this == obj) return true;
+      if (obj == null || getClass() != obj.getClass()) return false;
+      ScalingPolicy that = ScalingPolicy.class.cast(obj);
+      return Objects.equal(this.name, that.name) && 
+            Objects.equal(this.type, that.type) &&
+            Objects.equal(this.cooldown, that.cooldown) &&
+            Objects.equal(this.target, that.target) &&
+            Objects.equal(this.targetType, that.targetType);
+   }
+
+   protected ToStringHelper string() {
+      return Objects.toStringHelper(this)
+            .add("name", name)
+            .add("type", type)
+            .add("cooldown", cooldown)
+            .add("target", target)
+            .add("targetType", "targetType");
+   }
+
+   @Override
+   public String toString() {
+      return string().toString();
+   }
+
+   public static Builder builder() { 
+      return new Builder();
+   }
+
+   public Builder toBuilder() { 
+      return new Builder().fromScalingPolicy(this);
+   }
+
+   public static class Builder {
+      protected String name;
+      protected ScalingPolicyType type;
+      protected int cooldown;
+      protected int target;
+      protected ScalingPolicyTargetType targetType;
+
+      /** 
+       * @param name The name of this ScalingPolicy.
+       * @return The builder object.
+       * @see ScalingPolicy#getName()
+       */
+      public Builder name(String name) {
+         this.name = name;
+         return this;
+      }
+
+      /** 
+       * @param name The type for this ScalingPolicy.
+       * @return The builder object.
+       * @see ScalingPolicyType
+       * @see ScalingPolicy#getType()
+       */
+      public Builder type(ScalingPolicyType type) {
+         this.type = type;
+         return this;
+      }
+
+      /** 
+       * @param cooldown The cooldown of this ScalingPolicy.
+       * @return The builder object.
+       * @see ScalingPolicy#getCooldown()
+       */
+      public Builder cooldown(int cooldown) {
+         this.cooldown = cooldown;
+         return this;
+      }
+
+      /** 
+       * @param target The target of this ScalingPolicy.
+       * @return The builder object.
+       * @see ScalingPolicy#getTarget()
+       */
+      public Builder target(int target) {
+         this.target = target;
+         return this;
+      }
+
+      /** 
+       * @param target type The target type of this ScalingPolicy.
+       * @return The builder object.
+       * @see ScalingPolicyTargetType
+       * @see ScalingPolicy#getTargetType()
+       */
+      public Builder targetType(ScalingPolicyTargetType targetType) {
+         this.targetType = targetType;
+         return this;
+      }
+
+      /**
+       * @return A new ScalingPolicy object.
+       */
+      public ScalingPolicy build() {
+         return new ScalingPolicy(name, type, cooldown, target, targetType);
+      }
+
+      public Builder fromScalingPolicy(ScalingPolicy in) {
+         return this
+               .name(in.getName())
+               .type(in.getType())
+               .cooldown(in.getCooldown())
+               .target(in.getTarget())
+               .targetType(in.getTargetType());
+      }        
+   }
+
+   @Override
+   public int compareTo(ScalingPolicy that) {
+      return this.getName().compareTo(that.getName());
+   }
+
+   /**
+    * Enumerates different types of scaling policies
+    */
+   public static enum ScalingPolicyType {
+      WEBHOOK("webhook");
+
+      private final String name;
+
+      private ScalingPolicyType(String name) {
+         this.name = name;
+      }
+
+      public String toString() {
+         return name;
+      }
+
+      public static Optional<ScalingPolicyType> getByValue(String value){
+         for (final ScalingPolicyType element : EnumSet.allOf(ScalingPolicyType.class)) {
+            if (element.toString().equals(value)) {
+               return Optional.of(element);
+            }
+         }
+         return Optional.absent();
+      }
+   }
+
+   /**
+    * Enumerates different types of targets a policy might have
+    */
+   public static enum ScalingPolicyTargetType {
+      INCREMENTAL("change"),
+      DESIRED_CAPACITY("desiredCapacity"),
+      PERCENT_CHANGE("changePercent");
+
+      private final String name;
+
+      private ScalingPolicyTargetType(String name) {
+         this.name = name;
+      }
+
+      public String toString() {
+         return name;
+      }
+
+      public static Optional<ScalingPolicyTargetType> getByValue(String value){
+         for (final ScalingPolicyTargetType element : EnumSet.allOf(ScalingPolicyTargetType.class)) {
+            if (element.toString().equals(value)) {
+               return Optional.of(element);
+            }
+         }
+         return Optional.absent();
+      }
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/46f493ac/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/domain/ScalingPolicyResponse.java
----------------------------------------------------------------------
diff --git a/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/domain/ScalingPolicyResponse.java b/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/domain/ScalingPolicyResponse.java
new file mode 100644
index 0000000..c469719
--- /dev/null
+++ b/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/domain/ScalingPolicyResponse.java
@@ -0,0 +1,90 @@
+/*
+ * 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.rackspace.autoscale.v1.domain;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.beans.ConstructorProperties;
+import java.util.List;
+
+import org.jclouds.openstack.v2_0.domain.Link;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.collect.ImmutableList;
+
+/**
+ * Autoscale ScalingPolicyResponse. Extends ScalingPolicy with id and links.
+ * 
+ * @see Group#getScalingPolicies()
+ * @author Zack Shoylev
+ */
+public class ScalingPolicyResponse extends ScalingPolicy{
+   private final ImmutableList<Link> links;
+   private final String id;
+
+   @ConstructorProperties({
+      "name", "type", "cooldown", "target", "targetType", "links", "id"
+   })
+   public ScalingPolicyResponse(String name, ScalingPolicyType type, int cooldown, int target, ScalingPolicyTargetType targetType, List<Link> links, String id) {
+      super(name, type, cooldown, target, targetType);
+      this.id = checkNotNull(id, "id required");
+      this.links = ImmutableList.copyOf(checkNotNull(links, "links required"));
+   }
+
+   /**
+    * @return the unique id of this ScalingPolicy.
+    * @see ScalingPolicyResponse.Builder#id(String)
+    */
+   public String getId() {
+      return this.id;
+   }   
+
+   /**
+    * @return the links to this ScalingPolicy.
+    * @see ScalingPolicyResponse.Builder#links(String)
+    */
+   public ImmutableList<Link> getLinks() {
+      return this.links;
+   }
+
+   @Override
+   public int hashCode() {
+      return Objects.hashCode(super.hashCode(), links, id);
+   }
+
+   @Override
+   public boolean equals(Object obj) {
+      if (this == obj) return true;
+      if (obj == null || getClass() != obj.getClass()) return false;
+      ScalingPolicyResponse that = ScalingPolicyResponse.class.cast(obj);
+      return Objects.equal(this.id, that.id) && 
+            Objects.equal(this.links, that.links) &&
+            super.equals(obj);
+   }
+
+   protected ToStringHelper string() {
+      return super.string()
+            .add("links", links)
+            .add("id", id);
+   }
+
+   @Override
+   public String toString() {
+      return string().toString();
+   }   
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/46f493ac/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/features/GroupApi.java
----------------------------------------------------------------------
diff --git a/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/features/GroupApi.java b/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/features/GroupApi.java
new file mode 100644
index 0000000..f12b690
--- /dev/null
+++ b/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/features/GroupApi.java
@@ -0,0 +1,159 @@
+/*
+ * 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.rackspace.autoscale.v1.features;
+
+
+import java.util.List;
+
+import javax.inject.Named;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.Fallbacks.FalseOnNotFoundOr404;
+import org.jclouds.Fallbacks.NullOnNotFoundOr404;
+import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
+import org.jclouds.rackspace.autoscale.v1.binders.BindCreateGroupToJson;
+import org.jclouds.rackspace.autoscale.v1.domain.Group;
+import org.jclouds.rackspace.autoscale.v1.domain.GroupConfiguration;
+import org.jclouds.rackspace.autoscale.v1.domain.GroupState;
+import org.jclouds.rackspace.autoscale.v1.domain.LaunchConfiguration;
+import org.jclouds.rackspace.autoscale.v1.domain.ScalingPolicy;
+import org.jclouds.rackspace.autoscale.v1.functions.ParseGroupResponse;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.MapBinder;
+import org.jclouds.rest.annotations.PayloadParam;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.ResponseParser;
+import org.jclouds.rest.annotations.SelectJson;
+
+import com.google.common.collect.FluentIterable;
+
+/**
+ * The API for controlling scaling groups.
+ * A scaling group is a high-level autoscaling concept that encompasses a group configuration, a launch configuration, and a set of scaling policies.
+ * @author Zack Shoylev
+ */
+@RequestFilters(AuthenticateRequest.class)
+public interface GroupApi {
+
+   /**
+    * Create a scaling group.
+    * @param groupConfiguration The group configuration.
+    * @param launchConfiguration The launch configuration.
+    * @param scalingPolicies The list of scaling policies.
+    * @return Group The group created by this call.
+    * @see GroupConfiguration
+    * @see LaunchConfiguration
+    * @see ScalingPolicy
+    * @see Group
+    */
+   @Named("Group:create")
+   @POST
+   @Path("/groups")
+   @Consumes(MediaType.APPLICATION_JSON)
+   @Fallback(NullOnNotFoundOr404.class)
+   @MapBinder(BindCreateGroupToJson.class)
+   @ResponseParser(ParseGroupResponse.class)
+   Group create(@PayloadParam("groupConfiguration") GroupConfiguration groupConfiguration, 
+         @PayloadParam("launchConfiguration") LaunchConfiguration launchConfiguration,
+         @PayloadParam("scalingPolicies") List<ScalingPolicy> scalingPolicies);
+
+   /**
+    * This operation pauses the specified Autoscaling Group
+    *
+    * @param groupId The id for the specified Group.
+    * @return true if successful.
+    * @see GroupApi#resume(String)
+    */
+   @Named("Groups:pause/{groupId}")
+   @POST
+   @Path("/groups/{groupId}/pause")
+   @Consumes(MediaType.APPLICATION_JSON)
+   @Fallback(FalseOnNotFoundOr404.class)
+   boolean pause(@PathParam("groupId") String groupId);
+
+   /**
+    * This operation resumes the specified Autoscaling Group.
+    *
+    * @param groupId The id for the specified Group.
+    * @return true if successful.
+    * @see GroupApi#pause(String)
+    */
+   @Named("Groups:pause/{groupId}")
+   @POST
+   @Path("/groups/{groupId}/resume")
+   @Consumes(MediaType.APPLICATION_JSON)
+   @Fallback(FalseOnNotFoundOr404.class)
+   boolean resume(@PathParam("groupId") String groupId);
+
+   /**
+    * This operation deletes the specified Autoscaling Group
+    *
+    * @param groupId The id for the specified Group.
+    * @return true if successful.
+    */
+   @Named("Groups:delete/{id}")
+   @DELETE
+   @Path("/groups/{id}")
+   @Consumes(MediaType.APPLICATION_JSON)
+   @Fallback(FalseOnNotFoundOr404.class)
+   boolean delete(@PathParam("id") String groupId);
+
+   /**
+    * This operation gets group details for a group
+    * @param id The unique identifier of the scaling group.
+    * @return Group Full details for the scaling group.
+    */
+   @Named("Group:get/{id}")
+   @GET
+   @Path("/groups/{id}")
+   @Consumes(MediaType.APPLICATION_JSON)
+   @ResponseParser(ParseGroupResponse.class)
+   @Fallback(NullOnNotFoundOr404.class)
+   Group get(@PathParam("id") String id);
+
+   /**
+    * This operation gets the state of the Autoscaling Group. This is a slightly different set of information than the full details for a group.
+    * @param id The unique identifier of the scaling group.
+    * @return The state of the Group.
+    * @see GroupState
+    */
+   @Named("Group:state")
+   @GET
+   @Path("/groups/{id}/state")
+   @SelectJson("group")
+   @Consumes(MediaType.APPLICATION_JSON)
+   @Fallback(NullOnNotFoundOr404.class)
+   GroupState getState(@PathParam("id") String id);
+
+   /**
+    * This operation lists all autoscaling groups.
+    * @return A list of group states for all scaling groups.
+    * @see GroupState
+    */
+   @Named("Group:states")
+   @GET
+   @Path("/groups")
+   @SelectJson("groups")
+   @Consumes(MediaType.APPLICATION_JSON)
+   FluentIterable<GroupState> listGroupStates();
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/46f493ac/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/functions/ParseGroupResponse.java
----------------------------------------------------------------------
diff --git a/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/functions/ParseGroupResponse.java b/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/functions/ParseGroupResponse.java
new file mode 100644
index 0000000..5673a2c
--- /dev/null
+++ b/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/functions/ParseGroupResponse.java
@@ -0,0 +1,151 @@
+/*
+ * 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.rackspace.autoscale.v1.functions;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.net.URI;
+import java.util.List;
+import java.util.Map;
+
+import org.jclouds.http.HttpResponse;
+import org.jclouds.http.functions.ParseJson;
+import org.jclouds.openstack.v2_0.domain.Link;
+import org.jclouds.openstack.v2_0.domain.Link.Relation;
+import org.jclouds.rackspace.autoscale.v1.domain.Group;
+import org.jclouds.rackspace.autoscale.v1.domain.GroupConfiguration;
+import org.jclouds.rackspace.autoscale.v1.domain.LaunchConfiguration;
+import org.jclouds.rackspace.autoscale.v1.domain.LaunchConfiguration.LaunchConfigurationType;
+import org.jclouds.rackspace.autoscale.v1.domain.LoadBalancer;
+import org.jclouds.rackspace.autoscale.v1.domain.Personality;
+import org.jclouds.rackspace.autoscale.v1.domain.ScalingPolicy.ScalingPolicyTargetType;
+import org.jclouds.rackspace.autoscale.v1.domain.ScalingPolicy.ScalingPolicyType;
+import org.jclouds.rackspace.autoscale.v1.domain.ScalingPolicyResponse;
+
+import com.google.common.base.Function;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+import com.google.inject.Inject;
+
+/**
+ * This parses the group response and decouples domain objects from the json object returned by the service.
+ * @author Zack Shoylev
+ */
+public class ParseGroupResponse implements Function<HttpResponse, Group> {
+
+   private final ParseJson<Map<String, Object>> json;
+
+   @Inject
+   ParseGroupResponse(ParseJson<Map<String, Object>> json) {
+      this.json = checkNotNull(json, "json");
+   }
+
+   /**
+    * Extracts the user password from the json response
+    */
+   @SuppressWarnings("unchecked")
+   public Group apply(HttpResponse from) {
+      Map<String, Object> result = json.apply(from);
+
+      Map<String, Object> group = (Map<String, Object>) result.get("group");
+      Map<String, Object> groupConfigurationMap = (Map<String, Object>) group.get("groupConfiguration");
+      Map<String, Object> launchConfigurationMap = (Map<String, Object>) group.get("launchConfiguration");
+      List<ScalingPolicyResponse> scalingPoliciesList = Lists.newArrayList();
+      Map<String, Object> args = (Map<String, Object>) launchConfigurationMap.get("args");
+      Map<String, Object> server = (Map<String, Object>) args.get("server");      
+
+      List<Personality> personalities = Lists.newArrayList();
+      List<String> networks = Lists.newArrayList();
+      for(Map<String,String> jsonPersonality : (List<Map<String,String>>) server.get("personality")) {
+         personalities.add(Personality.builder().path(jsonPersonality.get("path")).contents(jsonPersonality.get("contents")).build());
+      }
+
+      for(Map<String,String> jsonNetwork : (List<Map<String,String>>) server.get("networks")) {
+         networks.add(jsonNetwork.get("uuid"));
+      }
+
+      List<LoadBalancer> loadBalancers = Lists.newArrayList();
+      for(Map<String,Double> jsonLoadBalancer : (List<Map<String,Double>>) args.get("loadBalancers")) {
+         loadBalancers.add(
+               LoadBalancer.builder().id( ((Double)jsonLoadBalancer.get("loadBalancerId")).intValue() ).port( ((Double)jsonLoadBalancer.get("port")).intValue() ).build()
+               );
+      }
+
+      LaunchConfiguration launchConfiguration = LaunchConfiguration.builder()
+            .loadBalancers(loadBalancers)
+            .serverName((String) server.get("name"))
+            .serverImageRef((String) server.get("imageRef"))
+            .serverFlavorRef((String) server.get("flavorRef"))
+            .serverDiskConfig((String) server.get("OS-DCF:diskConfig"))
+            .serverMetadata((Map<String, String>) server.get("metadata"))
+            .personalities(personalities)
+            .networks(networks)
+            .type(LaunchConfigurationType.getByValue((String) launchConfigurationMap.get("type")).get())
+            .build();
+
+      GroupConfiguration groupConfiguration = GroupConfiguration.builder()
+            .cooldown(((Double) groupConfigurationMap.get("cooldown")).intValue())
+            .minEntities(((Double) groupConfigurationMap.get("minEntities")).intValue())
+            .maxEntities(((Double) groupConfigurationMap.get("maxEntities")).intValue())
+            .name((String) groupConfigurationMap.get("name"))
+            .metadata((Map<String, String>) groupConfigurationMap.get("metadata"))
+            .build();
+
+      for(Map<String, Object> scalingPolicyMap : (List<Map<String, Object>>) group.get("scalingPolicies")) {
+         ScalingPolicyTargetType targetType = null;
+         for(String key : scalingPolicyMap.keySet()) {
+            if(ScalingPolicyTargetType.getByValue(key).isPresent()) {
+               targetType = ScalingPolicyTargetType.getByValue(key).get();
+               break;
+            }  
+         }
+
+         List<Link> links = Lists.newArrayList();
+         for(Map<String, String> linkMap : (List<Map<String, String>>) scalingPolicyMap.get("links")) {
+            Link link = Link.builder().href(URI.create(linkMap.get("href"))).relation(Relation.fromValue(linkMap.get("rel"))).build();
+            links.add(link);
+         }
+
+         ScalingPolicyResponse scalingPolicyResponse = 
+               new ScalingPolicyResponse(
+                     (String)scalingPolicyMap.get("name"),
+                     ScalingPolicyType.getByValue((String)scalingPolicyMap.get("type")).get(),
+                     ((Double)scalingPolicyMap.get("cooldown")).intValue(),
+                     ((Double)scalingPolicyMap.get(targetType.toString())).intValue(),
+                     targetType,
+                     ImmutableList.copyOf(links),
+                     (String) scalingPolicyMap.get("id")
+                     );
+         scalingPoliciesList.add(scalingPolicyResponse);
+      }
+
+      List<Link> links = Lists.newArrayList();
+      for(Map<String, String> linkMap : (List<Map<String, String>>) group.get("links")) {
+         Link link = Link.builder().href(URI.create(linkMap.get("href"))).relation(Relation.fromValue(linkMap.get("rel"))).build();
+         links.add(link);
+      }
+
+      String groupId = (String) group.get("id");
+      return Group.builder()
+            .id(groupId)
+            .scalingPolicy(scalingPoliciesList)
+            .groupConfiguration(groupConfiguration)
+            .launchConfiguration(launchConfiguration)
+            .links(links)
+            .build();
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/46f493ac/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/handlers/AutoscaleErrorHandler.java
----------------------------------------------------------------------
diff --git a/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/handlers/AutoscaleErrorHandler.java b/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/handlers/AutoscaleErrorHandler.java
new file mode 100644
index 0000000..202b5de
--- /dev/null
+++ b/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/handlers/AutoscaleErrorHandler.java
@@ -0,0 +1,67 @@
+/*
+ * 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.rackspace.autoscale.v1.handlers;
+
+import static org.jclouds.http.HttpUtils.closeClientButKeepContentStream;
+
+import javax.inject.Singleton;
+
+import org.jclouds.http.HttpCommand;
+import org.jclouds.http.HttpErrorHandler;
+import org.jclouds.http.HttpResponse;
+import org.jclouds.http.HttpResponseException;
+import org.jclouds.rest.AuthorizationException;
+import org.jclouds.rest.InsufficientResourcesException;
+import org.jclouds.rest.ResourceNotFoundException;
+
+/**
+ * This will parse and set an appropriate exception on the command object.
+ * @author Zack Shoylev
+ */
+@Singleton
+public class AutoscaleErrorHandler implements HttpErrorHandler {
+
+   public void handleError(HttpCommand command, HttpResponse response) {
+      // it is important to always read fully and close streams
+      byte[] data = closeClientButKeepContentStream(response);
+      String message = data != null ? new String(data) : null;
+
+      Exception exception = message != null ? new HttpResponseException(command, response, message)
+      : new HttpResponseException(command, response);
+      message = message != null ? message : String.format("%s -> %s", command.getCurrentRequest().getRequestLine(),
+            response.getStatusLine());
+      switch (response.getStatusCode()) {
+      case 400:
+         if (message.contains("quota exceeded"))
+            exception = new InsufficientResourcesException(message, exception);
+         break;
+      case 401:
+      case 403:
+         exception = new AuthorizationException(message, exception);
+         break;
+      case 404:
+         if (!command.getCurrentRequest().getMethod().equals("DELETE")) {
+            exception = new ResourceNotFoundException(message, exception);
+         }
+         break;
+      case 413:
+         exception = new InsufficientResourcesException(message, exception);
+         break;
+      }
+      command.setException(exception);
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/46f493ac/rackspace-autoscale/src/main/resources/META-INF/services/org.jclouds.apis.ApiMetadata
----------------------------------------------------------------------
diff --git a/rackspace-autoscale/src/main/resources/META-INF/services/org.jclouds.apis.ApiMetadata b/rackspace-autoscale/src/main/resources/META-INF/services/org.jclouds.apis.ApiMetadata
new file mode 100644
index 0000000..4ee5597
--- /dev/null
+++ b/rackspace-autoscale/src/main/resources/META-INF/services/org.jclouds.apis.ApiMetadata
@@ -0,0 +1,18 @@
+#
+# 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.
+#
+
+org.jclouds.rackspace.autoscale.v1.AutoscaleApiMetadata

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/46f493ac/rackspace-autoscale/src/test/java/org/jclouds/rackspace/autoscale/v1/features/GroupApiExpectTest.java
----------------------------------------------------------------------
diff --git a/rackspace-autoscale/src/test/java/org/jclouds/rackspace/autoscale/v1/features/GroupApiExpectTest.java b/rackspace-autoscale/src/test/java/org/jclouds/rackspace/autoscale/v1/features/GroupApiExpectTest.java
new file mode 100644
index 0000000..b6f4e87
--- /dev/null
+++ b/rackspace-autoscale/src/test/java/org/jclouds/rackspace/autoscale/v1/features/GroupApiExpectTest.java
@@ -0,0 +1,357 @@
+/*
+ * 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.rackspace.autoscale.v1.features;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.assertFalse;
+
+import java.net.URI;
+import java.util.List;
+
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.http.HttpResponse;
+import org.jclouds.openstack.v2_0.domain.Link;
+import org.jclouds.rackspace.autoscale.v1.domain.Group;
+import org.jclouds.rackspace.autoscale.v1.domain.GroupConfiguration;
+import org.jclouds.rackspace.autoscale.v1.domain.GroupState;
+import org.jclouds.rackspace.autoscale.v1.domain.LaunchConfiguration;
+import org.jclouds.rackspace.autoscale.v1.domain.LaunchConfiguration.LaunchConfigurationType;
+import org.jclouds.rackspace.autoscale.v1.domain.LoadBalancer;
+import org.jclouds.rackspace.autoscale.v1.domain.Personality;
+import org.jclouds.rackspace.autoscale.v1.domain.ScalingPolicy;
+import org.jclouds.rackspace.autoscale.v1.domain.ScalingPolicy.ScalingPolicyTargetType;
+import org.jclouds.rackspace.autoscale.v1.domain.ScalingPolicy.ScalingPolicyType;
+import org.jclouds.rackspace.autoscale.v1.internal.BaseAutoscaleApiExpectTest;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Lists;
+
+/**
+ * Tests GroupApi Guice wiring and parsing
+ *
+ * @author Zack Shoylev
+ */
+@Test(groups = "unit", testName = "GroupApiExpectTest")
+public class GroupApiExpectTest extends BaseAutoscaleApiExpectTest {
+
+   public void testCreateGroup() {
+      URI endpoint = URI.create("https://dfw.autoscale.api.rackspacecloud.com/v1.0/888888/groups");
+      GroupApi api = requestsSendResponses(
+            keystoneAuthWithUsernameAndPasswordAndTenantName,
+            responseWithKeystoneAccess,
+            authenticatedGET().method("POST").endpoint(endpoint).payload(payloadFromResourceWithContentType("/autoscale_groups_create_request.json", MediaType.APPLICATION_JSON)).build(),
+            HttpResponse.builder().statusCode(201).payload(payloadFromResource("/autoscale_groups_create_response.json")).build()
+            ).getGroupApiForZone("DFW");
+
+      GroupConfiguration groupConfiguration = GroupConfiguration.builder()
+            .maxEntities(10)
+            .cooldown(360)
+            .name("testscalinggroup198547")
+            .minEntities(0)
+            .metadata(ImmutableMap.of("gc_meta_key_2","gc_meta_value_2","gc_meta_key_1","gc_meta_value_1"))
+            .build();
+
+      LaunchConfiguration launchConfiguration = LaunchConfiguration.builder()
+            .loadBalancers(ImmutableList.of(LoadBalancer.builder().port(8080).id(9099).build()))
+            .serverName("autoscale_server")
+            .serverImageRef("0d589460-f177-4b0f-81c1-8ab8903ac7d8")
+            .serverFlavorRef("2")
+            .serverDiskConfig("AUTO")
+            .serverMetadata(ImmutableMap.of("build_config","core","meta_key_1","meta_value_1","meta_key_2","meta_value_2"))
+            .networks(ImmutableList.of("11111111-1111-1111-1111-111111111111","00000000-0000-0000-0000-000000000000"))
+            .personalities(ImmutableList.of(Personality.builder().path("/root/.csivh").contents("VGhpcyBpcyBhIHRlc3QgZmlsZS4=").build()))
+            .type(LaunchConfigurationType.LAUNCH_SERVER)
+            .build();
+
+      List<ScalingPolicy> scalingPolicies = Lists.newArrayList();
+
+      ScalingPolicy scalingPolicy = ScalingPolicy.builder()
+            .cooldown(0)
+            .type(ScalingPolicyType.WEBHOOK)
+            .name("scale up by 1")
+            .targetType(ScalingPolicyTargetType.INCREMENTAL)
+            .target(1)
+            .build();
+      scalingPolicies.add(scalingPolicy);
+
+      Group g = api.create(groupConfiguration, launchConfiguration, scalingPolicies);
+
+      assertNotNull(g);
+      assertEquals(g.getId(),"6791761b-821a-4d07-820d-0b2afc7dd7f6");
+      assertEquals(g.getLinks().size(), 1);
+      assertEquals(g.getLinks().get(0).getHref().toString(), "https://ord.autoscale.api.rackspacecloud.com/v1.0/829409/groups/6791761b-821a-4d07-820d-0b2afc7dd7f6/");
+      assertEquals(g.getLinks().get(0).getRelation(), Link.Relation.SELF);
+
+      assertEquals(g.getScalingPolicies().get(0).getId(), "dceb14ac-b2b3-4f06-aac9-a5b6cd5d40e1");
+      assertEquals(g.getScalingPolicies().get(0).getLinks().size(), 1);
+      assertEquals(g.getScalingPolicies().get(0).getLinks().get(0).getHref().toString(), "https://ord.autoscale.api.rackspacecloud.com/v1.0/829409/groups/6791761b-821a-4d07-820d-0b2afc7dd7f6/policies/dceb14ac-b2b3-4f06-aac9-a5b6cd5d40e1/");
+      assertEquals(g.getScalingPolicies().get(0).getLinks().get(0).getRelation(), Link.Relation.SELF);
+      assertEquals(g.getScalingPolicies().get(0).getCooldown(), 0);
+      assertEquals(g.getScalingPolicies().get(0).getTarget(), 1);
+      assertEquals(g.getScalingPolicies().get(0).getTargetType(), ScalingPolicyTargetType.INCREMENTAL);
+      assertEquals(g.getScalingPolicies().get(0).getType(), ScalingPolicyType.WEBHOOK);
+      assertEquals(g.getScalingPolicies().get(0).getName(), "scale up by 1");
+
+      assertEquals(g.getLaunchConfiguration().getLoadBalancers().size(), 1);
+      assertEquals(g.getLaunchConfiguration().getLoadBalancers().get(0).getId(), 9099);
+      assertEquals(g.getLaunchConfiguration().getLoadBalancers().get(0).getPort(), 8080);
+      assertEquals(g.getLaunchConfiguration().getServerName(), "autoscale_server");
+      assertEquals(g.getLaunchConfiguration().getServerImageRef(), "0d589460-f177-4b0f-81c1-8ab8903ac7d8");
+      assertEquals(g.getLaunchConfiguration().getServerFlavorRef(), "2");
+      assertEquals(g.getLaunchConfiguration().getServerDiskConfig(), "AUTO");
+      assertEquals(g.getLaunchConfiguration().getPersonalities().size(), 1);
+      assertEquals(g.getLaunchConfiguration().getPersonalities().get(0).getPath(), "/root/.csivh");
+      assertEquals(g.getLaunchConfiguration().getPersonalities().get(0).getContents(), "VGhpcyBpcyBhIHRlc3QgZmlsZS4=");
+      assertEquals(g.getLaunchConfiguration().getNetworks().size(), 2);
+      assertEquals(g.getLaunchConfiguration().getNetworks().get(0), "11111111-1111-1111-1111-111111111111");
+      assertEquals(g.getLaunchConfiguration().getNetworks().get(1), "00000000-0000-0000-0000-000000000000");
+      assertEquals(g.getLaunchConfiguration().getServerMetadata().size(), 3);
+      assertTrue(g.getLaunchConfiguration().getServerMetadata().containsKey("build_config"));
+      assertTrue(g.getLaunchConfiguration().getServerMetadata().containsValue("core"));
+      assertEquals(g.getLaunchConfiguration().getType(), LaunchConfigurationType.LAUNCH_SERVER);
+
+      assertEquals(g.getGroupConfiguration().getMaxEntities(), 10);
+      assertEquals(g.getGroupConfiguration().getCooldown(), 360);
+      assertEquals(g.getGroupConfiguration().getName(), "testscalinggroup198547");
+      assertEquals(g.getGroupConfiguration().getMinEntities(), 0);
+      assertEquals(g.getGroupConfiguration().getMetadata().size(), 2);
+      assertTrue(g.getGroupConfiguration().getMetadata().containsKey("gc_meta_key_2"));
+      assertTrue(g.getGroupConfiguration().getMetadata().containsValue("gc_meta_value_2"));
+   }
+
+   public void testCreateGroupFail() {
+      URI endpoint = URI.create("https://dfw.autoscale.api.rackspacecloud.com/v1.0/888888/groups");
+      GroupApi api = requestsSendResponses(
+            keystoneAuthWithUsernameAndPasswordAndTenantName,
+            responseWithKeystoneAccess,
+            authenticatedGET().method("POST").endpoint(endpoint).payload(payloadFromResourceWithContentType("/autoscale_groups_create_request.json", MediaType.APPLICATION_JSON)).build(),
+            HttpResponse.builder().statusCode(404).payload(payloadFromResource("/autoscale_groups_create_response.json")).build()
+            ).getGroupApiForZone("DFW");
+
+      GroupConfiguration groupConfiguration = GroupConfiguration.builder()
+            .maxEntities(10)
+            .cooldown(360)
+            .name("testscalinggroup198547")
+            .minEntities(0)
+            .metadata(ImmutableMap.of("gc_meta_key_2","gc_meta_value_2","gc_meta_key_1","gc_meta_value_1"))
+            .build();
+
+      LaunchConfiguration launchConfiguration = LaunchConfiguration.builder()
+            .loadBalancers(ImmutableList.of(LoadBalancer.builder().port(8080).id(9099).build()))
+            .serverName("autoscale_server")
+            .serverImageRef("0d589460-f177-4b0f-81c1-8ab8903ac7d8")
+            .serverFlavorRef("2")
+            .serverDiskConfig("AUTO")
+            .serverMetadata(ImmutableMap.of("build_config","core","meta_key_1","meta_value_1","meta_key_2","meta_value_2"))
+            .networks(ImmutableList.of("11111111-1111-1111-1111-111111111111","00000000-0000-0000-0000-000000000000"))
+            .personalities(ImmutableList.of(Personality.builder().path("/root/.csivh").contents("VGhpcyBpcyBhIHRlc3QgZmlsZS4=").build()))
+            .type(LaunchConfigurationType.LAUNCH_SERVER)
+            .build();
+
+      List<ScalingPolicy> scalingPolicies = Lists.newArrayList();
+
+      ScalingPolicy scalingPolicy = ScalingPolicy.builder()
+            .cooldown(0)
+            .type(ScalingPolicyType.WEBHOOK)
+            .name("scale up by 1")
+            .targetType(ScalingPolicyTargetType.INCREMENTAL)
+            .target(1)
+            .build();
+      scalingPolicies.add(scalingPolicy);
+
+      Group g = api.create(groupConfiguration, launchConfiguration, scalingPolicies);
+
+      assertNull(g);
+   }
+
+   public void testListGroups() {
+      URI endpoint = URI.create("https://dfw.autoscale.api.rackspacecloud.com/v1.0/888888/groups");
+      GroupApi api = requestsSendResponses(
+            keystoneAuthWithUsernameAndPasswordAndTenantName,
+            responseWithKeystoneAccess,
+            authenticatedGET().endpoint(endpoint).build(),
+            HttpResponse.builder().statusCode(200).payload(payloadFromResource("/autoscale_groups_list_response.json")).build()
+            ).getGroupApiForZone("DFW");
+
+      FluentIterable<GroupState> groupStates = api.listGroupStates();
+      assertEquals(groupStates.size(),2);
+
+      assertEquals(groupStates.get(0).getGroupInstances().size(), 0);
+      assertEquals(groupStates.get(0).getActiveCapacity(), 0);
+      assertEquals(groupStates.get(0).getDesiredCapacity(), 0);
+      assertEquals(groupStates.get(0).getId(), "e41380ae-173c-4b40-848a-25c16d7fa83d");
+      assertEquals(groupStates.get(0).getLinks().size(), 1);
+      assertEquals(groupStates.get(0).getLinks().get(0).getHref().toString(), "https://dfw.autoscale.api.rackspacecloud.com/v1.0/676873/groups/e41380ae-173c-4b40-848a-25c16d7fa83d/");
+      assertEquals(groupStates.get(0).getLinks().get(0).getRelation(), Link.Relation.SELF);
+      assertEquals(groupStates.get(0).getPaused(), false);
+      assertEquals(groupStates.get(0).getPendingCapacity(), 0);
+   }
+
+   @Test(expectedExceptions = org.jclouds.rest.ResourceNotFoundException.class)
+   public void testListGroupsFail() {
+      URI endpoint = URI.create("https://dfw.autoscale.api.rackspacecloud.com/v1.0/888888/groups");
+      GroupApi api = requestsSendResponses(
+            keystoneAuthWithUsernameAndPasswordAndTenantName,
+            responseWithKeystoneAccess,
+            authenticatedGET().endpoint(endpoint).build(),
+            HttpResponse.builder().statusCode(404).build()
+            ).getGroupApiForZone("DFW");
+
+      FluentIterable<GroupState> groupStates = api.listGroupStates();
+      assertEquals(groupStates.size(), 0);
+   }
+
+   public void testGetGroup() {
+      URI endpoint = URI.create("https://dfw.autoscale.api.rackspacecloud.com/v1.0/888888/groups/1234567890");
+      GroupApi api = requestsSendResponses(
+            keystoneAuthWithUsernameAndPasswordAndTenantName,
+            responseWithKeystoneAccess,
+            authenticatedGET().endpoint(endpoint).build(),
+            HttpResponse.builder().statusCode(200).payload(payloadFromResource("/autoscale_groups_get_response.json")).build()
+            ).getGroupApiForZone("DFW");
+
+      Group g = api.get("1234567890");
+      assertEquals(g.getId(), "1234567890");
+      assertEquals(g.getScalingPolicies().size(), 3);
+   }
+
+   public void testGetGroupFail() {
+      URI endpoint = URI.create("https://dfw.autoscale.api.rackspacecloud.com/v1.0/888888/groups/1234567890");
+      GroupApi api = requestsSendResponses(
+            keystoneAuthWithUsernameAndPasswordAndTenantName,
+            responseWithKeystoneAccess,
+            authenticatedGET().endpoint(endpoint).build(),
+            HttpResponse.builder().statusCode(404).build()
+            ).getGroupApiForZone("DFW");
+
+      Group g = api.get("1234567890");
+      assertNull(g);
+   }
+
+   public void testDeleteGroup() {
+      URI endpoint = URI.create("https://dfw.autoscale.api.rackspacecloud.com/v1.0/888888/groups/1234567890");
+      GroupApi api = requestsSendResponses(
+            keystoneAuthWithUsernameAndPasswordAndTenantName,
+            responseWithKeystoneAccess,
+            authenticatedGET().endpoint(endpoint).method("DELETE").build(),
+            HttpResponse.builder().statusCode(204).build()
+            ).getGroupApiForZone("DFW");
+
+      boolean success = api.delete("1234567890");
+      assertTrue(success);
+   }
+
+   public void testDeleteGroupFail() {
+      URI endpoint = URI.create("https://dfw.autoscale.api.rackspacecloud.com/v1.0/888888/groups/1234567890");
+      GroupApi api = requestsSendResponses(
+            keystoneAuthWithUsernameAndPasswordAndTenantName,
+            responseWithKeystoneAccess,
+            authenticatedGET().endpoint(endpoint).method("DELETE").build(),
+            HttpResponse.builder().statusCode(404).build()
+            ).getGroupApiForZone("DFW");
+
+      boolean success = api.delete("1234567890");
+      assertFalse(success);
+   }
+
+   public void testGetGroupState() {
+      URI endpoint = URI.create("https://dfw.autoscale.api.rackspacecloud.com/v1.0/888888/groups/1234567890/state");
+      GroupApi api = requestsSendResponses(
+            keystoneAuthWithUsernameAndPasswordAndTenantName,
+            responseWithKeystoneAccess,
+            authenticatedGET().endpoint(endpoint).build(),
+            HttpResponse.builder().statusCode(200).payload(payloadFromResource("/autoscale_groups_state_response.json")).build()
+            ).getGroupApiForZone("DFW");
+
+      GroupState gs = api.getState("1234567890");
+      assertEquals(gs.getId(), "1234567890");
+      assertEquals(gs.getGroupInstances().size(), 2);
+      assertEquals(gs.getGroupInstances().get(0).getId(), "444444");
+   }
+
+   public void testGetGroupStateFail() {
+      URI endpoint = URI.create("https://dfw.autoscale.api.rackspacecloud.com/v1.0/888888/groups/1234567890/state");
+      GroupApi api = requestsSendResponses(
+            keystoneAuthWithUsernameAndPasswordAndTenantName,
+            responseWithKeystoneAccess,
+            authenticatedGET().endpoint(endpoint).build(),
+            HttpResponse.builder().statusCode(404).payload(payloadFromResource("/autoscale_groups_state_response.json")).build()
+            ).getGroupApiForZone("DFW");
+
+      GroupState gs = api.getState("1234567890");
+      assertNull(gs);
+   }
+
+   public void testPause() {
+      URI endpoint = URI.create("https://dfw.autoscale.api.rackspacecloud.com/v1.0/888888/groups/1234567890/pause");
+      GroupApi api = requestsSendResponses(
+            keystoneAuthWithUsernameAndPasswordAndTenantName,
+            responseWithKeystoneAccess,
+            authenticatedGET().endpoint(endpoint).method("POST").build(),
+            HttpResponse.builder().statusCode(204).build()
+            ).getGroupApiForZone("DFW");
+
+      boolean success = api.pause("1234567890");
+      assertTrue(success);
+   }
+
+   public void testPauseFail() {
+      URI endpoint = URI.create("https://dfw.autoscale.api.rackspacecloud.com/v1.0/888888/groups/1234567890/pause");
+      GroupApi api = requestsSendResponses(
+            keystoneAuthWithUsernameAndPasswordAndTenantName,
+            responseWithKeystoneAccess,
+            authenticatedGET().endpoint(endpoint).method("POST").build(),
+            HttpResponse.builder().statusCode(404).build()
+            ).getGroupApiForZone("DFW");
+
+      boolean success = api.pause("1234567890");
+      assertFalse(success);
+   }
+
+   public void testResume() {
+      URI endpoint = URI.create("https://dfw.autoscale.api.rackspacecloud.com/v1.0/888888/groups/1234567890/resume");
+      GroupApi api = requestsSendResponses(
+            keystoneAuthWithUsernameAndPasswordAndTenantName,
+            responseWithKeystoneAccess,
+            authenticatedGET().endpoint(endpoint).method("POST").build(),
+            HttpResponse.builder().statusCode(204).build()
+            ).getGroupApiForZone("DFW");
+
+      boolean success = api.resume("1234567890");
+      assertTrue(success);
+   }
+
+   public void testResumeFail() {
+      URI endpoint = URI.create("https://dfw.autoscale.api.rackspacecloud.com/v1.0/888888/groups/1234567890/resume");
+      GroupApi api = requestsSendResponses(
+            keystoneAuthWithUsernameAndPasswordAndTenantName,
+            responseWithKeystoneAccess,
+            authenticatedGET().endpoint(endpoint).method("POST").build(),
+            HttpResponse.builder().statusCode(404).build()
+            ).getGroupApiForZone("DFW");
+
+      boolean success = api.resume("1234567890");
+      assertFalse(success);
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/46f493ac/rackspace-autoscale/src/test/java/org/jclouds/rackspace/autoscale/v1/features/GroupApiLiveTest.java
----------------------------------------------------------------------
diff --git a/rackspace-autoscale/src/test/java/org/jclouds/rackspace/autoscale/v1/features/GroupApiLiveTest.java b/rackspace-autoscale/src/test/java/org/jclouds/rackspace/autoscale/v1/features/GroupApiLiveTest.java
new file mode 100644
index 0000000..da6370b
--- /dev/null
+++ b/rackspace-autoscale/src/test/java/org/jclouds/rackspace/autoscale/v1/features/GroupApiLiveTest.java
@@ -0,0 +1,217 @@
+/*
+ * 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.rackspace.autoscale.v1.features;
+
+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.util.List;
+import java.util.Map;
+
+import org.jclouds.openstack.v2_0.domain.Link;
+import org.jclouds.rackspace.autoscale.v1.domain.Group;
+import org.jclouds.rackspace.autoscale.v1.domain.GroupConfiguration;
+import org.jclouds.rackspace.autoscale.v1.domain.GroupState;
+import org.jclouds.rackspace.autoscale.v1.domain.LaunchConfiguration;
+import org.jclouds.rackspace.autoscale.v1.domain.LaunchConfiguration.LaunchConfigurationType;
+import org.jclouds.rackspace.autoscale.v1.domain.LoadBalancer;
+import org.jclouds.rackspace.autoscale.v1.domain.Personality;
+import org.jclouds.rackspace.autoscale.v1.domain.ScalingPolicy;
+import org.jclouds.rackspace.autoscale.v1.domain.ScalingPolicy.ScalingPolicyTargetType;
+import org.jclouds.rackspace.autoscale.v1.domain.ScalingPolicy.ScalingPolicyType;
+import org.jclouds.rackspace.autoscale.v1.internal.BaseAutoscaleApiLiveTest;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+
+/**
+ * Tests GroupApi Guice live test
+ * 
+ * @author Zack Shoylev
+ */
+@Test(groups = "unit", testName = "GroupApiLiveTest")
+public class GroupApiLiveTest extends BaseAutoscaleApiLiveTest {
+
+   private static Map<String, List<Group>> created = Maps.newHashMap();
+
+   @Override
+   @BeforeClass(groups = { "integration", "live" })
+   public void setup() {
+      super.setup();
+      for (String zone : api.getConfiguredZones()) {
+         List<Group> createdGroupList = Lists.newArrayList();
+         created.put(zone, createdGroupList);
+         GroupApi groupApi = api.getGroupApiForZone(zone);
+
+         GroupConfiguration groupConfiguration = GroupConfiguration.builder().maxEntities(10).cooldown(360)
+               .name("testscalinggroup198547").minEntities(0)
+               .metadata(ImmutableMap.of("gc_meta_key_2", "gc_meta_value_2", "gc_meta_key_1", "gc_meta_value_1"))
+               .build();
+
+         LaunchConfiguration launchConfiguration = LaunchConfiguration
+               .builder()
+               .loadBalancers(ImmutableList.of(LoadBalancer.builder().port(8080).id(9099).build()))
+               .serverName("autoscale_server")
+               .serverImageRef("0d589460-f177-4b0f-81c1-8ab8903ac7d8")
+               .serverFlavorRef("1")
+               .serverDiskConfig("AUTO")
+               .serverMetadata(
+                     ImmutableMap
+                     .of("build_config", "core", "meta_key_1", "meta_value_1", "meta_key_2", "meta_value_2"))
+                     .networks(
+                           ImmutableList.of("11111111-1111-1111-1111-111111111111", "00000000-0000-0000-0000-000000000000"))
+                           .personalities(
+                                 ImmutableList.of(Personality.builder().path("/root/.csivh")
+                                       .contents("VGhpcyBpcyBhIHRlc3QgZmlsZS4=").build()))
+                                       .type(LaunchConfigurationType.LAUNCH_SERVER).build();
+
+         List<ScalingPolicy> scalingPolicies = Lists.newArrayList();
+
+         ScalingPolicy scalingPolicy = ScalingPolicy.builder().cooldown(0).type(ScalingPolicyType.WEBHOOK)
+               .name("scale up by 1").targetType(ScalingPolicyTargetType.INCREMENTAL).target(1).build();
+         scalingPolicies.add(scalingPolicy);
+
+         Group g = groupApi.create(groupConfiguration, launchConfiguration, scalingPolicies);
+         createdGroupList.add(g);
+
+         assertNotNull(g);
+         assertNotNull(g.getId());
+         assertEquals(g.getLinks().size(), 1);
+         assertEquals(g.getLinks().get(0).getHref().toString(),
+               "https://" + zone.toLowerCase() + ".autoscale.api.rackspacecloud.com/v1.0/" + api.getCurrentTenantId().get().getId() + "/groups/" + g.getId() + "/");
+         assertEquals(g.getLinks().get(0).getRelation(), Link.Relation.SELF);
+
+         assertNotNull(g.getScalingPolicies().get(0).getId());
+         assertEquals(g.getScalingPolicies().get(0).getLinks().size(), 1);
+         assertEquals(
+               g.getScalingPolicies().get(0).getLinks().get(0).getHref().toString(),
+               "https://" + zone.toLowerCase() + ".autoscale.api.rackspacecloud.com/v1.0/" + api.getCurrentTenantId().get().getId() + "/groups/" + g.getId() + "/policies/" + g.getScalingPolicies().get(0).getId() +"/");
+         assertEquals(g.getScalingPolicies().get(0).getLinks().get(0).getRelation(), Link.Relation.SELF);
+         assertEquals(g.getScalingPolicies().get(0).getCooldown(), 0);
+         assertEquals(g.getScalingPolicies().get(0).getTarget(), 1);
+         assertEquals(g.getScalingPolicies().get(0).getTargetType(), ScalingPolicyTargetType.INCREMENTAL);
+         assertEquals(g.getScalingPolicies().get(0).getType(), ScalingPolicyType.WEBHOOK);
+         assertEquals(g.getScalingPolicies().get(0).getName(), "scale up by 1");
+
+         assertEquals(g.getLaunchConfiguration().getLoadBalancers().size(), 1);
+         assertEquals(g.getLaunchConfiguration().getLoadBalancers().get(0).getId(), 9099);
+         assertEquals(g.getLaunchConfiguration().getLoadBalancers().get(0).getPort(), 8080);
+         assertEquals(g.getLaunchConfiguration().getServerName(), "autoscale_server");
+         assertNotNull(g.getLaunchConfiguration().getServerImageRef());
+         assertEquals(g.getLaunchConfiguration().getServerFlavorRef(), "1");
+         assertEquals(g.getLaunchConfiguration().getServerDiskConfig(), "AUTO");
+         assertEquals(g.getLaunchConfiguration().getPersonalities().size(), 1);
+         assertEquals(g.getLaunchConfiguration().getPersonalities().get(0).getPath(), "/root/.csivh");
+         assertEquals(g.getLaunchConfiguration().getPersonalities().get(0).getContents(),
+               "VGhpcyBpcyBhIHRlc3QgZmlsZS4=");
+         assertEquals(g.getLaunchConfiguration().getNetworks().size(), 2);
+         assertEquals(g.getLaunchConfiguration().getNetworks().get(0), "11111111-1111-1111-1111-111111111111");
+         assertEquals(g.getLaunchConfiguration().getNetworks().get(1), "00000000-0000-0000-0000-000000000000");
+         assertEquals(g.getLaunchConfiguration().getServerMetadata().size(), 3);
+         assertTrue(g.getLaunchConfiguration().getServerMetadata().containsKey("build_config"));
+         assertTrue(g.getLaunchConfiguration().getServerMetadata().containsValue("core"));
+         assertEquals(g.getLaunchConfiguration().getType(), LaunchConfigurationType.LAUNCH_SERVER);
+
+         assertEquals(g.getGroupConfiguration().getMaxEntities(), 10);
+         assertEquals(g.getGroupConfiguration().getCooldown(), 360);
+         assertEquals(g.getGroupConfiguration().getName(), "testscalinggroup198547");
+         assertEquals(g.getGroupConfiguration().getMinEntities(), 0);
+         assertEquals(g.getGroupConfiguration().getMetadata().size(), 2);
+         assertTrue(g.getGroupConfiguration().getMetadata().containsKey("gc_meta_key_2"));
+         assertTrue(g.getGroupConfiguration().getMetadata().containsValue("gc_meta_value_2"));
+      }
+   }
+
+   @Test
+   public void testGetGroup() {
+      for (String zone : api.getConfiguredZones()) {
+         GroupApi groupApi = api.getGroupApiForZone(zone);
+         String groupId = created.get(zone).get(0).getId();
+         Group testGroup = groupApi.get(groupId);
+         assertEquals(testGroup.getId(), groupId);
+         assertEquals(testGroup.getGroupConfiguration().getCooldown(), 360);
+         assertEquals(testGroup.getLaunchConfiguration().getServerName(), "autoscale_server");
+         assertEquals(testGroup.getScalingPolicies().get(0).getName(), "scale up by 1");
+      }
+   }
+
+   @Test
+   public void testGetState() {
+      for (String zone : api.getConfiguredZones()) {
+         GroupApi groupApi = api.getGroupApiForZone(zone);
+         String groupId = created.get(zone).get(0).getId();
+         GroupState testGroup = groupApi.getState(groupId);
+         assertEquals(testGroup.getId(), groupId);
+      }
+   }
+
+   @Test
+   public void testListGroups() {
+      for (String zone : api.getConfiguredZones()) {
+         GroupApi groupApi = api.getGroupApiForZone(zone);
+         FluentIterable<GroupState> groupsList = groupApi.listGroupStates();
+         String groupId = created.get(zone).get(0).getId();
+         for( GroupState groupState : groupsList) {
+            if( groupId.equals(groupState.getId()) ) {
+               return;
+            }
+         }
+         fail("Could not find known groupID " + groupId);
+      }
+   }
+
+   /* TODO: uncomment when implemented
+   @Test
+   public void testPause() {
+      for (String zone : api.getConfiguredZones()) {
+         GroupApi groupApi = api.getGroupApiForZone(zone);
+         String groupId = created.get(zone).get(0).getId();
+         assertTrue(groupApi.pause(groupId));
+      }
+   }
+
+   @Test
+   public void testResume() {
+      for (String zone : api.getConfiguredZones()) {
+         GroupApi groupApi = api.getGroupApiForZone(zone);
+         String groupId = created.get(zone).get(0).getId();
+         assertTrue(groupApi.resume(groupId));
+      }
+   }
+    */
+
+   @Override
+   @AfterClass(groups = { "integration", "live" })
+   public void tearDown() {
+      for (String zone : api.getConfiguredZones()) {
+         GroupApi groupApi = api.getGroupApiForZone(zone);
+         for (Group group : created.get(zone)) {
+            if (!groupApi.delete(group.getId()))
+               throw new RuntimeException("Could not delete an autoscale group after tests!");
+         }
+      }
+      super.tearDown();
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/46f493ac/rackspace-autoscale/src/test/java/org/jclouds/rackspace/autoscale/v1/internal/BaseAutoscaleApiExpectTest.java
----------------------------------------------------------------------
diff --git a/rackspace-autoscale/src/test/java/org/jclouds/rackspace/autoscale/v1/internal/BaseAutoscaleApiExpectTest.java b/rackspace-autoscale/src/test/java/org/jclouds/rackspace/autoscale/v1/internal/BaseAutoscaleApiExpectTest.java
new file mode 100644
index 0000000..4cf1527
--- /dev/null
+++ b/rackspace-autoscale/src/test/java/org/jclouds/rackspace/autoscale/v1/internal/BaseAutoscaleApiExpectTest.java
@@ -0,0 +1,27 @@
+/*
+ * 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.rackspace.autoscale.v1.internal;
+
+import org.jclouds.rackspace.autoscale.v1.AutoscaleApi;
+
+/**
+ * Base class for writing Autoscale Expect tests
+ * 
+ * @author Zack Shoylev
+ */
+public class BaseAutoscaleApiExpectTest extends BaseAutoscaleExpectTest<AutoscaleApi> {
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/46f493ac/rackspace-autoscale/src/test/java/org/jclouds/rackspace/autoscale/v1/internal/BaseAutoscaleApiLiveTest.java
----------------------------------------------------------------------
diff --git a/rackspace-autoscale/src/test/java/org/jclouds/rackspace/autoscale/v1/internal/BaseAutoscaleApiLiveTest.java b/rackspace-autoscale/src/test/java/org/jclouds/rackspace/autoscale/v1/internal/BaseAutoscaleApiLiveTest.java
new file mode 100644
index 0000000..56f4ffa
--- /dev/null
+++ b/rackspace-autoscale/src/test/java/org/jclouds/rackspace/autoscale/v1/internal/BaseAutoscaleApiLiveTest.java
@@ -0,0 +1,43 @@
+/*
+ * 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.rackspace.autoscale.v1.internal;
+
+import java.util.Properties;
+
+import org.jclouds.apis.BaseApiLiveTest;
+import org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties;
+import org.jclouds.rackspace.autoscale.v1.AutoscaleApi;
+
+/**
+ * Tests behavior of AutoscaleApi
+ * 
+ * @author Zack Shoylev
+ */
+public class BaseAutoscaleApiLiveTest extends BaseApiLiveTest<AutoscaleApi> {
+
+   public BaseAutoscaleApiLiveTest() {
+      provider = "rackspace-autoscale";
+   }
+
+   @Override
+   protected Properties setupProperties() {
+      Properties props = super.setupProperties();
+      setIfTestSystemPropertyPresent(props, KeystoneProperties.CREDENTIAL_TYPE);
+      setIfTestSystemPropertyPresent(props, KeystoneProperties.SERVICE_TYPE);
+      return props;
+   }
+}


[3/3] git commit: Adds Otter (Rackspace Autoscale) to labs https://issues.apache.org/jira/browse/JCLOUDS-215

Posted by za...@apache.org.
Adds Otter (Rackspace Autoscale) to labs https://issues.apache.org/jira/browse/JCLOUDS-215


Project: http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/commit/46f493ac
Tree: http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/tree/46f493ac
Diff: http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/diff/46f493ac

Branch: refs/heads/master
Commit: 46f493ac869890fef4085af3de6c1801736a4c23
Parents: 9f440d6
Author: Zack Shoylev <za...@rackspace.com>
Authored: Fri Aug 2 01:34:17 2013 -0500
Committer: Zack Shoylev <za...@rackspace.com>
Committed: Fri Aug 30 12:15:02 2013 -0500

----------------------------------------------------------------------
 pom.xml                                         |   2 +
 rackspace-autoscale-us/pom.xml                  | 145 ++++++++
 .../us/v1/AutoscaleUSProviderMetadata.java      | 114 ++++++
 .../org.jclouds.providers.ProviderMetadata      |  18 +
 .../AutoscaleUSProviderMetadataExpectTest.java  |  64 ++++
 .../us/v1/AutoscaleUSProviderTest.java          |  32 ++
 .../features/AutoscaleUSGroupApiLiveTest.java   |  32 ++
 .../src/test/resources/access_rax_us.json       | 249 +++++++++++++
 .../src/test/resources/logback.xml              |  69 ++++
 rackspace-autoscale/pom.xml                     | 134 +++++++
 .../rackspace/autoscale/v1/AutoscaleApi.java    |  61 ++++
 .../autoscale/v1/AutoscaleApiMetadata.java      |  96 +++++
 .../v1/binders/BindCreateGroupToJson.java       |  97 +++++
 .../v1/config/AutoscaleHttpApiModule.java       |  79 ++++
 .../v1/config/AutoscaleParserModule.java        |  32 ++
 .../rackspace/autoscale/v1/domain/Group.java    | 206 +++++++++++
 .../autoscale/v1/domain/GroupConfiguration.java | 221 ++++++++++++
 .../autoscale/v1/domain/GroupInstance.java      |  82 +++++
 .../autoscale/v1/domain/GroupState.java         | 145 ++++++++
 .../v1/domain/LaunchConfiguration.java          | 341 ++++++++++++++++++
 .../autoscale/v1/domain/LoadBalancer.java       | 129 +++++++
 .../autoscale/v1/domain/Personality.java        | 125 +++++++
 .../autoscale/v1/domain/ScalingPolicy.java      | 275 ++++++++++++++
 .../v1/domain/ScalingPolicyResponse.java        |  90 +++++
 .../autoscale/v1/features/GroupApi.java         | 159 +++++++++
 .../v1/functions/ParseGroupResponse.java        | 151 ++++++++
 .../v1/handlers/AutoscaleErrorHandler.java      |  67 ++++
 .../services/org.jclouds.apis.ApiMetadata       |  18 +
 .../v1/features/GroupApiExpectTest.java         | 357 +++++++++++++++++++
 .../autoscale/v1/features/GroupApiLiveTest.java | 217 +++++++++++
 .../v1/internal/BaseAutoscaleApiExpectTest.java |  27 ++
 .../v1/internal/BaseAutoscaleApiLiveTest.java   |  43 +++
 .../v1/internal/BaseAutoscaleExpectTest.java    |  82 +++++
 .../src/test/resources/access_rax.json          | 249 +++++++++++++
 .../autoscale_groups_create_request.json        |  56 +++
 .../autoscale_groups_create_response.json       |  72 ++++
 .../autoscale_groups_get_response.json          |  93 +++++
 .../autoscale_groups_list_response.json         |  33 ++
 .../autoscale_groups_state_response.json        |  35 ++
 39 files changed, 4497 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/46f493ac/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 814b44e..85e8642 100644
--- a/pom.xml
+++ b/pom.xml
@@ -69,6 +69,8 @@
     <module>openstack-swift</module>
     <module>rackspace-clouddatabases-us</module>
     <module>rackspace-clouddatabases-uk</module>
+    <module>rackspace-autoscale</module>
+    <module>rackspace-autoscale-us</module>
   </modules>
 
   <build>

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/46f493ac/rackspace-autoscale-us/pom.xml
----------------------------------------------------------------------
diff --git a/rackspace-autoscale-us/pom.xml b/rackspace-autoscale-us/pom.xml
new file mode 100644
index 0000000..e2f19a9
--- /dev/null
+++ b/rackspace-autoscale-us/pom.xml
@@ -0,0 +1,145 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.apache.jclouds</groupId>
+    <artifactId>jclouds-project</artifactId>
+    <version>1.7.0-SNAPSHOT</version>
+  </parent>
+
+  <!-- TODO: when out of labs, switch to org.jclouds.api -->
+  <groupId>org.apache.jclouds.labs</groupId>
+  <artifactId>rackspace-autoscale-us</artifactId>
+  <version>1.7.0-SNAPSHOT</version>
+  <name>jclouds rackspace-autoscale api provider</name>
+  <description>jclouds components to access Rackspace Autoscale</description>
+  <packaging>bundle</packaging>
+
+  <properties>
+    <!-- keystone endpoint -->
+    <test.rackspace-autoscale.endpoint>http://localhost:5000/v2.0/</test.rackspace-autoscale.endpoint>
+    <!-- keystone version -->
+    <test.rackspace-autoscale.api-version>2.0</test.rackspace-autoscale.api-version>
+    <test.rackspace-autoscale.build-version />
+    <test.rackspace-autoscale.identity>FIXME_IDENTITY</test.rackspace-autoscale.identity>
+    <test.rackspace-autoscale.credential>FIXME_CREDENTIALS</test.rackspace-autoscale.credential>
+    <test.jclouds.keystone.credential-type>passwordCredentials</test.jclouds.keystone.credential-type>
+
+    <jclouds.osgi.export>org.jclouds.rackspace.autoscale.v1_0*;version="${project.version}"</jclouds.osgi.export>
+    <jclouds.osgi.import>
+      org.jclouds.rest.internal;version="${jclouds.version}",
+      org.jclouds.labs*;version="${project.version}",
+      org.jclouds*;version="${jclouds.version}",
+      *
+    </jclouds.osgi.import>
+  </properties>
+  
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.jclouds.labs</groupId>
+      <artifactId>rackspace-autoscale</artifactId>
+      <version>${project.parent.version}</version>
+      <type>test-jar</type>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.jclouds.labs</groupId>
+      <artifactId>rackspace-autoscale</artifactId>
+      <version>${project.parent.version}</version>
+    </dependency>
+    <dependency>    
+      <groupId>org.apache.jclouds.api</groupId>
+      <artifactId>openstack-keystone</artifactId>
+      <version>${project.parent.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.jclouds.api</groupId>
+      <artifactId>openstack-keystone</artifactId>
+      <version>${project.parent.version}</version>
+      <type>test-jar</type>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.jclouds</groupId>
+      <artifactId>jclouds-core</artifactId>
+      <version>${project.parent.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.jclouds</groupId>
+      <artifactId>jclouds-core</artifactId>
+      <version>${project.parent.version}</version>
+      <type>test-jar</type>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.jclouds.driver</groupId>
+      <artifactId>jclouds-slf4j</artifactId>
+      <version>${project.parent.version}</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>ch.qos.logback</groupId>
+      <artifactId>logback-classic</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+    	<groupId>org.apache.jclouds.api</groupId>
+    	<artifactId>rackspace-cloudidentity</artifactId>
+    	<version>${project.parent.version}</version>
+    </dependency>
+  </dependencies>
+
+  <profiles>
+    <profile>
+      <id>live</id>
+      <build>
+        <plugins>
+          <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-surefire-plugin</artifactId>
+            <executions>
+              <execution>
+                <id>integration</id>
+                <phase>integration-test</phase>
+                <goals>
+                  <goal>test</goal>
+                </goals>
+                <configuration>
+                  <forkCount>5</forkCount>
+                  <reuseForks>true</reuseForks>
+                  <parallel>classes</parallel>
+                  <systemPropertyVariables>
+                    <test.rackspace-autoscale.endpoint>${test.rackspace-autoscale-us.endpoint}</test.rackspace-autoscale.endpoint>
+                    <test.rackspace-autoscale.api-version>${test.rackspace-autoscale-us.api-version}</test.rackspace-autoscale.api-version>
+                    <test.rackspace-autoscale.build-version>${test.rackspace-autoscale-us.build-version}</test.rackspace-autoscale.build-version>
+                    <test.rackspace-autoscale.identity>${test.rackspace-autoscale-us.identity}</test.rackspace-autoscale.identity>
+                    <test.rackspace-autoscale.credential>${test.rackspace-autoscale-us.credential}</test.rackspace-autoscale.credential>
+                  </systemPropertyVariables>
+                </configuration>
+              </execution>
+            </executions>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+  </profiles>
+
+</project>

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/46f493ac/rackspace-autoscale-us/src/main/java/org/jclouds/rackspace/autoscale/us/v1/AutoscaleUSProviderMetadata.java
----------------------------------------------------------------------
diff --git a/rackspace-autoscale-us/src/main/java/org/jclouds/rackspace/autoscale/us/v1/AutoscaleUSProviderMetadata.java b/rackspace-autoscale-us/src/main/java/org/jclouds/rackspace/autoscale/us/v1/AutoscaleUSProviderMetadata.java
new file mode 100644
index 0000000..f680c25
--- /dev/null
+++ b/rackspace-autoscale-us/src/main/java/org/jclouds/rackspace/autoscale/us/v1/AutoscaleUSProviderMetadata.java
@@ -0,0 +1,114 @@
+/*
+ * 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.rackspace.autoscale.us.v1;
+
+import static org.jclouds.location.reference.LocationConstants.ISO3166_CODES;
+import static org.jclouds.location.reference.LocationConstants.PROPERTY_ZONE;
+import static org.jclouds.location.reference.LocationConstants.PROPERTY_ZONES;
+import static org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties.CREDENTIAL_TYPE;
+import static org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties.SERVICE_TYPE;
+
+import java.net.URI;
+import java.util.Properties;
+
+import org.jclouds.apis.ApiMetadata;
+import org.jclouds.openstack.keystone.v2_0.config.KeystoneAuthenticationModule.ZoneModule;
+import org.jclouds.providers.ProviderMetadata;
+import org.jclouds.providers.internal.BaseProviderMetadata;
+import org.jclouds.rackspace.autoscale.v1.AutoscaleApiMetadata;
+import org.jclouds.rackspace.autoscale.v1.config.AutoscaleHttpApiModule;
+import org.jclouds.rackspace.autoscale.v1.config.AutoscaleParserModule;
+import org.jclouds.rackspace.cloudidentity.v2_0.config.CloudIdentityAuthenticationApiModule;
+import org.jclouds.rackspace.cloudidentity.v2_0.config.CloudIdentityAuthenticationModule;
+import org.jclouds.rackspace.cloudidentity.v2_0.config.CloudIdentityCredentialTypes;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.Module;
+
+/**
+ * Implementation of {@link ProviderMetadata} for Rackspace Autoscale API
+ * 
+ * @author Zack Shoylev
+ */
+public class AutoscaleUSProviderMetadata extends BaseProviderMetadata {
+
+   public static Builder builder() {
+      return new Builder();
+   }
+
+   @Override
+   public Builder toBuilder() {
+      return builder().fromProviderMetadata(this);
+   }
+
+   public AutoscaleUSProviderMetadata() {
+      super(builder());
+   }
+
+   public AutoscaleUSProviderMetadata(Builder builder) {
+      super(builder);
+   }
+
+   public static Properties defaultProperties() {
+      Properties properties = new Properties();
+      properties.setProperty(CREDENTIAL_TYPE, CloudIdentityCredentialTypes.API_KEY_CREDENTIALS);
+      properties.setProperty(SERVICE_TYPE, "rax:autoscale"); 
+      properties.setProperty(PROPERTY_ZONES, "ORD,DFW,SYD");
+      properties.setProperty(PROPERTY_ZONE + ".ORD." + ISO3166_CODES, "US-IL");
+      properties.setProperty(PROPERTY_ZONE + ".DFW." + ISO3166_CODES, "US-TX");
+      properties.setProperty(PROPERTY_ZONE + ".SYD." + ISO3166_CODES, "AU-NSW");
+      return properties;
+   }
+
+   public static class Builder extends BaseProviderMetadata.Builder {
+
+      protected Builder(){
+         id("rackspace-autoscale-us")
+         .name("Rackspace autoscale US")
+         .apiMetadata(new AutoscaleApiMetadata().toBuilder()
+               .identityName("${userName}")
+               .credentialName("${apiKey}")
+               .defaultEndpoint("https://identity.api.rackspacecloud.com/v2.0/")
+               .endpointName("identity service url ending in /v2.0/")
+               .documentation(URI.create("http://docs.rackspace.com/cbs/api/v1.0/cbs-devguide/content/overview.html"))
+               .defaultModules(ImmutableSet.<Class<? extends Module>>builder()
+                     .add(CloudIdentityAuthenticationApiModule.class)
+                     .add(CloudIdentityAuthenticationModule.class)
+                     .add(ZoneModule.class)
+                     .add(AutoscaleParserModule.class)
+                     .add(AutoscaleHttpApiModule.class).build())
+                     .build())
+                     .homepage(URI.create("http://www.rackspace.com/cloud/public/autoscale/"))
+                     .console(URI.create("https://mycloud.rackspace.com"))
+                     .linkedServices("rackspace-cloudservers-us", "cloudfiles-us")
+                     .iso3166Codes("US-IL", "US-TX", "AU-NSW")
+                     .endpoint("https://identity.api.rackspacecloud.com/v2.0/")
+                     .defaultProperties(AutoscaleUSProviderMetadata.defaultProperties());
+      }
+
+      @Override
+      public AutoscaleUSProviderMetadata build() {
+         return new AutoscaleUSProviderMetadata(this);
+      }
+
+      @Override
+      public Builder fromProviderMetadata(ProviderMetadata in) {
+         super.fromProviderMetadata(in);
+         return this;
+      }
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/46f493ac/rackspace-autoscale-us/src/main/resources/META-INF/services/org.jclouds.providers.ProviderMetadata
----------------------------------------------------------------------
diff --git a/rackspace-autoscale-us/src/main/resources/META-INF/services/org.jclouds.providers.ProviderMetadata b/rackspace-autoscale-us/src/main/resources/META-INF/services/org.jclouds.providers.ProviderMetadata
new file mode 100644
index 0000000..1717af9
--- /dev/null
+++ b/rackspace-autoscale-us/src/main/resources/META-INF/services/org.jclouds.providers.ProviderMetadata
@@ -0,0 +1,18 @@
+#
+# 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.
+#
+
+org.jclouds.rackspace.autoscale.us.v1.AutoscaleUSProviderMetadata

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/46f493ac/rackspace-autoscale-us/src/test/java/org/jclouds/rackspace/autoscale/us/v1/AutoscaleUSProviderMetadataExpectTest.java
----------------------------------------------------------------------
diff --git a/rackspace-autoscale-us/src/test/java/org/jclouds/rackspace/autoscale/us/v1/AutoscaleUSProviderMetadataExpectTest.java b/rackspace-autoscale-us/src/test/java/org/jclouds/rackspace/autoscale/us/v1/AutoscaleUSProviderMetadataExpectTest.java
new file mode 100644
index 0000000..f119e99
--- /dev/null
+++ b/rackspace-autoscale-us/src/test/java/org/jclouds/rackspace/autoscale/us/v1/AutoscaleUSProviderMetadataExpectTest.java
@@ -0,0 +1,64 @@
+/*
+ * 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.rackspace.autoscale.us.v1;
+
+import static org.testng.Assert.assertEquals;
+
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.HttpResponse;
+import org.jclouds.rackspace.autoscale.v1.AutoscaleApi;
+import org.jclouds.rackspace.autoscale.v1.internal.BaseAutoscaleApiExpectTest;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * This test ensures that the wiring in {@link AutoscaleUSProviderMetadata} is correct.
+ * 
+ * @author Zack Shoylev
+ */
+@Test(groups = "unit", testName = "AutoscaleUSProviderMetadataExpectTest")
+public class AutoscaleUSProviderMetadataExpectTest extends BaseAutoscaleApiExpectTest {
+
+   public AutoscaleUSProviderMetadataExpectTest() {
+      this.provider = "rackspace-autoscale-us";
+      this.identity = "myUsername";
+      this.credential = "myApiKey";
+   }
+
+   public void testCanGetConfiguredZones() {
+
+      HttpRequest authenticate = HttpRequest.builder().method("POST")
+            .endpoint("https://identity.api.rackspacecloud.com/v2.0/tokens")
+            .addHeader("Accept", "application/json")
+            .payload(payloadFromStringWithContentType(
+                  "{\"auth\":{\"RAX-KSKEY:apiKeyCredentials\":{\"username\":\"myUsername\",\"apiKey\":\"myApiKey\"}}}"
+                  , "application/json")).build();
+
+
+      HttpResponse authenticationResponse = HttpResponse.builder()
+            .statusCode(200)
+            .payload(payloadFromResourceWithContentType("/access_rax_us.json", "application/json"))
+            .build();
+
+      AutoscaleApi whenNovaRegionExists = requestSendsResponse(authenticate, authenticationResponse);
+
+      assertEquals(whenNovaRegionExists.getConfiguredZones(), ImmutableSet.of("ORD", "DFW"));
+
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/46f493ac/rackspace-autoscale-us/src/test/java/org/jclouds/rackspace/autoscale/us/v1/AutoscaleUSProviderTest.java
----------------------------------------------------------------------
diff --git a/rackspace-autoscale-us/src/test/java/org/jclouds/rackspace/autoscale/us/v1/AutoscaleUSProviderTest.java b/rackspace-autoscale-us/src/test/java/org/jclouds/rackspace/autoscale/us/v1/AutoscaleUSProviderTest.java
new file mode 100644
index 0000000..2d2ca2c
--- /dev/null
+++ b/rackspace-autoscale-us/src/test/java/org/jclouds/rackspace/autoscale/us/v1/AutoscaleUSProviderTest.java
@@ -0,0 +1,32 @@
+/*
+ * 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.rackspace.autoscale.us.v1;
+
+import org.jclouds.providers.internal.BaseProviderMetadataTest;
+import org.jclouds.rackspace.autoscale.v1.AutoscaleApiMetadata;
+import org.testng.annotations.Test;
+
+/**
+ * @author Zack Shoylev
+ */
+@Test(groups = "unit", testName = "AutoscaleUSProviderTest")
+public class AutoscaleUSProviderTest extends BaseProviderMetadataTest {
+
+   public AutoscaleUSProviderTest() {
+      super(new AutoscaleUSProviderMetadata(), new AutoscaleApiMetadata());
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/46f493ac/rackspace-autoscale-us/src/test/java/org/jclouds/rackspace/autoscale/us/v1/features/AutoscaleUSGroupApiLiveTest.java
----------------------------------------------------------------------
diff --git a/rackspace-autoscale-us/src/test/java/org/jclouds/rackspace/autoscale/us/v1/features/AutoscaleUSGroupApiLiveTest.java b/rackspace-autoscale-us/src/test/java/org/jclouds/rackspace/autoscale/us/v1/features/AutoscaleUSGroupApiLiveTest.java
new file mode 100644
index 0000000..08ac5fb
--- /dev/null
+++ b/rackspace-autoscale-us/src/test/java/org/jclouds/rackspace/autoscale/us/v1/features/AutoscaleUSGroupApiLiveTest.java
@@ -0,0 +1,32 @@
+/*
+ * 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.rackspace.autoscale.us.v1.features;
+
+import org.jclouds.rackspace.autoscale.v1.features.GroupApiLiveTest;
+import org.testng.annotations.Test;
+
+/**
+ * Tests GroupApi Guice wiring and parsing
+ *
+ * @author Zack Shoylev
+ */
+@Test(groups = "unit", testName = "AutoscaleUSGroupApiLiveTest")
+public class AutoscaleUSGroupApiLiveTest extends GroupApiLiveTest {
+   public AutoscaleUSGroupApiLiveTest() {
+      provider = "rackspace-autoscale-us";
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/46f493ac/rackspace-autoscale-us/src/test/resources/access_rax_us.json
----------------------------------------------------------------------
diff --git a/rackspace-autoscale-us/src/test/resources/access_rax_us.json b/rackspace-autoscale-us/src/test/resources/access_rax_us.json
new file mode 100644
index 0000000..2fba05d
--- /dev/null
+++ b/rackspace-autoscale-us/src/test/resources/access_rax_us.json
@@ -0,0 +1,249 @@
+{
+    "access":{
+        "token":{
+            "id":"bb03a23aa8271291a7aaa9aaa2aaaaaa",
+            "expires":"2013-08-02T16:55:24.229-05:00",
+            "tenant":{
+                "id":"888888",
+                "name":"888888"
+            },
+            "RAX-AUTH:authenticatedBy":[
+                "PASSWORD"
+            ]
+        },
+        "serviceCatalog":[
+            {
+                "name":"cloudFilesCDN",
+                "endpoints":[
+                    {
+                        "region":"ORD",
+                        "tenantId":"MossoCloudFS_0d629063-aa0f-4bf9-9e04-62e1fd6aaa2c",
+                        "publicURL":"https:\/\/cdn2.clouddrive.com\/v1\/MossoCloudFS_0d629063-aa0f-4bf9-9e04-62e1fd6aaa2c"
+                    },
+                    {
+                        "region":"DFW",
+                        "tenantId":"MossoCloudFS_0d629063-aa0f-4bf9-9e04-62e1fd6aaa2c",
+                        "publicURL":"https:\/\/cdn1.clouddrive.com\/v1\/MossoCloudFS_0d629063-aa0f-4bf9-9e04-62e1fd6aaa2c"
+                    },
+                    {
+                        "region":"SYD",
+                        "tenantId":"MossoCloudFS_0d629063-aa0f-4bf9-9e04-62e1fd6aaa2c",
+                        "publicURL":"https:\/\/cdn4.clouddrive.com\/v1\/MossoCloudFS_0d629063-aa0f-4bf9-9e04-62e1fd6aaa2c"
+                    }
+                ],
+                "type":"rax:object-cdn"
+            },
+            {
+                "name":"cloudFiles",
+                "endpoints":[
+                    {
+                        "region":"ORD",
+                        "tenantId":"MossoCloudFS_0d629063-aa0f-4bf9-9e04-62e1fd6aaa2c",
+                        "publicURL":"https:\/\/storage101.ord1.clouddrive.com\/v1\/MossoCloudFS_0d629063-aa0f-4bf9-9e04-62e1fd6aaa2c",
+                        "internalURL":"https:\/\/snet-storage101.ord1.clouddrive.com\/v1\/MossoCloudFS_0d629063-aa0f-4bf9-9e04-62e1fd6aaa2c"
+                    },
+                    {
+                        "region":"DFW",
+                        "tenantId":"MossoCloudFS_0d629063-aa0f-4bf9-9e04-62e1fd6aaa2c",
+                        "publicURL":"https:\/\/storage101.dfw1.clouddrive.com\/v1\/MossoCloudFS_0d629063-aa0f-4bf9-9e04-62e1fd6aaa2c",
+                        "internalURL":"https:\/\/snet-storage101.dfw1.clouddrive.com\/v1\/MossoCloudFS_0d629063-aa0f-4bf9-9e04-62e1fd6aaa2c"
+                    },
+                    {
+                        "region":"SYD",
+                        "tenantId":"MossoCloudFS_0d629063-aa0f-4bf9-9e04-62e1fd6aaa2c",
+                        "publicURL":"https:\/\/storage101.syd2.clouddrive.com\/v1\/MossoCloudFS_0d629063-aa0f-4bf9-9e04-62e1fd6aaa2c",
+                        "internalURL":"https:\/\/snet-storage101.syd2.clouddrive.com\/v1\/MossoCloudFS_0d629063-aa0f-4bf9-9e04-62e1fd6aaa2c"
+                    }
+                ],
+                "type":"object-store"
+            },
+            {
+                "name":"cloudLoadBalancers",
+                "endpoints":[
+                    {
+                        "region":"SYD",
+                        "tenantId":"888888",
+                        "publicURL":"https:\/\/syd.loadbalancers.api.rackspacecloud.com\/v1.0\/888888"
+                    },
+                    {
+                        "region":"DFW",
+                        "tenantId":"888888",
+                        "publicURL":"https:\/\/dfw.loadbalancers.api.rackspacecloud.com\/v1.0\/888888"
+                    },
+                    {
+                        "region":"ORD",
+                        "tenantId":"888888",
+                        "publicURL":"https:\/\/ord.loadbalancers.api.rackspacecloud.com\/v1.0\/888888"
+                    }
+                ],
+                "type":"rax:load-balancer"
+            },
+            {
+                "name":"cloudDatabases",
+                "endpoints":[
+                    {
+                        "region":"SYD",
+                        "tenantId":"888888",
+                        "publicURL":"https:\/\/syd.databases.api.rackspacecloud.com\/v1.0\/888888"
+                    },
+                    {
+                        "region":"DFW",
+                        "tenantId":"888888",
+                        "publicURL":"https:\/\/dfw.databases.api.rackspacecloud.com\/v1.0\/888888"
+                    },
+                    {
+                        "region":"ORD",
+                        "tenantId":"888888",
+                        "publicURL":"https:\/\/ord.databases.api.rackspacecloud.com\/v1.0\/888888"
+                    }
+                ],
+                "type":"rax:database"
+            },
+            {
+                "name":"cloudBlockStorage",
+                "endpoints":[
+                    {
+                        "region":"SYD",
+                        "tenantId":"888888",
+                        "publicURL":"https:\/\/syd.blockstorage.api.rackspacecloud.com\/v1\/888888"
+                    },
+                    {
+                        "region":"DFW",
+                        "tenantId":"888888",
+                        "publicURL":"https:\/\/dfw.blockstorage.api.rackspacecloud.com\/v1\/888888"
+                    },
+                    {
+                        "region":"ORD",
+                        "tenantId":"888888",
+                        "publicURL":"https:\/\/ord.blockstorage.api.rackspacecloud.com\/v1\/888888"
+                    }
+                ],
+                "type":"volume"
+            },
+            {
+                "name":"cloudServersOpenStack",
+                "endpoints":[
+                    {
+                        "region":"SYD",
+                        "tenantId":"888888",
+                        "publicURL":"https:\/\/syd.servers.api.rackspacecloud.com\/v2\/888888",
+                        "versionInfo":"https:\/\/syd.servers.api.rackspacecloud.com\/v2",
+                        "versionList":"https:\/\/syd.servers.api.rackspacecloud.com\/",
+                        "versionId":"2"
+                    },
+                    {
+                        "region":"DFW",
+                        "tenantId":"888888",
+                        "publicURL":"https:\/\/dfw.servers.api.rackspacecloud.com\/v2\/888888",
+                        "versionInfo":"https:\/\/dfw.servers.api.rackspacecloud.com\/v2",
+                        "versionList":"https:\/\/dfw.servers.api.rackspacecloud.com\/",
+                        "versionId":"2"
+                    },
+                    {
+                        "region":"ORD",
+                        "tenantId":"888888",
+                        "publicURL":"https:\/\/ord.servers.api.rackspacecloud.com\/v2\/888888",
+                        "versionInfo":"https:\/\/ord.servers.api.rackspacecloud.com\/v2",
+                        "versionList":"https:\/\/ord.servers.api.rackspacecloud.com\/",
+                        "versionId":"2"
+                    }
+                ],
+                "type":"compute"
+            },
+            {
+                "name":"autoscale",
+                "endpoints":[
+                    {
+                        "region":"ORD",
+                        "tenantId":"888888",
+                        "publicURL":"https:\/\/ord.autoscale.api.rackspacecloud.com\/v1.0\/888888",
+                        "versionInfo":null,
+                        "versionList":null,
+                        "versionId":"1.0"
+                    },
+                    {
+                        "region":"DFW",
+                        "tenantId":"888888",
+                        "publicURL":"https:\/\/dfw.autoscale.api.rackspacecloud.com\/v1.0\/888888",
+                        "versionInfo":null,
+                        "versionList":null,
+                        "versionId":"1.0"
+                    }
+                ],
+                "type":"rax:autoscale"
+            },
+            {
+                "name":"cloudMonitoring",
+                "endpoints":[
+                    {
+                        "tenantId":"888888",
+                        "publicURL":"https:\/\/monitoring.api.rackspacecloud.com\/v1.0\/888888"
+                    }
+                ],
+                "type":"rax:monitor"
+            },
+            {
+                "name":"cloudBackup",
+                "endpoints":[
+                    {
+                        "tenantId":"888888",
+                        "publicURL":"https:\/\/backup.api.rackspacecloud.com\/v1.0\/888888"
+                    }
+                ],
+                "type":"rax:backup"
+            },
+            {
+                "name":"cloudServers",
+                "endpoints":[
+                    {
+                        "tenantId":"888888",
+                        "publicURL":"https:\/\/servers.api.rackspacecloud.com\/v1.0\/888888",
+                        "versionInfo":"https:\/\/servers.api.rackspacecloud.com\/v1.0",
+                        "versionList":"https:\/\/servers.api.rackspacecloud.com\/",
+                        "versionId":"1.0"
+                    }
+                ],
+                "type":"compute"
+            },
+            {
+                "name":"cloudDNS",
+                "endpoints":[
+                    {
+                        "tenantId":"888888",
+                        "publicURL":"https:\/\/dns.api.rackspacecloud.com\/v1.0\/888888"
+                    }
+                ],
+                "type":"rax:dns"
+            }
+        ],
+        "user":{
+            "id":"335853",
+            "roles":[
+                {
+                    "id":"10000150",
+                    "description":"Checkmate Access role",
+                    "name":"checkmate"
+                },
+                {
+                    "tenantId":"MossoCloudFS_0d629063-aa0f-4bf9-9e04-62e1fd6aaa2c",
+                    "id":"5",
+                    "description":"A Role that allows a user access to keystone Service methods",
+                    "name":"object-store:default"
+                },
+                {
+                    "tenantId":"888888",
+                    "id":"6",
+                    "description":"A Role that allows a user access to keystone Service methods",
+                    "name":"compute:default"
+                },
+                {
+                    "id":"3",
+                    "description":"User Admin Role.",
+                    "name":"identity:user-admin"
+                }
+            ],
+            "name":"test",
+            "RAX-AUTH:defaultRegion":"ORD"
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/46f493ac/rackspace-autoscale-us/src/test/resources/logback.xml
----------------------------------------------------------------------
diff --git a/rackspace-autoscale-us/src/test/resources/logback.xml b/rackspace-autoscale-us/src/test/resources/logback.xml
new file mode 100644
index 0000000..6559c23
--- /dev/null
+++ b/rackspace-autoscale-us/src/test/resources/logback.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0"?>
+<!--
+
+    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.
+
+-->
+<configuration scan="false">
+    <appender name="FILE" class="ch.qos.logback.core.FileAppender">
+        <file>target/test-data/jclouds.log</file>
+
+        <encoder>
+            <Pattern>%d %-5p [%c] [%thread] %m%n</Pattern>
+        </encoder>
+    </appender>
+
+    <appender name="WIREFILE" class="ch.qos.logback.core.FileAppender">
+        <file>target/test-data/jclouds-wire.log</file>
+
+        <encoder>
+            <Pattern>%d %-5p [%c] [%thread] %m%n</Pattern>
+        </encoder>
+    </appender>
+
+    <appender name="BLOBSTOREFILE" class="ch.qos.logback.core.FileAppender">
+        <file>target/test-data/jclouds-blobstore.log</file>
+
+        <encoder>
+            <Pattern>%d %-5p [%c] [%thread] %m%n</Pattern>
+        </encoder>
+    </appender>
+
+    <root>
+        <level value="warn" />
+    </root>
+
+    <logger name="org.jclouds">
+        <level value="DEBUG" />
+        <appender-ref ref="FILE" />
+    </logger>
+
+    <logger name="jclouds.wire">
+        <level value="DEBUG" />
+        <appender-ref ref="WIREFILE" />
+    </logger>
+
+    <logger name="jclouds.headers">
+        <level value="DEBUG" />
+        <appender-ref ref="WIREFILE" />
+    </logger>
+
+    <logger name="jclouds.blobstore">
+        <level value="DEBUG" />
+        <appender-ref ref="BLOBSTOREFILE" />
+    </logger>
+
+</configuration>

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/46f493ac/rackspace-autoscale/pom.xml
----------------------------------------------------------------------
diff --git a/rackspace-autoscale/pom.xml b/rackspace-autoscale/pom.xml
new file mode 100644
index 0000000..58fffe9
--- /dev/null
+++ b/rackspace-autoscale/pom.xml
@@ -0,0 +1,134 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.apache.jclouds</groupId>
+    <artifactId>jclouds-project</artifactId>
+    <version>1.7.0-SNAPSHOT</version>
+  </parent>
+
+  <!-- TODO: when out of labs, switch to org.jclouds.api -->
+  <groupId>org.apache.jclouds.labs</groupId>
+  <artifactId>rackspace-autoscale</artifactId>
+  <version>1.7.0-SNAPSHOT</version>
+  <name>jclouds rackspace-autoscale api</name>
+  <description>jclouds components to access Rackspace Autoscale</description>
+  <packaging>bundle</packaging>
+
+  <properties>
+    <!-- keystone endpoint -->
+    <test.rackspace-autoscale.endpoint>http://localhost:5000/v2.0/</test.rackspace-autoscale.endpoint>
+    <!-- keystone version -->
+    <test.rackspace-autoscale.api-version>2.0</test.rackspace-autoscale.api-version>
+    <test.rackspace-autoscale.build-version />
+    <test.rackspace-autoscale.identity>FIXME_IDENTITY</test.rackspace-autoscale.identity>
+    <test.rackspace-autoscale.credential>FIXME_CREDENTIALS</test.rackspace-autoscale.credential>
+    <test.jclouds.keystone.credential-type>passwordCredentials</test.jclouds.keystone.credential-type>
+
+    <jclouds.osgi.export>org.jclouds.rackspace.autoscale.v1_0*;version="${project.version}"</jclouds.osgi.export>
+    <jclouds.osgi.import>
+      org.jclouds.rest.internal;version="${jclouds.version}",
+      org.jclouds.labs*;version="${project.version}",
+      org.jclouds*;version="${jclouds.version}",
+      *
+    </jclouds.osgi.import>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.jclouds.api</groupId>
+      <artifactId>openstack-keystone</artifactId>
+      <version>${project.parent.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.jclouds.api</groupId>
+      <artifactId>openstack-keystone</artifactId>
+      <version>${project.parent.version}</version>
+      <type>test-jar</type>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.jclouds</groupId>
+      <artifactId>jclouds-core</artifactId>
+      <version>${project.parent.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.jclouds</groupId>
+      <artifactId>jclouds-core</artifactId>
+      <version>${project.parent.version}</version>
+      <type>test-jar</type>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.jclouds.driver</groupId>
+      <artifactId>jclouds-slf4j</artifactId>
+      <version>${project.parent.version}</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>ch.qos.logback</groupId>
+      <artifactId>logback-classic</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+    	<groupId>org.apache.jclouds.api</groupId>
+    	<artifactId>rackspace-cloudidentity</artifactId>
+    	<version>${project.parent.version}</version>
+    </dependency>
+  </dependencies>
+
+  <profiles>
+    <profile>
+      <id>live</id>
+      <build>
+        <plugins>
+          <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-surefire-plugin</artifactId>
+            <executions>
+              <execution>
+                <id>integration</id>
+                <phase>integration-test</phase>
+                <goals>
+                  <goal>test</goal>
+                </goals>
+                <configuration>
+                  <forkCount>5</forkCount>
+                  <reuseForks>true</reuseForks>
+                  <parallel>classes</parallel>
+                  <systemPropertyVariables>
+                    <test.rackspace-autoscale.endpoint>${test.rackspace-autoscale.endpoint}</test.rackspace-autoscale.endpoint>
+                    <test.rackspace-autoscale.api-version>${test.rackspace-autoscale.api-version}</test.rackspace-autoscale.api-version>
+                    <test.rackspace-autoscale.build-version>${test.rackspace-autoscale.build-version}</test.rackspace-autoscale.build-version>
+                    <test.rackspace-autoscale.identity>${test.rackspace-autoscale.identity}</test.rackspace-autoscale.identity>
+                    <test.rackspace-autoscale.credential>${test.rackspace-autoscale.credential}</test.rackspace-autoscale.credential>
+                    <test.jclouds.keystone.credential-type>${test.jclouds.keystone.credential-type}</test.jclouds.keystone.credential-type>
+                  </systemPropertyVariables>
+                </configuration>
+              </execution>
+            </executions>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+  </profiles>
+
+</project>

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/46f493ac/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/AutoscaleApi.java
----------------------------------------------------------------------
diff --git a/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/AutoscaleApi.java b/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/AutoscaleApi.java
new file mode 100644
index 0000000..4563a3f
--- /dev/null
+++ b/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/AutoscaleApi.java
@@ -0,0 +1,61 @@
+/*
+ * 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.rackspace.autoscale.v1;
+
+import java.io.Closeable;
+import java.util.Set;
+
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.location.Zone;
+import org.jclouds.location.functions.ZoneToEndpoint;
+import org.jclouds.openstack.keystone.v2_0.domain.Tenant;
+import org.jclouds.rackspace.autoscale.v1.features.GroupApi;
+import org.jclouds.rest.annotations.Delegate;
+import org.jclouds.rest.annotations.EndpointParam;
+
+import com.google.common.base.Optional;
+import com.google.inject.Provides;
+
+/**
+ * Provides access to Rackspace Autoscale.
+ *  
+ * @see <a href="https://rackspace-autoscale.readthedocs.org">API Doc</a>
+ * @see <a href="http://docs.autoscale.apiary.io/">Apiary API Doc</a>
+ * @author Zack Shoylev
+ */
+public interface AutoscaleApi extends Closeable{
+   /**
+    * Provides a set of all zones available.
+    * 
+    * @return the Zone codes configured
+    */
+   @Provides
+   @Zone
+   Set<String> getConfiguredZones();
+
+   /**
+    * Provides access to all scaling Group features.
+    */
+   @Delegate
+   GroupApi getGroupApiForZone(@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
+
+   /**
+    * Provides the Tenant.
+    */
+   @Provides 
+   Optional<Tenant> getCurrentTenantId();
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/46f493ac/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/AutoscaleApiMetadata.java
----------------------------------------------------------------------
diff --git a/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/AutoscaleApiMetadata.java b/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/AutoscaleApiMetadata.java
new file mode 100644
index 0000000..0d36410
--- /dev/null
+++ b/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/AutoscaleApiMetadata.java
@@ -0,0 +1,96 @@
+/*
+ * 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.rackspace.autoscale.v1;
+
+import static org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties.CREDENTIAL_TYPE;
+import static org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties.SERVICE_TYPE;
+
+import java.net.URI;
+import java.util.Properties;
+
+import org.jclouds.apis.ApiMetadata;
+import org.jclouds.openstack.keystone.v2_0.config.CredentialTypes;
+import org.jclouds.openstack.keystone.v2_0.config.KeystoneAuthenticationModule.ZoneModule;
+import org.jclouds.rackspace.autoscale.v1.config.AutoscaleHttpApiModule;
+import org.jclouds.rackspace.autoscale.v1.config.AutoscaleParserModule;
+import org.jclouds.rackspace.cloudidentity.v2_0.config.CloudIdentityAuthenticationApiModule;
+import org.jclouds.rackspace.cloudidentity.v2_0.config.CloudIdentityAuthenticationModule;
+import org.jclouds.rest.internal.BaseHttpApiMetadata;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.Module;
+
+/**
+ * Implementation of {@link ApiMetadata} for the Rackspace Autoscale API
+ * 
+ * @see AutoscaleApi
+ * @author Zack Shoylev
+ */
+public class AutoscaleApiMetadata extends BaseHttpApiMetadata<AutoscaleApi> {
+
+   @Override
+   public Builder toBuilder() {
+      return new Builder().fromApiMetadata(this);
+   }
+
+   public AutoscaleApiMetadata() {
+      this(new Builder());
+   }
+
+   protected AutoscaleApiMetadata(Builder builder) {
+      super(builder);
+   }
+
+   public static Properties defaultProperties() {
+      Properties properties = BaseHttpApiMetadata.defaultProperties();
+      properties.setProperty(SERVICE_TYPE, "rax:autoscale");
+      properties.setProperty(CREDENTIAL_TYPE, CredentialTypes.PASSWORD_CREDENTIALS);
+      return properties;
+   }
+
+   public static class Builder extends BaseHttpApiMetadata.Builder<AutoscaleApi, Builder> {
+
+      protected Builder() {   
+         id("rackspace-autoscale")
+         .name("Rackspace Autoscale API")
+         .identityName("${tenantName}:${userName} or ${userName}, if your keystone supports a default tenant")
+         .credentialName("${password}")
+         .endpointName("Keystone base URL ending in /v2.0/")
+         .documentation(URI.create("http://api.openstack.org/"))
+         .version("1.0")
+         .defaultEndpoint("http://localhost:5000/v2.0/")
+         .defaultProperties(AutoscaleApiMetadata.defaultProperties())
+         .defaultModules(ImmutableSet.<Class<? extends Module>>builder()
+               .add(CloudIdentityAuthenticationApiModule.class)
+               .add(CloudIdentityAuthenticationModule.class)
+               .add(ZoneModule.class)
+               .add(AutoscaleParserModule.class)
+               .add(AutoscaleHttpApiModule.class)
+               .build());
+      }
+
+      @Override
+      public AutoscaleApiMetadata build() {
+         return new AutoscaleApiMetadata(this);
+      }
+
+      @Override
+      protected Builder self() {
+         return this;
+      }
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/46f493ac/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/binders/BindCreateGroupToJson.java
----------------------------------------------------------------------
diff --git a/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/binders/BindCreateGroupToJson.java b/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/binders/BindCreateGroupToJson.java
new file mode 100644
index 0000000..8e06f95
--- /dev/null
+++ b/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/binders/BindCreateGroupToJson.java
@@ -0,0 +1,97 @@
+/*
+ * 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.rackspace.autoscale.v1.binders;
+
+import java.util.List;
+import java.util.Map;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.rackspace.autoscale.v1.domain.GroupConfiguration;
+import org.jclouds.rackspace.autoscale.v1.domain.LaunchConfiguration;
+import org.jclouds.rackspace.autoscale.v1.domain.ScalingPolicy;
+import org.jclouds.rest.MapBinder;
+import org.jclouds.rest.binders.BindToJsonPayload;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.inject.Inject;
+
+/**
+ * Decouple building the json object from the domain objects structure by using the binder
+ * @author Zack Shoylev
+ */
+public class BindCreateGroupToJson implements MapBinder {
+
+   private final BindToJsonPayload jsonBinder;
+
+   @Inject
+   private BindCreateGroupToJson(BindToJsonPayload jsonBinder) {
+      this.jsonBinder = jsonBinder;
+   }
+
+   @SuppressWarnings("unchecked")
+   @Override    
+   public <R extends HttpRequest> R bindToRequest(R request, Map<String, Object> postParams) {
+      List<ScalingPolicy> scalingPoliciesRequest = (List<ScalingPolicy>) postParams.get("scalingPolicies");
+      LaunchConfiguration launchConfigurationRequest = (LaunchConfiguration) postParams.get("launchConfiguration");
+
+      GroupConfiguration groupConfiguration = (GroupConfiguration) postParams.get("groupConfiguration");
+
+      Map<String, Object> launchConfigurationMap = Maps.newHashMap();
+      List<Map<String, Object>> scalingPoliciesList = Lists.newArrayList();
+      Map<String, Object> args = Maps.newHashMap();
+      launchConfigurationMap.put("args", args);
+      launchConfigurationMap.put("type", launchConfigurationRequest.getType().toString());
+
+      args.put("loadBalancers", launchConfigurationRequest.getLoadBalancers());
+      Map<String, Object> server = Maps.newHashMap();
+      args.put("server", server);
+      server.put("name", launchConfigurationRequest.getServerName());
+      server.put("imageRef", launchConfigurationRequest.getServerImageRef());
+      server.put("flavorRef", launchConfigurationRequest.getServerFlavorRef());
+      server.put("OS-DCF:diskConfig", launchConfigurationRequest.getServerDiskConfig());
+      server.put("metadata", launchConfigurationRequest.getServerMetadata());
+      List<Map<String, String>> networks = Lists.newArrayList();
+      server.put("networks", networks);
+      for(String networkId : launchConfigurationRequest.getNetworks()) {
+         Map<String, String> network = Maps.newHashMap();
+         network.put("uuid", networkId);
+         networks.add(network);
+      }
+      server.put("personality", launchConfigurationRequest.getPersonalities());
+
+      for(ScalingPolicy scalingPolicy : scalingPoliciesRequest) {
+         Map<String,Object> scalingPolicyMap = Maps.newHashMap();
+         scalingPoliciesList.add(scalingPolicyMap);
+         scalingPolicyMap.put("cooldown", scalingPolicy.getCooldown());
+         scalingPolicyMap.put("type", scalingPolicy.getType().toString());
+         scalingPolicyMap.put("name", scalingPolicy.getName());
+         // A couple of different scaling policies are supported, such as percent or number based, or targeting specific numbers of instances
+         scalingPolicyMap.put(scalingPolicy.getTargetType().toString(), scalingPolicy.getTarget());
+      }
+
+      return jsonBinder.bindToRequest(request, ImmutableMap.of(
+            "launchConfiguration", launchConfigurationMap, 
+            "groupConfiguration", groupConfiguration, 
+            "scalingPolicies", scalingPoliciesList));
+   }
+
+   @Override
+   public <R extends HttpRequest> R bindToRequest(R request, Object toBind) {
+      throw new IllegalStateException("CreateInstance is a POST operation");
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/46f493ac/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/config/AutoscaleHttpApiModule.java
----------------------------------------------------------------------
diff --git a/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/config/AutoscaleHttpApiModule.java b/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/config/AutoscaleHttpApiModule.java
new file mode 100644
index 0000000..9311287
--- /dev/null
+++ b/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/config/AutoscaleHttpApiModule.java
@@ -0,0 +1,79 @@
+/*
+ * 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.rackspace.autoscale.v1.config;
+
+import java.net.URI;
+
+import javax.inject.Singleton;
+
+import org.jclouds.http.HttpErrorHandler;
+import org.jclouds.http.annotation.ClientError;
+import org.jclouds.http.annotation.Redirection;
+import org.jclouds.http.annotation.ServerError;
+import org.jclouds.openstack.keystone.v2_0.domain.Access;
+import org.jclouds.openstack.keystone.v2_0.domain.Tenant;
+import org.jclouds.rackspace.autoscale.v1.AutoscaleApi;
+import org.jclouds.rackspace.autoscale.v1.handlers.AutoscaleErrorHandler;
+import org.jclouds.rest.ConfiguresHttpApi;
+import org.jclouds.rest.config.HttpApiModule;
+
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.google.common.base.Supplier;
+import com.google.common.base.Suppliers;
+import com.google.common.collect.ImmutableMultimap;
+import com.google.common.collect.Multimap;
+import com.google.inject.Provides;
+
+/**
+ * Configures the Autoscale connection.
+ * 
+ * @author Zack Shoylev
+ */
+@ConfiguresHttpApi
+public class AutoscaleHttpApiModule extends HttpApiModule<AutoscaleApi> {
+   
+   @Override
+   protected void configure() {
+      super.configure();
+   }
+   
+   @Provides
+   @Singleton
+   public Multimap<URI, URI> aliases() {
+      return ImmutableMultimap.<URI, URI>builder().build();
+   }
+
+   @Override
+   protected void bindErrorHandlers() {
+      bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(AutoscaleErrorHandler.class);
+      bind(HttpErrorHandler.class).annotatedWith(ClientError.class).to(AutoscaleErrorHandler.class);
+      bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(AutoscaleErrorHandler.class);
+   }
+   
+   @Provides
+   Supplier<Optional<Tenant>> supplyTenant(Supplier<Access> access) {
+      return Suppliers.compose(GetTenant.INSTANCE, access);
+   }
+   
+   private static enum GetTenant implements Function<Access, Optional<Tenant>> {
+      INSTANCE;
+      public Optional<Tenant> apply(Access in){
+         return in.getToken().getTenant();
+      }
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/46f493ac/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/config/AutoscaleParserModule.java
----------------------------------------------------------------------
diff --git a/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/config/AutoscaleParserModule.java b/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/config/AutoscaleParserModule.java
new file mode 100644
index 0000000..580ff2a
--- /dev/null
+++ b/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/config/AutoscaleParserModule.java
@@ -0,0 +1,32 @@
+/*
+ * 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.rackspace.autoscale.v1.config;
+
+import org.jclouds.json.config.GsonModule;
+import org.jclouds.json.config.GsonModule.DateAdapter;
+
+import com.google.inject.AbstractModule;
+
+/**
+ * @author Zack Shoylev
+ */
+public class AutoscaleParserModule extends AbstractModule {
+   @Override
+   protected void configure() {
+      bind(DateAdapter.class).to(GsonModule.Iso8601DateAdapter.class);
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/46f493ac/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/domain/Group.java
----------------------------------------------------------------------
diff --git a/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/domain/Group.java b/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/domain/Group.java
new file mode 100644
index 0000000..091143c
--- /dev/null
+++ b/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/domain/Group.java
@@ -0,0 +1,206 @@
+/*
+ * 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.rackspace.autoscale.v1.domain;
+
+import java.util.List;
+
+import org.jclouds.openstack.v2_0.domain.Link;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.collect.ImmutableList;
+
+/**
+ * Autoscale Group.
+ * This domain object contains information about an autoscaling group.
+ * 
+ * @author Zack Shoylev
+ */
+
+public class Group {
+   private final String id;
+   private final ImmutableList<Link> links;
+   private final ImmutableList<ScalingPolicyResponse> scalingPolicy;
+   private final GroupConfiguration groupConfiguration;
+   private final LaunchConfiguration launchConfiguration;
+
+   protected Group(String id, ImmutableList<Link> links, ImmutableList<ScalingPolicyResponse> scalingPolicy, GroupConfiguration groupConfiguration, LaunchConfiguration launchConfiguration) {
+      this.id = id;
+      this.links = links;
+      this.scalingPolicy = scalingPolicy;
+      this.groupConfiguration = groupConfiguration;
+      this.launchConfiguration = launchConfiguration;
+   }      
+
+   /**
+    * Unique group identifier, usually UUID
+    * @return the id of this Group.
+    * @see Group.Builder#id(String)
+    */
+   public String getId() {
+      return this.id;
+   }
+
+   /**
+    * @return the links of this Group.
+    * @see Link
+    * @see Group.Builder#links(List)
+    */
+   public ImmutableList<Link> getLinks() {
+      return this.links;
+   }
+
+   /**
+    * @return A list of scaling policies for this Group.
+    * @see ScalingPolicy
+    * @see Group.Builder#scalingPolicy(List)
+    */
+   public ImmutableList<ScalingPolicyResponse> getScalingPolicies() {
+      return this.scalingPolicy;
+   }
+
+   /**
+    * @return the group configuration of this Group.
+    * @see GroupConfiguration
+    * @see Group.Builder#groupConfiguration(GroupConfiguration)
+    */
+   public GroupConfiguration getGroupConfiguration() {
+      return this.groupConfiguration;
+   }
+
+   /**
+    * @return the launch configuration of this Group.
+    * @see LaunchConfiguration
+    * @see Group.Builder#launchConfiguration(LaunchConfiguration)
+    */
+   public LaunchConfiguration getLaunchConfiguration() {
+      return this.launchConfiguration;
+   }
+
+   @Override
+   public int hashCode() {
+      return Objects.hashCode(id, links, scalingPolicy, groupConfiguration, launchConfiguration);
+   }
+
+   @Override
+   public boolean equals(Object obj) {
+      if (this == obj) return true;
+      if (obj == null || getClass() != obj.getClass()) return false;
+      Group that = Group.class.cast(obj);
+      return Objects.equal(this.id, that.id) && 
+            Objects.equal(this.links, that.links) &&
+            Objects.equal(this.scalingPolicy, that.scalingPolicy) &&
+            Objects.equal(this.groupConfiguration, that.groupConfiguration) &&
+            Objects.equal(this.launchConfiguration, that.launchConfiguration);
+   }
+
+   protected ToStringHelper string() {
+      return Objects.toStringHelper(this)
+            .add("id", id)
+            .add("links", links)
+            .add("scalingPolicy", scalingPolicy)
+            .add("groupConfiguration", groupConfiguration)
+            .add("launchConfiguration", "launchConfiguration");
+   }
+
+   @Override
+   public String toString() {
+      return string().toString();
+   }
+
+   public static Builder builder() { 
+      return new Builder();
+   }
+
+   public Builder toBuilder() { 
+      return new Builder().fromGroup(this);
+   }
+
+   public static class Builder {
+      protected String id;
+      protected ImmutableList<Link> links;
+      protected ImmutableList<ScalingPolicyResponse> scalingPolicy;
+      protected GroupConfiguration groupConfiguration;
+      protected LaunchConfiguration launchConfiguration;
+
+      /** 
+       * @param id The id of this Group.
+       * @return The builder object.
+       * @see Group#getId()
+       */
+      public Builder id(String id) {
+         this.id = id;
+         return this;
+      }
+
+      /** 
+       * @param links The links of this Group.
+       * @return The builder object.
+       * @see Group#getLinks()
+       */
+      public Builder links(List<Link> links) {
+         this.links = ImmutableList.copyOf(links);
+         return this;
+      }
+
+      /** 
+       * @param scalingPolicy The scaling policies list of this Group.
+       * @return The builder object.
+       * @see Group#getScalingPolicy()
+       */
+      public Builder scalingPolicy(List<ScalingPolicyResponse> scalingPolicy) {
+         this.scalingPolicy = ImmutableList.copyOf(scalingPolicy);
+         return this;
+      }
+
+      /** 
+       * @param groupConfiguration The groupConfiguration of this Group.
+       * @return The builder object.
+       * @see Group#getGroupConfiguration()
+       */
+      public Builder groupConfiguration(GroupConfiguration groupConfiguration) {
+         this.groupConfiguration = groupConfiguration;
+         return this;
+      }
+
+      /** 
+       * @param launchConfiguration The launchConfiguration of this Group.
+       * @return The builder object.
+       * @see Group#getLaunchConfiguration()
+       */
+      public Builder launchConfiguration(LaunchConfiguration launchConfiguration) {
+         this.launchConfiguration = launchConfiguration;
+         return this;
+      }
+
+      /**
+       * @return A new ScalingPolicy object.
+       */
+      public Group build() {
+         return new Group(id, links, scalingPolicy, groupConfiguration, launchConfiguration);
+      }
+
+      public Builder fromGroup(Group in) {
+         return this
+               .id(in.getId())
+               .links(in.getLinks())
+               .scalingPolicy(in.getScalingPolicies())
+               .groupConfiguration(in.getGroupConfiguration())
+               .launchConfiguration(in.getLaunchConfiguration());
+      }        
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/46f493ac/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/domain/GroupConfiguration.java
----------------------------------------------------------------------
diff --git a/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/domain/GroupConfiguration.java b/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/domain/GroupConfiguration.java
new file mode 100644
index 0000000..b2673d0
--- /dev/null
+++ b/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/domain/GroupConfiguration.java
@@ -0,0 +1,221 @@
+/*
+ * 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.rackspace.autoscale.v1.domain;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.beans.ConstructorProperties;
+import java.util.Map;
+
+import org.jclouds.rackspace.autoscale.v1.features.GroupApi;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.collect.ImmutableMap;
+
+/**
+ * Autoscale GroupConfiguration.
+ * 
+ * @see GroupApi#create(GroupConfiguration, LaunchConfiguration, java.util.List)
+ * @author Zack Shoylev
+ */
+public class GroupConfiguration implements Comparable<GroupConfiguration>{
+   private final String name;
+   private final int cooldown;
+   private final int minEntities;
+   private final int maxEntities;
+   private final ImmutableMap<String,String> metadata;
+
+   @ConstructorProperties({
+      "name", "cooldown", "minEntities", "maxEntities", "metadata"
+   })
+   protected GroupConfiguration(String name, int cooldown, int minEntities, int maxEntities, Map<String,String> metadata) {
+
+      this.name = checkNotNull(name, "name required");
+      checkArgument(cooldown >= 0, "cooldown should be non-negative");
+      checkArgument(minEntities >= 0, "minEntities should be non-negative");
+      checkArgument(maxEntities >= 0, "maxEntities should be non-negative");
+      this.cooldown = cooldown;
+      this.minEntities = minEntities;
+      this.maxEntities = maxEntities;
+      if(metadata == null) {
+         this.metadata = ImmutableMap.of();
+      } else {
+         this.metadata = ImmutableMap.copyOf(metadata);
+      }
+   }
+
+   /**
+    * @return the name of this GroupConfiguration. The name is not a unique or even sufficient identifier in some cases.
+    * @see GroupConfiguration.Builder#name(String)
+    */
+   public String getName() {
+      return this.name;
+   }   
+
+   /**
+    * @return the cooldown for this GroupConfiguration.
+    * @see GroupConfiguration.Builder#cooldown(int)
+    */
+   public int getCooldown() {
+      return this.cooldown;
+   }
+
+   /**
+    * @return the minimum number of entities for this GroupConfiguration.
+    * @see GroupConfiguration.Builder#minEntities(int)
+    */
+   public int getMinEntities() {
+      return this.minEntities;
+   }
+
+   /**
+    * @return the maximum number of entities for this GroupConfiguration.
+    * @see GroupConfiguration.Builder#maxEntities(int)
+    */
+   public int getMaxEntities() {
+      return this.maxEntities;
+   }
+
+   /**
+    * @return the metadata map for this GroupConfiguration.
+    * @see GroupConfiguration.Builder#metadata(Map<String,String>)
+    */
+   public ImmutableMap<String, String> getMetadata() {
+      return metadata;
+   }
+
+   @Override
+   public int hashCode() {
+      return Objects.hashCode(name, cooldown, minEntities, maxEntities, metadata);
+   }
+
+   @Override
+   public boolean equals(Object obj) {
+      if (this == obj) return true;
+      if (obj == null || getClass() != obj.getClass()) return false;
+      GroupConfiguration that = GroupConfiguration.class.cast(obj);
+      return Objects.equal(this.name, that.name) && 
+            Objects.equal(this.cooldown, that.cooldown) &&
+            Objects.equal(this.minEntities, that.minEntities) &&
+            Objects.equal(this.maxEntities, that.maxEntities) &&
+            Objects.equal(this.metadata, that.metadata);
+   }
+
+   protected ToStringHelper string() {
+      return Objects.toStringHelper(this)
+            .add("name", name)
+            .add("cooldown", cooldown)
+            .add("minEntities", minEntities)
+            .add("maxEntities", maxEntities)
+            .add("metadata", metadata);
+   }
+
+   @Override
+   public String toString() {
+      return string().toString();
+   }
+
+   public static Builder builder() { 
+      return new Builder();
+   }
+
+   public Builder toBuilder() { 
+      return new Builder().fromGroupConfiguration(this);
+   }
+
+   public static class Builder {
+      protected String name;
+      protected int cooldown;
+      protected int minEntities;
+      protected int maxEntities;
+      protected Map<String, String> metadata;
+
+      /** 
+       * @param name The name of this GroupConfiguration.
+       * @return The builder object.
+       * @see GroupConfiguration#getName()
+       */
+      public Builder name(String name) {
+         this.name = name;
+         return this;
+      }
+
+      /** 
+       * @param name The cooldown for this GroupConfiguration.
+       * @return The builder object.
+       * @see GroupConfiguration#getCooldown()
+       */
+      public Builder cooldown(int cooldown) {
+         this.cooldown = cooldown;
+         return this;
+      }
+
+      /** 
+       * @param name The cooldown for this GroupConfiguration.
+       * @return The builder object.
+       * @see GroupConfiguration#getCooldown()
+       */
+      public Builder minEntities(int minEntities) {
+         this.minEntities = minEntities;
+         return this;
+      }
+
+      /** 
+       * @param name The maxEntities for this GroupConfiguration.
+       * @return The builder object.
+       * @see GroupConfiguration#getCooldown()
+       */
+      public Builder maxEntities(int maxEntities) {
+         this.maxEntities = maxEntities;
+         return this;
+      }
+
+      /** 
+       * @param name The metadata for this GroupConfiguration.
+       * @return The builder object.
+       * @see GroupConfiguration#getDatabases()
+       */
+      public Builder metadata(Map<String, String> metadata) {
+         this.metadata = metadata;
+         return this;
+      }
+
+      /**
+       * 
+       * @return A new GroupConfiguration object.
+       */
+      public GroupConfiguration build() {
+         return new GroupConfiguration(name, cooldown, minEntities, maxEntities, metadata);
+      }
+
+      public Builder fromGroupConfiguration(GroupConfiguration in) {
+         return this
+               .name(in.getName())
+               .cooldown(in.getCooldown())
+               .minEntities(in.getMinEntities())
+               .maxEntities(in.getMaxEntities())
+               .metadata(in.getMetadata());
+      }        
+   }
+
+   @Override
+   public int compareTo(GroupConfiguration that) {
+      return this.getName().compareTo(that.getName());
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/46f493ac/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/domain/GroupInstance.java
----------------------------------------------------------------------
diff --git a/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/domain/GroupInstance.java b/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/domain/GroupInstance.java
new file mode 100644
index 0000000..70d265a
--- /dev/null
+++ b/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/domain/GroupInstance.java
@@ -0,0 +1,82 @@
+/*
+ * 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.rackspace.autoscale.v1.domain;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.beans.ConstructorProperties;
+
+import org.jclouds.openstack.v2_0.domain.Link;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.collect.ImmutableList;
+
+/**
+ * Autoscale Group Instance (as in hardware instance). Part of the group state.
+ * 
+ * @see GroupState#getGroupInstances()
+ * @author Zack Shoylev
+ */
+public class GroupInstance {
+   private final String id;
+   private final ImmutableList<Link> links;
+
+   @ConstructorProperties({ "id", "links" })
+   protected GroupInstance(String id, ImmutableList<Link> links) {
+      this.id = checkNotNull(id, "id should not be null");
+      this.links = checkNotNull(links, "links should not be null");
+   }
+
+   /**
+    * @return the id of this GroupInstance.
+    */
+   public String getId() {
+      return this.id;
+   }
+
+   /**
+    * @return the links for this GroupInstance.
+    */
+   public ImmutableList<Link> getLinks() {
+      return this.links;
+   }
+
+   @Override
+   public int hashCode() {
+      return Objects.hashCode(links, id);
+   }
+
+   @Override
+   public boolean equals(Object obj) {
+      if (this == obj)
+         return true;
+      if (obj == null || getClass() != obj.getClass())
+         return false;
+      GroupInstance that = GroupInstance.class.cast(obj);
+      return Objects.equal(this.id, that.id) && Objects.equal(this.links, that.links);
+   }
+
+   protected ToStringHelper string() {
+      return Objects.toStringHelper(this).add("id", id).add("links", links);
+   }
+
+   @Override
+   public String toString() {
+      return string().toString();
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/46f493ac/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/domain/GroupState.java
----------------------------------------------------------------------
diff --git a/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/domain/GroupState.java b/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/domain/GroupState.java
new file mode 100644
index 0000000..5b26e34
--- /dev/null
+++ b/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/domain/GroupState.java
@@ -0,0 +1,145 @@
+/*
+ * 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.rackspace.autoscale.v1.domain;
+
+import java.beans.ConstructorProperties;
+import java.util.List;
+
+import org.jclouds.openstack.v2_0.domain.Link;
+import org.jclouds.rackspace.autoscale.v1.features.GroupApi;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.collect.ImmutableList;
+import com.google.gson.annotations.SerializedName;
+
+/**
+ * Autoscale Group State. Contains information about a scaling group. 
+ * 
+ * @see Group
+ * @see GroupApi#listGroupStates()
+ * @see GroupApi#getState(String)
+ * @author Zack Shoylev
+ */
+public class GroupState implements Comparable<GroupState> {
+   private final String id;
+   private final ImmutableList<Link> links;
+   private final int activeCapacity;
+   private final int pendingCapacity;
+   private final int desiredCapacity;
+   private final boolean paused;
+   @SerializedName("active")
+   private final ImmutableList<GroupInstance> groupInstances;
+
+   @ConstructorProperties({ "id", "links", "activeCapacity", "pendingCapacity", "desiredCapacity", "paused",
+   "active" })
+   protected GroupState(String id, List<Link> links, int activeCapacity, int pendingCapacity,
+         int desiredCapacity, boolean paused, List<GroupInstance> groupInstances) {
+      this.id = id;
+      this.links = ImmutableList.copyOf(links);
+      this.activeCapacity = activeCapacity;
+      this.pendingCapacity = pendingCapacity;
+      this.desiredCapacity = desiredCapacity;
+      this.paused = paused;
+      this.groupInstances = ImmutableList.copyOf(groupInstances);
+   }
+
+   /**
+    * @return the id of this GroupState.
+    */
+   public String getId() {
+      return this.id;
+   }
+
+   /**
+    * @return the links for this GroupState.
+    */
+   public List<Link> getLinks() {
+      return this.links;
+   }
+
+   /**
+    * @return the active capacity for this GroupState.
+    */
+   public int getActiveCapacity() {
+      return this.activeCapacity;
+   }
+
+   /**
+    * @return the pending capacity for this GroupState.
+    */
+   public int getPendingCapacity() {
+      return this.pendingCapacity;
+   }
+
+   /**
+    * @return the desired capacity for this GroupState.
+    */
+   public int getDesiredCapacity() {
+      return this.desiredCapacity;
+   }
+
+   /**
+    * @return the paused status for this GroupState.
+    */
+   public boolean getPaused() {
+      return this.paused;
+   }
+
+   /**
+    * @return the group instances for this GroupState.
+    * @see GroupInstance
+    */
+   public List<GroupInstance> getGroupInstances() {
+      return this.groupInstances;
+   }
+
+   @Override
+   public int hashCode() {
+      return Objects.hashCode(id, links, activeCapacity, pendingCapacity, desiredCapacity, paused, groupInstances);
+   }
+
+   @Override
+   public boolean equals(Object obj) {
+      if (this == obj)
+         return true;
+      if (obj == null || getClass() != obj.getClass())
+         return false;
+      GroupState that = GroupState.class.cast(obj);
+      return Objects.equal(this.id, that.id) && Objects.equal(this.links, that.links)
+            && Objects.equal(this.activeCapacity, that.activeCapacity)
+            && Objects.equal(this.pendingCapacity, that.pendingCapacity)
+            && Objects.equal(this.desiredCapacity, that.desiredCapacity) && Objects.equal(this.paused, that.paused)
+            && Objects.equal(this.groupInstances, that.groupInstances);
+   }
+
+   protected ToStringHelper string() {
+      return Objects.toStringHelper(this).add("id", id).add("links", links).add("activeCapacity", activeCapacity)
+            .add("pendingCapacity", pendingCapacity).add("desiredCapacity", "desiredCapacity").add("paused", "paused")
+            .add("groupInstances", "groupInstances");
+   }
+
+   @Override
+   public String toString() {
+      return string().toString();
+   }
+
+   @Override
+   public int compareTo(GroupState that) {
+      return this.getId().compareTo(that.getId());
+   }   
+}