http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/9c4bd944/openstack-neutron/src/test/java/org/jclouds/openstack/neutron/v2/features/PortApiMockTest.java
----------------------------------------------------------------------
diff --git 
a/openstack-neutron/src/test/java/org/jclouds/openstack/neutron/v2/features/PortApiMockTest.java
 
b/openstack-neutron/src/test/java/org/jclouds/openstack/neutron/v2/features/PortApiMockTest.java
new file mode 100644
index 0000000..22258b2
--- /dev/null
+++ 
b/openstack-neutron/src/test/java/org/jclouds/openstack/neutron/v2/features/PortApiMockTest.java
@@ -0,0 +1,492 @@
+/*
+ * 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.features;
+
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.squareup.okhttp.mockwebserver.MockResponse;
+import com.squareup.okhttp.mockwebserver.MockWebServer;
+import org.jclouds.openstack.neutron.v2.NeutronApi;
+import org.jclouds.openstack.neutron.v2.domain.AddressPair;
+import org.jclouds.openstack.neutron.v2.domain.NetworkStatus;
+import org.jclouds.openstack.neutron.v2.domain.Port;
+import org.jclouds.openstack.neutron.v2.domain.Ports;
+import org.jclouds.openstack.neutron.v2.domain.VIFType;
+import org.jclouds.openstack.neutron.v2.domain.VNICType;
+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 java.io.IOException;
+import java.net.URISyntaxException;
+import java.util.List;
+import java.util.Map;
+
+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;
+
+/**
+ * Tests NetworkApi Guice wiring and parsing
+ *
+ */
+@Test
+public class PortApiMockTest extends BaseNeutronApiMockTest {
+
+   public void testCreatePort() 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("/port_create_response.json"))));
+
+      try {
+         NeutronApi neutronApi = api(server.getUrl("/").toString(), 
"openstack-neutron", overrides);
+         PortApi api = neutronApi.getPortApiForZone("RegionOne");
+
+         Port.CreateOptions createPort = 
Port.createOptions("6aeaf34a-c482-4bd3-9dc3-7faf36412f12")
+               .name("port1")
+               .adminStateUp(true)
+               .deviceId("d6b4d3a5-c700-476f-b609-1493dd9dadc0")
+               
.allowedAddressPairs(ImmutableSet.of(AddressPair.createOptions("12", 
"111.222.333.444").build()))
+               .build();
+
+         Port port = api.create(createPort);
+
+         /*
+          * Check request
+          */
+         assertAuthentication(server);
+         assertRequest(server.takeRequest(), "POST", "/v2.0/ports", 
"/port_create_request.json");
+
+         /*
+          * Check response
+          */
+         assertNotNull(port);
+         
assertEquals(port.getAllowedAddressPairs().iterator().next().getIpAddress(),"192.168.1.1");
+         
assertEquals(port.getAllowedAddressPairs().iterator().next().getMacAddress(),"12:12");
+         assertEquals(port.getName(), "port1");
+         assertEquals(port.getStatus(), NetworkStatus.ACTIVE);
+         assertEquals(port.getId(), "ebe69f1e-bc26-4db5-bed0-c0afb4afe3db");
+         assertEquals(port.getDeviceId(), 
"d6b4d3a5-c700-476f-b609-1493dd9dadc0");
+         assertEquals(port.getDeviceOwner(), "");
+         assertEquals(port.getMacAddress(), "fa:16:3e:a6:50:c1");
+         assertEquals(port.getNetworkId(), 
"6aeaf34a-c482-4bd3-9dc3-7faf36412f12");
+         assertEquals(port.getFixedIps().iterator().next().getIpAddress(), 
"192.168.111.4");
+         assertEquals(port.getFixedIps().iterator().next().getSubnetId(), 
"22b44fc2-4ffb-4de4-b0f9-69d58b37ae27");
+         assertEquals(port.getTenantId(), "cf1a5775e766426cb1968766d0191908");
+      } finally {
+         server.shutdown();
+      }
+   }
+
+   @Test(expectedExceptions = ResourceNotFoundException.class)
+   public void testCreatePortFail() 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);
+         PortApi api = neutronApi.getPortApiForZone("RegionOne");
+
+         Port.CreateOptions createPort = 
Port.createOptions("6aeaf34a-c482-4bd3-9dc3-7faf36412f12")
+               .name("port1")
+               .adminStateUp(true)
+               .deviceId("d6b4d3a5-c700-476f-b609-1493dd9dadc0")
+               
.allowedAddressPairs(ImmutableSet.of(AddressPair.createOptions("12","111.222.333.444").build()))
+               .build();
+
+         Port port = api.create(createPort);
+      } finally {
+         server.shutdown();
+      }
+   }
+
+   public void testListSpecificPagePort() 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("/port_list_response_paged1.json"))));
+
+      try {
+         NeutronApi neutronApi = api(server.getUrl("/").toString(), 
"openstack-neutron", overrides);
+         PortApi api = neutronApi.getPortApiForZone("RegionOne");
+
+         Ports ports = 
api.list(PaginationOptions.Builder.limit(2).marker("abcdefg"));
+
+         /*
+          * Check request
+          */
+         assertAuthentication(server);
+         assertRequest(server.takeRequest(), "GET", 
"/v2.0/ports?limit=2&marker=abcdefg");
+
+         /*
+          * Check response
+          */
+         assertNotNull(ports);
+         assertEquals(ports.size(), 2);
+         
assertEquals(ports.first().get().getId(),"24e6637e-c521-45fc-8b8b-d7331aa3c99f");
+      } finally {
+         server.shutdown();
+      }
+   }
+
+   public void testListSpecificPagePortFail() 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);
+         PortApi api = neutronApi.getPortApiForZone("RegionOne");
+
+         Ports ports = 
api.list(PaginationOptions.Builder.limit(2).marker("abcdefg"));
+
+         /*
+          * Check request
+          */
+         assertAuthentication(server);
+         assertRequest(server.takeRequest(), "GET", 
"/v2.0/ports?limit=2&marker=abcdefg");
+
+         /*
+          * Check response
+          */
+         assertTrue(ports.isEmpty());
+      } finally {
+         server.shutdown();
+      }
+   }
+
+   public void testListPagedPort() 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("/port_list_response_paged1.json"))));
+      server.enqueue(addCommonHeaders(new 
MockResponse().setResponseCode(200).setBody(stringFromResource("/port_list_response_paged2.json"))));
+
+      try {
+         NeutronApi neutronApi = api(server.getUrl("/").toString(), 
"openstack-neutron", overrides);
+         PortApi api = neutronApi.getPortApiForZone("RegionOne");
+
+         // Note: Lazy! Have to actually look at the collection.
+         List<Port> ports = api.list().concat().toList();
+
+         /*
+          * Check request
+          */
+         assertEquals(server.getRequestCount(), 3);
+         assertAuthentication(server);
+         assertRequest(server.takeRequest(), "GET", "/v2.0/ports");
+         assertRequest(server.takeRequest(), "GET", 
"/v2.0/ports?marker=71c1e68c-171a-4aa2-aca5-50ea153a3718");
+
+         /*
+          * Check response
+          */
+         assertNotNull(ports);
+         assertEquals(ports.size(), 4);
+         
assertEquals(ports.get(0).getId(),"24e6637e-c521-45fc-8b8b-d7331aa3c99f");
+         
assertEquals(ports.get(3).getId(),"e54dfd9b-ce6e-47f7-af47-1609cfd1cdb0_4");
+      } finally {
+         server.shutdown();
+      }
+   }
+
+   public void testListPagedPortFail() 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);
+         PortApi api = neutronApi.getPortApiForZone("RegionOne");
+
+         // Note: Lazy! Have to actually look at the collection.
+         List<Port> ports = api.list().concat().toList();
+
+         /*
+          * Check request
+          */
+         assertEquals(server.getRequestCount(), 2);
+         assertAuthentication(server);
+         assertRequest(server.takeRequest(), "GET", "/v2.0/ports");
+
+         /*
+          * Check response
+          */
+         assertTrue(ports.isEmpty());
+      } finally {
+         server.shutdown();
+      }
+   }
+
+   public void testCreateBulkPort() 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("/port_create_bulk_response.json"))));
+
+      try {
+         NeutronApi neutronApi = api(server.getUrl("/").toString(), 
"openstack-neutron", overrides);
+         PortApi api = neutronApi.getPortApiForZone("RegionOne");
+
+         Port.CreateOptions createPort1 = 
Port.createOptions("64239a54-dcc4-4b39-920b-b37c2144effa")
+               .name("port1")
+               .adminStateUp(true)
+               .deviceId("24df1d04-d5cb-41e1-8de5-61ed77c558df")
+               
.securityGroups(ImmutableSet.of("dbc107f4-afcd-4d5a-9352-f68f82241d5b"))
+               .build();
+
+         Port.CreateOptions createPort2 = 
Port.createOptions("e6031bc2-901a-4c66-82da-f4c32ed89406")
+               .name("port2")
+               .adminStateUp(false)
+               .securityGroups(
+                     ImmutableSet.of("8bf3f7cc-8471-40b1-815f-9da47e79775b", 
"dbc107f4-afcd-4d5a-9352-f68f82241d5b"))
+               .build();
+
+         FluentIterable<Port> ports = 
api.createBulk(ImmutableList.of(createPort1, createPort2));
+
+         /*
+          * Check request
+          */
+         assertAuthentication(server);
+         assertRequest(server.takeRequest(), "POST", "/v2.0/ports", 
"/port_create_bulk_request.json");
+
+         /*
+          * Check response
+          */
+         assertNotNull(ports);
+         assertEquals(ports.size(), 2);
+         assertEquals(ports.get(0).getName(), "port1");
+         assertEquals(ports.get(1).getName(), "port2");
+      } finally {
+         server.shutdown();
+      }
+   }
+
+   @Test(expectedExceptions = ResourceNotFoundException.class)
+   public void testCreateBulkPortFail() 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);
+         PortApi api = neutronApi.getPortApiForZone("RegionOne");
+
+         Port.CreateOptions createPort1 = 
Port.createOptions("64239a54-dcc4-4b39-920b-b37c2144effa")
+               .name("port1")
+               .adminStateUp(true)
+               .deviceId("24df1d04-d5cb-41e1-8de5-61ed77c558df")
+               
.securityGroups(ImmutableSet.of("dbc107f4-afcd-4d5a-9352-f68f82241d5b"))
+               .build();
+
+         Port.CreateOptions createPort2 = 
Port.createOptions("e6031bc2-901a-4c66-82da-f4c32ed89406")
+               .name("port2")
+               .adminStateUp(false)
+               .securityGroups(
+                     ImmutableSet.of("8bf3f7cc-8471-40b1-815f-9da47e79775b", 
"dbc107f4-afcd-4d5a-9352-f68f82241d5b"))
+               .build();
+
+         FluentIterable<Port> ports = 
api.createBulk(ImmutableList.of(createPort1, createPort2));
+      } finally {
+         server.shutdown();
+      }
+   }
+
+   public void testGetPort() 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("/port_get_response.json"))));
+
+      try {
+         NeutronApi neutronApi = api(server.getUrl("/").toString(), 
"openstack-neutron", overrides);
+         PortApi api = neutronApi.getPortApiForZone("RegionOne");
+
+         Port port = api.get("12345");
+
+         /*
+          * Check request
+          */
+         assertAuthentication(server);
+         assertRequest(server.takeRequest(), "GET", "/v2.0/ports/12345");
+
+         /*
+          * Check response
+          */
+         assertNotNull(port);
+         assertEquals(port.getName(), "jclouds-wibble");
+         assertEquals(port.getStatus(), NetworkStatus.ACTIVE);
+         assertEquals(port.getId(), "624312ff-d14b-4ba3-9834-1c78d23d574d");
+         assertEquals(port.getTenantId(), "1234567890");
+         assertEquals(port.getNetworkId(), "1234567890");
+         assertEquals(port.getVnicType(), VNICType.NORMAL);
+         assertEquals(port.getVifType(), VIFType.HYPERV);
+         assertEquals(port.getVifDetails().get("name1"), "value1");
+         assertEquals(((Map<String, 
Double>)port.getVifDetails().get("name2")).get("mapname2").intValue(), 3);
+      } finally {
+         server.shutdown();
+      }
+   }
+
+   public void testGetPortFail() 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);
+         PortApi api = neutronApi.getPortApiForZone("RegionOne");
+
+         Port port = api.get("12345");
+
+         /*
+          * Check request
+          */
+         assertAuthentication(server);
+         assertRequest(server.takeRequest(), "GET", "/v2.0/ports/12345");
+
+         /*
+          * Check response
+          */
+         assertNull(port);
+      } finally {
+         server.shutdown();
+      }
+   }
+
+   public void testUpdatePort() 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("/port_update_response.json"))));
+
+      try {
+         NeutronApi neutronApi = api(server.getUrl("/").toString(), 
"openstack-neutron", overrides);
+         PortApi api = neutronApi.getPortApiForZone("RegionOne");
+
+         Port.UpdateOptions updatePort = Port.updateOptions()
+               .securityGroups(
+                     ImmutableSet.of("85cc3048-abc3-43cc-89b3-377341426ac5", 
"c5ab5c29-2c99-44cb-a4b8-e70a88b77799"))
+               .build();
+
+         Port port = api.update("12345", updatePort);
+
+         /*
+          * Check request
+          */
+         assertAuthentication(server);
+         assertRequest(server.takeRequest(), "PUT", "/v2.0/ports/12345", 
"/port_update_request.json");
+
+         /*
+          * Check response
+          */
+         assertNotNull(port);
+         assertEquals(port.getId(), "1d8591f4-7b62-428e-857d-e82a15e5a7f1");
+      } finally {
+         server.shutdown();
+      }
+   }
+
+   public void testUpdatePortFail() 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);
+         PortApi api = neutronApi.getPortApiForZone("RegionOne");
+
+         Port.UpdateOptions updatePort = Port.updateOptions()
+               
.securityGroups(ImmutableSet.of("85cc3048-abc3-43cc-89b3-377341426ac5","c5ab5c29-2c99-44cb-a4b8-e70a88b77799"))
+               .build();
+
+         Port port = api.update("12345", updatePort);
+
+         /*
+          * Check request
+          */
+         assertAuthentication(server);
+         assertRequest(server.takeRequest(), "PUT", "/v2.0/ports/12345", 
"/port_update_request.json");
+
+         /*
+          * Check response
+          */
+         assertNull(port);
+      } finally {
+         server.shutdown();
+      }
+   }
+
+   public void testDeletePort() 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);
+         PortApi api = neutronApi.getPortApiForZone("RegionOne");
+
+         boolean result = api.delete("12345");
+
+         /*
+          * Check request
+          */
+         assertAuthentication(server);
+         assertRequest(server.takeRequest(), "DELETE", "/v2.0/ports/12345");
+
+         /*
+          * Check response
+          */
+         assertTrue(result);
+      } finally {
+         server.shutdown();
+      }
+   }
+
+   public void testDeletePortFail() 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);
+         PortApi api = neutronApi.getPortApiForZone("RegionOne");
+
+         boolean result = api.delete("12345");
+
+         /*
+          * Check request
+          */
+         assertAuthentication(server);
+         assertRequest(server.takeRequest(), "DELETE", "/v2.0/ports/12345");
+
+         /*
+          * Check response
+          */
+         assertFalse(result);
+      } finally {
+         server.shutdown();
+      }
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/9c4bd944/openstack-neutron/src/test/java/org/jclouds/openstack/neutron/v2/features/RouterApiLiveTest.java
----------------------------------------------------------------------
diff --git 
a/openstack-neutron/src/test/java/org/jclouds/openstack/neutron/v2/features/RouterApiLiveTest.java
 
