You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jclouds.apache.org by ab...@apache.org on 2013/07/01 21:15:05 UTC

[18/24] JCLOUDS-151 - CloudStack refactored to remove async, *Client renamed to *Api.

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/c6986efd/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/SecurityGroupApi.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/SecurityGroupApi.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/SecurityGroupApi.java
new file mode 100644
index 0000000..1b839c8
--- /dev/null
+++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/SecurityGroupApi.java
@@ -0,0 +1,245 @@
+/*
+ * 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.cloudstack.features;
+
+import java.util.Set;
+
+import javax.inject.Named;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
+import org.jclouds.Fallbacks.NullOnNotFoundOr404;
+import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
+import org.jclouds.cloudstack.binders.BindAccountSecurityGroupPairsToIndexedQueryParams;
+import org.jclouds.cloudstack.binders.BindCIDRsToCommaDelimitedQueryParam;
+import org.jclouds.cloudstack.domain.SecurityGroup;
+import org.jclouds.cloudstack.filters.AuthenticationFilter;
+import org.jclouds.cloudstack.options.AccountInDomainOptions;
+import org.jclouds.cloudstack.options.ListSecurityGroupsOptions;
+import org.jclouds.rest.annotations.BinderParam;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.OnlyElement;
+import org.jclouds.rest.annotations.QueryParams;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.SelectJson;
+
+import com.google.common.collect.Multimap;
+/**
+ * Provides synchronous access to cloudstack via their REST API.
+ * <p/>
+ * 
+ * @see <a href="http://download.cloud.com/releases/2.2.0/api_2.2.12/TOC_User.html" />
+ * @author Adrian Cole
+ */
+@RequestFilters(AuthenticationFilter.class)
+@QueryParams(keys = "response", values = "json")
+public interface SecurityGroupApi {
+
+   /**
+    * Lists security groups
+    * 
+    * @param options
+    *           if present, how to constrain the list.
+    * @return security groups matching query, or empty set, if no security
+    *         groups are found
+    */
+   @Named("listSecurityGroups")
+   @GET
+   @QueryParams(keys = { "command", "listAll" }, values = { "listSecurityGroups", "true" })
+   @SelectJson("securitygroup")
+   @Consumes(MediaType.APPLICATION_JSON)
+   @Fallback(EmptySetOnNotFoundOr404.class)
+   Set<SecurityGroup> listSecurityGroups(ListSecurityGroupsOptions... options);
+
+   /**
+    * get a specific security group by id
+    * 
+    * @param id
+    *           group to get
+    * @return security group or null if not found
+    */
+   @Named("listSecurityGroups")
+   @GET
+   @QueryParams(keys = { "command", "listAll" }, values = { "listSecurityGroups", "true" })
+   @SelectJson("securitygroup")
+   @OnlyElement
+   @Consumes(MediaType.APPLICATION_JSON)
+   @Fallback(NullOnNotFoundOr404.class)
+   SecurityGroup getSecurityGroup(@QueryParam("id") String id);
+
+   /**
+    * get a specific security group by name
+    * 
+    * @param securityGroupName
+    *           group to get
+    * @return security group or null if not found
+    */
+   @Named("listSecurityGroups")
+   @GET
+   @QueryParams(keys = { "command", "listAll" }, values = { "listSecurityGroups", "true" })
+   @SelectJson("securitygroup")
+   @OnlyElement
+   @Consumes(MediaType.APPLICATION_JSON)
+   @Fallback(NullOnNotFoundOr404.class)
+   SecurityGroup getSecurityGroupByName(@QueryParam("securitygroupname") String securityGroupName);
+
+   /**
+    * Creates a security group
+    * 
+    * @param name
+    *           name of the security group
+    * @return security group
+    */
+   @Named("createSecurityGroup")
+   @GET
+   @QueryParams(keys = "command", values = "createSecurityGroup")
+   @SelectJson("securitygroup")
+   @Consumes(MediaType.APPLICATION_JSON)
+   SecurityGroup createSecurityGroup(@QueryParam("name") String name);
+
+   /**
+    * Authorizes a particular TCP or UDP ingress rule for this security group
+    * 
+    * @param securityGroupId
+    *           The ID of the security group
+    * @param protocol
+    *           tcp or udp
+    * @param startPort
+    *           start port for this ingress rule
+    * @param endPort
+    *           end port for this ingress rule
+    * @param cidrList
+    *           the cidr list associated
+    * @return response relating to the creation of this ingress rule
+    */
+   @Named("authorizeSecurityGroupIngress")
+   @GET
+   @QueryParams(keys = "command", values = "authorizeSecurityGroupIngress")
+   @SelectJson("jobid")
+   @Consumes(MediaType.APPLICATION_JSON)
+   String authorizeIngressPortsToCIDRs(@QueryParam("securitygroupid") String securityGroupId,
+         @QueryParam("protocol") String protocol, @QueryParam("startport") int startPort,
+         @QueryParam("endport") int endPort,
+         @BinderParam(BindCIDRsToCommaDelimitedQueryParam.class) Iterable<String> cidrList,
+         AccountInDomainOptions... options);
+
+   /**
+    * Authorizes a particular TCP or UDP ingress rule for this security group
+    * 
+    * @param securityGroupId
+    *           The ID of the security group
+    * @param protocol
+    *           tcp or udp
+    * @param startPort
+    *           start port for this ingress rule
+    * @param endPort
+    *           end port for this ingress rule
+    * @param accountToGroup
+    *           mapping of account names to security groups you wish to
+    *           authorize
+    * @return response relating to the creation of this ingress rule
+    */
+   @Named("authorizeSecurityGroupIngress")
+   @GET
+   @QueryParams(keys = "command", values = "authorizeSecurityGroupIngress")
+   @SelectJson("jobid")
+   @Consumes(MediaType.APPLICATION_JSON)
+   String authorizeIngressPortsToSecurityGroups(@QueryParam("securitygroupid") String securityGroupId,
+         @QueryParam("protocol") String protocol, @QueryParam("startport") int startPort,
+         @QueryParam("endport") int endPort,
+         @BinderParam(BindAccountSecurityGroupPairsToIndexedQueryParams.class) Multimap<String, String> accountToGroup,
+         AccountInDomainOptions... options);
+
+   /**
+    * Authorizes a particular ICMP ingress rule for this security group
+    * 
+    * @param securityGroupId
+    *           The ID of the security group
+    * @param ICMPCode
+    *           type of the icmp message being sent
+    * @param ICMPType
+    *           error code for this icmp message
+    * @param cidrList
+    *           the cidr list associated
+    * @return response relating to the creation of this ingress rule
+    */
+   @Named("authorizeSecurityGroupIngress")
+   @GET
+   @QueryParams(keys = { "command", "protocol" }, values = { "authorizeSecurityGroupIngress", "ICMP" })
+   @SelectJson("jobid")
+   @Consumes(MediaType.APPLICATION_JSON)
+   String authorizeIngressICMPToCIDRs(@QueryParam("securitygroupid") String securityGroupId,
+         @QueryParam("icmpcode") int ICMPCode, @QueryParam("icmptype") int ICMPType,
+         @BinderParam(BindCIDRsToCommaDelimitedQueryParam.class) Iterable<String> cidrList,
+         AccountInDomainOptions... options);
+
+   /**
+    * Authorizes a particular ICMP ingress rule for this security group
+    * 
+    * @param securityGroupId
+    *           The ID of the security group
+    * @param ICMPCode
+    *           type of the icmp message being sent
+    * @param ICMPType
+    *           error code for this icmp message
+    * @param accountToGroup
+    *           mapping of account names to security groups you wish to
+    *           authorize
+    * @return response relating to the creation of this ingress rule
+    */
+   @Named("authorizeSecurityGroupIngress")
+   @GET
+   @QueryParams(keys = { "command", "protocol" }, values = { "authorizeSecurityGroupIngress", "ICMP" })
+   @SelectJson("jobid")
+   @Consumes(MediaType.APPLICATION_JSON)
+   String authorizeIngressICMPToSecurityGroups(@QueryParam("securitygroupid") String securityGroupId,
+         @QueryParam("icmpcode") int ICMPCode, @QueryParam("icmptype") int ICMPType,
+         @BinderParam(BindAccountSecurityGroupPairsToIndexedQueryParams.class) Multimap<String, String> accountToGroup,
+         AccountInDomainOptions... options);
+
+   /**
+    * Deletes a particular ingress rule from this security group
+    * 
+    * @param id
+    *           The ID of the ingress rule
+    * @param options
+    *           scope of the rule.
+    */
+   @Named("revokeSecurityGroupIngress")
+   @GET
+   @QueryParams(keys = "command", values = "revokeSecurityGroupIngress")
+   @Fallback(VoidOnNotFoundOr404.class)
+   @SelectJson("jobid")
+   @Consumes(MediaType.APPLICATION_JSON)
+   String revokeIngressRule(@QueryParam("id") String id, AccountInDomainOptions... options);
+
+   /**
+    * delete a specific security group by id
+    * 
+    * @param id
+    *           group to delete
+    */
+   @Named("deleteSecurityGroup")
+   @GET
+   @QueryParams(keys = "command", values = "deleteSecurityGroup")
+   @Fallback(VoidOnNotFoundOr404.class)
+   void deleteSecurityGroup(@QueryParam("id") String id);
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/c6986efd/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/SecurityGroupAsyncClient.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/SecurityGroupAsyncClient.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/SecurityGroupAsyncClient.java
deleted file mode 100644
index 283ff5b..0000000
--- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/SecurityGroupAsyncClient.java
+++ /dev/null
@@ -1,177 +0,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.
- */
-package org.jclouds.cloudstack.features;
-
-import java.util.Set;
-
-import javax.inject.Named;
-import javax.ws.rs.Consumes;
-import javax.ws.rs.GET;
-import javax.ws.rs.QueryParam;
-import javax.ws.rs.core.MediaType;
-
-import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
-import org.jclouds.Fallbacks.NullOnNotFoundOr404;
-import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
-import org.jclouds.cloudstack.binders.BindAccountSecurityGroupPairsToIndexedQueryParams;
-import org.jclouds.cloudstack.binders.BindCIDRsToCommaDelimitedQueryParam;
-import org.jclouds.cloudstack.domain.SecurityGroup;
-import org.jclouds.cloudstack.filters.AuthenticationFilter;
-import org.jclouds.cloudstack.options.AccountInDomainOptions;
-import org.jclouds.cloudstack.options.ListSecurityGroupsOptions;
-import org.jclouds.rest.annotations.BinderParam;
-import org.jclouds.rest.annotations.Fallback;
-import org.jclouds.rest.annotations.OnlyElement;
-import org.jclouds.rest.annotations.QueryParams;
-import org.jclouds.rest.annotations.RequestFilters;
-import org.jclouds.rest.annotations.SelectJson;
-
-import com.google.common.collect.Multimap;
-import com.google.common.util.concurrent.ListenableFuture;
-
-/**
- * Provides asynchronous access to cloudstack via their REST API.
- * <p/>
- * 
- * @see OfferingClient
- * @see <a href="http://download.cloud.com/releases/2.2.0/api_2.2.12/TOC_User.html" />
- * @author Adrian Cole
- */
-@RequestFilters(AuthenticationFilter.class)
-@QueryParams(keys = "response", values = "json")
-public interface SecurityGroupAsyncClient {
-
-   /**
-    * @see SecurityGroupClient#listSecurityGroups
-    */
-   @Named("listSecurityGroups")
-   @GET
-   @QueryParams(keys = { "command", "listAll" }, values = { "listSecurityGroups", "true" })
-   @SelectJson("securitygroup")
-   @Consumes(MediaType.APPLICATION_JSON)
-   @Fallback(EmptySetOnNotFoundOr404.class)
-   ListenableFuture<Set<SecurityGroup>> listSecurityGroups(ListSecurityGroupsOptions... options);
-
-   /**
-    * @see SecurityGroupClient#getSecurityGroup
-    */
-   @Named("listSecurityGroups")
-   @GET
-   @QueryParams(keys = { "command", "listAll" }, values = { "listSecurityGroups", "true" })
-   @SelectJson("securitygroup")
-   @OnlyElement
-   @Consumes(MediaType.APPLICATION_JSON)
-   @Fallback(NullOnNotFoundOr404.class)
-   ListenableFuture<SecurityGroup> getSecurityGroup(@QueryParam("id") String id);
-
-   /**
-    * @see SecurityGroupClient#getSecurityGroupByName
-    */
-   @Named("listSecurityGroups")
-   @GET
-   @QueryParams(keys = { "command", "listAll" }, values = { "listSecurityGroups", "true" })
-   @SelectJson("securitygroup")
-   @OnlyElement
-   @Consumes(MediaType.APPLICATION_JSON)
-   @Fallback(NullOnNotFoundOr404.class)
-   ListenableFuture<SecurityGroup> getSecurityGroupByName(@QueryParam("securitygroupname") String securityGroupName);
-
-   /**
-    * @see SecurityGroupClient#createSecurityGroup
-    */
-   @Named("createSecurityGroup")
-   @GET
-   @QueryParams(keys = "command", values = "createSecurityGroup")
-   @SelectJson("securitygroup")
-   @Consumes(MediaType.APPLICATION_JSON)
-   ListenableFuture<SecurityGroup> createSecurityGroup(@QueryParam("name") String name);
-
-   /**
-    * @see SecurityGroupClient#authorizeIngressPortsToCIDRs
-    */
-   @Named("authorizeSecurityGroupIngress")
-   @GET
-   @QueryParams(keys = "command", values = "authorizeSecurityGroupIngress")
-   @SelectJson("jobid")
-   @Consumes(MediaType.APPLICATION_JSON)
-   ListenableFuture<String> authorizeIngressPortsToCIDRs(@QueryParam("securitygroupid") String securityGroupId,
-         @QueryParam("protocol") String protocol, @QueryParam("startport") int startPort,
-         @QueryParam("endport") int endPort,
-         @BinderParam(BindCIDRsToCommaDelimitedQueryParam.class) Iterable<String> cidrList,
-         AccountInDomainOptions... options);
-
-   /**
-    * @see SecurityGroupClient#authorizeIngressPortsToSecurityGroups
-    */
-   @Named("authorizeSecurityGroupIngress")
-   @GET
-   @QueryParams(keys = "command", values = "authorizeSecurityGroupIngress")
-   @SelectJson("jobid")
-   @Consumes(MediaType.APPLICATION_JSON)
-   ListenableFuture<String> authorizeIngressPortsToSecurityGroups(@QueryParam("securitygroupid") String securityGroupId,
-         @QueryParam("protocol") String protocol, @QueryParam("startport") int startPort,
-         @QueryParam("endport") int endPort,
-         @BinderParam(BindAccountSecurityGroupPairsToIndexedQueryParams.class) Multimap<String, String> accountToGroup,
-         AccountInDomainOptions... options);
-
-   /**
-    * @see SecurityGroupClient#authorizeIngressICMPToCIDRs
-    */
-   @Named("authorizeSecurityGroupIngress")
-   @GET
-   @QueryParams(keys = { "command", "protocol" }, values = { "authorizeSecurityGroupIngress", "ICMP" })
-   @SelectJson("jobid")
-   @Consumes(MediaType.APPLICATION_JSON)
-   ListenableFuture<String> authorizeIngressICMPToCIDRs(@QueryParam("securitygroupid") String securityGroupId,
-         @QueryParam("icmpcode") int ICMPCode, @QueryParam("icmptype") int ICMPType,
-         @BinderParam(BindCIDRsToCommaDelimitedQueryParam.class) Iterable<String> cidrList,
-         AccountInDomainOptions... options);
-
-   /**
-    * @see SecurityGroupClient#authorizeIngressICMPToSecurityGroups
-    */
-   @Named("authorizeSecurityGroupIngress")
-   @GET
-   @QueryParams(keys = { "command", "protocol" }, values = { "authorizeSecurityGroupIngress", "ICMP" })
-   @SelectJson("jobid")
-   @Consumes(MediaType.APPLICATION_JSON)
-   ListenableFuture<String> authorizeIngressICMPToSecurityGroups(@QueryParam("securitygroupid") String securityGroupId,
-         @QueryParam("icmpcode") int ICMPCode, @QueryParam("icmptype") int ICMPType,
-         @BinderParam(BindAccountSecurityGroupPairsToIndexedQueryParams.class) Multimap<String, String> accountToGroup,
-         AccountInDomainOptions... options);
-
-   /**
-    * @see SecurityGroupClient#revokeIngressRule
-    */
-   @Named("revokeSecurityGroupIngress")
-   @GET
-   @QueryParams(keys = "command", values = "revokeSecurityGroupIngress")
-   @Fallback(VoidOnNotFoundOr404.class)
-   @SelectJson("jobid")
-   @Consumes(MediaType.APPLICATION_JSON)
-   ListenableFuture<String> revokeIngressRule(@QueryParam("id") String id, AccountInDomainOptions... options);
-
-   /**
-    * @see SecurityGroupClient#deleteSecurityGroup
-    */
-   @Named("deleteSecurityGroup")
-   @GET
-   @QueryParams(keys = "command", values = "deleteSecurityGroup")
-   @Fallback(VoidOnNotFoundOr404.class)
-   ListenableFuture<Void> deleteSecurityGroup(@QueryParam("id") String id);
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/c6986efd/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/SecurityGroupClient.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/SecurityGroupClient.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/SecurityGroupClient.java
deleted file mode 100644
index ddb9422..0000000
--- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/SecurityGroupClient.java
+++ /dev/null
@@ -1,159 +0,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.
- */
-package org.jclouds.cloudstack.features;
-
-import java.util.Set;
-import org.jclouds.cloudstack.domain.SecurityGroup;
-import org.jclouds.cloudstack.options.AccountInDomainOptions;
-import org.jclouds.cloudstack.options.ListSecurityGroupsOptions;
-
-import com.google.common.collect.Multimap;
-
-/**
- * Provides synchronous access to CloudStack security group features.
- * <p/>
- * 
- * @see SecurityGroupAsyncClient
- * @see <a href="http://download.cloud.com/releases/2.2.0/api_2.2.12/TOC_User.html" />
- * @author Adrian Cole
- */
-public interface SecurityGroupClient {
-   /**
-    * Lists security groups
-    * 
-    * @param options
-    *           if present, how to constrain the list.
-    * @return security groups matching query, or empty set, if no security
-    *         groups are found
-    */
-   Set<SecurityGroup> listSecurityGroups(ListSecurityGroupsOptions... options);
-
-   /**
-    * Authorizes a particular TCP or UDP ingress rule for this security group
-    * 
-    * @param securityGroupId
-    *           The ID of the security group
-    * @param protocol
-    *           tcp or udp
-    * @param startPort
-    *           start port for this ingress rule
-    * @param endPort
-    *           end port for this ingress rule
-    * @param cidrList
-    *           the cidr list associated
-    * @return response relating to the creation of this ingress rule
-    */
-   String authorizeIngressPortsToCIDRs(String securityGroupId, String protocol, int startPort, int endPort,
-         Iterable<String> cidrList, AccountInDomainOptions... options);
-
-   /**
-    * Authorizes a particular TCP or UDP ingress rule for this security group
-    * 
-    * @param securityGroupId
-    *           The ID of the security group
-    * @param protocol
-    *           tcp or udp
-    * @param startPort
-    *           start port for this ingress rule
-    * @param endPort
-    *           end port for this ingress rule
-    * @param accountToGroup
-    *           mapping of account names to security groups you wish to
-    *           authorize
-    * @return response relating to the creation of this ingress rule
-    */
-   String authorizeIngressPortsToSecurityGroups(String securityGroupId, String protocol, int startPort, int endPort,
-         Multimap<String, String> accountToGroup, AccountInDomainOptions... options);
-
-   /**
-    * Authorizes a particular ICMP ingress rule for this security group
-    * 
-    * @param securityGroupId
-    *           The ID of the security group
-    * @param ICMPCode
-    *           type of the icmp message being sent
-    * @param ICMPType
-    *           error code for this icmp message
-    * @param cidrList
-    *           the cidr list associated
-    * @return response relating to the creation of this ingress rule
-    */
-   String authorizeIngressICMPToCIDRs(String securityGroupId, int ICMPCode, int ICMPType, Iterable<String> cidrList,
-         AccountInDomainOptions... options);
-
-   /**
-    * Authorizes a particular ICMP ingress rule for this security group
-    * 
-    * @param securityGroupId
-    *           The ID of the security group
-    * @param ICMPCode
-    *           type of the icmp message being sent
-    * @param ICMPType
-    *           error code for this icmp message
-    * @param accountToGroup
-    *           mapping of account names to security groups you wish to
-    *           authorize
-    * @return response relating to the creation of this ingress rule
-    */
-   String authorizeIngressICMPToSecurityGroups(String securityGroupId, int ICMPCode, int ICMPType,
-         Multimap<String, String> accountToGroup, AccountInDomainOptions... options);
-
-   /**
-    * Deletes a particular ingress rule from this security group
-    * 
-    * @param id
-    *           The ID of the ingress rule
-    * @param options
-    *           scope of the rule.
-    */
-   String revokeIngressRule(String id, AccountInDomainOptions... options);;
-
-   /**
-    * get a specific security group by id
-    * 
-    * @param id
-    *           group to get
-    * @return security group or null if not found
-    */
-   SecurityGroup getSecurityGroup(String id);
-
-   /**
-    * get a specific security group by name
-    * 
-    * @param securityGroupName
-    *           group to get
-    * @return security group or null if not found
-    */
-   SecurityGroup getSecurityGroupByName(String securityGroupName);
-
-   /**
-    * Creates a security group
-    * 
-    * @param name
-    *           name of the security group
-    * @return security group
-    */
-   SecurityGroup createSecurityGroup(String name);
-
-   /**
-    * delete a specific security group by id
-    * 
-    * @param id
-    *           group to delete
-    */
-   void deleteSecurityGroup(String id);
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/c6986efd/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/SessionApi.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/SessionApi.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/SessionApi.java
new file mode 100644
index 0000000..9fb3e20
--- /dev/null
+++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/SessionApi.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.cloudstack.features;
+
+import javax.inject.Named;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.Fallbacks.NullOnNotFoundOr404;
+import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
+import org.jclouds.cloudstack.domain.LoginResponse;
+import org.jclouds.cloudstack.functions.ParseLoginResponseFromHttpResponse;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.QueryParams;
+import org.jclouds.rest.annotations.ResponseParser;
+
+/**
+ * Provides synchronous access to Cloudstack Sessions
+ * <p/>
+ * 
+ * @see <a href="http://download.cloud.com/releases/2.2.0/api_2.2.12/TOC_User.html" />
+ * @author Andrei Savu
+ */
+@QueryParams(keys = "response", values = "json")
+public interface SessionApi {
+
+   /**
+    * Logs a user into Cloudstack.  A successful login attempt will generate a JSESSIONID
+    * cookie value that can be passed in subsequent Query command calls until the "logout"
+    * command has been issued or the session has expired.
+    *
+    *
+    *
+    * @param userName
+    *          user account name
+    * @param domain
+    *          domain name, if empty defaults to ROOT
+    * @param hashedPassword
+    *          hashed password (by default MD5)
+    * @return
+    *          login response with session key or null
+    */
+   @Named("login")
+   @GET
+   @QueryParams(keys = "command", values = "login")
+   @ResponseParser(ParseLoginResponseFromHttpResponse.class)
+   @Consumes(MediaType.APPLICATION_JSON)
+   @Fallback(NullOnNotFoundOr404.class)
+   LoginResponse loginUserInDomainWithHashOfPassword(@QueryParam("username") String userName,
+      @QueryParam("domain") String domain, @QueryParam("password") String hashedPassword);
+
+   /**
+    * Logs out the user by invalidating the session key
+    *
+    * @param sessionKey
+    *          user session key
+    */
+   @Named("logout")
+   @GET
+   @QueryParams(keys = "command", values = "logout")
+   @Fallback(VoidOnNotFoundOr404.class)
+   void logoutUser(@QueryParam("sessionkey") String sessionKey);
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/c6986efd/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/SessionAsyncClient.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/SessionAsyncClient.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/SessionAsyncClient.java
deleted file mode 100644
index 80d02f3..0000000
--- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/SessionAsyncClient.java
+++ /dev/null
@@ -1,66 +0,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.
- */
-package org.jclouds.cloudstack.features;
-
-import javax.inject.Named;
-import javax.ws.rs.Consumes;
-import javax.ws.rs.GET;
-import javax.ws.rs.QueryParam;
-import javax.ws.rs.core.MediaType;
-
-import org.jclouds.Fallbacks.NullOnNotFoundOr404;
-import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
-import org.jclouds.cloudstack.domain.LoginResponse;
-import org.jclouds.cloudstack.functions.ParseLoginResponseFromHttpResponse;
-import org.jclouds.rest.annotations.Fallback;
-import org.jclouds.rest.annotations.QueryParams;
-import org.jclouds.rest.annotations.ResponseParser;
-
-import com.google.common.util.concurrent.ListenableFuture;
-
-/**
- * Provides asynchronous access to Cloudstack Sessions
- * <p/>
- * 
- * @see org.jclouds.cloudstack.features.SessionClient
- * @see <a href="http://download.cloud.com/releases/2.2.0/api_2.2.12/TOC_User.html" />
- * @author Andrei Savu
- */
-@QueryParams(keys = "response", values = "json")
-public interface SessionAsyncClient {
-
-   /**
-    * @see SessionClient#loginUserInDomainWithHashOfPassword
-    */
-   @Named("login")
-   @GET
-   @QueryParams(keys = "command", values = "login")
-   @ResponseParser(ParseLoginResponseFromHttpResponse.class)
-   @Consumes(MediaType.APPLICATION_JSON)
-   @Fallback(NullOnNotFoundOr404.class)
-   ListenableFuture<LoginResponse> loginUserInDomainWithHashOfPassword(@QueryParam("username") String userName,
-      @QueryParam("domain") String domain, @QueryParam("password") String hashedPassword);
-
-   /**
-    * @see SessionClient#logoutUser
-    */
-   @Named("logout")
-   @GET
-   @QueryParams(keys = "command", values = "logout")
-   @Fallback(VoidOnNotFoundOr404.class)
-   ListenableFuture<Void> logoutUser(@QueryParam("sessionkey") String sessionKey);
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/c6986efd/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/SessionClient.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/SessionClient.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/SessionClient.java
deleted file mode 100644
index 2ae3802..0000000
--- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/SessionClient.java
+++ /dev/null
@@ -1,57 +0,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.
- */
-package org.jclouds.cloudstack.features;
-
-import org.jclouds.cloudstack.domain.LoginResponse;
-
-/**
- * Provides synchronous access to CloudStack Sessions
- * <p/>
- * 
- * @see <a href="http://download.cloud.com/releases/2.2.0/api_2.2.12/TOC_User.html" />
- * @author Andrei Savu
- */
-public interface SessionClient {
-
-   /**
-    * Logs a user into Cloudstack.  A successful login attempt will generate a JSESSIONID
-    * cookie value that can be passed in subsequent Query command calls until the "logout"
-    * command has been issued or the session has expired.
-    *
-    *
-    *
-    * @param userName
-    *          user account name
-    * @param domain
-    *          domain name, if empty defaults to ROOT
-    * @param hashedPassword
-    *          hashed password (by default MD5)
-    * @return
-    *          login response with session key or null
-    */
-   LoginResponse loginUserInDomainWithHashOfPassword(String userName, String domain, String hashedPassword);
-
-
-   /**
-    * Logs out the user by invalidating the session key
-    *
-    * @param sessionKey
-    *          user session key
-    */
-   void logoutUser(String sessionKey);
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/c6986efd/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/SnapshotApi.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/SnapshotApi.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/SnapshotApi.java
new file mode 100644
index 0000000..295e419
--- /dev/null
+++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/SnapshotApi.java
@@ -0,0 +1,172 @@
+/*
+ * 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.cloudstack.features;
+
+import java.util.Set;
+
+import javax.inject.Named;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
+import org.jclouds.Fallbacks.NullOnNotFoundOr404;
+import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
+import org.jclouds.cloudstack.binders.BindIdListToCommaDelimitedQueryParam;
+import org.jclouds.cloudstack.binders.BindSnapshotPolicyScheduleToQueryParam;
+import org.jclouds.cloudstack.domain.AsyncCreateResponse;
+import org.jclouds.cloudstack.domain.Snapshot;
+import org.jclouds.cloudstack.domain.SnapshotPolicy;
+import org.jclouds.cloudstack.domain.SnapshotPolicySchedule;
+import org.jclouds.cloudstack.filters.AuthenticationFilter;
+import org.jclouds.cloudstack.options.CreateSnapshotOptions;
+import org.jclouds.cloudstack.options.ListSnapshotPoliciesOptions;
+import org.jclouds.cloudstack.options.ListSnapshotsOptions;
+import org.jclouds.rest.annotations.BinderParam;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.OnlyElement;
+import org.jclouds.rest.annotations.QueryParams;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.SelectJson;
+import org.jclouds.rest.annotations.Unwrap;
+
+/**
+ * Provides synchronous access to CloudStack Snapshot features.
+ * <p/>
+ * 
+ * @see http://download.cloud.com/releases/2.2.0/api/TOC_User.html
+ * @author Richard Downer
+ */
+@RequestFilters(AuthenticationFilter.class)
+@QueryParams(keys = "response", values = "json")
+public interface SnapshotApi {
+
+   /**
+    * Creates an instant snapshot of a volume.
+    *
+    * @param volumeId The ID of the disk volume
+    * @param options optional arguments
+    * @return an asynchronous job structure
+    */
+   @Named("createSnapshot")
+   @GET
+   @Consumes(MediaType.APPLICATION_JSON)
+   @QueryParams(keys = "command", values = "createSnapshot")
+   @Unwrap
+   AsyncCreateResponse createSnapshot(@QueryParam("volumeid") String volumeId, CreateSnapshotOptions... options);
+
+   /**
+    * Lists all available snapshots for the account, matching the query described by the options.
+    *
+    * @param options optional arguments
+    * @return the snapshots matching the query
+    */
+   @Named("listSnapshots")
+   @GET
+   @Consumes(MediaType.APPLICATION_JSON)
+   @QueryParams(keys = { "command", "listAll" }, values = { "listSnapshots", "true" })
+   @SelectJson("snapshot")
+   @Unwrap
+   @Fallback(EmptySetOnNotFoundOr404.class)
+   Set<Snapshot> listSnapshots(ListSnapshotsOptions... options);
+
+   /**
+    * Gets a snapshot by its ID.
+    *
+    * @param id the snapshot ID
+    * @return the snapshot with the requested ID
+    */
+   @Named("listSnapshots")
+   @GET
+   @Consumes(MediaType.APPLICATION_JSON)
+   @QueryParams(keys = { "command", "listAll" }, values = { "listSnapshots", "true" })
+   @SelectJson("snapshot")
+   @OnlyElement
+   @Fallback(NullOnNotFoundOr404.class)
+   Snapshot getSnapshot(@QueryParam("id") String id);
+
+   /**
+    * Deletes a snapshot of a disk volume.
+    *
+    * @param id The ID of the snapshot
+    * @return an asynchronous job structure
+    */
+   @Named("deleteSnapshot")
+   @GET
+   @Consumes(MediaType.APPLICATION_JSON)
+   @QueryParams(keys = "command", values = "deleteSnapshot")
+   @Fallback(VoidOnNotFoundOr404.class)
+   void deleteSnapshot(@QueryParam("id") String id);
+
+   /**
+    * Creates a snapshot policy for the account.
+    *
+    * @param schedule how to schedule snapshots
+    * @param numberToRetain maximum number of snapshots to retain
+    * @param timezone Specifies a timezone for this command. For more information on the timezone parameter, see Time Zone Format.
+    * @param volumeId the ID of the disk volume
+    * @return the newly-created snapshot policy
+    */
+   @Named("createSnapshotPolicy")
+   @GET
+   @Consumes(MediaType.APPLICATION_JSON)
+   @Unwrap
+   @QueryParams(keys = "command", values = "createSnapshotPolicy")
+   SnapshotPolicy createSnapshotPolicy(@BinderParam(BindSnapshotPolicyScheduleToQueryParam.class) SnapshotPolicySchedule schedule, @QueryParam("maxsnaps") String numberToRetain, @QueryParam("timezone") String timezone, @QueryParam("volumeid") String volumeId);
+
+   /**
+    * Deletes a snapshot policy for the account.
+    *
+    * @param id The ID of the snapshot policy
+    * @return
+    */
+   @Named("deleteSnapshotPolicies")
+   @GET
+   @Consumes(MediaType.APPLICATION_JSON)
+   @QueryParams(keys = "command", values = "deleteSnapshotPolicies")
+   @Fallback(VoidOnNotFoundOr404.class)
+   void deleteSnapshotPolicy(@QueryParam("id") String id);
+
+   /**
+    * Deletes snapshot policies for the account.
+    *
+    * @param id IDs of snapshot policies
+    * @return
+    */
+   @Named("deleteSnapshotPolicies")
+   @GET
+   @Consumes(MediaType.APPLICATION_JSON)
+   @QueryParams(keys = "command", values = "deleteSnapshotPolicies")
+   @Fallback(VoidOnNotFoundOr404.class)
+   void deleteSnapshotPolicies(@BinderParam(BindIdListToCommaDelimitedQueryParam.class) Iterable<String> id);
+
+   /**
+    * Lists snapshot policies.
+    *
+    * @param volumeId the ID of the disk volume
+    * @param options optional arguments
+    * @return the snapshot policies matching the query
+    */
+   @Named("listSnapshotPolicies")
+   @GET
+   @Consumes(MediaType.APPLICATION_JSON)
+   @QueryParams(keys = { "command", "listAll" }, values = { "listSnapshotPolicies", "true" })
+   @Unwrap
+   @Fallback(EmptySetOnNotFoundOr404.class)
+   Set<SnapshotPolicy> listSnapshotPolicies(@QueryParam("volumeid") String volumeId, ListSnapshotPoliciesOptions... options);
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/c6986efd/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/SnapshotAsyncClient.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/SnapshotAsyncClient.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/SnapshotAsyncClient.java
deleted file mode 100644
index eedf050..0000000
--- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/SnapshotAsyncClient.java
+++ /dev/null
@@ -1,175 +0,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.
- */
-package org.jclouds.cloudstack.features;
-
-import java.util.Set;
-
-import javax.inject.Named;
-import javax.ws.rs.Consumes;
-import javax.ws.rs.GET;
-import javax.ws.rs.QueryParam;
-import javax.ws.rs.core.MediaType;
-
-import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
-import org.jclouds.Fallbacks.NullOnNotFoundOr404;
-import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
-import org.jclouds.cloudstack.binders.BindIdListToCommaDelimitedQueryParam;
-import org.jclouds.cloudstack.binders.BindSnapshotPolicyScheduleToQueryParam;
-import org.jclouds.cloudstack.domain.AsyncCreateResponse;
-import org.jclouds.cloudstack.domain.Snapshot;
-import org.jclouds.cloudstack.domain.SnapshotPolicy;
-import org.jclouds.cloudstack.domain.SnapshotPolicySchedule;
-import org.jclouds.cloudstack.filters.AuthenticationFilter;
-import org.jclouds.cloudstack.options.CreateSnapshotOptions;
-import org.jclouds.cloudstack.options.ListSnapshotPoliciesOptions;
-import org.jclouds.cloudstack.options.ListSnapshotsOptions;
-import org.jclouds.rest.annotations.BinderParam;
-import org.jclouds.rest.annotations.Fallback;
-import org.jclouds.rest.annotations.OnlyElement;
-import org.jclouds.rest.annotations.QueryParams;
-import org.jclouds.rest.annotations.RequestFilters;
-import org.jclouds.rest.annotations.SelectJson;
-import org.jclouds.rest.annotations.Unwrap;
-
-import com.google.common.util.concurrent.ListenableFuture;
-
-/**
- * Provides synchronous access to CloudStack Snapshot features.
- * <p/>
- * 
- * @see SnapshotClient
- * @see http://download.cloud.com/releases/2.2.0/api/TOC_User.html
- * @author Richard Downer
- */
-@RequestFilters(AuthenticationFilter.class)
-@QueryParams(keys = "response", values = "json")
-public interface SnapshotAsyncClient {
-
-   /**
-    * Creates an instant snapshot of a volume.
-    *
-    * @param volumeId The ID of the disk volume
-    * @param options optional arguments
-    * @return an asynchronous job structure
-    */
-   @Named("createSnapshot")
-   @GET
-   @Consumes(MediaType.APPLICATION_JSON)
-   @QueryParams(keys = "command", values = "createSnapshot")
-   @Unwrap
-   ListenableFuture<AsyncCreateResponse> createSnapshot(@QueryParam("volumeid") String volumeId, CreateSnapshotOptions... options);
-
-   /**
-    * Lists all available snapshots for the account, matching the query described by the options.
-    *
-    * @param options optional arguments
-    * @return the snapshots matching the query
-    */
-   @Named("listSnapshots")
-   @GET
-   @Consumes(MediaType.APPLICATION_JSON)
-   @QueryParams(keys = { "command", "listAll" }, values = { "listSnapshots", "true" })
-   @SelectJson("snapshot")
-   @Unwrap
-   @Fallback(EmptySetOnNotFoundOr404.class)
-   ListenableFuture<Set<Snapshot>> listSnapshots(ListSnapshotsOptions... options);
-
-   /**
-    * Gets a snapshot by its ID.
-    *
-    * @param id the snapshot ID
-    * @return the snapshot with the requested ID
-    */
-   @Named("listSnapshots")
-   @GET
-   @Consumes(MediaType.APPLICATION_JSON)
-   @QueryParams(keys = { "command", "listAll" }, values = { "listSnapshots", "true" })
-   @SelectJson("snapshot")
-   @OnlyElement
-   @Fallback(NullOnNotFoundOr404.class)
-   ListenableFuture<Snapshot> getSnapshot(@QueryParam("id") String id);
-
-   /**
-    * Deletes a snapshot of a disk volume.
-    *
-    * @param id The ID of the snapshot
-    * @return an asynchronous job structure
-    */
-   @Named("deleteSnapshot")
-   @GET
-   @Consumes(MediaType.APPLICATION_JSON)
-   @QueryParams(keys = "command", values = "deleteSnapshot")
-   @Fallback(VoidOnNotFoundOr404.class)
-   ListenableFuture<Void> deleteSnapshot(@QueryParam("id") String id);
-
-   /**
-    * Creates a snapshot policy for the account.
-    *
-    * @param schedule how to schedule snapshots
-    * @param numberToRetain maximum number of snapshots to retain
-    * @param timezone Specifies a timezone for this command. For more information on the timezone parameter, see Time Zone Format.
-    * @param volumeId the ID of the disk volume
-    * @return the newly-created snapshot policy
-    */
-   @Named("createSnapshotPolicy")
-   @GET
-   @Consumes(MediaType.APPLICATION_JSON)
-   @Unwrap
-   @QueryParams(keys = "command", values = "createSnapshotPolicy")
-   ListenableFuture<SnapshotPolicy> createSnapshotPolicy(@BinderParam(BindSnapshotPolicyScheduleToQueryParam.class) SnapshotPolicySchedule schedule, @QueryParam("maxsnaps") String numberToRetain, @QueryParam("timezone") String timezone, @QueryParam("volumeid") String volumeId);
-
-   /**
-    * Deletes a snapshot policy for the account.
-    *
-    * @param id The ID of the snapshot policy
-    * @return
-    */
-   @Named("deleteSnapshotPolicies")
-   @GET
-   @Consumes(MediaType.APPLICATION_JSON)
-   @QueryParams(keys = "command", values = "deleteSnapshotPolicies")
-   @Fallback(VoidOnNotFoundOr404.class)
-   ListenableFuture<Void> deleteSnapshotPolicy(@QueryParam("id") String id);
-
-   /**
-    * Deletes snapshot policies for the account.
-    *
-    * @param id IDs of snapshot policies
-    * @return
-    */
-   @Named("deleteSnapshotPolicies")
-   @GET
-   @Consumes(MediaType.APPLICATION_JSON)
-   @QueryParams(keys = "command", values = "deleteSnapshotPolicies")
-   @Fallback(VoidOnNotFoundOr404.class)
-   ListenableFuture<Void> deleteSnapshotPolicies(@BinderParam(BindIdListToCommaDelimitedQueryParam.class) Iterable<String> id);
-
-   /**
-    * Lists snapshot policies.
-    *
-    * @param volumeId the ID of the disk volume
-    * @param options optional arguments
-    * @return the snapshot policies matching the query
-    */
-   @Named("listSnapshotPolicies")
-   @GET
-   @Consumes(MediaType.APPLICATION_JSON)
-   @QueryParams(keys = { "command", "listAll" }, values = { "listSnapshotPolicies", "true" })
-   @Unwrap
-   @Fallback(EmptySetOnNotFoundOr404.class)
-   ListenableFuture<Set<SnapshotPolicy>> listSnapshotPolicies(@QueryParam("volumeid") String volumeId, ListSnapshotPoliciesOptions... options);
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/c6986efd/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/SnapshotClient.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/SnapshotClient.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/SnapshotClient.java
deleted file mode 100644
index 4b17e2e..0000000
--- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/SnapshotClient.java
+++ /dev/null
@@ -1,107 +0,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.
- */
-package org.jclouds.cloudstack.features;
-
-import java.util.Set;
-import org.jclouds.cloudstack.domain.AsyncCreateResponse;
-import org.jclouds.cloudstack.domain.Snapshot;
-import org.jclouds.cloudstack.domain.SnapshotPolicy;
-import org.jclouds.cloudstack.domain.SnapshotPolicySchedule;
-import org.jclouds.cloudstack.options.CreateSnapshotOptions;
-import org.jclouds.cloudstack.options.ListSnapshotPoliciesOptions;
-import org.jclouds.cloudstack.options.ListSnapshotsOptions;
-
-/**
- * Provides synchronous access to CloudStack Snapshot features.
- * <p/>
- * 
- * @see SnapshotAsyncClient
- * @see http://download.cloud.com/releases/2.2.0/api/TOC_User.html
- * @author Richard Downer
- */
-public interface SnapshotClient {
-
-   /**
-    * Creates an instant snapshot of a volume.
-    *
-    * @param volumeId The ID of the disk volume
-    * @param options optional arguments
-    * @return an asynchronous job structure
-    */
-   AsyncCreateResponse createSnapshot(String volumeId, CreateSnapshotOptions... options);
-
-   /**
-    * Lists all available snapshots for the account, matching the query described by the options.
-    *
-    * @param options optional arguments
-    * @return the snapshots matching the query
-    */
-   Set<Snapshot> listSnapshots(ListSnapshotsOptions... options);
-
-   /**
-    * Gets a snapshot by its ID.
-    *
-    * @param id the snapshot ID
-    * @return the snapshot with the requested ID
-    */
-   Snapshot getSnapshot(String id);
-
-   /**
-    * Deletes a snapshot of a disk volume.
-    *
-    * @param id The ID of the snapshot
-    * @return an asynchronous job structure
-    */
-   void deleteSnapshot(String id);
-
-   /**
-    * Creates a snapshot policy for the account.
-    *
-    * @param schedule how to schedule snapshots
-    * @param numberToRetain maximum number of snapshots to retain
-    * @param timezone Specifies a timezone for this command. For more information on the timezone parameter, see Time Zone Format.
-    * @param volumeId the ID of the disk volume
-    * @return the newly-created snapshot policy
-    */
-   SnapshotPolicy createSnapshotPolicy(SnapshotPolicySchedule schedule, String numberToRetain, String timezone, String volumeId);
-
-   /**
-    * Deletes a snapshot policy for the account.
-    *
-    * @param id The ID of the snapshot policy
-    * @return
-    */
-   void deleteSnapshotPolicy(String id);
-
-   /**
-    * Deletes snapshot policies for the account.
-    *
-    * @param id IDs of snapshot policies
-    * @return
-    */
-   void deleteSnapshotPolicies(Iterable<String> id);
-
-   /**
-    * Lists snapshot policies.
-    *
-    * @param volumeId the ID of the disk volume
-    * @param options optional arguments
-    * @return the snapshot policies matching the query
-    */
-   Set<SnapshotPolicy> listSnapshotPolicies(String volumeId, ListSnapshotPoliciesOptions... options);
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/c6986efd/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/TemplateApi.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/TemplateApi.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/TemplateApi.java
new file mode 100644
index 0000000..c28d833
--- /dev/null
+++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/TemplateApi.java
@@ -0,0 +1,295 @@
+/*
+ * 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.cloudstack.features;
+
+import java.util.Set;
+
+import javax.inject.Named;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
+import org.jclouds.Fallbacks.NullOnNotFoundOr404;
+import org.jclouds.cloudstack.binders.BindTemplateMetadataToQueryParams;
+import org.jclouds.cloudstack.domain.AsyncCreateResponse;
+import org.jclouds.cloudstack.domain.ExtractMode;
+import org.jclouds.cloudstack.domain.Template;
+import org.jclouds.cloudstack.domain.TemplateMetadata;
+import org.jclouds.cloudstack.domain.TemplatePermission;
+import org.jclouds.cloudstack.filters.AuthenticationFilter;
+import org.jclouds.cloudstack.options.AccountInDomainOptions;
+import org.jclouds.cloudstack.options.CreateTemplateOptions;
+import org.jclouds.cloudstack.options.DeleteTemplateOptions;
+import org.jclouds.cloudstack.options.ExtractTemplateOptions;
+import org.jclouds.cloudstack.options.ListTemplatesOptions;
+import org.jclouds.cloudstack.options.RegisterTemplateOptions;
+import org.jclouds.cloudstack.options.UpdateTemplateOptions;
+import org.jclouds.cloudstack.options.UpdateTemplatePermissionsOptions;
+import org.jclouds.rest.annotations.BinderParam;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.OnlyElement;
+import org.jclouds.rest.annotations.QueryParams;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.SelectJson;
+import org.jclouds.rest.annotations.Unwrap;
+
+/**
+ * Provides synchronous access to cloudstack via their REST API.
+ * <p/>
+ * 
+ * @see <a
+ *      href="http://download.cloud.com/releases/2.2.0/api_2.2.12/TOC_User.html"
+ *      />
+ * @author Adrian Cole
+ */
+@RequestFilters(AuthenticationFilter.class)
+@QueryParams(keys = "response", values = "json")
+public interface TemplateApi {
+
+   /**
+    * Creates a template of a virtual machine. The virtual machine must be in a
+    * STOPPED state. A template created from this command is automatically
+    * designated as a private template visible to the account that created it.
+    * 
+    * @see http
+    *      ://download.cloud.com/releases/2.2.0/api_2.2.8/user/createTemplate
+    *      .html
+    * @param templateMetadata
+    *           overall description of the template
+    * @param options
+    *           optional arguments
+    * @return an asynchronous job response
+    */
+   @Named("createTemplate")
+   @GET
+   @QueryParams(keys = "command", values = "createTemplate")
+   @Unwrap
+   @Consumes(MediaType.APPLICATION_JSON)
+   AsyncCreateResponse createTemplate(
+         @BinderParam(BindTemplateMetadataToQueryParams.class) TemplateMetadata templateMetadata,
+         CreateTemplateOptions... options);
+
+   /**
+    * Registers an existing template into the Cloud.com cloud.
+    * 
+    * @see http 
+    *      ://download.cloud.com/releases/2.2.0/api_2.2.8/user/registerTemplate
+    *      .html
+    * @param templateMetadata
+    *           overall description of the template
+    * @param format
+    *           the format for the template. Possible values include QCOW2, RAW,
+    *           and VHD.
+    * 
+    * @param url
+    *           the URL of where the template is hosted. Possible URL include
+    *           http:// and https://
+    * @param zoneId
+    *           the ID of the zone the template is to be hosted on
+    * @param options
+    *           optional arguments
+    * @return data about the newly-registered template
+    */
+   @Named("registerTemplate")
+   @GET
+   @QueryParams(keys = "command", values = "registerTemplate")
+   @SelectJson("template")
+   @Consumes(MediaType.APPLICATION_JSON)
+   Set<Template> registerTemplate(
+         @BinderParam(BindTemplateMetadataToQueryParams.class) TemplateMetadata templateMetadata,
+         @QueryParam("format") String format, @QueryParam("hypervisor") String hypervisor,
+         @QueryParam("url") String url, @QueryParam("zoneid") String zoneId, RegisterTemplateOptions... options);
+
+   /**
+    * Updates attributes of a template.
+    * 
+    * @see http
+    *      ://download.cloud.com/releases/2.2.0/api_2.2.8/user/updateTemplate
+    *      .html
+    * @param id
+    *           the ID of the image file
+    * @param options
+    *           optional arguments
+    * @return updated data about the template
+    */
+   @Named("updateTemplate")
+   @GET
+   @QueryParams(keys = "command", values = "updateTemplate")
+   @SelectJson("template")
+   @Consumes(MediaType.APPLICATION_JSON)
+   Template updateTemplate(@QueryParam("id") String id, UpdateTemplateOptions... options);
+
+   /**
+    * Copies a template from one zone to another.
+    * 
+    * @see http 
+    *      ://download.cloud.com/releases/2.2.0/api_2.2.8/user/copyTemplate.html
+    * @param id
+    *           Template ID.
+    * @param sourceZoneId
+    *           ID of the zone the template is currently hosted on.
+    * @param destZoneId
+    *           ID of the zone the template is being copied to.
+    * @return an asynchronous job response
+    */
+   @Named("copyTemplate")
+   @GET
+   @QueryParams(keys = "command", values = "copyTemplate")
+   @Unwrap
+   @Consumes(MediaType.APPLICATION_JSON)
+   AsyncCreateResponse copyTemplateToZone(@QueryParam("id") String id,
+         @QueryParam("sourcezoneid") String sourceZoneId, @QueryParam("destzoneid") String destZoneId);
+
+   /**
+    * Deletes a template from the system. All virtual machines using the deleted
+    * template will not be affected.
+    * 
+    * @see http
+    *      ://download.cloud.com/releases/2.2.0/api_2.2.8/user/deleteTemplate
+    *      .html
+    * @param id
+    *           the ID of the template
+    * @param options
+    *           optional arguments
+    */
+   @Named("deleteTemplate")
+   @GET
+   @QueryParams(keys = "command", values = "deleteTemplate")
+   @Unwrap
+   @Consumes(MediaType.APPLICATION_JSON)
+   AsyncCreateResponse deleteTemplate(@QueryParam("id") String id, DeleteTemplateOptions... options);
+
+   /**
+    * List all executable templates.
+    * 
+    * @see http
+    *      ://download.cloud.com/releases/2.2.0/api_2.2.8/user/listTemplates.
+    *      html
+    * @return all executable templates, or empty set, if no templates are found
+    */
+   @Named("listTemplates")
+   @GET
+   @QueryParams(keys = { "command", "listAll", "templatefilter" }, values = { "listTemplates", "true", "executable" })
+   @SelectJson("template")
+   @Consumes(MediaType.APPLICATION_JSON)
+   @Fallback(EmptySetOnNotFoundOr404.class)
+   Set<Template> listTemplates();
+
+   /**
+    * List all public, private, and privileged templates.
+    * 
+    * @see http
+    *      ://download.cloud.com/releases/2.2.0/api_2.2.8/user/listTemplates.
+    *      html
+    * @param options
+    *           if present, how to constrain the list, defaults to all
+    *           executable templates
+    * @return templates matching query, or empty set, if no templates are found
+    * @see TemplateFilter
+    */
+   @Named("listTemplates")
+   @GET
+   @QueryParams(keys = { "command", "listAll" }, values = { "listTemplates", "true" })
+   @SelectJson("template")
+   @Consumes(MediaType.APPLICATION_JSON)
+   @Fallback(EmptySetOnNotFoundOr404.class)
+   Set<Template> listTemplates(ListTemplatesOptions options);
+
+   /**
+    * get a specific template by id
+    * 
+    * 
+    * @param templateId
+    * @param zoneId
+    *           zone template is defined in
+    * @return template or null if not found
+    */
+   @Named("listTemplates")
+   @GET
+   // templatefilter required in at least 2.2.8 version
+   @QueryParams(keys = { "command", "listAll", "templatefilter" }, values = { "listTemplates", "true", "executable" })
+   @SelectJson("template")
+   @OnlyElement
+   @Consumes(MediaType.APPLICATION_JSON)
+   @Fallback(NullOnNotFoundOr404.class)
+   Template getTemplateInZone(@QueryParam("id") String templateId, @QueryParam("zoneid") String zoneId);
+
+   /**
+    * Updates a template visibility permissions. A public template is visible to
+    * all accounts within the same domain. A private template is visible only to
+    * the owner of the template. A privileged template is a private template
+    * with account permissions added. Only accounts specified under the template
+    * permissions are visible to them.
+    * 
+    * @see http://download.cloud.com/releases/2.2.0/api_2.2.8/user/
+    *      updateTemplatePermissions.html
+    * @param id
+    *           the template ID
+    * @param options
+    *           optional arguments
+    */
+   @Named("updateTemplatePermissions")
+   @GET
+   @QueryParams(keys = "command", values = "updateTemplatePermissions")
+   void updateTemplatePermissions(@QueryParam("id") String id,
+         UpdateTemplatePermissionsOptions... options);
+
+   /**
+    * List template visibility and all accounts that have permissions to view
+    * this template.
+    * 
+    * @see http://download.cloud.com/releases/2.2.0/api_2.2.8/user/
+    *      listTemplatePermissions.html
+    * @param id
+    *           the template ID
+    * @param options
+    *           optional arguments
+    * @return the list of permissions that apply to the template
+    */
+   @Named("listTemplatePermissions")
+   @GET
+   @QueryParams(keys = { "command", "listAll" }, values = { "listTemplatePermissions", "true" })
+   @Unwrap
+   @Consumes(MediaType.APPLICATION_JSON)
+   Set<TemplatePermission> listTemplatePermissions(@QueryParam("id") String id,
+         AccountInDomainOptions... options);
+
+   /**
+    * 
+    * @see http 
+    *      ://download.cloud.com/releases/2.2.0/api_2.2.8/user/extractTemplate
+    *      .html
+    * @param id
+    *           the ID of the template
+    * @param mode
+    *           FIXME the mode of extraction - HTTP_DOWNLOAD or FTP_UPLOAD
+    * @param zoneId
+    *           the ID of the zone where the ISO is originally located
+    * @param options
+    *           optional arguments
+    * @return an asynchronous job response
+    */
+   @Named("extractTemplate")
+   @GET
+   @QueryParams(keys = "command", values = "extractTemplate")
+   @Unwrap
+   @Consumes(MediaType.APPLICATION_JSON)
+   AsyncCreateResponse extractTemplate(@QueryParam("id") String id,
+         @QueryParam("mode") ExtractMode mode, @QueryParam("zoneid") String zoneId, ExtractTemplateOptions... options);
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/c6986efd/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/TemplateAsyncClient.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/TemplateAsyncClient.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/TemplateAsyncClient.java
deleted file mode 100644
index 767889c..0000000
--- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/TemplateAsyncClient.java
+++ /dev/null
@@ -1,189 +0,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.
- */
-package org.jclouds.cloudstack.features;
-
-import java.util.Set;
-
-import javax.inject.Named;
-import javax.ws.rs.Consumes;
-import javax.ws.rs.GET;
-import javax.ws.rs.QueryParam;
-import javax.ws.rs.core.MediaType;
-
-import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
-import org.jclouds.Fallbacks.NullOnNotFoundOr404;
-import org.jclouds.cloudstack.binders.BindTemplateMetadataToQueryParams;
-import org.jclouds.cloudstack.domain.AsyncCreateResponse;
-import org.jclouds.cloudstack.domain.ExtractMode;
-import org.jclouds.cloudstack.domain.Template;
-import org.jclouds.cloudstack.domain.TemplateMetadata;
-import org.jclouds.cloudstack.domain.TemplatePermission;
-import org.jclouds.cloudstack.filters.AuthenticationFilter;
-import org.jclouds.cloudstack.options.AccountInDomainOptions;
-import org.jclouds.cloudstack.options.CreateTemplateOptions;
-import org.jclouds.cloudstack.options.DeleteTemplateOptions;
-import org.jclouds.cloudstack.options.ExtractTemplateOptions;
-import org.jclouds.cloudstack.options.ListTemplatesOptions;
-import org.jclouds.cloudstack.options.RegisterTemplateOptions;
-import org.jclouds.cloudstack.options.UpdateTemplateOptions;
-import org.jclouds.cloudstack.options.UpdateTemplatePermissionsOptions;
-import org.jclouds.rest.annotations.BinderParam;
-import org.jclouds.rest.annotations.Fallback;
-import org.jclouds.rest.annotations.OnlyElement;
-import org.jclouds.rest.annotations.QueryParams;
-import org.jclouds.rest.annotations.RequestFilters;
-import org.jclouds.rest.annotations.SelectJson;
-import org.jclouds.rest.annotations.Unwrap;
-
-import com.google.common.util.concurrent.ListenableFuture;
-
-/**
- * Provides asynchronous access to cloudstack via their REST API.
- * <p/>
- * 
- * @see TemplateClient
- * @see <a
- *      href="http://download.cloud.com/releases/2.2.0/api_2.2.12/TOC_User.html"
- *      />
- * @author Adrian Cole
- */
-@RequestFilters(AuthenticationFilter.class)
-@QueryParams(keys = "response", values = "json")
-public interface TemplateAsyncClient {
-
-   /**
-    * @see TemplateClient#createTemplate
-    */
-   @Named("createTemplate")
-   @GET
-   @QueryParams(keys = "command", values = "createTemplate")
-   @Unwrap
-   @Consumes(MediaType.APPLICATION_JSON)
-   ListenableFuture<AsyncCreateResponse> createTemplate(
-         @BinderParam(BindTemplateMetadataToQueryParams.class) TemplateMetadata templateMetadata,
-         CreateTemplateOptions... options);
-
-   /**
-    * @see TemplateClient#registerTemplate
-    */
-   @Named("registerTemplate")
-   @GET
-   @QueryParams(keys = "command", values = "registerTemplate")
-   @SelectJson("template")
-   @Consumes(MediaType.APPLICATION_JSON)
-   ListenableFuture<Set<Template>> registerTemplate(
-         @BinderParam(BindTemplateMetadataToQueryParams.class) TemplateMetadata templateMetadata,
-         @QueryParam("format") String format, @QueryParam("hypervisor") String hypervisor,
-         @QueryParam("url") String url, @QueryParam("zoneid") String zoneId, RegisterTemplateOptions... options);
-
-   /**
-    * @see TemplateClient#updateTemplate
-    */
-   @Named("updateTemplate")
-   @GET
-   @QueryParams(keys = "command", values = "updateTemplate")
-   @SelectJson("template")
-   @Consumes(MediaType.APPLICATION_JSON)
-   ListenableFuture<Template> updateTemplate(@QueryParam("id") String id, UpdateTemplateOptions... options);
-
-   /**
-    * @see TemplateClient#copyTemplate
-    */
-   @Named("copyTemplate")
-   @GET
-   @QueryParams(keys = "command", values = "copyTemplate")
-   @Unwrap
-   @Consumes(MediaType.APPLICATION_JSON)
-   ListenableFuture<AsyncCreateResponse> copyTemplateToZone(@QueryParam("id") String id,
-         @QueryParam("sourcezoneid") String sourceZoneId, @QueryParam("destzoneid") String destZoneId);
-
-   /**
-    * @see TemplateClient#deleteTemplate
-    */
-   @Named("deleteTemplate")
-   @GET
-   @QueryParams(keys = "command", values = "deleteTemplate")
-   @Unwrap
-   @Consumes(MediaType.APPLICATION_JSON)
-   ListenableFuture<AsyncCreateResponse> deleteTemplate(@QueryParam("id") String id, DeleteTemplateOptions... options);
-
-   /**
-    * @see TemplateClient#listTemplates
-    */
-   @Named("listTemplates")
-   @GET
-   @QueryParams(keys = { "command", "listAll", "templatefilter" }, values = { "listTemplates", "true", "executable" })
-   @SelectJson("template")
-   @Consumes(MediaType.APPLICATION_JSON)
-   @Fallback(EmptySetOnNotFoundOr404.class)
-   ListenableFuture<Set<Template>> listTemplates();
-
-   /**
-    * @see TemplateClient#listTemplates(ListTemplatesOptions)
-    */
-   @Named("listTemplates")
-   @GET
-   @QueryParams(keys = { "command", "listAll" }, values = { "listTemplates", "true" })
-   @SelectJson("template")
-   @Consumes(MediaType.APPLICATION_JSON)
-   @Fallback(EmptySetOnNotFoundOr404.class)
-   ListenableFuture<Set<Template>> listTemplates(ListTemplatesOptions options);
-
-   /**
-    * @see TemplateClient#getTemplate
-    */
-   @Named("listTemplates")
-   @GET
-   // templatefilter required in at least 2.2.8 version
-   @QueryParams(keys = { "command", "listAll", "templatefilter" }, values = { "listTemplates", "true", "executable" })
-   @SelectJson("template")
-   @OnlyElement
-   @Consumes(MediaType.APPLICATION_JSON)
-   @Fallback(NullOnNotFoundOr404.class)
-   ListenableFuture<Template> getTemplateInZone(@QueryParam("id") String templateId, @QueryParam("zoneid") String zoneId);
-
-   /**
-    * @see TemplateClient#updateTemplatePermissions
-    */
-   @Named("updateTemplatePermissions")
-   @GET
-   @QueryParams(keys = "command", values = "updateTemplatePermissions")
-   ListenableFuture<Void> updateTemplatePermissions(@QueryParam("id") String id,
-         UpdateTemplatePermissionsOptions... options);
-
-   /**
-    * @see TemplateClient#listTemplatePermissions
-    */
-   @Named("listTemplatePermissions")
-   @GET
-   @QueryParams(keys = { "command", "listAll" }, values = { "listTemplatePermissions", "true" })
-   @Unwrap
-   @Consumes(MediaType.APPLICATION_JSON)
-   ListenableFuture<Set<TemplatePermission>> listTemplatePermissions(@QueryParam("id") String id,
-         AccountInDomainOptions... options);
-
-   /**
-    * @see TemplateClient#extractTemplate
-    */
-   @Named("extractTemplate")
-   @GET
-   @QueryParams(keys = "command", values = "extractTemplate")
-   @Unwrap
-   @Consumes(MediaType.APPLICATION_JSON)
-   ListenableFuture<AsyncCreateResponse> extractTemplate(@QueryParam("id") String id,
-         @QueryParam("mode") ExtractMode mode, @QueryParam("zoneid") String zoneId, ExtractTemplateOptions... options);
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/c6986efd/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/TemplateClient.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/TemplateClient.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/TemplateClient.java
deleted file mode 100644
index 14db6ab..0000000
--- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/TemplateClient.java
+++ /dev/null
@@ -1,210 +0,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.
- */
-package org.jclouds.cloudstack.features;
-
-import java.util.Set;
-import org.jclouds.cloudstack.domain.AsyncCreateResponse;
-import org.jclouds.cloudstack.domain.ExtractMode;
-import org.jclouds.cloudstack.domain.Template;
-import org.jclouds.cloudstack.domain.TemplateMetadata;
-import org.jclouds.cloudstack.domain.TemplatePermission;
-import org.jclouds.cloudstack.options.AccountInDomainOptions;
-import org.jclouds.cloudstack.options.CreateTemplateOptions;
-import org.jclouds.cloudstack.options.DeleteTemplateOptions;
-import org.jclouds.cloudstack.options.ExtractTemplateOptions;
-import org.jclouds.cloudstack.options.ListTemplatesOptions;
-import org.jclouds.cloudstack.options.RegisterTemplateOptions;
-import org.jclouds.cloudstack.options.UpdateTemplateOptions;
-import org.jclouds.cloudstack.options.UpdateTemplatePermissionsOptions;
-
-/**
- * Provides synchronous access to CloudStack template features.
- * <p/>
- * 
- * @see TemplateAsyncClient
- * @see <a
- *      href="http://download.cloud.com/releases/2.2.0/api_2.2.12/TOC_User.html"
- *      />
- * @author Adrian Cole
- */
-public interface TemplateClient {
-   /**
-    * Creates a template of a virtual machine. The virtual machine must be in a
-    * STOPPED state. A template created from this command is automatically
-    * designated as a private template visible to the account that created it.
-    * 
-    * @see http
-    *      ://download.cloud.com/releases/2.2.0/api_2.2.8/user/createTemplate
-    *      .html
-    * @param templateMetadata
-    *           overall description of the template
-    * @param options
-    *           optional arguments
-    * @return an asynchronous job response
-    */
-   AsyncCreateResponse createTemplate(TemplateMetadata templateMetadata, CreateTemplateOptions... options);
-
-   /**
-    * Registers an existing template into the Cloud.com cloud.
-    * 
-    * @see http 
-    *      ://download.cloud.com/releases/2.2.0/api_2.2.8/user/registerTemplate
-    *      .html
-    * @param templateMetadata
-    *           overall description of the template
-    * @param format
-    *           the format for the template. Possible values include QCOW2, RAW,
-    *           and VHD.
-    * 
-    * @param url
-    *           the URL of where the template is hosted. Possible URL include
-    *           http:// and https://
-    * @param zoneId
-    *           the ID of the zone the template is to be hosted on
-    * @param options
-    *           optional arguments
-    * @return data about the newly-registered template
-    */
-   Set<Template> registerTemplate(TemplateMetadata templateMetadata, String format, String hypervisor, String url,
-         String zoneId, RegisterTemplateOptions... options);
-
-   /**
-    * Updates attributes of a template.
-    * 
-    * @see http
-    *      ://download.cloud.com/releases/2.2.0/api_2.2.8/user/updateTemplate
-    *      .html
-    * @param id
-    *           the ID of the image file
-    * @param options
-    *           optional arguments
-    * @return updated data about the template
-    */
-   Template updateTemplate(String id, UpdateTemplateOptions... options);
-
-   /**
-    * Copies a template from one zone to another.
-    * 
-    * @see http 
-    *      ://download.cloud.com/releases/2.2.0/api_2.2.8/user/copyTemplate.html
-    * @param id
-    *           Template ID.
-    * @param sourceZoneId
-    *           ID of the zone the template is currently hosted on.
-    * @param destZoneId
-    *           ID of the zone the template is being copied to.
-    * @return an asynchronous job response
-    */
-   AsyncCreateResponse copyTemplateToZone(String id, String sourceZoneId, String destZoneId);
-
-   /**
-    * Deletes a template from the system. All virtual machines using the deleted
-    * template will not be affected.
-    * 
-    * @see http
-    *      ://download.cloud.com/releases/2.2.0/api_2.2.8/user/deleteTemplate
-    *      .html
-    * @param id
-    *           the ID of the template
-    * @param options
-    *           optional arguments
-    */
-   AsyncCreateResponse deleteTemplate(String id, DeleteTemplateOptions... options);
-
-   /**
-    * List all executable templates.
-    * 
-    * @see http
-    *      ://download.cloud.com/releases/2.2.0/api_2.2.8/user/listTemplates.
-    *      html
-    * @return all executable templates, or empty set, if no templates are found
-    */
-   Set<Template> listTemplates();
-
-   /**
-    * List all public, private, and privileged templates.
-    * 
-    * @see http
-    *      ://download.cloud.com/releases/2.2.0/api_2.2.8/user/listTemplates.
-    *      html
-    * @param options
-    *           if present, how to constrain the list, defaults to all
-    *           executable templates
-    * @return templates matching query, or empty set, if no templates are found
-    * @see TemplateFilter
-    */
-   Set<Template> listTemplates(ListTemplatesOptions options);
-
-   /**
-    * get a specific template by id
-    * 
-    * 
-    * @param templateId
-    * @param zoneId
-    *           zone template is defined in
-    * @return template or null if not found
-    */
-   Template getTemplateInZone(String templateId, String zoneId);
-
-   /**
-    * Updates a template visibility permissions. A public template is visible to
-    * all accounts within the same domain. A private template is visible only to
-    * the owner of the template. A privileged template is a private template
-    * with account permissions added. Only accounts specified under the template
-    * permissions are visible to them.
-    * 
-    * @see http://download.cloud.com/releases/2.2.0/api_2.2.8/user/
-    *      updateTemplatePermissions.html
-    * @param id
-    *           the template ID
-    * @param options
-    *           optional arguments
-    */
-   void updateTemplatePermissions(String id, UpdateTemplatePermissionsOptions... options);
-
-   /**
-    * List template visibility and all accounts that have permissions to view
-    * this template.
-    * 
-    * @see http://download.cloud.com/releases/2.2.0/api_2.2.8/user/
-    *      listTemplatePermissions.html
-    * @param id
-    *           the template ID
-    * @param options
-    *           optional arguments
-    * @return the list of permissions that apply to the template
-    */
-   Set<TemplatePermission> listTemplatePermissions(String id, AccountInDomainOptions... options);
-
-   /**
-    * 
-    * @see http 
-    *      ://download.cloud.com/releases/2.2.0/api_2.2.8/user/extractTemplate
-    *      .html
-    * @param id
-    *           the ID of the template
-    * @param mode
-    *           FIXME the mode of extraction - HTTP_DOWNLOAD or FTP_UPLOAD
-    * @param zoneId
-    *           the ID of the zone where the ISO is originally located
-    * @param options
-    *           optional arguments
-    * @return an asynchronous job response
-    */
-   AsyncCreateResponse extractTemplate(String id, ExtractMode mode, String zoneId,
-         ExtractTemplateOptions... options);
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/c6986efd/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/VMGroupApi.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/VMGroupApi.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/VMGroupApi.java
new file mode 100644
index 0000000..a3f2c4b
--- /dev/null
+++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/VMGroupApi.java
@@ -0,0 +1,115 @@
+/*
+ * 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.cloudstack.features;
+
+import java.util.Set;
+
+import javax.inject.Named;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
+import org.jclouds.Fallbacks.NullOnNotFoundOr404;
+import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
+import org.jclouds.cloudstack.domain.VMGroup;
+import org.jclouds.cloudstack.filters.AuthenticationFilter;
+import org.jclouds.cloudstack.options.CreateVMGroupOptions;
+import org.jclouds.cloudstack.options.ListVMGroupsOptions;
+import org.jclouds.cloudstack.options.UpdateVMGroupOptions;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.OnlyElement;
+import org.jclouds.rest.annotations.QueryParams;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.SelectJson;
+
+/**
+ * Provides synchronous access to CloudStack VM group features.
+ * <p/>
+ *
+ * @author Richard Downer
+ * @see <a href="http://download.cloud.com/releases/2.2.0/api_2.2.12/TOC_User.html" />
+ */
+@RequestFilters(AuthenticationFilter.class)
+@QueryParams(keys = "response", values = "json")
+public interface VMGroupApi {
+   /**
+    * Lists VM groups
+    *
+    * @param options if present, how to constrain the list.
+    * @return VM groups matching query, or empty set, if no zones are found
+    */
+   @Named("listInstanceGroups")
+   @GET
+   @QueryParams(keys = { "command", "listAll" }, values = { "listInstanceGroups", "true" })
+   @SelectJson("instancegroup")
+   @Consumes(MediaType.APPLICATION_JSON)
+   @Fallback(EmptySetOnNotFoundOr404.class)
+   Set<VMGroup> listInstanceGroups(ListVMGroupsOptions... options);
+
+   /**
+    * @see VMGroupApi#getInstanceGroup
+    */
+   @Named("listInstanceGroups")
+   @GET
+   @QueryParams(keys = { "command", "listAll" }, values = { "listInstanceGroups", "true" })
+   @SelectJson("instancegroup")
+   @OnlyElement
+   @Consumes(MediaType.APPLICATION_JSON)
+   @Fallback(NullOnNotFoundOr404.class)
+   VMGroup getInstanceGroup(@QueryParam("id") String id);
+
+   /**
+    * Creates a VM group
+    *
+    * @param name    the name of the VM group
+    * @param options optional parameters
+    * @return the new VMGroup
+    */
+   @Named("createInstanceGroup")
+   @GET
+   @QueryParams(keys = "command", values = "createInstanceGroup")
+   @SelectJson("instancegroup")
+   @Consumes(MediaType.APPLICATION_JSON)
+   VMGroup createInstanceGroup(@QueryParam("name") String name, CreateVMGroupOptions... options);
+
+   /**
+    * Modify a VM group
+    *
+    * @param name the new name of the group
+    * @return the modified VMGroup
+    */
+   @Named("updateInstanceGroup")
+   @GET
+   @QueryParams(keys = "command", values = "updateInstanceGroup")
+   @SelectJson("instancegroup")
+   @Consumes(MediaType.APPLICATION_JSON)
+   VMGroup updateInstanceGroup(@QueryParam("id") String id, UpdateVMGroupOptions... options);
+
+   /**
+    * Delete a VM group
+    *
+    * @param id the ID of the VM group
+    * @return a future with a void data type
+    */
+   @Named("deleteInstanceGroup")
+   @GET
+   @QueryParams(keys = "command", values = "deleteInstanceGroup")
+   @Fallback(VoidOnNotFoundOr404.class)
+   void deleteInstanceGroup(@QueryParam("id") String id);
+}