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 2014/08/30 03:38:13 UTC

git commit: Adds support for Floating IP

Repository: jclouds-labs-openstack
Updated Branches:
  refs/heads/master 67b9f4721 -> e7a52c1ae


Adds support for Floating IP


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

Branch: refs/heads/master
Commit: e7a52c1aecef2f989f9bde57c1b83e97a81538f9
Parents: 67b9f47
Author: Zack Shoylev <za...@rackspace.com>
Authored: Fri Aug 22 01:06:34 2014 -0500
Committer: Zack Shoylev <za...@rackspace.com>
Committed: Fri Aug 29 20:35:48 2014 -0500

----------------------------------------------------------------------
 .../openstack/neutron/v2/NeutronApi.java        |  14 +-
 .../openstack/neutron/v2/domain/FloatingIP.java | 316 ++++++++++++++
 .../neutron/v2/domain/FloatingIPs.java          |  36 ++
 .../openstack/neutron/v2/domain/Networks.java   |   7 +-
 .../openstack/neutron/v2/domain/Ports.java      |   9 +-
 .../openstack/neutron/v2/domain/Routers.java    |   9 +-
 .../openstack/neutron/v2/domain/Subnets.java    |   9 +-
 .../neutron/v2/extensions/FloatingIPApi.java    | 138 ++++++
 .../v2/fallbacks/EmptyFloatingIPsFallback.java  |  45 ++
 .../functions/FloatingIPsToPagedIterable.java   |  64 +++
 .../neutron/v2/functions/ParseFloatingIPs.java  |  37 ++
 .../v2/functions/RouterToPagedIterable.java     |  13 +-
 .../v2/extensions/FloatingIPApiLiveTest.java    |  92 ++++
 .../v2/extensions/FloatingIPApiMockTest.java    | 436 +++++++++++++++++++
 .../v2/extensions/RouterApiLiveTest.java        |  16 +-
 .../v2/extensions/RouterApiMockTest.java        |  55 ++-
 .../resources/floatingip_create_request.json    |   6 +
 .../resources/floatingip_create_response.json   |  11 +
 .../test/resources/floatingip_get_response.json |  11 +
 .../resources/floatingip_list_response.json     |  22 +
 .../floatingip_list_response_paged1.json        |  32 ++
 .../floatingip_list_response_paged2.json        |  28 ++
 .../floatingip_update_dissociate_request.json   |   5 +
 .../floatingip_update_dissociate_response.json  |  11 +
 .../resources/floatingip_update_request.json    |   5 +
 .../resources/floatingip_update_response.json   |  11 +
 26 files changed, 1385 insertions(+), 53 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/e7a52c1a/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/NeutronApi.java
----------------------------------------------------------------------
diff --git a/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/NeutronApi.java b/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/NeutronApi.java
index 358e38f..b54fa39 100644
--- a/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/NeutronApi.java
+++ b/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/NeutronApi.java
@@ -22,8 +22,10 @@ import java.util.Set;
 import javax.ws.rs.Path;
 
 import org.jclouds.Constants;
+
 import org.jclouds.location.Region;
 import org.jclouds.location.functions.RegionToEndpoint;
+import org.jclouds.openstack.neutron.v2.extensions.FloatingIPApi;
 import org.jclouds.openstack.neutron.v2.extensions.RouterApi;
 import org.jclouds.openstack.neutron.v2.extensions.SecurityGroupApi;
 import org.jclouds.openstack.neutron.v2.features.NetworkApi;