b/openstack-neutron/src/test/java/org/jclouds/openstack/neutron/v2/features/RouterApiLiveTest.java
new file mode 100644
index 0000000..69625a3
--- /dev/null
+++ 
b/openstack-neutron/src/test/java/org/jclouds/openstack/neutron/v2/features/RouterApiLiveTest.java
@@ -0,0 +1,171 @@
+/*
+ * 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.features;
+
+import org.jclouds.openstack.neutron.v2.domain.ExternalGatewayInfo;
+import org.jclouds.openstack.neutron.v2.domain.Network;
+import org.jclouds.openstack.neutron.v2.domain.NetworkType;
+import org.jclouds.openstack.neutron.v2.domain.Port;
+import org.jclouds.openstack.neutron.v2.domain.Router;
+import org.jclouds.openstack.neutron.v2.domain.RouterInterface;
+import org.jclouds.openstack.neutron.v2.domain.Subnet;
+import org.jclouds.openstack.neutron.v2.extensions.RouterApi;
+import org.jclouds.openstack.neutron.v2.internal.BaseNeutronApiLiveTest;
+import org.testng.annotations.Test;
+
+import java.util.Set;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+
+/**
+ * Tests parsing and Guice wiring of RouterApi
+ */
+@Test(groups = "live", testName = "RouterApiLiveTest")
+public class RouterApiLiveTest extends BaseNeutronApiLiveTest {
+
+   public void testCreateUpdateAndDeleteRouter() {
+      for (String zone : api.getConfiguredRegions()) {
+         RouterApi routerApi = api.getRouterExtensionForZone(zone).get();
+         NetworkApi networkApi = api.getNetworkApiForZone(zone);
+         SubnetApi subnetApi = api.getSubnetApiForZone(zone);
+
+         Network network = networkApi.create(
+               
Network.createOptions("jclouds-network-test").external(true).networkType(NetworkType.LOCAL).build());
+         assertNotNull(network);
+
+         Subnet subnet = 
subnetApi.create(Subnet.createOptions(network.getId(), 
"192.168.0.0/16").ipVersion(4).build());
+         assertNotNull(subnet);
+
+         Router router = 
routerApi.create(Router.createOptions().name("jclouds-router-test")
+            
.externalGatewayInfo(ExternalGatewayInfo.builder().networkId(network.getId()).build()).build());
+         assertNotNull(router);
+
+         /* List and Get test */
+         Set<Router> routers = 
api.getRouterExtensionForZone(zone).get().list().concat().toSet();
+         Router routerList = routers.iterator().next();
+         Router routerGet = 
api.getRouterExtensionForZone(zone).get().get(routerList.getId());
+
+         assertNotNull(routerGet);
+         assertEquals(routerGet, routerList);
+         /***/
+
+         routerGet = routerApi.get(router.getId());
+
+         assertEquals(routerGet.getName(), router.getName());
+         assertEquals(routerGet.getId(), router.getId());
+         assertEquals(routerGet.getExternalGatewayInfo(), 
router.getExternalGatewayInfo());
+
+         Router routerUpdate = routerApi.update(router.getId(), 
Router.updateOptions().name("jclouds-router-test-rename").build());
+         assertNotNull(routerUpdate);
+         assertEquals(routerUpdate.getName(), "jclouds-router-test-rename");
+
+         routerGet = routerApi.get(router.getId());
+
+         assertEquals(routerGet.getId(), router.getId());
+         assertEquals(routerGet.getName(), "jclouds-router-test-rename");
+
+         assertTrue(routerApi.delete(router.getId()));
+         assertTrue(subnetApi.delete(subnet.getId()));
+         assertTrue(networkApi.delete(network.getId()));
+      }
+   }
+
+   public void testCreateAndDeleteRouterInterfaceForSubnet() {
+      for (String zone : api.getConfiguredRegions()) {
+         RouterApi routerApi = api.getRouterExtensionForZone(zone).get();
+         NetworkApi networkApi = api.getNetworkApiForZone(zone);
+         SubnetApi subnetApi = api.getSubnetApiForZone(zone);
+
+         Network network = 
networkApi.create(Network.createOptions("jclouds-network-test").external(true).networkType(NetworkType.LOCAL).build());
+         assertNotNull(network);
+
+         Subnet subnet = 
subnetApi.create(Subnet.createOptions(network.getId(), 
"192.168.0.0/16").ipVersion(4).build());
+         assertNotNull(subnet);
+
+         Network network2 = 
networkApi.create(Network.createOptions("jclouds-network-test2").external(true).networkType(NetworkType.LOCAL).build());
+         assertNotNull(network2);
+
+         Subnet subnet2 = 
subnetApi.create(Subnet.createOptions(network2.getId(), 
"192.169.0.0/16").ipVersion(4).build());
+         assertNotNull(subnet2);
+
+         Router router = 
routerApi.create(Router.createOptions().name("jclouds-router-test").build());
+         assertNotNull(router);
+
+         RouterInterface routerInterface = 
routerApi.addInterfaceForSubnet(router.getId(), subnet.getId());
+         assertNotNull(routerInterface);
+
+         RouterInterface routerInterface2 = 
routerApi.addInterfaceForSubnet(router.getId(), subnet2.getId());
+         assertNotNull(routerInterface2);
+
+         assertTrue(routerApi.removeInterfaceForSubnet(router.getId(), 
subnet.getId()));
+         assertTrue(routerApi.removeInterfaceForSubnet(router.getId(), 
subnet2.getId()));
+         assertTrue(routerApi.delete(router.getId()));
+         assertTrue(subnetApi.delete(subnet.getId()));
+         assertTrue(networkApi.delete(network.getId()));
+         assertTrue(subnetApi.delete(subnet2.getId()));
+         assertTrue(networkApi.delete(network2.getId()));
+      }
+   }
+
+   public void testCreateAndDeleteRouterInterfaceForPort() {
+      for (String zone : api.getConfiguredRegions()) {
+         RouterApi routerApi = api.getRouterExtensionForZone(zone).get();
+         NetworkApi networkApi = api.getNetworkApiForZone(zone);
+         SubnetApi subnetApi = api.getSubnetApiForZone(zone);
+         PortApi portApi = api.getPortApiForZone(zone);
+
+         Network network = 
networkApi.create(Network.createOptions("jclouds-network-test").external(true).networkType(NetworkType.LOCAL).build());
+         assertNotNull(network);
+
+         Subnet subnet = 
subnetApi.create(Subnet.createOptions(network.getId(), 
"192.168.0.0/16").ipVersion(4).build());
+         assertNotNull(subnet);
+
+         Network network2 = 
networkApi.create(Network.createOptions("jclouds-network-test2").external(true).networkType(NetworkType.LOCAL).build());
+         assertNotNull(network2);
+
+         Subnet subnet2 = 
subnetApi.create(Subnet.createOptions(network2.getId(), 
"192.169.0.0/16").ipVersion(4).build());
+         assertNotNull(subnet2);
+
+         Port port = 
portApi.create(Port.createOptions(network.getId()).build());
+         assertNotNull(port);
+
+         Port port2 = 
portApi.create(Port.createOptions(network2.getId()).build());
+         assertNotNull(port2);
+
+         Router router = 
routerApi.create(Router.createOptions().name("jclouds-router-test").build());
+         assertNotNull(router);
+
+         RouterInterface routerInterface = 
routerApi.addInterfaceForPort(router.getId(), port.getId());
+         assertNotNull(routerInterface);
+
+         RouterInterface routerInterface2 = 
routerApi.addInterfaceForPort(router.getId(), port2.getId());
+         assertNotNull(routerInterface2);
+
+         assertTrue(routerApi.removeInterfaceForPort(router.getId(), 
port.getId()));
+         assertTrue(routerApi.removeInterfaceForPort(router.getId(), 
port2.getId()));
+         assertTrue(routerApi.delete(router.getId()));
+         assertTrue(subnetApi.delete(subnet.getId()));
+         assertTrue(networkApi.delete(network.getId()));
+         assertTrue(subnetApi.delete(subnet2.getId()));
+         assertTrue(networkApi.delete(network2.getId()));
+      }
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/9c4bd944/openstack-neutron/src/test/java/org/jclouds/openstack/neutron/v2/features/RouterApiMockTest.java
----------------------------------------------------------------------
diff --git 
a/openstack-neutron/src/test/java/org/jclouds/openstack/neutron/v2/features/RouterApiMockTest.java
 
b/openstack-neutron/src/test/java/org/jclouds/openstack/neutron/v2/features/RouterApiMockTest.java
new file mode 100644
index 0000000..bcbb8db
--- /dev/null
+++ 
b/openstack-neutron/src/test/java/org/jclouds/openstack/neutron/v2/features/RouterApiMockTest.java
@@ -0,0 +1,631 @@
+/*
+ * 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.features;
+
+import com.squareup.okhttp.mockwebserver.MockResponse;
+import com.squareup.okhttp.mockwebserver.MockWebServer;
+import org.jclouds.openstack.neutron.v2.NeutronApi;
+import org.jclouds.openstack.neutron.v2.domain.ExternalGatewayInfo;
+import org.jclouds.openstack.neutron.v2.domain.NetworkStatus;
+import org.jclouds.openstack.neutron.v2.domain.Router;
+import org.jclouds.openstack.neutron.v2.domain.RouterInterface;
+import org.jclouds.openstack.neutron.v2.domain.Routers;
+import org.jclouds.openstack.neutron.v2.extensions.RouterApi;
+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 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;
+
+/**
+ * Tests NetworkApi Guice wiring and parsing
+ *
+ */
+@Test
+public class RouterApiMockTest extends BaseNeutronApiMockTest {
+
+   public void testCreateRouter() 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("/router_create_response.json"))));
+
+      try {
+         NeutronApi neutronApi = api(server.getUrl("/").toString(), 
"openstack-neutron", overrides);
+         RouterApi api = 
neutronApi.getRouterExtensionForZone("RegionOne").get();
+
+         Router.CreateOptions createRouter = 
Router.createOptions().name("another_router").adminStateUp(true)
+               
.externalGatewayInfo(ExternalGatewayInfo.builder().networkId("8ca37218-28ff-41cb-9b10-039601ea7e6b").build())
+               .build();
+
+         Router router = api.create(createRouter);
+
+         /*
+          * Check request
+          */
+         assertAuthentication(server);
+         assertRequest(server.takeRequest(), "POST", "/v2.0/routers", 
"/router_create_request.json");
+
+         /*
+          * Check response
+          */
+         assertNotNull(router);
+         assertEquals(router.getName(), "another_router");
+         assertEquals(router.getExternalGatewayInfo().getNetworkId(), 
"8ca37218-28ff-41cb-9b10-039601ea7e6b");
+         assertEquals(router.getStatus(), NetworkStatus.ACTIVE);
+         assertEquals(router.isAdminStateUp().booleanValue(), true);
+         assertEquals(router.getId(), "8604a0de-7f6b-409a-a47c-a1cc7bc77b2e");
+         assertEquals(router.getTenantId(), 
"6b96ff0cb17a4b859e1e575d221683d3");
+      } finally {
+         server.shutdown();
+      }
+   }
+
+   @Test(expectedExceptions = ResourceNotFoundException.class)
+   public void testCreateRouterFail() 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.getRouterExtensionForZone("RegionOne").get();
+
+         Router.CreateOptions createRouter = 
Router.createOptions().name("another_router").adminStateUp(true)
+               
.externalGatewayInfo(ExternalGatewayInfo.builder().networkId("8ca37218-28ff-41cb-9b10-039601ea7e6b").build())
+               .build();
+
+         Router router = api.create(createRouter);
+         fail("Should have failed with not found exception");
+
+      } finally {
+         server.shutdown();
+      }
+   }
+
+   public void testListSpecificPagePort() 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.getRouterExtensionForZone("RegionOne").get();
+
+         Routers routers = 
api.list(PaginationOptions.Builder.limit(2).marker("abcdefg"));
+
+         /*
+          * Check request
+          */
+         assertAuthentication(server);
+         assertRequest(server.takeRequest(), "GET", 
"/v2.0/routers?limit=2&marker=abcdefg");
+
+         /*
+          * Check response
+          */
+         assertNotNull(routers);
+         assertEquals(routers.size(), 2);
+         
assertEquals(routers.first().get().getId(),"a9254bdb-2613-4a13-ac4c-adc581fba50d");
+      } finally {
+         server.shutdown();
+      }
+   }
+
+   public void testListSpecificPagePortFail() 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.getRouterExtensionForZone("RegionOne").get();
+
+         Routers routers = 
api.list(PaginationOptions.Builder.limit(2).marker("abcdefg"));
+
+         /*
+          * Check request
+          */
+         assertAuthentication(server);
+         assertRequest(server.takeRequest(), "GET", 
"/v2.0/routers?limit=2&marker=abcdefg");
+
+         /*
+          * Check response
+          */
+         assertNotNull(routers);
+         assertTrue(routers.isEmpty());
+      } finally {
+         server.shutdown();
+      }
+   }
+
+   public void testListPagedRouter() 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"))));
+      server.enqueue(addCommonHeaders(new 
MockResponse().setResponseCode(200).setBody(stringFromResource("/router_list_response_paged2.json"))));
+
+      try {
+         NeutronApi neutronApi = api(server.getUrl("/").toString(), 
"openstack-neutron", overrides);
+         RouterApi api = 
neutronApi.getRouterExtensionForZone("RegionOne").get();
+
+         // Note: Lazy! Have to actually look at the collection.
+         List<Router> routers = api.list().concat().toList();
+
+         /*
+          * Check request
+          */
+         assertEquals(server.getRequestCount(), 3);
+         assertAuthentication(server);
+         assertRequest(server.takeRequest(), "GET", "/v2.0/routers");
+         assertRequest(server.takeRequest(), "GET", 
"/v2.0/routers?marker=71c1e68c-171a-4aa2-aca5-50ea153a3718");
+
+         /*
+          * Check response
+          */
+         assertNotNull(routers);
+         assertEquals(routers.size(), 4);
+         
assertEquals(routers.get(0).getId(),"a9254bdb-2613-4a13-ac4c-adc581fba50d");
+         
assertEquals(routers.get(3).getId(),"a9254bdb-2613-4a13-ac4c-adc581fba50d_4");
+      } finally {
+         server.shutdown();
+      }
+   }
+
+   public void testListPagedRouterFail() 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.getRouterExtensionForZone("RegionOne").get();
+
+         // Note: Lazy! Have to actually look at the collection.
+         List<Router> routers = api.list().concat().toList();
+
+         /*
+          * Check request
+          */
+         assertEquals(server.getRequestCount(), 2);
+         assertAuthentication(server);
+         assertRequest(server.takeRequest(), "GET", "/v2.0/routers");
+
+         /*
+          * Check response
+          */
+         assertNotNull(routers);
+         assertTrue(routers.isEmpty());
+      } finally {
+         server.shutdown();
+      }
+   }
+
+   public void testGetRouter() 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("/router_get_response.json"))));
+
+      try {
+         NeutronApi neutronApi = api(server.getUrl("/").toString(), 
"openstack-neutron", overrides);
+         RouterApi api = 
neutronApi.getRouterExtensionForZone("RegionOne").get();
+
+         Router router = api.get("12345");
+
+         /*
+          * Check request
+          */
+         assertAuthentication(server);
+         assertRequest(server.takeRequest(), "GET", "/v2.0/routers/12345");
+
+         /*
+          * Check response
+          */
+         assertNotNull(router);
+         assertEquals(router.getName(), "router1");
+         assertEquals(router.getExternalGatewayInfo().getNetworkId(), 
"3c5bcddd-6af9-4e6b-9c3e-c153e521cab8");
+         assertEquals(router.getStatus(), NetworkStatus.ACTIVE);
+         assertEquals(router.isAdminStateUp().booleanValue(), true);
+         assertEquals(router.getId(), "a9254bdb-2613-4a13-ac4c-adc581fba50d");
+         assertEquals(router.getTenantId(), 
"33a40233088643acb66ff6eb0ebea679");
+      } finally {
+         server.shutdown();
+      }
+   }
+
+   public void testGetRouterFail() 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.getRouterExtensionForZone("RegionOne").get();
+
+         Router router = api.get("12345");
+
+         /*
+          * Check request
+          */
+         assertAuthentication(server);
+         assertRequest(server.takeRequest(), "GET", "/v2.0/routers/12345");
+
+         /*
+          * Check response
+          */
+         assertNull(router);
+      } finally {
+         server.shutdown();
+      }
+   }
+
+   public void testUpdateRouter() 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("/router_update_response.json"))));
+
+      try {
+         NeutronApi neutronApi = api(server.getUrl("/").toString(), 
"openstack-neutron", overrides);
+         RouterApi api = 
neutronApi.getRouterExtensionForZone("RegionOne").get();
+
+         Router.UpdateOptions updateOptions = Router.updateOptions()
+               .externalGatewayInfo(
+                     
ExternalGatewayInfo.builder().networkId("8ca37218-28ff-41cb-9b10-039601ea7e6b").build())
+               .build();
+
+         Router router = api.update("12345", updateOptions);
+
+         /*
+          * Check request
+          */
+         assertAuthentication(server);
+         assertRequest(server.takeRequest(), "PUT", "/v2.0/routers/12345", 
"/router_update_request.json");
+
+         /*
+          * Check response
+          */
+         assertNotNull(router);
+         assertEquals(router.getName(), "another_router");
+         assertEquals(router.getExternalGatewayInfo().getNetworkId(), 
"8ca37218-28ff-41cb-9b10-039601ea7e6b");
+         assertEquals(router.getStatus(), NetworkStatus.ACTIVE);
+         assertEquals(router.isAdminStateUp().booleanValue(), true);
+         assertEquals(router.getId(), "8604a0de-7f6b-409a-a47c-a1cc7bc77b2e");
+         assertEquals(router.getTenantId(), 
"6b96ff0cb17a4b859e1e575d221683d3");
+      } finally {
+         server.shutdown();
+      }
+   }
+
+   public void testUpdateRouterFail() 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.getRouterExtensionForZone("RegionOne").get();
+
+         Router.UpdateOptions updateOptions = Router.updateOptions()
+               .externalGatewayInfo(
+                     
ExternalGatewayInfo.builder().networkId("8ca37218-28ff-41cb-9b10-039601ea7e6b").build())
+               .build();
+
+         Router router = api.update("12345", updateOptions);
+
+         /*
+          * Check request
+          */
+         assertAuthentication(server);
+         assertRequest(server.takeRequest(), "PUT", "/v2.0/routers/12345", 
"/router_update_request.json");
+
+         /*
+          * Check response
+          */
+         assertNull(router);
+      } finally {
+         server.shutdown();
+      }
+   }
+
+   public void testDeleteRouter() 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);
+         RouterApi api = 
neutronApi.getRouterExtensionForZone("RegionOne").get();
+
+         boolean result = api.delete("12345");
+
+         /*
+          * Check request
+          */
+         assertAuthentication(server);
+         assertRequest(server.takeRequest(), "DELETE", "/v2.0/routers/12345");
+
+         /*
+          * Check response
+          */
+         assertTrue(result);
+      } finally {
+         server.shutdown();
+      }
+   }
+
+   public void testDeleteRouterFail() 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.getRouterExtensionForZone("RegionOne").get();
+
+         boolean result = api.delete("12345");
+
+         /*
+          * Check request
+          */
+         assertAuthentication(server);
+         assertRequest(server.takeRequest(), "DELETE", "/v2.0/routers/12345");
+
+         /*
+          * Check response
+          */
+         assertFalse(result);
+      } finally {
+         server.shutdown();
+      }
+   }
+
+   public void testAddRouterInterfaceForSubnet() 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("/router_add_interface_response.json"))));
+
+      try {
+         NeutronApi neutronApi = api(server.getUrl("/").toString(), 
"openstack-neutron", overrides);
+         RouterApi api = 
neutronApi.getRouterExtensionForZone("RegionOne").get();
+
+         RouterInterface routerInterface = api.addInterfaceForSubnet("12345", 
"a2f1f29d-571b-4533-907f-5803ab96ead1");
+
+         /*
+          * Check request
+          */
+         assertAuthentication(server);
+         assertRequest(server.takeRequest(), "PUT", 
"/v2.0/routers/12345/add_router_interface", 
"/router_add_interface_request.json");
+
+         /*
+          * Check response
+          */
+         assertNotNull(routerInterface);
+         assertEquals(routerInterface.getSubnetId(), 
"a2f1f29d-571b-4533-907f-5803ab96ead1");
+         assertEquals(routerInterface.getPortId(), 
"3a44f4e5-1694-493a-a1fb-393881c673a4");
+      } finally {
+         server.shutdown();
+      }
+   }
+
+   public void testAddRouterInterfaceForSubnetFail() 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.getRouterExtensionForZone("RegionOne").get();
+
+         RouterInterface routerInterface = api.addInterfaceForSubnet("12345", 
"a2f1f29d-571b-4533-907f-5803ab96ead1");
+
+         /*
+          * Check request
+          */
+         assertAuthentication(server);
+         assertRequest(server.takeRequest(), "PUT", 
"/v2.0/routers/12345/add_router_interface", 
"/router_add_interface_request.json");
+
+         /*
+          * Check response
+          */
+         assertNull(routerInterface);
+      } finally {
+         server.shutdown();
+      }
+   }
+
+   public void testAddRouterInterfaceForPort() 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("/router_add_interface_response.json"))));
+
+      try {
+         NeutronApi neutronApi = api(server.getUrl("/").toString(), 
"openstack-neutron", overrides);
+         RouterApi api = 
neutronApi.getRouterExtensionForZone("RegionOne").get();
+
+         RouterInterface routerInterface = api.addInterfaceForPort("12345", 
"portid");
+
+         /*
+          * Check request
+          */
+         assertAuthentication(server);
+         assertRequest(server.takeRequest(), "PUT", 
"/v2.0/routers/12345/add_router_interface", 
"/router_add_interface_port_request.json");
+
+         /*
+          * Check response
+          */
+         assertNotNull(routerInterface);
+         assertEquals(routerInterface.getSubnetId(), 
"a2f1f29d-571b-4533-907f-5803ab96ead1");
+         assertEquals(routerInterface.getPortId(), 
"3a44f4e5-1694-493a-a1fb-393881c673a4");
+      } finally {
+         server.shutdown();
+      }
+   }
+
+   public void testAddRouterInterfaceForPortFail() 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.getRouterExtensionForZone("RegionOne").get();
+
+         RouterInterface routerInterface = api.addInterfaceForPort("12345", 
"portid");
+
+         /*
+          * Check request
+          */
+         assertAuthentication(server);
+         assertRequest(server.takeRequest(), "PUT", 
"/v2.0/routers/12345/add_router_interface", 
"/router_add_interface_port_request.json");
+
+         /*
+          * Check response
+          */
+         assertNull(routerInterface);
+      } finally {
+         server.shutdown();
+      }
+   }
+
+   public void testRemoveRouterInterfaceForSubnet() 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);
+         RouterApi api = 
neutronApi.getRouterExtensionForZone("RegionOne").get();
+
+         boolean result = api.removeInterfaceForSubnet("12345", 
"a2f1f29d-571b-4533-907f-5803ab96ead1");
+
+         /*
+          * Check request
+          */
+         assertAuthentication(server);
+         assertRequest(server.takeRequest(), "PUT", 
"/v2.0/routers/12345/remove_router_interface", 
"/router_remove_interface_subnet_request.json");
+
+         /*
+          * Check response
+          */
+         assertTrue(result);
+      } finally {
+         server.shutdown();
+      }
+   }
+
+   public void testRemoveRouterInterfaceForSubnetFail() 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.getRouterExtensionForZone("RegionOne").get();
+
+         boolean result = api.removeInterfaceForSubnet("12345", 
"a2f1f29d-571b-4533-907f-5803ab96ead1");
+
+         /*
+          * Check request
+          */
+         assertAuthentication(server);
+         assertRequest(server.takeRequest(), "PUT", 
"/v2.0/routers/12345/remove_router_interface", 
"/router_remove_interface_subnet_request.json");
+
+         /*
+          * Check response
+          */
+         assertFalse(result);
+      } finally {
+         server.shutdown();
+      }
+   }
+
+   public void testRemoveRouterInterfaceForPort() 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);
+         RouterApi api = 
neutronApi.getRouterExtensionForZone("RegionOne").get();
+
+         boolean result = api.removeInterfaceForPort("12345", "portid");
+
+         /*
+          * Check request
+          */
+         assertAuthentication(server);
+         assertRequest(server.takeRequest(), "PUT", 
"/v2.0/routers/12345/remove_router_interface", 
"/router_remove_interface_port_request.json");
+
+         /*
+          * Check response
+          */
+         assertTrue(result);
+      } finally {
+         server.shutdown();
+      }
+   }
+
+   public void testRemoveRouterInterfaceForPortFail() 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.getRouterExtensionForZone("RegionOne").get();
+
+         boolean result = api.removeInterfaceForPort("12345", "portid");
+
+         /*
+          * Check request
+          */
+         assertAuthentication(server);
+         assertRequest(server.takeRequest(), "PUT", 
"/v2.0/routers/12345/remove_router_interface", 
"/router_remove_interface_port_request.json");
+
+         /*
+          * Check response
+          */
+         assertFalse(result);
+      } finally {
+         server.shutdown();
+      }
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/9c4bd944/openstack-neutron/src/test/java/org/jclouds/openstack/neutron/v2/features/SubnetApiLiveTest.java
----------------------------------------------------------------------
diff --git 
a/openstack-neutron/src/test/java/org/jclouds/openstack/neutron/v2/features/SubnetApiLiveTest.java
 
