From e7a52c1aecef2f989f9bde57c1b83e97a81538f9 Mon Sep 17 00:00:00 2001 From: Zack Shoylev Date: Fri, 22 Aug 2014 01:06:34 -0500 Subject: [PATCH] Adds support for Floating IP --- .../openstack/neutron/v2/NeutronApi.java | 14 +- .../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 ++++++ .../fallbacks/EmptyFloatingIPsFallback.java | 45 ++ .../functions/FloatingIPsToPagedIterable.java | 64 +++ .../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 + .../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(-) create mode 100644 openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/FloatingIP.java create mode 100644 openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/FloatingIPs.java create mode 100644 openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/extensions/FloatingIPApi.java create mode 100644 openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/fallbacks/EmptyFloatingIPsFallback.java create mode 100644 openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/functions/FloatingIPsToPagedIterable.java create mode 100644 openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/functions/ParseFloatingIPs.java create mode 100644 openstack-neutron/src/test/java/org/jclouds/openstack/neutron/v2/extensions/FloatingIPApiLiveTest.java create mode 100644 openstack-neutron/src/test/java/org/jclouds/openstack/neutron/v2/extensions/FloatingIPApiMockTest.java create mode 100644 openstack-neutron/src/test/resources/floatingip_create_request.json create mode 100644 openstack-neutron/src/test/resources/floatingip_create_response.json create mode 100644 openstack-neutron/src/test/resources/floatingip_get_response.json create mode 100644 openstack-neutron/src/test/resources/floatingip_list_response.json create mode 100644 openstack-neutron/src/test/resources/floatingip_list_response_paged1.json create mode 100644 openstack-neutron/src/test/resources/floatingip_list_response_paged2.json create mode 100644 openstack-neutron/src/test/resources/floatingip_update_dissociate_request.json create mode 100644 openstack-neutron/src/test/resources/floatingip_update_dissociate_response.json create mode 100644 openstack-neutron/src/test/resources/floatingip_update_request.json create mode 100644 openstack-neutron/src/test/resources/floatingip_update_response.json 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 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 getRouterApi(@EndpointParam(parser = RegionToEndpoint.class) String region); + Optional 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. + * + *

NOTE