@@ -80,15 +82,17 @@ public interface NeutronApi extends Closeable {
     * to determine if it is present.
     */
    @Delegate
-   Optional<? extends RouterApi> getRouterApi(@EndpointParam(parser = RegionToEndpoint.class) String region);
+   Optional<RouterApi> getRouterApi(@EndpointParam(parser = RegionToEndpoint.class) String region);
 
    /**
-    * Provides access to Router features.
-    * @deprecated Please use {@link #getRouterApi(String)} as this method will be removed in jclouds 3.0.
+    * Provides access to Floating IP features.
+    *
+    * <h3>NOTE</h3>
+    * This API is an extension that may or may not be present in your OpenStack cloud. Use the Optional return type
+    * to determine if it is present.
     */
-   @Deprecated
    @Delegate
-   Optional<? extends RouterApi> getRouterExtensionApi(@EndpointParam(parser = RegionToEndpoint.class) String region);
+   Optional<FloatingIPApi> getFloatingIPApi(@EndpointParam(parser = RegionToEndpoint.class) String region);
 
    /**
     * Provides access to SecurityGroup features.

http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/e7a52c1a/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/FloatingIP.java
----------------------------------------------------------------------
diff --git a/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/FloatingIP.java b/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/FloatingIP.java
new file mode 100644
index 0000000..c5c3b7d
--- /dev/null
+++ b/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/FloatingIP.java
@@ -0,0 +1,316 @@
+/*
+ * 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.openstack.neutron.v2.domain;
+
+import java.beans.ConstructorProperties;
+import javax.inject.Named;
+
+import org.jclouds.javax.annotation.Nullable;
+import com.google.common.base.MoreObjects;
+import com.google.common.base.Objects;
+
+/**
+ * A Neutron Floating IP
+ *
+ */
+public class FloatingIP {
+
+   private String id;
+   @Named("router_id")
+   private String routerId;
+   @Named("tenant_id")
+   private String tenantId;
+   // Only mandatory attribute when creating
+   @Named("floating_network_id")
+   private String floatingNetworkId;
+   @Named("fixed_ip_address")
+   private String fixedIpAddress;
+   @Named("floating_ip_address")
+   private String floatingIpAddress;
+   @Named("port_id")
+   private String portId;
+
+   /**
+    * Deserialization constructor
+    */
+   @ConstructorProperties({"id", "router_id", "tenant_id", "floating_network_id", "fixed_ip_address",
+         "floating_ip_address", "port_id"})
+   private FloatingIP(String id, String routerId, String tenantId, String floatingNetworkId, String fixedIpAddress,
+         String floatingIpAddress, String portId) {
+      this.id = id;
+      this.routerId = routerId;
+      this.tenantId = tenantId;
+      this.floatingNetworkId = floatingNetworkId;
+      this.fixedIpAddress = fixedIpAddress;
+      this.floatingIpAddress = floatingIpAddress;
+      this.portId = portId;
+   }
+
+   private FloatingIP() {}
+
+   /**
+    * @param floatingIP The floating IP to copy from
+    */
+   private FloatingIP(FloatingIP floatingIP) {
+      this(floatingIP.id, floatingIP.routerId, floatingIP.tenantId, floatingIP.floatingNetworkId,
+            floatingIP.fixedIpAddress, floatingIP.floatingIpAddress, floatingIP.portId);
+   }
+
+   /**
+    * @return the id of the floating IP
+    */
+   @Nullable
+   public String getId() {
+      return id;
+   }
+
+   /**
+    * @return the router id of this floating IP
+    */
+   @Nullable
+   public String getRouterId() {
+      return routerId;
+   }
+
+   /**
+    * @return the tenant id of the Floating IP
+    */
+   @Nullable
+   public String getTenantId() {
+      return tenantId;
+   }
+
+   /**
+    * @return the floating network id for this floating IP
+    */
+   @Nullable
+   public String getFloatingNetworkId() {
+      return floatingNetworkId;
+   }
+
+   /**
+    * @return the fixed IP address for this floating IP
+    */
+   @Nullable
+   public String getFixedIpAddress() {
+      return fixedIpAddress;
+   }
+
+   /**
+    * @return the floating IP address for this floating IP
+    */
+   @Nullable
+   public String getFloatingIpAddress() {
+      return floatingIpAddress;
+   }
+
+   /**
+    * @return the port id for this floating IP
+    */
+   @Nullable
+   public String getPortId() {
+      return portId;
+   }
+
+   @Override
+   public boolean equals(Object o) {
+      if (this == o)
+         return true;
+      if (o == null || getClass() != o.getClass())
+         return false;
+
+      FloatingIP that = (FloatingIP) o;
+
+      return Objects.equal(this.id, that.id) &&
+            Objects.equal(this.routerId, that.routerId) &&
+            Objects.equal(this.tenantId, that.tenantId) &&
+            Objects.equal(this.floatingNetworkId, that.floatingNetworkId) &&
+            Objects.equal(this.fixedIpAddress, that.fixedIpAddress) &&
+            Objects.equal(this.floatingIpAddress, that.floatingIpAddress) &&
+            Objects.equal(this.portId, that.portId);
+   }
+
+   @Override
+   public int hashCode() {
+      return Objects.hashCode(id, routerId, tenantId, floatingNetworkId, fixedIpAddress, floatingIpAddress,
+            portId);
+   }
+
+   @Override
+   public String toString() {
+      return MoreObjects.toStringHelper(this)
+            .add("id", id)
+            .add("routerId", routerId)
+            .add("tenantId", tenantId)
+            .add("floatingNetworkId", floatingNetworkId)
+            .add("fixedIpAddress", fixedIpAddress)
+            .add("floatingIpAddress", floatingIpAddress)
+            .add("portId", portId)
+            .toString();
+   }
+
+   /**
+    * @return the Builder for creating a new floating IP
+    */
+   public static CreateBuilder createOptions(String floatingNetworkId) {
+      return new CreateBuilder(floatingNetworkId);
+   }
+
+   /**
+    * @return the Builder for updating a floating IP
+    */
+   public static UpdateBuilder updateOptions() {
+      return new UpdateBuilder();
+   }
+
+   private abstract static class Builder<ParameterizedBuilderType> {
+      protected FloatingIP floatingIP;
+
+      /**
+       * No-parameters constructor.
+       * */
+      private Builder() {
+         floatingIP = new FloatingIP();
+      }
+
+      protected abstract ParameterizedBuilderType self();
+
+      /**
+       * Provide the tenantId for this Floating IP. Admin-only.
+       * When keystone is enabled, it is not mandatory to specify tenant_id for resources in create requests, as the
+       * tenant identifier will be derived from the Authentication token. Please note that the default authorization
+       * settings only allow administrative users to create resources on behalf of a different tenant.
+       *
+       * @return the Builder.
+       * @see FloatingIP#getTenantId()
+       */
+      public ParameterizedBuilderType tenantId(String tenantId) {
+         floatingIP.tenantId = tenantId;
+         return self();
+      }
+
+      /**
+       * Provides the floating network id for this Floating IP.
+       * Mandatory when creating a floating IP.
+       * Floating IPs can only be created on external networks. If the network specified by floating_network_id is not
+       * external (for example, router:external=false), a 400 error is returned.
+       *
+       * @return the Builder.
+       * @see FloatingIP#getFloatingNetworkId() ()
+       */
+      public ParameterizedBuilderType floatingNetworkId(String floatingNetworkId) {
+         floatingIP.floatingNetworkId = floatingNetworkId;
+         return self();
+      }
+
+      /**
+       * Provides the fixed ip address for this Floating IP.
+       * As an OpenStack Networking port might be associated with multiple IP addresses, the particular IP address to
+       * associate with the floating IP can be specified using the fixed_ip_address request body parameter. The default
+       * logic of this operation is to associate the floating IP with a single IP address configured on a port; hence,
+       * if a port has multiple IP addresses, it is mandatory to specify the fixed_ip_address attribute. If an invalid
+       * IP address is specified in fixed_ip_address a 400 error will be returned.
+       *
+       * @return the Builder.
+       * @see FloatingIP#getFixedIpAddress()
+       */
+      public ParameterizedBuilderType fixedIpAddress(String fixedIpAddress) {
+         floatingIP.fixedIpAddress = fixedIpAddress;
+         return self();
+      }
+
+      /**
+       * Provides the port id for this Floating IP.
+       * Users can associate the floating IP with an internal port using the port_id attribute in the request body.
+       * If an invalid port identifier is specified, a 404 error will be returned. The internal OpenStack Networking
+       * port associated with the Floating IP must have at least an IP address configured, otherwise a 400 error will
+       * be returned.
+       *
+       * @return the Builder.
+       * @see FloatingIP#getPortId()
+       */
+      public ParameterizedBuilderType portId(String portId) {
+         floatingIP.portId = portId;
+         return self();
+      }
+   }
+
+   public static class CreateBuilder extends Builder<CreateBuilder> {
+      /**
+       * Supply required properties for creating a Builder
+       */
+      private CreateBuilder(String floatingNetworkId) {
+         floatingIP.floatingNetworkId = floatingNetworkId;
+      }
+
+      /**
+       * @return a CreateOptions constructed with this Builder.
+       */
+      public CreateOptions build() {
+         return new CreateOptions(floatingIP);
+      }
+
+      protected CreateBuilder self() {
+         return this;
+      }
+   }
+
+   public static class UpdateBuilder extends Builder<UpdateBuilder> {
+      /**
+       * Supply required properties for updating a Builder
+       */
+      private UpdateBuilder() {
+      }
+
+      /**
+       * Provide the floating ip address for this Floating IP.
+       * An address for the floating ip will be automatically allocated, unless the floating_ip_address attribute is
+       * specified in the request body. If the requested floating IP address does not fall in the external network's
+       * subnet range, a 400 error will be returned. If the requested floating IP address is already in use, a 409
+       * error code will be returned.
+       *
+       * @return the Builder.
+       * @see FloatingIP#getFloatingIpAddress()
+       */
+      public UpdateBuilder floatingIpAddress(String floatingIpAddress) {
+         floatingIP.floatingIpAddress = floatingIpAddress;
+         return this;
+      }
+
+      /**
+       * @return a UpdateOptions constructed with this Builder.
+       */
+      public UpdateOptions build() {
+         return new UpdateOptions(floatingIP);
+      }
+
+      protected UpdateBuilder self() {
+         return this;
+      }
+   }
+
+   public static class CreateOptions extends FloatingIP {
+      private CreateOptions(FloatingIP floatingIP) {
+         super(floatingIP);
+      }
+   }
+   public static class UpdateOptions extends FloatingIP {
+      private UpdateOptions(FloatingIP floatingIP) {
+         super(floatingIP);
+      }
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/e7a52c1a/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/FloatingIPs.java
----------------------------------------------------------------------
diff --git a/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/FloatingIPs.java b/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/FloatingIPs.java
new file mode 100644
index 0000000..8befa3e
--- /dev/null
+++ b/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/FloatingIPs.java
@@ -0,0 +1,36 @@
+/*
+ * 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.openstack.neutron.v2.domain;
+
+import java.beans.ConstructorProperties;
+
+import org.jclouds.openstack.v2_0.domain.Link;
+import org.jclouds.openstack.v2_0.domain.PaginatedCollection;
+
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * A collection of Floating IPs
+ */
+public class FloatingIPs extends PaginatedCollection<FloatingIP> {
+   public static final FloatingIPs EMPTY = new FloatingIPs(ImmutableSet.<FloatingIP> of(), ImmutableSet.<Link> of());
+
+   @ConstructorProperties({"floatingips", "floatingips_links"})
+   protected FloatingIPs(Iterable<FloatingIP> floatingIPs, Iterable<Link> floatingIPsLinks) {
+      super(floatingIPs, floatingIPsLinks);
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/e7a52c1a/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/Networks.java
----------------------------------------------------------------------
diff --git a/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/Networks.java b/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/Networks.java
index 45f6c56..9b3bf10 100644
--- a/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/Networks.java
+++ b/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/Networks.java
@@ -16,11 +16,12 @@
  */
 package org.jclouds.openstack.neutron.v2.domain;
 
-import com.google.common.collect.ImmutableSet;
+import java.beans.ConstructorProperties;
+
 import org.jclouds.openstack.v2_0.domain.Link;
 import org.jclouds.openstack.v2_0.domain.PaginatedCollection;
 
-import java.beans.ConstructorProperties;
+import com.google.common.collect.ImmutableSet;
 
 /**
  * A collection of Networks
@@ -28,7 +29,7 @@ import java.beans.ConstructorProperties;
 public class Networks extends PaginatedCollection<Network> {
    public static final Networks EMPTY = new Networks(ImmutableSet.<Network> of(), ImmutableSet.<Link> of());
 
-   @ConstructorProperties({ "networks", "networks_links" })
+   @ConstructorProperties({"networks", "networks_links"})
    protected Networks(Iterable<Network> networks, Iterable<Link> networksLinks) {
       super(networks, networksLinks);
    }

http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/e7a52c1a/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/Ports.java
----------------------------------------------------------------------
diff --git a/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/Ports.java b/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/Ports.java
index f7a6d5d..8cf449b 100644
--- a/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/Ports.java
+++ b/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/Ports.java
@@ -16,19 +16,20 @@
  */
 package org.jclouds.openstack.neutron.v2.domain;
 
-import com.google.common.collect.ImmutableSet;
+import java.beans.ConstructorProperties;
+
 import org.jclouds.openstack.v2_0.domain.Link;
 import org.jclouds.openstack.v2_0.domain.PaginatedCollection;
 
-import java.beans.ConstructorProperties;
+import com.google.common.collect.ImmutableSet;
 
 /**
- * A collection of Networks
+ * A collection of Ports
  */
 public class Ports extends PaginatedCollection<Port> {
    public static final Ports EMPTY = new Ports(ImmutableSet.<Port> of(), ImmutableSet.<Link> of());
 
-   @ConstructorProperties({ "ports", "ports_links" })
+   @ConstructorProperties({"ports", "ports_links"})
    protected Ports(Iterable<Port> ports, Iterable<Link> portsLinks) {
       super(ports, portsLinks);
    }

http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/e7a52c1a/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/Routers.java
----------------------------------------------------------------------
diff --git a/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/Routers.java b/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/Routers.java
index 8f926bf..c02c382 100644
--- a/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/Routers.java
+++ b/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/Routers.java
@@ -16,19 +16,20 @@
  */
 package org.jclouds.openstack.neutron.v2.domain;
 
-import com.google.common.collect.ImmutableSet;
+import java.beans.ConstructorProperties;
+
 import org.jclouds.openstack.v2_0.domain.Link;
 import org.jclouds.openstack.v2_0.domain.PaginatedCollection;
 
-import java.beans.ConstructorProperties;
+import com.google.common.collect.ImmutableSet;
 
 /**
- * A collection of Networks
+ * A collection of Routers
  */
 public class Routers extends PaginatedCollection<Router> {
    public static final Routers EMPTY = new Routers(ImmutableSet.<Router> of(), ImmutableSet.<Link> of());
 
-   @ConstructorProperties({ "routers", "routers_links" })
+   @ConstructorProperties({"routers", "routers_links"})
    protected Routers(Iterable<Router> routers, Iterable<Link> routersLinks) {
       super(routers, routersLinks);
    }

http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/e7a52c1a/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/Subnets.java
----------------------------------------------------------------------
diff --git a/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/Subnets.java b/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/Subnets.java
index ac36a2b..fb9896e 100644
--- a/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/Subnets.java
+++ b/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/Subnets.java
@@ -16,19 +16,20 @@
  */
 package org.jclouds.openstack.neutron.v2.domain;
 
-import com.google.common.collect.ImmutableSet;
+import java.beans.ConstructorProperties;
+
 import org.jclouds.openstack.v2_0.domain.Link;
 import org.jclouds.openstack.v2_0.domain.PaginatedCollection;
 
-import java.beans.ConstructorProperties;
+import com.google.common.collect.ImmutableSet;
 
 /**
- * A collection of Networks
+ * A collection of Subnets
  */
 public class Subnets extends PaginatedCollection<Subnet> {
    public static final Subnets EMPTY = new Subnets(ImmutableSet.<Subnet> of(), ImmutableSet.<Link> of());
 
-   @ConstructorProperties({ "subnets", "subnets_links" })
+   @ConstructorProperties({"subnets", "subnets_links"})
    protected Subnets(Iterable<Subnet> subnets, Iterable<Link> subnetsLinks) {
       super(subnets, subnetsLinks);
    }

http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/e7a52c1a/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/extensions/FloatingIPApi.java
----------------------------------------------------------------------
diff --git a/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/extensions/FloatingIPApi.java b/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/extensions/FloatingIPApi.java
new file mode 100644
index 0000000..5565668
--- /dev/null
+++ b/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/extensions/FloatingIPApi.java
@@ -0,0 +1,138 @@
+/*
+ * 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.openstack.neutron.v2.extensions;
+
+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.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.Fallbacks.EmptyPagedIterableOnNotFoundOr404;
+import org.jclouds.Fallbacks.FalseOnNotFoundOr404;
+import org.jclouds.Fallbacks.NullOnNotFoundOr404;
+import org.jclouds.collect.PagedIterable;
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
+import org.jclouds.openstack.neutron.v2.domain.FloatingIP;
+import org.jclouds.openstack.neutron.v2.domain.FloatingIPs;
+import org.jclouds.openstack.neutron.v2.fallbacks.EmptyFloatingIPsFallback;
+import org.jclouds.openstack.neutron.v2.functions.FloatingIPsToPagedIterable;
+import org.jclouds.openstack.neutron.v2.functions.ParseFloatingIPs;
+import org.jclouds.openstack.v2_0.options.PaginationOptions;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.ResponseParser;
+import org.jclouds.rest.annotations.SelectJson;
+import org.jclouds.rest.annotations.Transform;
+import org.jclouds.rest.annotations.WrapWith;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * Provides access to Floating IP operations for the OpenStack Networking (Neutron) v2 API.
+ * <p/>
+ * A floating IP is an IP address on an external network, which is associated with a specific port, and optionally a
+ * specific IP address, on a private OpenStack Networking network. Therefore a floating IP allows access to an
+ * instance on a private network from an external network. Floating IPs can only be defined on networks for which the
+ * attribute floatingip:external (by the external network extension) has been set to True.
+ */
+@Beta
+@Path("/floatingips")
+@RequestFilters(AuthenticateRequest.class)
+@Consumes(MediaType.APPLICATION_JSON)
+public interface FloatingIPApi {
+
+   /**
+    * Returns a list of floating IPs to which the tenant has access. Default policy settings return only
+    * those floating IPs that are owned by the tenant who submits the request, unless the request is submitted by an
+    * user with administrative rights.
+    *
+    * @return the list of all floatingIP references configured for the tenant.
+    */
+   @Named("floatingip:list")
+   @GET
+   @Transform(FloatingIPsToPagedIterable.class)
+   @ResponseParser(ParseFloatingIPs.class)
+   @Fallback(EmptyPagedIterableOnNotFoundOr404.class)
+   PagedIterable<FloatingIP> list();
+
+   /**
+    * @return the list of all floatingIP references configured for the tenant.
+    */
+   @Named("floatingip:list")
+   @GET
+   @ResponseParser(ParseFloatingIPs.class)
+   @Fallback(EmptyFloatingIPsFallback.class)
+   FloatingIPs list(PaginationOptions options);
+
+   /**
+    * Returns the details for a specific floating IP.
+    *
+    * @param id the id of the floatingIP to return
+    * @return FloatingIPs collection or empty if not found
+    */
+   @Named("floatingip:get")
+   @GET
+   @Path("/{id}")
+   @SelectJson("floatingip")
+   @Fallback(NullOnNotFoundOr404.class)
+   @Nullable
+   FloatingIP get(@PathParam("id") String id);
+
+   /**
+    * Creates a floating IP.
+    *
+    * @param createOptions Options for creating a Floating IP
+    * @return the newly created Floating IP
+    */
+   @Named("floatingip:create")
+   @POST
+   @SelectJson("floatingip")
+   FloatingIP create(@WrapWith("floatingip") FloatingIP.CreateOptions createOptions);
+
+   /**
+    * Update a Floating IP
+    *
+    * @param id the id of the Floating IP to update
+    * @param updateOptions Contains only the attributes to update
+    * @return The modified Floating IP
+    */
+   @Named("floatingip:update")
+   @PUT
+   @Path("/{id}")
+   @SelectJson("floatingip")
+   @Fallback(NullOnNotFoundOr404.class)
+   @Nullable
+   FloatingIP update(@PathParam("id") String id, @WrapWith("floatingip") FloatingIP.UpdateOptions updateOptions);
+
+   /**
+    * Deletes the specified floatingIP
+    *
+    * @param id the id of the floatingIP to delete
+    * @return true if delete successful, false if not
+    */
+   @Named("floatingip:delete")
+   @DELETE
+   @Path("/{id}")
+   @Fallback(FalseOnNotFoundOr404.class)
+   boolean delete(@PathParam("id") String id);
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/e7a52c1a/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/fallbacks/EmptyFloatingIPsFallback.java
----------------------------------------------------------------------
diff --git a/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/fallbacks/EmptyFloatingIPsFallback.java b/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/fallbacks/EmptyFloatingIPsFallback.java
new file mode 100644
index 0000000..b9b03c4
--- /dev/null
+++ b/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/fallbacks/EmptyFloatingIPsFallback.java
@@ -0,0 +1,45 @@
+/*
+ * 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.openstack.neutron.v2.fallbacks;
+
+import com.google.common.util.concurrent.ListenableFuture;
+import org.jclouds.Fallback;
+import org.jclouds.openstack.neutron.v2.domain.FloatingIPs;
+import org.jclouds.rest.ResourceNotFoundException;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Throwables.propagate;
+import static com.google.common.util.concurrent.Futures.immediateFuture;
+import static org.jclouds.http.HttpUtils.contains404;
+import static org.jclouds.util.Throwables2.getFirstThrowableOfType;
+
+public class EmptyFloatingIPsFallback implements Fallback<FloatingIPs> {
+
+   public ListenableFuture<FloatingIPs> create(Throwable t) throws Exception {
+      return immediateFuture(createOrPropagate(t));
+   }
+
+   @Override
+   public FloatingIPs createOrPropagate(Throwable t) throws Exception {
+      if ((getFirstThrowableOfType(checkNotNull(t, "throwable"), ResourceNotFoundException.class) != null)
+            || contains404(t)) {
+         return FloatingIPs.EMPTY;
+      }
+      throw propagate(t);
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/e7a52c1a/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/functions/FloatingIPsToPagedIterable.java
----------------------------------------------------------------------
diff --git a/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/functions/FloatingIPsToPagedIterable.java b/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/functions/FloatingIPsToPagedIterable.java
new file mode 100644
index 0000000..4d54d1f
--- /dev/null
+++ b/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/functions/FloatingIPsToPagedIterable.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.openstack.neutron.v2.functions;
+
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import org.jclouds.collect.IterableWithMarker;
+import org.jclouds.collect.internal.Arg0ToPagedIterable;
+import org.jclouds.openstack.neutron.v2.NeutronApi;
+import org.jclouds.openstack.neutron.v2.domain.FloatingIP;
+import org.jclouds.openstack.neutron.v2.extensions.FloatingIPApi;
+import org.jclouds.openstack.v2_0.options.PaginationOptions;
+
+import javax.inject.Inject;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Ensures Floating IPs works as PagedIterable.
+ */
+public class FloatingIPsToPagedIterable extends Arg0ToPagedIterable.FromCaller<FloatingIP, FloatingIPsToPagedIterable> {
+
+   private final NeutronApi api;
+
+   @Inject
+   protected FloatingIPsToPagedIterable(NeutronApi api) {
+      this.api = checkNotNull(api, "api");
+   }
+
+   @Override
+   protected Function<Object, IterableWithMarker<FloatingIP>> markerToNextForArg0(Optional<Object> arg0) {
+      String region = arg0.isPresent() ? arg0.get().toString() : null;
+      final FloatingIPApi floatingIPApi = api.getFloatingIPApi(region).get();
+      return new Function<Object, IterableWithMarker<FloatingIP>>() {
+
+         @SuppressWarnings("unchecked")
+         @Override
+         public IterableWithMarker<FloatingIP> apply(Object input) {
+            PaginationOptions paginationOptions = PaginationOptions.class.cast(input);
+            return IterableWithMarker.class.cast(floatingIPApi.list(paginationOptions));
+         }
+
+         @Override
+         public String toString() {
+            return "listfloatingIPs()";
+         }
+      };
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/e7a52c1a/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/functions/ParseFloatingIPs.java
----------------------------------------------------------------------
diff --git a/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/functions/ParseFloatingIPs.java b/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/functions/ParseFloatingIPs.java
new file mode 100644
index 0000000..6529627
--- /dev/null
+++ b/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/functions/ParseFloatingIPs.java
@@ -0,0 +1,37 @@
+/*
+ * 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.openstack.neutron.v2.functions;
+
+import com.google.inject.TypeLiteral;
+import org.jclouds.http.functions.ParseJson;
+import org.jclouds.json.Json;
+import org.jclouds.openstack.neutron.v2.domain.FloatingIPs;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/**
+ * Used by jclouds to provide more specific collections and fallbacks.
+ */
+@Singleton
+public class ParseFloatingIPs extends ParseJson<FloatingIPs> {
+
+   @Inject
+   public ParseFloatingIPs(Json json) {
+      super(json, TypeLiteral.get(FloatingIPs.class));
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/e7a52c1a/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/functions/RouterToPagedIterable.java
----------------------------------------------------------------------
diff --git a/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/functions/RouterToPagedIterable.java b/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/functions/RouterToPagedIterable.java
index dabe293..5ce4def 100644
--- a/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/functions/RouterToPagedIterable.java
+++ b/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/functions/RouterToPagedIterable.java
@@ -16,8 +16,10 @@
  */
 package org.jclouds.openstack.neutron.v2.functions;
 
-import com.google.common.base.Function;
-import com.google.common.base.Optional;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import javax.inject.Inject;
+
 import org.jclouds.collect.IterableWithMarker;
 import org.jclouds.collect.internal.Arg0ToPagedIterable;
 import org.jclouds.openstack.neutron.v2.NeutronApi;
@@ -25,9 +27,8 @@ import org.jclouds.openstack.neutron.v2.domain.Router;
 import org.jclouds.openstack.neutron.v2.extensions.RouterApi;
 import org.jclouds.openstack.v2_0.options.PaginationOptions;
 
-import javax.inject.Inject;
-
-import static com.google.common.base.Preconditions.checkNotNull;
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
 
 /**
  * Ensures Routers works as PagedIterable.
@@ -44,7 +45,7 @@ public class RouterToPagedIterable extends Arg0ToPagedIterable.FromCaller<Router
    @Override
    protected Function<Object, IterableWithMarker<Router>> markerToNextForArg0(Optional<Object> arg0) {
       String region = arg0.isPresent() ? arg0.get().toString() : null;
-      final RouterApi routerApi = api.getRouterExtensionApi(region).get();
+      final RouterApi routerApi = api.getRouterApi(region).get();
       return new Function<Object, IterableWithMarker<Router>>() {
 
          @SuppressWarnings("unchecked")

http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/e7a52c1a/openstack-neutron/src/test/java/org/jclouds/openstack/neutron/v2/extensions/FloatingIPApiLiveTest.java
----------------------------------------------------------------------
diff --git a/openstack-neutron/src/test/java/org/jclouds/openstack/neutron/v2/extensions/FloatingIPApiLiveTest.java b/openstack-neutron/src/test/java/org/jclouds/openstack/neutron/v2/extensions/FloatingIPApiLiveTest.java
new file mode 100644
index 0000000..dd3dd8d
--- /dev/null
+++ b/openstack-neutron/src/test/java/org/jclouds/openstack/neutron/v2/extensions/FloatingIPApiLiveTest.java
@@ -0,0 +1,92 @@
+/*
+ * 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.openstack.neutron.v2.extensions;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+
+import java.util.Set;
+
+import org.jclouds.openstack.neutron.v2.domain.FloatingIP;
+import org.jclouds.openstack.neutron.v2.domain.IP;
+import org.jclouds.openstack.neutron.v2.domain.Network;
+import org.jclouds.openstack.neutron.v2.domain.NetworkType;
+import org.jclouds.openstack.neutron.v2.domain.Subnet;
+import org.jclouds.openstack.neutron.v2.features.NetworkApi;
+import org.jclouds.openstack.neutron.v2.features.SubnetApi;
+import org.jclouds.openstack.neutron.v2.internal.BaseNeutronApiLiveTest;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * Tests parsing and Guice wiring of RouterApi
+ */
+@Test(groups = "live", testName = "FloatingIPApiLiveTest")
+public class FloatingIPApiLiveTest extends BaseNeutronApiLiveTest {
+
+   public void testCreateUpdateAndDeleteFloatingIP() {
+      for (String region : api.getConfiguredRegions()) {
+
+         SubnetApi subnetApi = api.getSubnetApi(region);
+         FloatingIPApi floatingIPApi = api.getFloatingIPApi(region).get();
+         NetworkApi networkApi = api.getNetworkApi(region);
+
+         FloatingIP floatingIPGet = null;
+         String ipv4SubnetId = null;
+         Network network = null;
+
+         try {
+            network = networkApi.create(
+                  Network.createOptions("jclouds-network-test").external(true).networkType(NetworkType.LOCAL).build());
+            assertNotNull(network);
+
+            ipv4SubnetId = subnetApi.create(Subnet.createOptions(network.getId(), "198.51.100.0/24").ipVersion(4)
+                  .name("JClouds-Live-IPv4-Subnet").build()).getId();
+
+            floatingIPApi.create(FloatingIP.createOptions(network.getId()).build());
+
+            /* List and Get test */
+            Set<FloatingIP> floatingIPs = floatingIPApi.list().concat().toSet();
+            FloatingIP floatingIPList = floatingIPs.iterator().next();
+            floatingIPGet = floatingIPApi.get(floatingIPList.getId());
+
+            assertNotNull(floatingIPGet);
+            assertEquals(floatingIPGet, floatingIPList);
+         }
+         finally {
+            try {
+               assertTrue(floatingIPApi.delete(floatingIPGet.getId()));
+            }
+            finally {
+               try {
+                  assertTrue(subnetApi.delete(ipv4SubnetId));
+               }
+               finally {
+                  assertTrue(networkApi.delete(network.getId()));
+               }
+            }
+         }
+      }
+   }
+
+   public Set<IP> getFixedAddresses(String subnetId) {
+      return ImmutableSet.of(IP.builder().subnetId(subnetId).build());
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/e7a52c1a/openstack-neutron/src/test/java/org/jclouds/openstack/neutron/v2/extensions/FloatingIPApiMockTest.java
----------------------------------------------------------------------
diff --git a/openstack-neutron/src/test/java/org/jclouds/openstack/neutron/v2/extensions/FloatingIPApiMockTest.java b/openstack-neutron/src/test/java/org/jclouds/openstack/neutron/v2/extensions/FloatingIPApiMockTest.java
new file mode 100644
index 0000000..6187cd3
--- /dev/null
+++ b/openstack-neutron/src/test/java/org/jclouds/openstack/neutron/v2/extensions/FloatingIPApiMockTest.java
@@ -0,0 +1,436 @@
+/*
+ * 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.openstack.neutron.v2.extensions;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.util.List;
+
+import org.jclouds.openstack.neutron.v2.NeutronApi;
+import org.jclouds.openstack.neutron.v2.domain.FloatingIP;
+import org.jclouds.openstack.neutron.v2.domain.FloatingIPs;
+import org.jclouds.openstack.neutron.v2.internal.BaseNeutronApiMockTest;
+import org.jclouds.openstack.v2_0.options.PaginationOptions;
+import org.jclouds.rest.ResourceNotFoundException;
+import org.testng.annotations.Test;
+
+import com.squareup.okhttp.mockwebserver.MockResponse;
+import com.squareup.okhttp.mockwebserver.MockWebServer;
+
+/**
+ * Tests Floating Api Guice wiring and parsing
+ *
+ */
+@Test
+public class FloatingIPApiMockTest extends BaseNeutronApiMockTest {
+
+   public void testCreateFloatingIP() throws IOException, InterruptedException, URISyntaxException {
+      MockWebServer server = mockOpenStackServer();
+      server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
+      server.enqueue(addCommonHeaders(
+            new MockResponse().setResponseCode(201).setBody(stringFromResource("/floatingip_create_response.json"))));
+
+      try {
+         NeutronApi neutronApi = api(server.getUrl("/").toString(), "openstack-neutron", overrides);
+         FloatingIPApi api = neutronApi.getFloatingIPApi("RegionOne").get();
+
+         FloatingIP.CreateOptions createFip = FloatingIP.createOptions("376da547-b977-4cfe-9cba-275c80debf57")
+               .portId("ce705c24-c1ef-408a-bda3-7bbd946164ab")
+               .build();
+
+         FloatingIP floatingIP = api.create(createFip);
+
+         /*
+          * Check request
+          */
+         assertAuthentication(server);
+         assertRequest(server.takeRequest(), "POST", "/v2.0/floatingips", "/floatingip_create_request.json");
+
+         /*
+          * Check response
+          */
+         assertNotNull(floatingIP);
+         assertEquals(floatingIP.getRouterId(), "d23abc8d-2991-4a55-ba98-2aaea84cc72f");
+         assertEquals(floatingIP.getTenantId(), "4969c491a3c74ee4af974e6d800c62de");
+         assertEquals(floatingIP.getFloatingNetworkId(), "376da547-b977-4cfe-9cba-275c80debf57");
+         assertEquals(floatingIP.getFixedIpAddress(), "10.0.0.3");
+         assertEquals(floatingIP.getFloatingIpAddress(), "172.24.4.228");
+         assertEquals(floatingIP.getPortId(), "ce705c24-c1ef-408a-bda3-7bbd946164ab");
+         assertEquals(floatingIP.getId(), "2f245a7b-796b-4f26-9cf9-9e82d248fda7");
+
+      } finally {
+         server.shutdown();
+      }
+   }
+
+   @Test(expectedExceptions = ResourceNotFoundException.class)
+   public void testCreateFloatingIPFail() throws IOException, InterruptedException, URISyntaxException {
+      MockWebServer server = mockOpenStackServer();
+      server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
+      server.enqueue(addCommonHeaders(
+            new MockResponse().setResponseCode(404)));
+
+      try {
+         NeutronApi neutronApi = api(server.getUrl("/").toString(), "openstack-neutron", overrides);
+         FloatingIPApi api = neutronApi.getFloatingIPApi("RegionOne").get();
+
+         FloatingIP.CreateOptions createFip = FloatingIP.createOptions("376da547-b977-4cfe-9cba-275c80debf57")
+               .portId("ce705c24-c1ef-408a-bda3-7bbd946164ab")
+               .build();
+
+         FloatingIP floatingIP = api.create(createFip);
+      } finally {
+         server.shutdown();
+      }
+   }
+
+   public void testListSpecificPageFloatingIP() throws IOException, InterruptedException, URISyntaxException {
+      MockWebServer server = mockOpenStackServer();
+      server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
+      server.enqueue(addCommonHeaders(new MockResponse().setResponseCode(200).setBody(stringFromResource("/floatingip_list_response_paged1.json"))));
+
+      try {
+         NeutronApi neutronApi = api(server.getUrl("/").toString(), "openstack-neutron", overrides);
+         FloatingIPApi api = neutronApi.getFloatingIPApi("RegionOne").get();
+
+         FloatingIPs floatingIPs = api.list(PaginationOptions.Builder.limit(2).marker("abcdefg"));
+
+         /*
+          * Check request
+          */
+         assertAuthentication(server);
+         assertRequest(server.takeRequest(), "GET", "/v2.0/floatingips?limit=2&marker=abcdefg");
+
+         /*
+          * Check response
+          */
+         assertNotNull(floatingIPs);
+         assertEquals(floatingIPs.size(), 2);
+         assertEquals(floatingIPs.first().get().getId(), "2f245a7b-796b-4f26-9cf9-9e82d248fda7");
+         assertEquals(floatingIPs.get(1).getId(), "61cea855-49cb-4846-997d-801b70c71bdd");
+      } finally {
+         server.shutdown();
+      }
+   }
+
+   public void testListSpecificPageFloatingIPFail() throws IOException, InterruptedException, URISyntaxException {
+      MockWebServer server = mockOpenStackServer();
+      server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
+      server.enqueue(addCommonHeaders(new MockResponse().setResponseCode(404)));
+
+      try {
+         NeutronApi neutronApi = api(server.getUrl("/").toString(), "openstack-neutron", overrides);
+         FloatingIPApi api = neutronApi.getFloatingIPApi("RegionOne").get();
+
+         FloatingIPs floatingIPs = api.list(PaginationOptions.Builder.limit(2).marker("abcdefg"));
+
+         /*
+          * Check request
+          */
+         assertAuthentication(server);
+         assertRequest(server.takeRequest(), "GET", "/v2.0/floatingips?limit=2&marker=abcdefg");
+
+         /*
+          * Check response
+          */
+         assertNotNull(floatingIPs);
+         assertTrue(floatingIPs.isEmpty());
+      } finally {
+         server.shutdown();
+      }
+   }
+
+   public void testListPagedFloatingIP() throws IOException, InterruptedException, URISyntaxException {
+      MockWebServer server = mockOpenStackServer();
+      server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
+      server.enqueue(addCommonHeaders(new MockResponse().setResponseCode(200).setBody(stringFromResource("/floatingip_list_response_paged1.json"))));
+      server.enqueue(addCommonHeaders(new MockResponse().setResponseCode(200).setBody(stringFromResource("/floatingip_list_response_paged2.json"))));
+
+      try {
+         NeutronApi neutronApi = api(server.getUrl("/").toString(), "openstack-neutron", overrides);
+         FloatingIPApi api = neutronApi.getFloatingIPApi("RegionOne").get();
+
+         // Note: Lazy! Have to actually look at the collection.
+         List<FloatingIP> floatingIPs = api.list().concat().toList();
+
+         /*
+          * Check request
+          */
+         assertEquals(server.getRequestCount(), 3);
+         assertAuthentication(server);
+         assertRequest(server.takeRequest(), "GET", "/v2.0/floatingips");
+         assertRequest(server.takeRequest(), "GET", "/v2.0/floatingips?marker=71c1e68c-171a-4aa2-aca5-50ea153a3718");
+
+         /*
+          * Check response
+          */
+         assertNotNull(floatingIPs);
+         assertEquals(floatingIPs.size(), 4);
+         assertEquals(floatingIPs.get(0).getId(), "2f245a7b-796b-4f26-9cf9-9e82d248fda7");
+         assertEquals(floatingIPs.get(3).getId(), "61cea855-49cb-4846-997d-801b70c71bdd2");
+      } finally {
+         server.shutdown();
+      }
+   }
+
+   public void testListPagedFloatingIPFail() throws IOException, InterruptedException, URISyntaxException {
+      MockWebServer server = mockOpenStackServer();
+      server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
+      server.enqueue(addCommonHeaders(new MockResponse().setResponseCode(404)));
+
+      try {
+         NeutronApi neutronApi = api(server.getUrl("/").toString(), "openstack-neutron", overrides);
+         FloatingIPApi api = neutronApi.getFloatingIPApi("RegionOne").get();
+
+         // Note: Lazy! Have to actually look at the collection.
+         List<FloatingIP> floatingIPs = api.list().concat().toList();
+
+         /*
+          * Check request
+          */
+         assertEquals(server.getRequestCount(), 2);
+         assertAuthentication(server);
+         assertRequest(server.takeRequest(), "GET", "/v2.0/floatingips");
+
+         /*
+          * Check response
+          */
+         assertNotNull(floatingIPs);
+         assertTrue(floatingIPs.isEmpty());
+      } finally {
+         server.shutdown();
+      }
+   }
+
+   public void testGetFloatingIP() throws IOException, InterruptedException, URISyntaxException {
+      MockWebServer server = mockOpenStackServer();
+      server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
+      server.enqueue(addCommonHeaders(
+            new MockResponse().setResponseCode(201).setBody(stringFromResource("/floatingip_get_response.json"))));
+
+      try {
+         NeutronApi neutronApi = api(server.getUrl("/").toString(), "openstack-neutron", overrides);
+         FloatingIPApi api = neutronApi.getFloatingIPApi("RegionOne").get();
+
+         FloatingIP floatingIP = api.get("12345");
+
+         /*
+          * Check request
+          */
+         assertAuthentication(server);
+         assertRequest(server.takeRequest(), "GET", "/v2.0/floatingips/12345");
+
+         /*
+          * Check response
+          */
+         assertNotNull(floatingIP);
+         assertEquals(floatingIP.getId(), "2f245a7b-796b-4f26-9cf9-9e82d248fda7");
+         assertEquals(floatingIP.getPortId(), "ce705c24-c1ef-408a-bda3-7bbd946164ab");
+         assertEquals(floatingIP.getFloatingIpAddress(), "172.24.4.228");
+         assertEquals(floatingIP.getFixedIpAddress(), "10.0.0.3");
+         assertEquals(floatingIP.getFloatingNetworkId(), "376da547-b977-4cfe-9cba-275c80debf57");
+         assertEquals(floatingIP.getRouterId(), "d23abc8d-2991-4a55-ba98-2aaea84cc72f");
+         assertEquals(floatingIP.getTenantId(), "4969c491a3c74ee4af974e6d800c62de");
+
+      } finally {
+         server.shutdown();
+      }
+   }
+
+   public void testGetFloatingIPFail() throws IOException, InterruptedException, URISyntaxException {
+      MockWebServer server = mockOpenStackServer();
+      server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
+      server.enqueue(addCommonHeaders(
+            new MockResponse().setResponseCode(404)));
+
+      try {
+         NeutronApi neutronApi = api(server.getUrl("/").toString(), "openstack-neutron", overrides);
+         FloatingIPApi api = neutronApi.getFloatingIPApi("RegionOne").get();
+
+         FloatingIP floatingIP = api.get("12345");
+
+         /*
+          * Check request
+          */
+         assertAuthentication(server);
+         assertRequest(server.takeRequest(), "GET", "/v2.0/floatingips/12345");
+
+         /*
+          * Check response
+          */
+         assertNull(floatingIP);
+
+      } finally {
+         server.shutdown();
+      }
+   }
+
+   public void testUpdateFloatingIP() throws IOException, InterruptedException, URISyntaxException {
+      MockWebServer server = mockOpenStackServer();
+      server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
+      server.enqueue(addCommonHeaders(
+            new MockResponse().setResponseCode(201).setBody(stringFromResource("/floatingip_update_response.json"))));
+
+      try {
+         NeutronApi neutronApi = api(server.getUrl("/").toString(), "openstack-neutron", overrides);
+         FloatingIPApi api = neutronApi.getFloatingIPApi("RegionOne").get();
+
+         FloatingIP.UpdateOptions updateOptions = FloatingIP.updateOptions()
+               .portId("fc861431-0e6c-4842-a0ed-e2363f9bc3a8")
+               .build();
+
+         FloatingIP floatingIP = api.update("12345", updateOptions);
+
+         /*
+          * Check request
+          */
+         assertAuthentication(server);
+         assertRequest(server.takeRequest(), "PUT", "/v2.0/floatingips/12345", "/floatingip_update_request.json");
+
+         /*
+          * Check response
+          */
+         assertNotNull(floatingIP);
+         assertEquals(floatingIP.getPortId(), "fc861431-0e6c-4842-a0ed-e2363f9bc3a8");
+
+      } finally {
+         server.shutdown();
+      }
+   }
+
+   public void testUpdateFloatingIPDissociate() throws IOException, InterruptedException, URISyntaxException {
+      MockWebServer server = mockOpenStackServer();
+      server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
+      server.enqueue(addCommonHeaders(
+            new MockResponse().setResponseCode(201).setBody(stringFromResource("/floatingip_update_dissociate_response.json"))));
+
+      try {
+         NeutronApi neutronApi = api(server.getUrl("/").toString(), "openstack-neutron", overrides);
+         FloatingIPApi api = neutronApi.getFloatingIPApi("RegionOne").get();
+
+         FloatingIP.UpdateOptions updateOptions = FloatingIP.updateOptions().build();
+
+         FloatingIP floatingIP = api.update("12345", updateOptions);
+
+         /*
+          * Check request
+          */
+         assertAuthentication(server);
+         assertRequest(server.takeRequest(), "PUT", "/v2.0/floatingips/12345", "/floatingip_update_dissociate_request.json");
+
+         /*
+          * Check response
+          */
+         assertNotNull(floatingIP);
+         assertNull(floatingIP.getPortId());
+
+      } finally {
+         server.shutdown();
+      }
+   }
+
+   public void testUpdateFloatingIPFail() throws IOException, InterruptedException, URISyntaxException {
+      MockWebServer server = mockOpenStackServer();
+      server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
+      server.enqueue(addCommonHeaders(
+            new MockResponse().setResponseCode(404)));
+
+      try {
+         NeutronApi neutronApi = api(server.getUrl("/").toString(), "openstack-neutron", overrides);
+         FloatingIPApi api = neutronApi.getFloatingIPApi("RegionOne").get();
+
+         FloatingIP.UpdateOptions updateOptions = FloatingIP.updateOptions()
+               .portId("fc861431-0e6c-4842-a0ed-e2363f9bc3a8")
+               .build();
+
+         FloatingIP floatingIP = api.update("12345", updateOptions);
+
+         /*
+          * Check request
+          */
+         assertAuthentication(server);
+         assertRequest(server.takeRequest(), "PUT", "/v2.0/floatingips/12345", "/floatingip_update_request.json");
+
+         /*
+          * Check response
+          */
+         assertNull(floatingIP);
+      } finally {
+         server.shutdown();
+      }
+   }
+
+   public void testDeleteFloatingIP() throws IOException, InterruptedException, URISyntaxException {
+      MockWebServer server = mockOpenStackServer();
+      server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
+      server.enqueue(addCommonHeaders(
+            new MockResponse().setResponseCode(201)));
+
+      try {
+         NeutronApi neutronApi = api(server.getUrl("/").toString(), "openstack-neutron", overrides);
+         FloatingIPApi api = neutronApi.getFloatingIPApi("RegionOne").get();
+
+         boolean result = api.delete("12345");
+
+         /*
+          * Check request
+          */
+         assertAuthentication(server);
+         assertRequest(server.takeRequest(), "DELETE", "/v2.0/floatingips/12345");
+
+         /*
+          * Check response
+          */
+         assertTrue(result);
+      } finally {
+         server.shutdown();
+      }
+   }
+
+   public void testDeleteFloatingIPFail() throws IOException, InterruptedException, URISyntaxException {
+      MockWebServer server = mockOpenStackServer();
+      server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
+      server.enqueue(addCommonHeaders(
+            new MockResponse().setResponseCode(404)));
+
+      try {
+         NeutronApi neutronApi = api(server.getUrl("/").toString(), "openstack-neutron", overrides);
+         FloatingIPApi api = neutronApi.getFloatingIPApi("RegionOne").get();
+
+         boolean result = api.delete("12345");
+
+         /*
+          * Check request
+          */
+         assertAuthentication(server);
+         assertRequest(server.takeRequest(), "DELETE", "/v2.0/floatingips/12345");
+
+         /*
+          * Check response
+          */
+         assertFalse(result);
+      } finally {
+         server.shutdown();
+      }
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/e7a52c1a/openstack-neutron/src/test/java/org/jclouds/openstack/neutron/v2/extensions/RouterApiLiveTest.java
----------------------------------------------------------------------
diff --git a/openstack-neutron/src/test/java/org/jclouds/openstack/neutron/v2/extensions/RouterApiLiveTest.java b/openstack-neutron/src/test/java/org/jclouds/openstack/neutron/v2/extensions/RouterApiLiveTest.java
index 5f06195..050dc72 100644
--- a/openstack-neutron/src/test/java/org/jclouds/openstack/neutron/v2/extensions/RouterApiLiveTest.java
+++ b/openstack-neutron/src/test/java/org/jclouds/openstack/neutron/v2/extensions/RouterApiLiveTest.java
@@ -23,6 +23,12 @@ import static org.testng.Assert.assertTrue;
 
 import java.util.Set;
 
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+
+import java.util.Set;
+
 import org.jclouds.openstack.neutron.v2.domain.ExternalGatewayInfo;
 import org.jclouds.openstack.neutron.v2.domain.Network;
 import org.jclouds.openstack.neutron.v2.domain.NetworkType;
@@ -44,7 +50,7 @@ public class RouterApiLiveTest extends BaseNeutronApiLiveTest {
 
    public void testCreateUpdateAndDeleteRouter() {
       for (String region : api.getConfiguredRegions()) {
-         RouterApi routerApi = api.getRouterExtensionApi(region).get();
+         RouterApi routerApi = api.getRouterApi(region).get();
          NetworkApi networkApi = api.getNetworkApi(region);
          SubnetApi subnetApi = api.getSubnetApi(region);
 
@@ -60,9 +66,9 @@ public class RouterApiLiveTest extends BaseNeutronApiLiveTest {
          assertNotNull(router);
 
          /* List and Get test */
-         Set<Router> routers = api.getRouterExtensionApi(region).get().list().concat().toSet();
+         Set<Router> routers = api.getRouterApi(region).get().list().concat().toSet();
          Router routerList = routers.iterator().next();
-         Router routerGet = api.getRouterExtensionApi(region).get().get(routerList.getId());
+         Router routerGet = api.getRouterApi(region).get().get(routerList.getId());
 
          assertNotNull(routerGet);
          assertEquals(routerGet, routerList);
@@ -91,7 +97,7 @@ public class RouterApiLiveTest extends BaseNeutronApiLiveTest {
 
    public void testCreateAndDeleteRouterInterfaceForSubnet() {
       for (String region : api.getConfiguredRegions()) {
-         RouterApi routerApi = api.getRouterExtensionApi(region).get();
+         RouterApi routerApi = api.getRouterApi(region).get();
          NetworkApi networkApi = api.getNetworkApi(region);
          SubnetApi subnetApi = api.getSubnetApi(region);
 
@@ -128,7 +134,7 @@ public class RouterApiLiveTest extends BaseNeutronApiLiveTest {
 
    public void testCreateAndDeleteRouterInterfaceForPort() {
       for (String region : api.getConfiguredRegions()) {
-         RouterApi routerApi = api.getRouterExtensionApi(region).get();
+         RouterApi routerApi = api.getRouterApi(region).get();
          NetworkApi networkApi = api.getNetworkApi(region);
          SubnetApi subnetApi = api.getSubnetApi(region);
          PortApi portApi = api.getPortApi(region);

http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/e7a52c1a/openstack-neutron/src/test/java/org/jclouds/openstack/neutron/v2/extensions/RouterApiMockTest.java
----------------------------------------------------------------------
diff --git a/openstack-neutron/src/test/java/org/jclouds/openstack/neutron/v2/extensions/RouterApiMockTest.java b/openstack-neutron/src/test/java/org/jclouds/openstack/neutron/v2/extensions/RouterApiMockTest.java
index 0d16f39..36face9 100644
--- a/openstack-neutron/src/test/java/org/jclouds/openstack/neutron/v2/extensions/RouterApiMockTest.java
+++ b/openstack-neutron/src/test/java/org/jclouds/openstack/neutron/v2/extensions/RouterApiMockTest.java
@@ -27,6 +27,17 @@ import java.io.IOException;
 import java.net.URISyntaxException;
 import java.util.List;
 
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
+
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.util.List;
+
 import org.jclouds.openstack.neutron.v2.NeutronApi;
 import org.jclouds.openstack.neutron.v2.domain.ExternalGatewayInfo;
 import org.jclouds.openstack.neutron.v2.domain.NetworkStatus;
@@ -56,7 +67,7 @@ public class RouterApiMockTest extends BaseNeutronApiMockTest {
 
       try {
          NeutronApi neutronApi = api(server.getUrl("/").toString(), "openstack-neutron", overrides);
-         RouterApi api = neutronApi.getRouterExtensionApi("RegionOne").get();
+         RouterApi api = neutronApi.getRouterApi("RegionOne").get();
 
          Router.CreateOptions createRouter = Router.createOptions().name("another_router").adminStateUp(true)
                .externalGatewayInfo(ExternalGatewayInfo.builder().networkId("8ca37218-28ff-41cb-9b10-039601ea7e6b").build())
@@ -94,7 +105,7 @@ public class RouterApiMockTest extends BaseNeutronApiMockTest {
 
       try {
          NeutronApi neutronApi = api(server.getUrl("/").toString(), "openstack-neutron", overrides);
-         RouterApi api = neutronApi.getRouterExtensionApi("RegionOne").get();
+         RouterApi api = neutronApi.getRouterApi("RegionOne").get();
 
          Router.CreateOptions createRouter = Router.createOptions().name("another_router").adminStateUp(true)
                .externalGatewayInfo(ExternalGatewayInfo.builder().networkId("8ca37218-28ff-41cb-9b10-039601ea7e6b").build())
@@ -108,14 +119,14 @@ public class RouterApiMockTest extends BaseNeutronApiMockTest {
       }
    }
 
-   public void testListSpecificPagePort() throws IOException, InterruptedException, URISyntaxException {
+   public void testListSpecificPageRouter() throws IOException, InterruptedException, URISyntaxException {
       MockWebServer server = mockOpenStackServer();
       server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
       server.enqueue(addCommonHeaders(new MockResponse().setResponseCode(200).setBody(stringFromResource("/router_list_response_paged1.json"))));
 
       try {
          NeutronApi neutronApi = api(server.getUrl("/").toString(), "openstack-neutron", overrides);
-         RouterApi api = neutronApi.getRouterExtensionApi("RegionOne").get();
+         RouterApi api = neutronApi.getRouterApi("RegionOne").get();
 
          Routers routers = api.list(PaginationOptions.Builder.limit(2).marker("abcdefg"));
 
@@ -136,14 +147,14 @@ public class RouterApiMockTest extends BaseNeutronApiMockTest {
       }
    }
 
-   public void testListSpecificPagePortFail() throws IOException, InterruptedException, URISyntaxException {
+   public void testListSpecificPageRouterFail() throws IOException, InterruptedException, URISyntaxException {
       MockWebServer server = mockOpenStackServer();
       server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
       server.enqueue(addCommonHeaders(new MockResponse().setResponseCode(404)));
 
       try {
          NeutronApi neutronApi = api(server.getUrl("/").toString(), "openstack-neutron", overrides);
-         RouterApi api = neutronApi.getRouterExtensionApi("RegionOne").get();
+         RouterApi api = neutronApi.getRouterApi("RegionOne").get();
 
          Routers routers = api.list(PaginationOptions.Builder.limit(2).marker("abcdefg"));
 
@@ -171,7 +182,7 @@ public class RouterApiMockTest extends BaseNeutronApiMockTest {
 
       try {
          NeutronApi neutronApi = api(server.getUrl("/").toString(), "openstack-neutron", overrides);
-         RouterApi api = neutronApi.getRouterExtensionApi("RegionOne").get();
+         RouterApi api = neutronApi.getRouterApi("RegionOne").get();
 
          // Note: Lazy! Have to actually look at the collection.
          List<Router> routers = api.list().concat().toList();
@@ -203,7 +214,7 @@ public class RouterApiMockTest extends BaseNeutronApiMockTest {
 
       try {
          NeutronApi neutronApi = api(server.getUrl("/").toString(), "openstack-neutron", overrides);
-         RouterApi api = neutronApi.getRouterExtensionApi("RegionOne").get();
+         RouterApi api = neutronApi.getRouterApi("RegionOne").get();
 
          // Note: Lazy! Have to actually look at the collection.
          List<Router> routers = api.list().concat().toList();
@@ -233,7 +244,7 @@ public class RouterApiMockTest extends BaseNeutronApiMockTest {
 
       try {
          NeutronApi neutronApi = api(server.getUrl("/").toString(), "openstack-neutron", overrides);
-         RouterApi api = neutronApi.getRouterExtensionApi("RegionOne").get();
+         RouterApi api = neutronApi.getRouterApi("RegionOne").get();
 
          Router router = api.get("12345");
 
@@ -266,7 +277,7 @@ public class RouterApiMockTest extends BaseNeutronApiMockTest {
 
       try {
          NeutronApi neutronApi = api(server.getUrl("/").toString(), "openstack-neutron", overrides);
-         RouterApi api = neutronApi.getRouterExtensionApi("RegionOne").get();
+         RouterApi api = neutronApi.getRouterApi("RegionOne").get();
 
          Router router = api.get("12345");
 
@@ -293,7 +304,7 @@ public class RouterApiMockTest extends BaseNeutronApiMockTest {
 
       try {
          NeutronApi neutronApi = api(server.getUrl("/").toString(), "openstack-neutron", overrides);
-         RouterApi api = neutronApi.getRouterExtensionApi("RegionOne").get();
+         RouterApi api = neutronApi.getRouterApi("RegionOne").get();
 
          Router.UpdateOptions updateOptions = Router.updateOptions()
                .externalGatewayInfo(
@@ -331,7 +342,7 @@ public class RouterApiMockTest extends BaseNeutronApiMockTest {
 
       try {
          NeutronApi neutronApi = api(server.getUrl("/").toString(), "openstack-neutron", overrides);
-         RouterApi api = neutronApi.getRouterExtensionApi("RegionOne").get();
+         RouterApi api = neutronApi.getRouterApi("RegionOne").get();
 
          Router.UpdateOptions updateOptions = Router.updateOptions()
                .externalGatewayInfo(
@@ -363,7 +374,7 @@ public class RouterApiMockTest extends BaseNeutronApiMockTest {
 
       try {
          NeutronApi neutronApi = api(server.getUrl("/").toString(), "openstack-neutron", overrides);
-         RouterApi api = neutronApi.getRouterExtensionApi("RegionOne").get();
+         RouterApi api = neutronApi.getRouterApi("RegionOne").get();
 
          boolean result = api.delete("12345");
 
@@ -390,7 +401,7 @@ public class RouterApiMockTest extends BaseNeutronApiMockTest {
 
       try {
          NeutronApi neutronApi = api(server.getUrl("/").toString(), "openstack-neutron", overrides);
-         RouterApi api = neutronApi.getRouterExtensionApi("RegionOne").get();
+         RouterApi api = neutronApi.getRouterApi("RegionOne").get();
 
          boolean result = api.delete("12345");
 
@@ -417,7 +428,7 @@ public class RouterApiMockTest extends BaseNeutronApiMockTest {
 
       try {
          NeutronApi neutronApi = api(server.getUrl("/").toString(), "openstack-neutron", overrides);
-         RouterApi api = neutronApi.getRouterExtensionApi("RegionOne").get();
+         RouterApi api = neutronApi.getRouterApi("RegionOne").get();
 
          RouterInterface routerInterface = api.addInterfaceForSubnet("12345", "a2f1f29d-571b-4533-907f-5803ab96ead1");
 
@@ -446,7 +457,7 @@ public class RouterApiMockTest extends BaseNeutronApiMockTest {
 
       try {
          NeutronApi neutronApi = api(server.getUrl("/").toString(), "openstack-neutron", overrides);
-         RouterApi api = neutronApi.getRouterExtensionApi("RegionOne").get();
+         RouterApi api = neutronApi.getRouterApi("RegionOne").get();
 
          RouterInterface routerInterface = api.addInterfaceForSubnet("12345", "a2f1f29d-571b-4533-907f-5803ab96ead1");
 
@@ -473,7 +484,7 @@ public class RouterApiMockTest extends BaseNeutronApiMockTest {
 
       try {
          NeutronApi neutronApi = api(server.getUrl("/").toString(), "openstack-neutron", overrides);
-         RouterApi api = neutronApi.getRouterExtensionApi("RegionOne").get();
+         RouterApi api = neutronApi.getRouterApi("RegionOne").get();
 
          RouterInterface routerInterface = api.addInterfaceForPort("12345", "portid");
 
@@ -502,7 +513,7 @@ public class RouterApiMockTest extends BaseNeutronApiMockTest {
 
       try {
          NeutronApi neutronApi = api(server.getUrl("/").toString(), "openstack-neutron", overrides);
-         RouterApi api = neutronApi.getRouterExtensionApi("RegionOne").get();
+         RouterApi api = neutronApi.getRouterApi("RegionOne").get();
 
          RouterInterface routerInterface = api.addInterfaceForPort("12345", "portid");
 
@@ -529,7 +540,7 @@ public class RouterApiMockTest extends BaseNeutronApiMockTest {
 
       try {
          NeutronApi neutronApi = api(server.getUrl("/").toString(), "openstack-neutron", overrides);
-         RouterApi api = neutronApi.getRouterExtensionApi("RegionOne").get();
+         RouterApi api = neutronApi.getRouterApi("RegionOne").get();
 
          boolean result = api.removeInterfaceForSubnet("12345", "a2f1f29d-571b-4533-907f-5803ab96ead1");
 
@@ -556,7 +567,7 @@ public class RouterApiMockTest extends BaseNeutronApiMockTest {
 
       try {
          NeutronApi neutronApi = api(server.getUrl("/").toString(), "openstack-neutron", overrides);
-         RouterApi api = neutronApi.getRouterExtensionApi("RegionOne").get();
+         RouterApi api = neutronApi.getRouterApi("RegionOne").get();
 
          boolean result = api.removeInterfaceForSubnet("12345", "a2f1f29d-571b-4533-907f-5803ab96ead1");
 
@@ -583,7 +594,7 @@ public class RouterApiMockTest extends BaseNeutronApiMockTest {
 
       try {
          NeutronApi neutronApi = api(server.getUrl("/").toString(), "openstack-neutron", overrides);
-         RouterApi api = neutronApi.getRouterExtensionApi("RegionOne").get();
+         RouterApi api = neutronApi.getRouterApi("RegionOne").get();
 
          boolean result = api.removeInterfaceForPort("12345", "portid");
 
@@ -610,7 +621,7 @@ public class RouterApiMockTest extends BaseNeutronApiMockTest {
 
       try {
          NeutronApi neutronApi = api(server.getUrl("/").toString(), "openstack-neutron", overrides);
-         RouterApi api = neutronApi.getRouterExtensionApi("RegionOne").get();
+         RouterApi api = neutronApi.getRouterApi("RegionOne").get();
 
          boolean result = api.removeInterfaceForPort("12345", "portid");
 

http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/e7a52c1a/openstack-neutron/src/test/resources/floatingip_create_request.json
----------------------------------------------------------------------
diff --git a/openstack-neutron/src/test/resources/floatingip_create_request.json b/openstack-neutron/src/test/resources/floatingip_create_request.json
new file mode 100644
index 0000000..72ed72f
--- /dev/null
+++ b/openstack-neutron/src/test/resources/floatingip_create_request.json
@@ -0,0 +1,6 @@
+{
+    "floatingip": {
+        "floating_network_id": "376da547-b977-4cfe-9cba-275c80debf57",
+        "port_id": "ce705c24-c1ef-408a-bda3-7bbd946164ab"
+    }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/e7a52c1a/openstack-neutron/src/test/resources/floatingip_create_response.json
----------------------------------------------------------------------
diff --git a/openstack-neutron/src/test/resources/floatingip_create_response.json b/openstack-neutron/src/test/resources/floatingip_create_response.json
new file mode 100644
index 0000000..4dbb82c
--- /dev/null
+++ b/openstack-neutron/src/test/resources/floatingip_create_response.json
@@ -0,0 +1,11 @@
+{
+    "floatingip": {
+        "router_id": "d23abc8d-2991-4a55-ba98-2aaea84cc72f",
+        "tenant_id": "4969c491a3c74ee4af974e6d800c62de",
+        "floating_network_id": "376da547-b977-4cfe-9cba-275c80debf57",
+        "fixed_ip_address": "10.0.0.3",
+        "floating_ip_address": "172.24.4.228",
+        "port_id": "ce705c24-c1ef-408a-bda3-7bbd946164ab",
+        "id": "2f245a7b-796b-4f26-9cf9-9e82d248fda7"
+    }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/e7a52c1a/openstack-neutron/src/test/resources/floatingip_get_response.json
----------------------------------------------------------------------
diff --git a/openstack-neutron/src/test/resources/floatingip_get_response.json b/openstack-neutron/src/test/resources/floatingip_get_response.json
new file mode 100644
index 0000000..4dbb82c
--- /dev/null
+++ b/openstack-neutron/src/test/resources/floatingip_get_response.json
@@ -0,0 +1,11 @@
+{
+    "floatingip": {
+        "router_id": "d23abc8d-2991-4a55-ba98-2aaea84cc72f",
+        "tenant_id": "4969c491a3c74ee4af974e6d800c62de",
+        "floating_network_id": "376da547-b977-4cfe-9cba-275c80debf57",
+        "fixed_ip_address": "10.0.0.3",
+        "floating_ip_address": "172.24.4.228",
+        "port_id": "ce705c24-c1ef-408a-bda3-7bbd946164ab",
+        "id": "2f245a7b-796b-4f26-9cf9-9e82d248fda7"
+    }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/e7a52c1a/openstack-neutron/src/test/resources/floatingip_list_response.json
----------------------------------------------------------------------
diff --git a/openstack-neutron/src/test/resources/floatingip_list_response.json b/openstack-neutron/src/test/resources/floatingip_list_response.json
new file mode 100644
index 0000000..6b41bf9
--- /dev/null
+++ b/openstack-neutron/src/test/resources/floatingip_list_response.json
@@ -0,0 +1,22 @@
+{
+    "floatingips": [
+        {
+            "router_id": "d23abc8d-2991-4a55-ba98-2aaea84cc72f",
+            "tenant_id": "4969c491a3c74ee4af974e6d800c62de",
+            "floating_network_id": "376da547-b977-4cfe-9cba-275c80debf57",
+            "fixed_ip_address": "10.0.0.3",
+            "floating_ip_address": "172.24.4.228",
+            "port_id": "ce705c24-c1ef-408a-bda3-7bbd946164ab",
+            "id": "2f245a7b-796b-4f26-9cf9-9e82d248fda7"
+        },
+        {
+            "router_id": null,
+            "tenant_id": "4969c491a3c74ee4af974e6d800c62de",
+            "floating_network_id": "376da547-b977-4cfe-9cba-275c80debf57",
+            "fixed_ip_address": null,
+            "floating_ip_address": "172.24.4.227",
+            "port_id": null,
+            "id": "61cea855-49cb-4846-997d-801b70c71bdd"
+        }
+    ]
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/e7a52c1a/openstack-neutron/src/test/resources/floatingip_list_response_paged1.json
----------------------------------------------------------------------
diff --git a/openstack-neutron/src/test/resources/floatingip_list_response_paged1.json b/openstack-neutron/src/test/resources/floatingip_list_response_paged1.json
new file mode 100644
index 0000000..7b809f8
--- /dev/null
+++ b/openstack-neutron/src/test/resources/floatingip_list_response_paged1.json
@@ -0,0 +1,32 @@
+{
+    "floatingips": [
+        {
+            "router_id": "d23abc8d-2991-4a55-ba98-2aaea84cc72f",
+            "tenant_id": "4969c491a3c74ee4af974e6d800c62de",
+            "floating_network_id": "376da547-b977-4cfe-9cba-275c80debf57",
+            "fixed_ip_address": "10.0.0.3",
+            "floating_ip_address": "172.24.4.228",
+            "port_id": "ce705c24-c1ef-408a-bda3-7bbd946164ab",
+            "id": "2f245a7b-796b-4f26-9cf9-9e82d248fda7"
+        },
+        {
+            "router_id": null,
+            "tenant_id": "4969c491a3c74ee4af974e6d800c62de",
+            "floating_network_id": "376da547-b977-4cfe-9cba-275c80debf57",
+            "fixed_ip_address": null,
+            "floating_ip_address": "172.24.4.227",
+            "port_id": null,
+            "id": "61cea855-49cb-4846-997d-801b70c71bdd"
+        }
+    ],
+    "floatingips_links": [
+        {
+            "href": "/v2.0/floatingips.json?marker=71c1e68c-171a-4aa2-aca5-50ea153a3718",
+            "rel": "next"
+        },
+        {
+            "href": "/v2.0/floatingips.json?marker=396f12f8-521e-4b91-8e21-2e003500433a&page_reverse=True",
+            "rel": "previous"
+        }
+    ]
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/e7a52c1a/openstack-neutron/src/test/resources/floatingip_list_response_paged2.json
----------------------------------------------------------------------
diff --git a/openstack-neutron/src/test/resources/floatingip_list_response_paged2.json b/openstack-neutron/src/test/resources/floatingip_list_response_paged2.json
new file mode 100644
index 0000000..9ca8cd2
--- /dev/null
+++ b/openstack-neutron/src/test/resources/floatingip_list_response_paged2.json
@@ -0,0 +1,28 @@
+{
+    "floatingips": [
+        {
+            "router_id": "d23abc8d-2991-4a55-ba98-2aaea84cc72f2",
+            "tenant_id": "4969c491a3c74ee4af974e6d800c62de2",
+            "floating_network_id": "376da547-b977-4cfe-9cba-275c80debf572",
+            "fixed_ip_address": "10.0.0.3",
+            "floating_ip_address": "172.24.4.228",
+            "port_id": "ce705c24-c1ef-408a-bda3-7bbd946164ab2",
+            "id": "2f245a7b-796b-4f26-9cf9-9e82d248fda72"
+        },
+        {
+            "router_id": null,
+            "tenant_id": "4969c491a3c74ee4af974e6d800c62de2",
+            "floating_network_id": "376da547-b977-4cfe-9cba-275c80debf572",
+            "fixed_ip_address": null,
+            "floating_ip_address": "172.24.4.227",
+            "port_id": null,
+            "id": "61cea855-49cb-4846-997d-801b70c71bdd2"
+        }
+    ],
+    "floatingips_links": [
+        {
+            "href": "/v2.0/floatingips.json?marker=396f12f8-521e-4b91-8e21-2e003500433a&page_reverse=True",
+            "rel": "previous"
+        }
+    ]
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/e7a52c1a/openstack-neutron/src/test/resources/floatingip_update_dissociate_request.json
----------------------------------------------------------------------
diff --git a/openstack-neutron/src/test/resources/floatingip_update_dissociate_request.json b/openstack-neutron/src/test/resources/floatingip_update_dissociate_request.json
new file mode 100644
index 0000000..a45f500
--- /dev/null
+++ b/openstack-neutron/src/test/resources/floatingip_update_dissociate_request.json
@@ -0,0 +1,5 @@
+{
+    "floatingip": {
+
+    }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/e7a52c1a/openstack-neutron/src/test/resources/floatingip_update_dissociate_response.json
----------------------------------------------------------------------
diff --git a/openstack-neutron/src/test/resources/floatingip_update_dissociate_response.json b/openstack-neutron/src/test/resources/floatingip_update_dissociate_response.json
new file mode 100644
index 0000000..5515a22
--- /dev/null
+++ b/openstack-neutron/src/test/resources/floatingip_update_dissociate_response.json
@@ -0,0 +1,11 @@
+{
+    "floatingip": {
+        "router_id": "d23abc8d-2991-4a55-ba98-2aaea84cc72f",
+        "tenant_id": "4969c491a3c74ee4af974e6d800c62de",
+        "floating_network_id": "376da547-b977-4cfe-9cba-275c80debf57",
+        "fixed_ip_address": null,
+        "floating_ip_address": "172.24.4.228",
+        "port_id": null,
+        "id": "2f245a7b-796b-4f26-9cf9-9e82d248fda7"
+    }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/e7a52c1a/openstack-neutron/src/test/resources/floatingip_update_request.json
----------------------------------------------------------------------
diff --git a/openstack-neutron/src/test/resources/floatingip_update_request.json b/openstack-neutron/src/test/resources/floatingip_update_request.json
new file mode 100644
index 0000000..2772b5a
--- /dev/null
+++ b/openstack-neutron/src/test/resources/floatingip_update_request.json
@@ -0,0 +1,5 @@
+{
+    "floatingip": {
+        "port_id": "fc861431-0e6c-4842-a0ed-e2363f9bc3a8"
+    }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/e7a52c1a/openstack-neutron/src/test/resources/floatingip_update_response.json
----------------------------------------------------------------------
diff --git a/openstack-neutron/src/test/resources/floatingip_update_response.json b/openstack-neutron/src/test/resources/floatingip_update_response.json
new file mode 100644
index 0000000..59c8a68
--- /dev/null
+++ b/openstack-neutron/src/test/resources/floatingip_update_response.json
@@ -0,0 +1,11 @@
+{
+    "floatingip": {
+        "router_id": "d23abc8d-2991-4a55-ba98-2aaea84cc72f",
+        "tenant_id": "4969c491a3c74ee4af974e6d800c62de",
+        "floating_network_id": "376da547-b977-4cfe-9cba-275c80debf57",
+        "fixed_ip_address": "10.0.0.4",
+        "floating_ip_address": "172.24.4.228",
+        "port_id": "fc861431-0e6c-4842-a0ed-e2363f9bc3a8",
+        "id": "2f245a7b-796b-4f26-9cf9-9e82d248fda7"
+    }
+}