b/openstack-neutron/src/test/java/org/jclouds/openstack/neutron/v2/features/SubnetApiLiveTest.java
new file mode 100644
index 0000000..84b8228
--- /dev/null
+++ 
b/openstack-neutron/src/test/java/org/jclouds/openstack/neutron/v2/features/SubnetApiLiveTest.java
@@ -0,0 +1,118 @@
+/*
+ * 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.features;
+
+import com.google.common.base.Predicate;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Sets;
+import org.jclouds.openstack.neutron.v2.domain.AllocationPool;
+import org.jclouds.openstack.neutron.v2.domain.HostRoute;
+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.internal.BaseNeutronApiLiveTest;
+import org.jclouds.openstack.neutron.v2.util.PredicateUtil;
+import org.testng.annotations.Test;
+
+import java.util.Set;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+
+/**
+ * Tests subnet api in combination with the network api
+ */
+@Test(groups = "live", testName = "SubnetApiLiveTest")
+public class SubnetApiLiveTest extends BaseNeutronApiLiveTest {
+
+   public void testCreateUpdateAndDeleteSubnet() {
+      for (String zone : api.getConfiguredRegions()) {
+         NetworkApi networkApi = api.getNetworkApiForZone(zone);
+         String networkId = 
networkApi.create(Network.createOptions("jclouds-live-test").networkType(NetworkType.LOCAL).build()).getId();
+
+         SubnetApi subnetApi = api.getSubnetApiForZone(zone);
+         ImmutableSet<AllocationPool> allocationPools = ImmutableSet.of(
+            
AllocationPool.builder().start("a3:bc00::10").end("a3:bc00::20").build(),
+            
AllocationPool.builder().start("a3:bc00::50").end("a3:bc00::90").build()
+         );
+         ImmutableSet<HostRoute> hostRoutes = ImmutableSet.of(
+            
HostRoute.builder().destinationCidr("a3:bc00::/48").nextHop("a3:bc00::0004").build()
+         );
+         Subnet subnet = subnetApi.create(Subnet.createOptions(networkId, 
"a3:bc00::/48").ipVersion(6).allocationPools(allocationPools).hostRoutes(hostRoutes).build());
+         assertNotNull(subnet);
+
+         /* Test list and get */
+         Subnet subnetList = 
api.getSubnetApiForZone(zone).list().concat().toSet().iterator().next();
+         assertNotNull(subnetList);
+         Subnet subnetGet = 
api.getSubnetApiForZone(zone).get(subnetList.getId());
+         assertEquals(subnetList, subnetGet);
+         /***/
+
+         Subnet retrievedSubnet = subnetApi.get(subnet.getId());
+
+         assertEquals(retrievedSubnet.getId(), subnet.getId());
+         assertEquals(retrievedSubnet.getCidr(), "a3:bc00::/48");
+         assertTrue(retrievedSubnet.getDnsNameservers().isEmpty());
+         assertEquals(retrievedSubnet.getAllocationPools().size(), 2);
+         assertEquals(retrievedSubnet.getHostRoutes().size(), 1);
+         assertNotNull(subnetApi.update(retrievedSubnet.getId(), 
Subnet.updateOptions().name("jclouds-live-test-update").build()));
+
+         retrievedSubnet = subnetApi.get(retrievedSubnet.getId());
+
+         assertEquals(retrievedSubnet.getId(), subnet.getId());
+         assertEquals(retrievedSubnet.getName(), "jclouds-live-test-update");
+         assertTrue(retrievedSubnet.getDnsNameservers().isEmpty());
+
+         Subnet subnet2 = subnetApi.create(Subnet.createOptions(networkId, 
"a3:bd01::/48").ipVersion(6).build());
+         assertNotNull(subnet2);
+
+         assertTrue(subnetApi.delete(subnet.getId()));
+         assertTrue(subnetApi.delete(subnet2.getId()));
+         assertTrue(networkApi.delete(networkId));
+      }
+   }
+
+   public void testBulkCreateSubnet() {
+      for (String zone : api.getConfiguredRegions()) {
+         NetworkApi networkApi = api.getNetworkApiForZone(zone);
+         String networkId = 
networkApi.create(Network.createOptions("jclouds-live-test").networkType(NetworkType.LOCAL).build()).getId();
+
+         SubnetApi subnetApi = api.getSubnetApiForZone(zone);
+         Set<? extends Subnet> subnets = subnetApi.createBulk(
+               ImmutableList.of(
+                  Subnet.createOptions("jclouds-live-test-1", 
"a3:bd01::/48").ipVersion(6).networkId(networkId).build(),
+                  Subnet.createOptions("jclouds-live-test-2", 
"a3:bd02::/48").ipVersion(6).networkId(networkId).build(),
+                  Subnet.createOptions("jclouds-live-test-3", 
"a3:bd03::/48").ipVersion(6).networkId(networkId).build()
+               )
+         ).toSet();
+         Set<Subnet> existingSubnets = subnetApi.list().concat().toSet();
+
+         assertNotNull(subnets);
+         assertTrue(!subnets.isEmpty());
+         assertEquals(subnets.size(), 3);
+
+         for (Subnet net : subnets) {
+            Predicate<Subnet> idEqualsPredicate = 
PredicateUtil.createIdEqualsPredicate(net.getId());
+            assertEquals(1, Sets.filter(existingSubnets, 
idEqualsPredicate).size());
+            assertTrue(subnetApi.delete(net.getId()));
+         }
+         assertTrue(networkApi.delete(networkId));
+      }
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/9c4bd944/openstack-neutron/src/test/java/org/jclouds/openstack/neutron/v2/features/SubnetApiMockTest.java
----------------------------------------------------------------------
diff --git 
a/openstack-neutron/src/test/java/org/jclouds/openstack/neutron/v2/features/SubnetApiMockTest.java
 
b/openstack-neutron/src/test/java/org/jclouds/openstack/neutron/v2/features/SubnetApiMockTest.java
new file mode 100644
index 0000000..7e725bf
--- /dev/null
+++ 
b/openstack-neutron/src/test/java/org/jclouds/openstack/neutron/v2/features/SubnetApiMockTest.java
@@ -0,0 +1,472 @@
+/*
+ * 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.features;
+
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.ImmutableList;
+import com.squareup.okhttp.mockwebserver.MockResponse;
+import com.squareup.okhttp.mockwebserver.MockWebServer;
+import org.jclouds.openstack.neutron.v2.NeutronApi;
+import org.jclouds.openstack.neutron.v2.domain.IPv6DHCPMode;
+import org.jclouds.openstack.neutron.v2.domain.Subnet;
+import org.jclouds.openstack.neutron.v2.domain.Subnets;
+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 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;
+
+/**
+ * Tests NetworkApi Guice wiring and parsing
+ *
+ */
+@Test
+public class SubnetApiMockTest extends BaseNeutronApiMockTest {
+
+   public void testCreateSubnet() 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("/subnet_create_response.json"))));
+
+      try {
+         NeutronApi neutronApi = api(server.getUrl("/").toString(), 
"openstack-neutron", overrides);
+         SubnetApi api = neutronApi.getSubnetApiForZone("RegionOne");
+
+         Subnet.CreateOptions createSubnet = 
Subnet.createOptions("1234567890", "10.0.3.0/24")
+               .name("jclouds-wibble")
+               .ipVersion(4)
+               .build();
+
+         Subnet subnet = api.create(createSubnet);
+
+         /*
+          * Check request
+          */
+         assertAuthentication(server);
+         assertRequest(server.takeRequest(), "POST", "/v2.0/subnets", 
"/subnet_create_request.json");
+
+         /*
+          * Check response
+          */
+         assertNotNull(subnet);
+         assertEquals(subnet.getName(),"jclouds-wibble");
+         assertEquals(subnet.getIpVersion().intValue(), 4);
+         assertEquals(subnet.getCidr(), "10.0.3.0/24");
+         assertEquals(subnet.getTenantId(), "1234567890");
+         assertEquals(subnet.getId(), "624312ff-d14b-4ba3-9834-1c78d23d574d");
+      } finally {
+         server.shutdown();
+      }
+   }
+
+   @Test(expectedExceptions = ResourceNotFoundException.class)
+   public void testCreateSubnetFail() 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);
+         SubnetApi api = neutronApi.getSubnetApiForZone("RegionOne");
+
+         Subnet.CreateOptions createSubnet = 
Subnet.createOptions("1234567890", "cidr")
+               .name("jclouds-wibble")
+               .ipVersion(4)
+               .build();
+
+         Subnet subnet = api.create(createSubnet);
+      } finally {
+         server.shutdown();
+      }
+   }
+
+   public void testListSpecificPageSubnet() 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("/subnet_list_response_pages1.json"))));
+
+      try {
+         NeutronApi neutronApi = api(server.getUrl("/").toString(), 
"openstack-neutron", overrides);
+         SubnetApi api = neutronApi.getSubnetApiForZone("RegionOne");
+
+         Subnets subnets = 
api.list(PaginationOptions.Builder.limit(2).marker("abcdefg"));
+
+         /*
+          * Check request
+          */
+         assertAuthentication(server);
+         assertRequest(server.takeRequest(), "GET", 
"/v2.0/subnets?limit=2&marker=abcdefg");
+
+         /*
+          * Check response
+          */
+         assertNotNull(subnets);
+         
assertEquals(subnets.first().get().getId(),"16dba3bc-f3fa-4775-afdc-237e12c72f6a");
+      } finally {
+         server.shutdown();
+      }
+   }
+
+   public void testListSpecificPageSubnetFail() 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);
+         SubnetApi api = neutronApi.getSubnetApiForZone("RegionOne");
+
+         Subnets subnets = 
api.list(PaginationOptions.Builder.limit(2).marker("abcdefg"));
+
+         /*
+          * Check request
+          */
+         assertAuthentication(server);
+         assertRequest(server.takeRequest(), "GET", 
"/v2.0/subnets?limit=2&marker=abcdefg");
+
+         /*
+          * Check response
+          */
+         assertTrue(subnets.isEmpty());
+      } finally {
+         server.shutdown();
+      }
+   }
+
+   public void testListPagedSubnet() 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("/subnet_list_response_pages1.json"))));
+      server.enqueue(addCommonHeaders(new 
MockResponse().setResponseCode(200).setBody(stringFromResource("/subnet_list_response_pages2.json"))));
+
+      try {
+         NeutronApi neutronApi = api(server.getUrl("/").toString(), 
"openstack-neutron", overrides);
+         SubnetApi api = neutronApi.getSubnetApiForZone("RegionOne");
+
+         // Note: Lazy! Have to actually look at the collection.
+         List<Subnet> subnets = api.list().concat().toList();
+
+         /*
+          * Check request
+          */
+         assertEquals(server.getRequestCount(), 3);
+         assertAuthentication(server);
+         assertRequest(server.takeRequest(), "GET", "/v2.0/subnets");
+         assertRequest(server.takeRequest(), "GET", 
"/v2.0/subnets?marker=71c1e68c-171a-4aa2-aca5-50ea153a3718");
+
+         /*
+          * Check response
+          */
+         assertNotNull(subnets);
+         assertEquals(subnets.size(), 4);
+         
assertEquals(subnets.get(0).getId(),"16dba3bc-f3fa-4775-afdc-237e12c72f6a");
+         
assertEquals(subnets.get(3).getId(),"6ba4c788-661f-49ab-9bf8-5f10cbbb2f57");
+      } finally {
+         server.shutdown();
+      }
+   }
+
+   public void testListPagedSubnetFail() 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);
+         SubnetApi api = neutronApi.getSubnetApiForZone("RegionOne");
+
+         // Note: Lazy! Have to actually look at the collection.
+         List<Subnet> subnets = api.list().concat().toList();
+
+         /*
+          * Check request
+          */
+         assertEquals(server.getRequestCount(), 2);
+         assertAuthentication(server);
+         assertRequest(server.takeRequest(), "GET", "/v2.0/subnets");
+
+         /*
+          * Check response
+          */
+         assertTrue(subnets.isEmpty());
+      } finally {
+         server.shutdown();
+      }
+   }
+
+   public void testGetSubnet() 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("/subnet_get_response.json"))));
+
+      try {
+         NeutronApi neutronApi = api(server.getUrl("/").toString(), 
"openstack-neutron", overrides);
+         SubnetApi api = neutronApi.getSubnetApiForZone("RegionOne");
+
+         Subnet subnet = api.get("12345");
+
+         /*
+          * Check request
+          */
+         assertEquals(server.getRequestCount(), 2);
+         assertAuthentication(server);
+         assertRequest(server.takeRequest(), "GET", "/v2.0/subnets/12345");
+
+         /*
+          * Check response
+          */
+         assertNotNull(subnet);
+         assertEquals(subnet.getName(),"jclouds-wibble");
+         assertEquals(subnet.getId(),"624312ff-d14b-4ba3-9834-1c78d23d574d");
+         assertEquals(subnet.getTenantId(),"1234567890");
+         assertEquals(subnet.getIPv6AddressMode(), IPv6DHCPMode.SLAAC);
+      } finally {
+         server.shutdown();
+      }
+   }
+
+   public void testGetSubnetFail() 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);
+         SubnetApi api = neutronApi.getSubnetApiForZone("RegionOne");
+
+         Subnet subnet = api.get("12345");
+
+         /*
+          * Check request
+          */
+         assertEquals(server.getRequestCount(), 2);
+         assertAuthentication(server);
+         assertRequest(server.takeRequest(), "GET", "/v2.0/subnets/12345");
+
+         /*
+          * Check response
+          */
+         assertNull(subnet);
+      } finally {
+         server.shutdown();
+      }
+   }
+
+   public void testCreateBulkSubnet() 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("/subnet_bulk_create_response.json"))));
+
+      try {
+         NeutronApi neutronApi = api(server.getUrl("/").toString(), 
"openstack-neutron", overrides);
+         SubnetApi api = neutronApi.getSubnetApiForZone("RegionOne");
+
+         Subnet.CreateOptions createSubnet1 = 
Subnet.createOptions("e6031bc2-901a-4c66-82da-f4c32ed89406",
+               "192.168.199.0/24")
+               .ipVersion(4)
+               .build();
+
+         Subnet.CreateOptions createSubnet2 = 
Subnet.createOptions("64239a54-dcc4-4b39-920b-b37c2144effa",
+               "10.56.4.0/22")
+               .ipVersion(4)
+               .build();
+
+         FluentIterable<Subnet> subnets = 
api.createBulk(ImmutableList.of(createSubnet1, createSubnet2));
+
+         /*
+          * Check request
+          */
+         assertAuthentication(server);
+         assertRequest(server.takeRequest(), "POST", "/v2.0/subnets", 
"/subnet_bulk_create_request.json");
+
+         /*
+          * Check response
+          */
+         assertNotNull(subnets);
+         assertEquals(subnets.size(), 2);
+         assertEquals(subnets.get(0).getName(), "");
+         assertEquals(subnets.get(0).getIpVersion().intValue(), 4);
+         assertEquals(subnets.get(0).getCidr(), "192.168.199.0/24");
+         assertTrue(subnets.get(0).getDnsNameservers().isEmpty());
+         assertTrue(subnets.get(0).getEnableDhcp());
+         assertTrue(subnets.get(0).getHostRoutes().isEmpty());
+         assertEquals(subnets.get(0).getTenantId(), 
"d19231fc08ec4bc4829b668040d34512");
+         assertEquals(subnets.get(0).getId(), 
"0468a7a7-290d-4127-aedd-6c9449775a24");
+         assertEquals(subnets.get(0).getNetworkId(), 
"e6031bc2-901a-4c66-82da-f4c32ed89406");
+         
assertEquals(subnets.get(0).getAllocationPools().iterator().next().getStart(), 
"192.168.199.2");
+         
assertEquals(subnets.get(0).getAllocationPools().iterator().next().getEnd(), 
"192.168.199.254");
+      } finally {
+         server.shutdown();
+      }
+   }
+
+   @Test(expectedExceptions = ResourceNotFoundException.class)
+   public void testCreateBulkSubnetFail() 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);
+         SubnetApi api = neutronApi.getSubnetApiForZone("RegionOne");
+
+         Subnet.CreateOptions createSubnet1 = 
Subnet.createOptions("e6031bc2-901a-4c66-82da-f4c32ed89406",
+               "192.168.199.0/24")
+               .ipVersion(4)
+               .build();
+
+         Subnet.CreateOptions createSubnet2 = 
Subnet.createOptions("64239a54-dcc4-4b39-920b-b37c2144effa",
+               "10.56.4.0/22")
+               .ipVersion(4)
+               .build();
+
+         FluentIterable<Subnet> subnets = 
api.createBulk(ImmutableList.of(createSubnet1, createSubnet2));
+      } finally {
+         server.shutdown();
+      }
+   }
+
+   public void testUpdateSubnet() 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("/subnet_update_response.json"))));
+
+      try {
+         NeutronApi neutronApi = api(server.getUrl("/").toString(), 
"openstack-neutron", overrides);
+         SubnetApi api = neutronApi.getSubnetApiForZone("RegionOne");
+
+         Subnet.UpdateOptions updateSubnet = Subnet.updateOptions()
+               .name("new_name")
+               .gatewayIp("10.0.3.254")
+               .build();
+
+         Subnet subnet = api.update("12345", updateSubnet);
+
+         /*
+          * Check request
+          */
+         assertEquals(server.getRequestCount(), 2);
+         assertAuthentication(server);
+         assertRequest(server.takeRequest(), "PUT", "/v2.0/subnets/12345", 
"/subnet_update_request.json");
+
+         /*
+          * Check response
+          */
+         assertNotNull(subnet);
+         assertEquals(subnet.getName(),"new_name");
+         assertEquals(subnet.getId(),"9436e561-47bf-436a-b1f1-fe23a926e031");
+         assertEquals(subnet.getTenantId(),"c1210485b2424d48804aad5d39c61b8f");
+      } finally {
+         server.shutdown();
+      }
+   }
+
+   public void testUpdateSubnetFail() 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);
+         SubnetApi api = neutronApi.getSubnetApiForZone("RegionOne");
+
+         Subnet.UpdateOptions updateSubnet = Subnet.updateOptions()
+               .name("new_name")
+               .gatewayIp("10.0.3.254")
+               .build();
+
+         Subnet subnet = api.update("12345", updateSubnet);
+
+         /*
+          * Check request
+          */
+         assertEquals(server.getRequestCount(), 2);
+         assertAuthentication(server);
+         assertRequest(server.takeRequest(), "PUT", "/v2.0/subnets/12345", 
"/subnet_update_request.json");
+
+         /*
+          * Check response
+          */
+         assertNull(subnet);
+      } finally {
+         server.shutdown();
+      }
+   }
+
+   public void testDeleteSubnet() throws IOException, InterruptedException, 
URISyntaxException {
+      MockWebServer server = mockOpenStackServer();
+      server.enqueue(addCommonHeaders(new 
MockResponse().setBody(stringFromResource("/access.json"))));
+      server.enqueue(addCommonHeaders(new 
MockResponse().setResponseCode(200)));
+
+      try {
+         NeutronApi neutronApi = api(server.getUrl("/").toString(), 
"openstack-neutron", overrides);
+         SubnetApi api = neutronApi.getSubnetApiForZone("RegionOne");
+
+         boolean result = api.delete("12345");
+
+         /*
+          * Check request
+          */
+         assertEquals(server.getRequestCount(), 2);
+         assertAuthentication(server);
+         assertRequest(server.takeRequest(), "DELETE", "/v2.0/subnets/12345");
+
+         /*
+          * Check response
+          */
+         assertTrue(result);
+      } finally {
+         server.shutdown();
+      }
+   }
+
+   public void testDeleteSubnetFail() 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);
+         SubnetApi api = neutronApi.getSubnetApiForZone("RegionOne");
+
+         boolean result = api.delete("12345");
+
+         /*
+          * Check request
+          */
+         assertEquals(server.getRequestCount(), 2);
+         assertAuthentication(server);
+         assertRequest(server.takeRequest(), "DELETE", "/v2.0/subnets/12345");
+
+         /*
+          * Check response
+          */
+         assertFalse(result);
+      } finally {
+         server.shutdown();
+      }
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/9c4bd944/openstack-neutron/src/test/java/org/jclouds/openstack/neutron/v2/internal/BaseNeutronApiLiveTest.java
----------------------------------------------------------------------
diff --git 
a/openstack-neutron/src/test/java/org/jclouds/openstack/neutron/v2/internal/BaseNeutronApiLiveTest.java
 