+ * 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 getRouterExtensionApi(@EndpointParam(parser = RegionToEndpoint.class) String region); + Optional getFloatingIPApi(@EndpointParam(parser = RegionToEndpoint.class) String region); /** * Provides access to SecurityGroup features. 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 { + 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 { + /** + * 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 { + /** + * 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); + } + } +} 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 { + public static final FloatingIPs EMPTY = new FloatingIPs(ImmutableSet. of(), ImmutableSet. of()); + + @ConstructorProperties({"floatingips", "floatingips_links"}) + protected FloatingIPs(Iterable floatingIPs, Iterable floatingIPsLinks) { + super(floatingIPs, floatingIPsLinks); + } +} 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 @@ public class Networks extends PaginatedCollection { public static final Networks EMPTY = new Networks(ImmutableSet. of(), ImmutableSet. of()); - @ConstructorProperties({ "networks", "networks_links" }) + @ConstructorProperties({"networks", "networks_links"}) protected Networks(Iterable networks, Iterable networksLinks) { super(networks, networksLinks); } 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 { public static final Ports EMPTY = new Ports(ImmutableSet. of(), ImmutableSet. of()); - @ConstructorProperties({ "ports", "ports_links" }) + @ConstructorProperties({"ports", "ports_links"}) protected Ports(Iterable ports, Iterable portsLinks) { super(ports, portsLinks); } 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 { public static final Routers EMPTY = new Routers(ImmutableSet. of(), ImmutableSet. of()); - @ConstructorProperties({ "routers", "routers_links" }) + @ConstructorProperties({"routers", "routers_links"}) protected Routers(Iterable routers, Iterable routersLinks) { super(routers, routersLinks); } 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 { public static final Subnets EMPTY = new Subnets(ImmutableSet. of(), ImmutableSet. of()); - @ConstructorProperties({ "subnets", "subnets_links" }) + @ConstructorProperties({"subnets", "subnets_links"}) protected Subnets(Iterable subnets, Iterable subnetsLinks) { super(subnets, subnetsLinks); } 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. + *

+ * 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 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); +} 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 { + + public ListenableFuture 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); + } +} 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 { + + private final NeutronApi api; + + @Inject + protected FloatingIPsToPagedIterable(NeutronApi api) { + this.api = checkNotNull(api, "api"); + } + + @Override + protected Function> markerToNextForArg0(Optional arg0) { + String region = arg0.isPresent() ? arg0.get().toString() : null; + final FloatingIPApi floatingIPApi = api.getFloatingIPApi(region).get(); + return new Function>() { + + @SuppressWarnings("unchecked") + @Override + public IterableWithMarker apply(Object input) { + PaginationOptions paginationOptions = PaginationOptions.class.cast(input); + return IterableWithMarker.class.cast(floatingIPApi.list(paginationOptions)); + } + + @Override + public String toString() { + return "listfloatingIPs()"; + } + }; + } + +} 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 { + + @Inject + public ParseFloatingIPs(Json json) { + super(json, TypeLiteral.get(FloatingIPs.class)); + } +} 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.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 @@ protected RouterToPagedIterable(NeutronApi api) { @Override protected Function> markerToNextForArg0(Optional 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>() { @SuppressWarnings("unchecked") 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 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 getFixedAddresses(String subnetId) { + return ImmutableSet.of(IP.builder().subnetId(subnetId).build()); + } +} 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 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 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(); + } + } +} 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 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 void testCreateUpdateAndDeleteRouter() { assertNotNull(router); /* List and Get test */ - Set routers = api.getRouterExtensionApi(region).get().list().concat().toSet(); + Set 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 void testCreateUpdateAndDeleteRouter() { 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 void testCreateAndDeleteRouterInterfaceForSubnet() { 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); 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.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 void testCreateRouter() throws IOException, InterruptedException, URISynt 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 void testCreateRouterFail() throws IOException, InterruptedException, URI 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 void testCreateRouterFail() throws IOException, InterruptedException, URI } } - 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 void testListSpecificPagePort() throws IOException, InterruptedException, } } - 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 void testListPagedRouter() throws IOException, InterruptedException, URIS 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 routers = api.list().concat().toList(); @@ -203,7 +214,7 @@ public void testListPagedRouterFail() throws IOException, InterruptedException, 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 routers = api.list().concat().toList(); @@ -233,7 +244,7 @@ public void testGetRouter() throws IOException, InterruptedException, URISyntaxE 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 void testGetRouterFail() throws IOException, InterruptedException, URISyn 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 void testUpdateRouter() throws IOException, InterruptedException, URISynt 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 void testUpdateRouterFail() throws IOException, InterruptedException, URI 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 void testDeleteRouter() throws IOException, InterruptedException, URISynt 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 void testDeleteRouterFail() throws IOException, InterruptedException, URI 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 void testAddRouterInterfaceForSubnet() throws IOException, InterruptedExc 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 void testAddRouterInterfaceForSubnetFail() throws IOException, Interrupte 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 void testAddRouterInterfaceForPort() throws IOException, InterruptedExcep 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 void testAddRouterInterfaceForPortFail() throws IOException, InterruptedE 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 void testRemoveRouterInterfaceForSubnet() throws IOException, Interrupted 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 void testRemoveRouterInterfaceForSubnetFail() throws IOException, Interru 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 void testRemoveRouterInterfaceForPort() throws IOException, InterruptedEx 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 void testRemoveRouterInterfaceForPortFail() throws IOException, Interrupt 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"); 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" + } +} 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" + } +} 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" + } +} 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" + } + ] +} 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" + } + ] +} 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" + } + ] +} 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": { + + } +} 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" + } +} 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" + } +} 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" + } +}