b/openstack-neutron/src/test/java/org/jclouds/openstack/neutron/v2/internal/BaseNeutronApiLiveTest.java
new file mode 100644
index 0000000..7ebcaf6
--- /dev/null
+++ 
b/openstack-neutron/src/test/java/org/jclouds/openstack/neutron/v2/internal/BaseNeutronApiLiveTest.java
@@ -0,0 +1,46 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds 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.internal;
+
+import org.jclouds.apis.BaseApiLiveTest;
+import org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties;
+import org.jclouds.openstack.neutron.v2.NeutronApi;
+import org.testng.annotations.Test;
+
+import java.util.Properties;
+
+/**
+ * Tests behavior of {@code NeutronApi}
+ *
+ */
+@Test(groups = "live")
+public class BaseNeutronApiLiveTest extends BaseApiLiveTest<NeutronApi> {
+
+   public BaseNeutronApiLiveTest() {
+      provider = "openstack-neutron";
+   }
+
+   @Override
+   protected Properties setupProperties() {
+      Properties props = super.setupProperties();
+      setIfTestSystemPropertyPresent(props, 
KeystoneProperties.CREDENTIAL_TYPE);
+      return props;
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/9c4bd944/openstack-neutron/src/test/java/org/jclouds/openstack/neutron/v2/internal/BaseNeutronApiMockTest.java
----------------------------------------------------------------------
diff --git 
a/openstack-neutron/src/test/java/org/jclouds/openstack/neutron/v2/internal/BaseNeutronApiMockTest.java
 
b/openstack-neutron/src/test/java/org/jclouds/openstack/neutron/v2/internal/BaseNeutronApiMockTest.java
new file mode 100644
index 0000000..a1ac790
--- /dev/null
+++ 
b/openstack-neutron/src/test/java/org/jclouds/openstack/neutron/v2/internal/BaseNeutronApiMockTest.java
@@ -0,0 +1,41 @@
+/*
+ * 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.internal;
+
+import org.jclouds.openstack.keystone.v2_0.config.CredentialTypes;
+import org.jclouds.openstack.neutron.v2.NeutronApi;
+import org.jclouds.openstack.v2_0.internal.BaseOpenStackMockTest;
+
+import java.util.Properties;
+
+import static 
org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties.CREDENTIAL_TYPE;
+
+/**
+ * Base class for writing Neutron Mock tests
+ *
+ */
+public class BaseNeutronApiMockTest extends BaseOpenStackMockTest<NeutronApi> {
+   protected Properties overrides;
+   /**
+    * Base Mock Test
+    */
+   public BaseNeutronApiMockTest() {
+      overrides = new Properties();
+      //overrides.setProperty(SERVICE_TYPE, "neutron");
+      overrides.setProperty(CREDENTIAL_TYPE, 
CredentialTypes.PASSWORD_CREDENTIALS);
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/9c4bd944/openstack-neutron/src/test/java/org/jclouds/openstack/neutron/v2/util/ClassUtil.java
----------------------------------------------------------------------
diff --git 
a/openstack-neutron/src/test/java/org/jclouds/openstack/neutron/v2/util/ClassUtil.java
 
b/openstack-neutron/src/test/java/org/jclouds/openstack/neutron/v2/util/ClassUtil.java
new file mode 100644
index 0000000..b9ba915
--- /dev/null
+++ 
b/openstack-neutron/src/test/java/org/jclouds/openstack/neutron/v2/util/ClassUtil.java
@@ -0,0 +1,39 @@
+/*
+ * 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.util;
+
+import java.lang.reflect.Field;
+
+public class ClassUtil {
+
+    public static Field findField(Class clazz, String fieldName) {
+        Field fieldToFind = null;
+        if (clazz.getSuperclass() != null)
+            fieldToFind = findField(clazz.getSuperclass(), fieldName);
+
+        if (fieldToFind != null)
+            return fieldToFind;
+
+        for (Field field : clazz.getDeclaredFields()) {
+            if (field.getName().equals(fieldName))
+                return field;
+        }
+        return null;
+    }
+
+}

Reply via email to