You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jclouds.apache.org by za...@apache.org on 2014/07/25 23:20:07 UTC

[4/5] Neutron Refactoring v2_0 -> v2 No options (redesign) More features (extension-related) Live tests Redesigned domain objects for create/update options.

http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/9c4bd944/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/Port.java
----------------------------------------------------------------------
diff --git a/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/Port.java b/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/Port.java
new file mode 100644
index 0000000..404961f
--- /dev/null
+++ b/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/Port.java
@@ -0,0 +1,765 @@
+/*
+ * 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.domain;
+
+import com.google.common.base.Objects;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import org.jclouds.javax.annotation.Nullable;
+
+import javax.inject.Named;
+import java.beans.ConstructorProperties;
+import java.util.Map;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * A Neutron port
+ *
+ * @see <a
+ *      href="http://docs.openstack.org/api/openstack-network/1.0/content/Ports.html">api
+ *      doc</a>
+ */
+public class Port {
+
+   private String id;
+   private NetworkStatus status;
+
+   // Extensions
+
+   // portbindings.py
+   // The service will return the vif type for the specific port.
+   @Named("binding:vif_type")
+   private VIFType vifType;
+   // The service may return a dictionary containing additional
+   // information needed by the interface driver. The set of items
+   // returned may depend on the value of VIF_TYPE.
+   @Named("binding:vif_details")
+   private ImmutableMap<String, Object> vifDetails;
+
+   // Plugins
+
+   // qos.py
+   @Named("queue_id")
+   private String qosQueueId;
+
+   private String name;
+   @Named("network_id")
+   private String networkId;
+   @Named("admin_state_up")
+   private Boolean adminStateUp;
+   @Named("mac_address")
+   private String macAddress;
+   @Named("fixed_ips")
+   private ImmutableSet<IP> fixedIps;
+   @Named("device_id")
+   private String deviceId;
+   @Named("device_owner")
+   private String deviceOwner;
+   @Named("tenant_id")
+   private String tenantId;
+   @Named("security_groups")
+   private ImmutableSet<String> securityGroups;
+
+   // Extensions
+
+   // allowedaddresspairs.py
+   @Named("allowed_address_pairs")
+   private ImmutableSet<AddressPair> allowedAddressPairs;
+
+   // extra_dhcp_opt.py
+   @Named("extra_dhcp_opts")
+   private ImmutableSet<ExtraDhcpOption> extraDhcpOptions;
+
+   // portbindings.py
+   // The type of vnic that this port should be attached to
+   @Named("binding:vnic_type")
+   private VNICType vnicType;
+   // In some cases different implementations may be run on different hosts.
+   // The host on which the port will be allocated.
+   @Named("binding:host_id")
+   private String hostId;
+   // The profile will be a dictionary that enables the application running
+   // on the specific host to pass and receive vif port specific information to
+   // the plugin.
+   @Named("binding:profile")
+   private ImmutableMap<String, Object> profile;
+
+   // portsecurity.py
+   @Named("port_security_enabled")
+   private Boolean portSecurity;
+
+   // Plugins
+
+   // n1kv.py
+   @Named("n1kv:profile_id")
+   private String profileId;
+
+   // maclearning.py
+   @Named("mac_learning_enabled")
+   private Boolean macLearning;
+
+   // qos.py
+   @Named("rxtx_factor")
+   private Integer qosRxtxFactor;
+
+   @ConstructorProperties({"id", "status", "binding:vif_type", "binding:vif_details", "queue_id", "name", "network_id",
+         "admin_state_up", "mac_address", "fixed_ips", "device_id", "device_owner", "tenant_id", "security_groups",
+         "allowed_address_pairs", "extra_dhcp_opts", "binding:vnic_type", "binding:host_id", "binding:profile",
+         "port_security_enabled", "n1kv:profile_id", "mac_learning_enabled", "rxtx_factor"})
+   protected Port(String id, NetworkStatus status, VIFType vifType, Map<String, Object> vifDetails, String qosQueueId,
+         String name, String networkId, Boolean adminStateUp, String macAddress, ImmutableSet<IP> fixedIps, String deviceId,
+         String deviceOwner, String tenantId, ImmutableSet<String> securityGroups, ImmutableSet<AddressPair> allowedAddressPairs,
+         ImmutableSet<ExtraDhcpOption> extraDhcpOptions, VNICType vnicType, String hostId, Map<String, Object> profile,
+         Boolean portSecurity, String profileId, Boolean macLearning, Integer qosRxtxFactor) {
+      this.id = id;
+      this.status = status;
+      this.vifType = vifType;
+      // This will not be needed once jclouds core supports ImmutableMap deserialization
+      this.vifDetails = vifDetails !=null ? ImmutableMap.copyOf(vifDetails) : null;
+      this.qosQueueId = qosQueueId;
+      this.name = name;
+      this.networkId = networkId;
+      this.adminStateUp = adminStateUp;
+      this.macAddress = macAddress;
+      this.fixedIps = fixedIps;
+      this.deviceId = deviceId;
+      this.deviceOwner = deviceOwner;
+      this.tenantId = tenantId;
+      this.securityGroups = securityGroups;
+      this.allowedAddressPairs = allowedAddressPairs;
+      this.extraDhcpOptions = extraDhcpOptions;
+      this.vnicType = vnicType;
+      this.hostId = hostId;
+      this.profile = profile != null ? ImmutableMap.copyOf(profile) : null;
+      this.portSecurity = portSecurity;
+      this.profileId = profileId;
+      this.macLearning = macLearning;
+      this.qosRxtxFactor = qosRxtxFactor;
+   }
+
+   /**
+    * Default constructor.
+    */
+   private Port() {}
+
+   /**
+    * Copy constructor
+    * @param port
+    */
+   private Port(Port port) {
+      this(port.id,
+      port.status,
+      port.vifType,
+      port.vifDetails,
+      port.qosQueueId,
+      port.name,
+      port.networkId,
+      port.adminStateUp,
+      port.macAddress,
+      port.fixedIps,
+      port.deviceId,
+      port.deviceOwner,
+      port.tenantId,
+      port.securityGroups,
+      port.allowedAddressPairs,
+      port.extraDhcpOptions,
+      port.vnicType,
+      port.hostId,
+      port.profile,
+      port.portSecurity,
+      port.profileId,
+      port.macLearning,
+      port.qosRxtxFactor);
+   }
+
+   /**
+    * @return the id of the Port
+    */
+   @Nullable
+   public String getId() {
+      return id;
+   }
+
+   /**
+    * @return the status of the Port
+    */
+   @Nullable
+   public NetworkStatus getStatus() {
+      return status;
+   }
+
+   /**
+    *
+    * @return the vifType of the Port. Visible to only administrative users.
+    *
+    */
+   @Nullable
+   public VIFType getVifType() {
+      return vifType;
+   }
+
+   /**
+    * @return the vifDetails of the Port. A dictionary that enables the application to pass information about functions
+    * that Networking API v2.0 provides. Specify the following value: port_filter : Boolean to define whether
+    * Networking API v2.0 provides port filtering features such as security group and anti-MAC/IP spoofing. Visible to
+    * only administrative users.
+    */
+   @Nullable
+   public ImmutableMap<String, Object> getVifDetails() {
+      return vifDetails;
+   }
+
+   /**
+    * @return the qosQueueId of the Port
+    */
+   @Nullable
+   public String getQosQueueId() {
+      return qosQueueId;
+   }
+
+   /**
+    * @return the name of the Port
+    */
+   @Nullable
+   public String getName() {
+      return name;
+   }
+
+   /**
+    * @return the id of the network where this port is associated with.
+    */
+   @Nullable
+   public String getNetworkId() {
+      return networkId;
+   }
+
+   /**
+    * @return the administrative state of port. If false, port does not forward packets.
+    */
+   @Nullable
+   public boolean isAdminStateUp() {
+      return adminStateUp;
+   }
+
+   /**
+    * @return the macAddress of the Port
+    */
+   @Nullable
+   public String getMacAddress() {
+      return macAddress;
+   }
+
+   /**
+    * @return the set of fixed ips this port has been assigned.
+    */
+   @Nullable
+   public ImmutableSet<IP> getFixedIps() {
+      return fixedIps;
+   }
+
+   /**
+    * @return the id of the device (e.g. server) using this port.
+    */
+   @Nullable
+   public String getDeviceId() {
+      return deviceId;
+   }
+
+   /**
+    * @return the entity (e.g.: dhcp agent) using this port.
+    */
+   @Nullable
+   public String getDeviceOwner() {
+      return deviceOwner;
+   }
+
+   /**
+    * @return the tenantId of the Port
+    */
+   @Nullable
+   public String getTenantId() {
+      return tenantId;
+   }
+
+   /**
+    * @return the set of security groups
+    */
+   @Nullable
+   public ImmutableSet<String> getSecurityGroups() {
+      return securityGroups;
+   }
+
+   /**
+    * @return the allowedAddressPairs of the Port
+    */
+   @Nullable
+   public ImmutableSet<AddressPair> getAllowedAddressPairs() {
+      return allowedAddressPairs;
+   }
+
+   /**
+    * @return the extraDhcpOptions of the Port
+    */
+   @Nullable
+   public ImmutableSet<ExtraDhcpOption> getExtraDhcpOptions() {
+      return extraDhcpOptions;
+   }
+
+   /**
+    * @return the vnicType of the Port. This extended attribute is visible to only port owners and administrative users.
+    * Specifies a value of normal (virtual nic), direct (pci passthrough), or macvtap (virtual interface with a
+    * tap-like software interface). These values support SR-IOV PCI passthrough networking. The ML2 plug-in supports
+    * the vnic_type.
+    */
+   @Nullable
+   public VNICType getVnicType() {
+      return vnicType;
+   }
+
+   /**
+    * @return the hostId of the Port. The ID of the host where the port is allocated. In some cases, different
+    * implementations can run on different hosts. Visible to only administrative users.
+    */
+   @Nullable
+   public String getHostId() {
+      return hostId;
+   }
+
+   /**
+    * @return the profile of the Port. A dictionary that enables the application to pass information about functions
+    * that the Networking API provides. To enable or disable port filtering features such as security group and
+    * anti-MAC/IP spoofing, specify port_filter: True or port_filter: False. Visible to only administrative users.
+    */
+   @Nullable
+   public ImmutableMap<String, Object> getProfile() {
+      return profile;
+   }
+
+   /**
+    * @return the portSecurity of the Port
+    */
+   @Nullable
+   public Boolean isPortSecurity() {
+      return portSecurity;
+   }
+
+   /**
+    * @return the profileId of the Port
+    */
+   @Nullable
+   public String getProfileId() {
+      return profileId;
+   }
+
+   /**
+    * @return the macLearning of the Port
+    */
+   @Nullable
+   public Boolean isMacLearning() {
+      return macLearning;
+   }
+
+   /**
+    * @return the qosRxtxFactor of the Port
+    */
+   @Nullable
+   public Integer getQosRxtxFactor() {
+      return qosRxtxFactor;
+   }
+
+   @Override
+   public boolean equals(Object o) {
+      if (this == o)
+         return true;
+      if (o == null || getClass() != o.getClass())
+         return false;
+
+      Port that = (Port) o;
+
+      return Objects.equal(this.id, that.id) &&
+            Objects.equal(this.status, that.status) &&
+            Objects.equal(this.vifType, that.vifType) &&
+            Objects.equal(this.vifDetails, that.vifDetails) &&
+            Objects.equal(this.qosQueueId, that.qosQueueId) &&
+            Objects.equal(this.name, that.name) &&
+            Objects.equal(this.networkId, that.networkId) &&
+            Objects.equal(this.adminStateUp, that.adminStateUp) &&
+            Objects.equal(this.macAddress, that.macAddress) &&
+            Objects.equal(this.fixedIps, that.fixedIps) &&
+            Objects.equal(this.deviceId, that.deviceId) &&
+            Objects.equal(this.deviceOwner, that.deviceOwner) &&
+            Objects.equal(this.tenantId, that.tenantId) &&
+            Objects.equal(this.securityGroups, that.securityGroups) &&
+            Objects.equal(this.allowedAddressPairs, that.allowedAddressPairs) &&
+            Objects.equal(this.extraDhcpOptions, that.extraDhcpOptions) &&
+            Objects.equal(this.vnicType, that.vnicType) &&
+            Objects.equal(this.hostId, that.hostId) &&
+            Objects.equal(this.profile, that.profile) &&
+            Objects.equal(this.portSecurity, that.portSecurity) &&
+            Objects.equal(this.profileId, that.profileId) &&
+            Objects.equal(this.macLearning, that.macLearning) &&
+            Objects.equal(this.qosRxtxFactor, that.qosRxtxFactor);
+   }
+
+   @Override
+   public int hashCode() {
+      return Objects.hashCode(id, status, vifType, vifDetails, qosQueueId, name,
+            networkId, adminStateUp, macAddress, fixedIps, deviceId,
+            deviceOwner, tenantId, securityGroups, allowedAddressPairs, extraDhcpOptions,
+            vnicType, hostId, profile, portSecurity, profileId,
+            macLearning, qosRxtxFactor);
+   }
+
+   @Override
+   public String toString() {
+      return Objects.toStringHelper(this)
+            .add("id", id)
+            .add("status", status)
+            .add("vifType", vifType)
+            .add("vifDetails", vifDetails)
+            .add("qosQueueId", qosQueueId)
+            .add("name", name)
+            .add("networkId", networkId)
+            .add("adminStateUp", adminStateUp)
+            .add("macAddress", macAddress)
+            .add("fixedIps", fixedIps)
+            .add("deviceId", deviceId)
+            .add("deviceOwner", deviceOwner)
+            .add("tenantId", tenantId)
+            .add("securityGroups", securityGroups)
+            .add("allowedAddressPairs", allowedAddressPairs)
+            .add("extraDhcpOptions", extraDhcpOptions)
+            .add("vnicType", vnicType)
+            .add("hostId", hostId)
+            .add("profile", profile)
+            .add("portSecurity", portSecurity)
+            .add("profileId", profileId)
+            .add("macLearning", macLearning)
+            .add("qosRxtxFactor", qosRxtxFactor)
+            .toString();
+   }
+
+   /*
+    * Methods to get the Create and Update builders follow
+    */
+
+   /**
+    * @return the Builder for creating a new Router
+    */
+   public static CreateBuilder createOptions(String networkId) {
+      return new CreateBuilder(networkId);
+   }
+
+   /**
+    * @return the Builder for updating a Router
+    */
+   public static UpdateBuilder updateOptions() {
+      return new UpdateBuilder();
+   }
+
+   private static abstract class Builder<ParameterizedBuilderType> {
+      protected Port port;
+
+      /**
+       * No-parameters constructor used when updating.
+       */
+      private Builder() {
+         port = new Port();
+      }
+
+      protected abstract ParameterizedBuilderType self();
+
+      /**
+       * Provide the name to the Port's Builder.
+       *
+       * @return the Builder.
+       * @see Port#getName()
+       */
+      public ParameterizedBuilderType name(String name) {
+         port.name = name;
+         return self();
+      }
+
+      /**
+       * Provide the networkId to the Port's Builder.
+       *
+       * @return the Builder.
+       * @see Port#getNetworkId()
+       */
+      public ParameterizedBuilderType networkId(String networkId) {
+         port.networkId = networkId;
+         return self();
+      }
+
+      /**
+       * Provide the adminStateUp to the Port's Builder.
+       *
+       * @return the Builder.
+       * @see Port#isAdminStateUp()
+       */
+      public ParameterizedBuilderType adminStateUp(boolean adminStateUp) {
+         port.adminStateUp = adminStateUp;
+         return self();
+      }
+
+      /**
+       * Provide the macAddress to the Port's Builder.
+       *
+       * @return the Builder.
+       * @see Port#getMacAddress()
+       */
+      public ParameterizedBuilderType macAddress(String macAddress) {
+         port.macAddress = macAddress;
+         return self();
+      }
+
+      /**
+       * Provide the fixedIps to the Port's Builder.
+       *
+       * @return the Builder.
+       * @see Port#getFixedIps()
+       */
+      public ParameterizedBuilderType fixedIps(ImmutableSet<IP> fixedIps) {
+         port.fixedIps = fixedIps;
+         return self();
+      }
+
+      /**
+       * Provide the deviceId to the Port's Builder.
+       *
+       * @return the Builder.
+       * @see Port#getDeviceId()
+       */
+      public ParameterizedBuilderType deviceId(String deviceId) {
+         port.deviceId = deviceId;
+         return self();
+      }
+
+      /**
+       * Provide the deviceOwner to the Port's Builder.
+       *
+       * @return the Builder.
+       * @see Port#getDeviceOwner()
+       */
+      public ParameterizedBuilderType deviceOwner(String deviceOwner) {
+         port.deviceOwner = deviceOwner;
+         return self();
+      }
+
+      /**
+       * Provide the tenantId to the Port's Builder.
+       *
+       * @return the Builder.
+       * @see Port#getTenantId()
+       */
+      public ParameterizedBuilderType tenantId(String tenantId) {
+         port.tenantId = tenantId;
+         return self();
+      }
+
+      /**
+       * Provide the tenantId to the Port's Builder.
+       *
+       * @return the Builder.
+       * @see Port#getSecurityGroups()
+       */
+      public ParameterizedBuilderType securityGroups(ImmutableSet<String> securityGroups) {
+         port.securityGroups = securityGroups;
+         return self();
+      }
+
+      /**
+       * Provide the allowedAddressPairs to the Port's Builder.
+       *
+       * @return the Builder.
+       * @see Port#getAllowedAddressPairs()
+       */
+      public ParameterizedBuilderType allowedAddressPairs(ImmutableSet<AddressPair> allowedAddressPairs) {
+         port.allowedAddressPairs = allowedAddressPairs;
+         return self();
+      }
+
+      /**
+       * Provide the extraDhcpOptions to the Port's Builder.
+       *
+       * @return the Builder.
+       * @see Port#getExtraDhcpOptions()
+       */
+      public ParameterizedBuilderType extraDhcpOptions(ImmutableSet<ExtraDhcpOption> extraDhcpOptions) {
+         port.extraDhcpOptions = extraDhcpOptions;
+         return self();
+      }
+
+      /**
+       * Provide the vnicType to the Port's Builder.
+       * Specify a value of normal (virtual nic), direct (pci passthrough), or macvtap (virtual interface with a
+       * tap-like software interface). These values support SR-IOV PCI passthrough networking. The ML2 plug-in supports
+       * the vnic_type.
+       *
+       * @return the Builder.
+       * @see Port#getVnicType()
+       */
+      public ParameterizedBuilderType vnicType(VNICType vnicType) {
+         port.vnicType = vnicType;
+         return self();
+      }
+
+      /**
+       * Provide the hostId to the Port's Builder.
+       *
+       * @return the Builder.
+       * @see Port#getHostId()
+       */
+      public ParameterizedBuilderType hostId(String hostId) {
+         port.hostId = hostId;
+         return self();
+      }
+
+      /**
+       * Provide the profile to the Port's Builder.
+       * This attribute is a dictionary that can be used (with admin credentials) to supply information influencing the
+       * binding of the port. This functionality is needed for SR-IOV PCI passthrough.
+       *
+       * @return the Builder.
+       * @see Port#getProfile()
+       */
+      public ParameterizedBuilderType profile(ImmutableMap<String, Object> profile) {
+         port.profile = profile;
+         return self();
+      }
+
+      /**
+       * Provide the portSecurity to the Port's Builder.
+       *
+       * @return the Builder.
+       * @see Port#isPortSecurity()
+       */
+      public ParameterizedBuilderType portSecurity(boolean portSecurity) {
+         port.portSecurity = portSecurity;
+         return self();
+      }
+
+      /**
+       * Provide the profileId to the Port's Builder.
+       *
+       * @return the Builder.
+       * @see Port#getProfileId()
+       */
+      public ParameterizedBuilderType profileId(String profileId) {
+         port.profileId = profileId;
+         return self();
+      }
+
+      /**
+       * Provide the macLearning to the Port's Builder.
+       *
+       * @return the Builder.
+       * @see Port#isMacLearning()
+       */
+      public ParameterizedBuilderType macLearning(boolean macLearning) {
+         port.macLearning = macLearning;
+         return self();
+      }
+
+      /**
+       * Provide the qosRxtxFactor to the Port's Builder.
+       *
+       * @return the Builder.
+       * @see Port#getQosRxtxFactor()
+       */
+      public ParameterizedBuilderType qosRxtxFactor(int qosRxtxFactor) {
+         port.qosRxtxFactor = qosRxtxFactor;
+         return self();
+      }
+   }
+
+   /**
+    * Create and Update builders (inheriting from Builder)
+    */
+   public static class CreateBuilder extends Builder<CreateBuilder> {
+      /**
+       *
+       * Supply required properties for creating a Builder
+       */
+      private CreateBuilder(String networkId) {
+         port.networkId = networkId;
+      }
+
+      /**
+       * @return a CreateOptions constructed with this Builder.
+       */
+      public CreateOptions build() {
+         return new CreateOptions(port);
+      }
+
+      protected CreateBuilder self() {
+         return this;
+      }
+   }
+
+   /**
+    * Create and Update builders (inheriting from Builder)
+    */
+   public static class UpdateBuilder extends Builder<UpdateBuilder> {
+      /**
+       * Supply required properties for updating a Builder
+       */
+      private UpdateBuilder() {
+      }
+
+      /**
+       * @return a UpdateOptions constructed with this Builder.
+       */
+      public UpdateOptions build() {
+         return new UpdateOptions(port);
+      }
+
+      protected UpdateBuilder self() {
+         return this;
+      }
+   }
+
+   /**
+    * Create and Update options - extend the domain class, passed to API update and create calls.
+    * Essentially the same as the domain class. Ensure validation and safe typing.
+    */
+   public static class CreateOptions extends Port {
+      /**
+       * Copy constructor
+       */
+      private CreateOptions(Port port) {
+         super(port);
+         checkNotNull(port.networkId, "networkId should not be null");
+      }
+   }
+
+   /**
+    * Create and Update options - extend the domain class, passed to API update and create calls.
+    * Essentially the same as the domain class. Ensure validation and safe typing.
+    */
+   public static class UpdateOptions extends Port {
+      /**
+       * Copy constructor
+       */
+      private UpdateOptions(Port port) {
+         super(port);
+      }
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/9c4bd944/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/Ports.java
----------------------------------------------------------------------
diff --git a/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/Ports.java b/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/Ports.java
new file mode 100644
index 0000000..f7a6d5d
--- /dev/null
+++ b/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/Ports.java
@@ -0,0 +1,35 @@
+/*
+ * 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 com.google.common.collect.ImmutableSet;
+import org.jclouds.openstack.v2_0.domain.Link;
+import org.jclouds.openstack.v2_0.domain.PaginatedCollection;
+
+import java.beans.ConstructorProperties;
+
+/**
+ * A collection of Networks
+ */
+public class Ports extends PaginatedCollection<Port> {
+   public static final Ports EMPTY = new Ports(ImmutableSet.<Port> of(), ImmutableSet.<Link> of());
+
+   @ConstructorProperties({ "ports", "ports_links" })
+   protected Ports(Iterable<Port> ports, Iterable<Link> portsLinks) {
+      super(ports, portsLinks);
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/9c4bd944/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/Router.java
----------------------------------------------------------------------
diff --git a/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/Router.java b/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/Router.java
new file mode 100644
index 0000000..fb50d07
--- /dev/null
+++ b/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/Router.java
@@ -0,0 +1,285 @@
+/**
+ * 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.domain;
+
+import com.google.common.base.Objects;
+import org.jclouds.javax.annotation.Nullable;
+
+import javax.inject.Named;
+import java.beans.ConstructorProperties;
+
+/**
+ * A Neutron Router
+ *
+ * @see <a
+ *      href="http://docs.openstack.org/api/openstack-network/2.0/content/router_ext_concepts.html">api
+ *      doc</a>
+ */
+public class Router {
+
+   private String id;
+   private NetworkStatus status;
+
+   private String name;
+   @Named("tenant_id")
+   private String tenantId;
+   @Named("admin_state_up")
+   private Boolean adminStateUp;
+   @Named("external_gateway_info")
+   private ExternalGatewayInfo externalGatewayInfo;
+
+   /**
+    * @param id
+    * @param status
+    * @param name
+    * @param tenantId
+    * @param adminStateUp
+    * @param externalGatewayInfo
+    */
+   @ConstructorProperties({"id", "status", "name", "tenant_id", "admin_state_up", "external_gateway_info"})
+   private Router(String id, NetworkStatus status, String name, String tenantId, Boolean adminStateUp, ExternalGatewayInfo externalGatewayInfo) {
+      this.id = id;
+      this.status = status;
+      this.name = name;
+      this.tenantId = tenantId;
+      this.adminStateUp = adminStateUp;
+      this.externalGatewayInfo = externalGatewayInfo;
+   }
+
+   /**
+    * Default constructor.
+    */
+   private Router() {}
+
+   /**
+    * Copy constructor
+    * @param router
+    */
+   private Router(Router router) {
+      this(router.id, router.status, router.name, router.tenantId, router.adminStateUp, router.externalGatewayInfo);
+   }
+
+   /**
+    * @return the id of the Router
+    */
+   @Nullable
+   public String getId() {
+      return id;
+   }
+
+   /**
+    * @return the status of the Router
+    */
+   @Nullable
+   public NetworkStatus getStatus() {
+      return status;
+   }
+
+   /**
+    * @return the name of the Router
+    */
+   @Nullable
+   public String getName() {
+      return name;
+   }
+
+   /**
+    * @return the tenantId of the Router
+    */
+   @Nullable
+   public String getTenantId() {
+      return tenantId;
+   }
+
+   /**
+    * @return the adminStateUp of the Router
+    */
+   @Nullable
+   public Boolean isAdminStateUp() {
+      return adminStateUp;
+   }
+
+   /**
+    * @return the externalGatewayInfo of the Router
+    */
+   @Nullable
+   public ExternalGatewayInfo getExternalGatewayInfo() {
+      return externalGatewayInfo;
+   }
+
+   /**
+    * @return the Builder for creating a new Router
+    */
+   public static CreateBuilder createOptions() {
+      return new CreateBuilder();
+   }
+
+   /**
+    * @return the Builder for updating a Router
+    */
+   public static UpdateBuilder updateOptions() {
+      return new UpdateBuilder();
+   }
+
+   @Override
+   public boolean equals(Object o) {
+      if (this == o)
+         return true;
+      if (o == null || getClass() != o.getClass())
+         return false;
+
+      Router that = (Router) o;
+
+      return Objects.equal(this.id, that.id) &&
+            Objects.equal(this.status, that.status) &&
+            Objects.equal(this.name, that.name) &&
+            Objects.equal(this.tenantId, that.tenantId) &&
+            Objects.equal(this.adminStateUp, that.adminStateUp) &&
+            Objects.equal(this.externalGatewayInfo, that.externalGatewayInfo);
+   }
+
+   @Override
+   public int hashCode() {
+      return Objects.hashCode(id, status, name, tenantId, adminStateUp, externalGatewayInfo);
+   }
+
+   @Override
+   public String toString() {
+      return Objects.toStringHelper(this)
+            .add("id", id)
+            .add("status", status)
+            .add("name", name)
+            .add("tenantId", tenantId)
+            .add("adminStateUp", adminStateUp)
+            .add("externalGatewayInfo", externalGatewayInfo)
+            .toString();
+   }
+
+   private static abstract class Builder<ParameterizedBuilderType> {
+      protected Router router;
+
+      /**
+       * No-parameters constructor used when updating.
+       * */
+      private Builder() {
+         router = new Router();
+      }
+
+      protected abstract ParameterizedBuilderType self();
+
+      /**
+       * Provide the name to the Router's Builder.
+       *
+       * @return the Builder.
+       * @see Router#getName()
+       */
+      public ParameterizedBuilderType name(String name) {
+         router.name = name;
+         return self();
+      }
+
+      /**
+       * Provide the tenantId to the Router's Builder.
+       *
+       * @return the Builder.
+       * @see Router#getTenantId()
+       */
+      public ParameterizedBuilderType tenantId(String tenantId) {
+         router.tenantId = tenantId;
+         return self();
+      }
+
+      /**
+       * Provide the adminStateUp to the Router's Builder.
+       *
+       * @return the Builder.
+       * @see Router#isAdminStateUp()
+       */
+      public ParameterizedBuilderType adminStateUp(boolean adminStateUp) {
+         router.adminStateUp = adminStateUp;
+         return self();
+      }
+
+      /**
+       * Provide the externalGatewayInfo to the Router's Builder.
+       *
+       * @return the Builder.
+       * @see Router#getExternalGatewayInfo()
+       */
+      public ParameterizedBuilderType externalGatewayInfo(ExternalGatewayInfo externalGatewayInfo) {
+         router.externalGatewayInfo = externalGatewayInfo;
+         return self();
+      }
+   }
+
+   public static class CreateBuilder extends Builder<CreateBuilder> {
+      /**
+       * Supply required properties for creating a Builder
+       */
+      private CreateBuilder() {
+      }
+
+      /**
+       * @return a CreateOptions constructed with this Builder.
+       */
+      public CreateOptions build() {
+         return new CreateOptions(router);
+      }
+
+      protected CreateBuilder self() {
+         return this;
+      }
+   }
+
+   public static class UpdateBuilder extends Builder<UpdateBuilder> {
+      /**
+       * Supply required properties for updating a Builder
+       */
+      private UpdateBuilder() {
+      }
+
+      /**
+       * @return a UpdateOptions constructed with this Builder.
+       */
+      public UpdateOptions build() {
+         return new UpdateOptions(router);
+      }
+
+      protected UpdateBuilder self() {
+         return this;
+      }
+   }
+
+   public static class CreateOptions extends Router{
+      /**
+       * Copy constructor
+       */
+      private CreateOptions(Router router) {
+         super(router);
+      }
+   }
+   public static class UpdateOptions extends Router{
+      /**
+       * Copy constructor
+       */
+      private UpdateOptions(Router router) {
+         super(router);
+      }
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/9c4bd944/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/RouterInterface.java
----------------------------------------------------------------------
diff --git a/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/RouterInterface.java b/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/RouterInterface.java
new file mode 100644
index 0000000..091bf99
--- /dev/null
+++ b/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/RouterInterface.java
@@ -0,0 +1,136 @@
+/**
+ * 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.domain;
+
+import com.google.common.base.Objects;
+
+import javax.inject.Named;
+
+/**
+ * A Neutron Router Interface
+ *
+ * @see <a
+ *      href="http://docs.openstack.org/api/openstack-network/2.0/content/router_add_interface.html">api
+ *      doc</a>
+ */
+public class RouterInterface {
+
+   @Named("subnet_id")
+   protected final String subnetId;
+   @Named("port_id")
+   protected final String portId;
+
+   protected RouterInterface(String subnetId, String portId) {
+      this.subnetId = subnetId;
+      this.portId = portId;
+   }
+
+   /**
+    * @return the subnetId of the RouterInterface
+    */
+   public String getSubnetId() {
+      return subnetId;
+   }
+
+   /**
+    * @return the portId of the RouterInterface
+    */
+   public String getPortId() {
+      return portId;
+   }
+
+   @Override
+   public int hashCode() {
+      return Objects.hashCode(subnetId, portId);
+   }
+
+   @Override
+   public boolean equals(Object obj) {
+      if (this == obj)
+         return true;
+      if (obj == null || getClass() != obj.getClass())
+         return false;
+      RouterInterface that = RouterInterface.class.cast(obj);
+      return Objects.equal(this.subnetId, that.subnetId) && Objects.equal(this.portId, that.portId);
+   }
+
+   protected Objects.ToStringHelper string() {
+      return Objects.toStringHelper(this).add("subnetId", subnetId).add("portId", portId);
+   }
+
+   @Override
+   public String toString() {
+      return string().toString();
+   }
+
+   /**
+    * @return the Builder for RouterInterface
+    */
+   public static Builder builder() {
+      return new Builder();
+   }
+
+   /**
+    * Gets a Builder configured as this object.
+    */
+   public Builder toBuilder() {
+      return new Builder().fromRouterInterface(this);
+   }
+
+   public static class Builder {
+      protected String subnetId;
+      protected String portId;
+
+      /**
+       * Provide the subnetId to the RouterInterface's Builder.
+       *
+       * @return the Builder.
+       * @see RouterInterface#getSubnetId()
+       */
+      public Builder subnetId(String subnetId) {
+         this.subnetId = subnetId;
+         return this;
+      }
+
+      /**
+       * Provide the portId to the RouterInterface's Builder.
+       *
+       * @return the Builder.
+       * @see RouterInterface#getPortId()
+       */
+      public Builder portId(String portId) {
+         this.portId = portId;
+         return this;
+      }
+
+      /**
+       * @return a RouterInterface constructed with this Builder.
+       */
+      public RouterInterface build() {
+         return new RouterInterface(subnetId, portId);
+      }
+
+      /**
+       * @return a Builder from another RouterInterface.
+       */
+      public Builder fromRouterInterface(RouterInterface in) {
+         return this.subnetId(in.getSubnetId()).portId(in.getPortId());
+      }
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/9c4bd944/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/Routers.java
----------------------------------------------------------------------
diff --git a/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/Routers.java b/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/Routers.java
new file mode 100644
index 0000000..8f926bf
--- /dev/null
+++ b/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/Routers.java
@@ -0,0 +1,35 @@
+/*
+ * 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 com.google.common.collect.ImmutableSet;
+import org.jclouds.openstack.v2_0.domain.Link;
+import org.jclouds.openstack.v2_0.domain.PaginatedCollection;
+
+import java.beans.ConstructorProperties;
+
+/**
+ * A collection of Networks
+ */
+public class Routers extends PaginatedCollection<Router> {
+   public static final Routers EMPTY = new Routers(ImmutableSet.<Router> of(), ImmutableSet.<Link> of());
+
+   @ConstructorProperties({ "routers", "routers_links" })
+   protected Routers(Iterable<Router> routers, Iterable<Link> routersLinks) {
+      super(routers, routersLinks);
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/9c4bd944/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/Subnet.java
----------------------------------------------------------------------
diff --git a/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/Subnet.java b/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/Subnet.java
new file mode 100644
index 0000000..31d3327
--- /dev/null
+++ b/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/Subnet.java
@@ -0,0 +1,467 @@
+/*
+ * 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.domain;
+
+import com.google.common.base.Objects;
+import com.google.common.collect.ImmutableSet;
+import org.jclouds.javax.annotation.Nullable;
+
+import javax.inject.Named;
+import java.beans.ConstructorProperties;
+import java.util.Collection;
+import java.util.Set;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * A Neutron subnet
+ *
+ * @see <a href="http://docs.openstack.org/api/openstack-network/2.0/content/Subnets.html">api doc</a>
+ */
+public class Subnet {
+
+   private String id;
+
+   private String name;
+   @Named("network_id")
+   private String networkId;
+   @Named("tenant_id")
+   private String tenantId;
+   // Cannot be used for updates.
+   @Named("allocation_pools")
+   private ImmutableSet<AllocationPool> allocationPools;
+   @Named("gateway_ip")
+   private String gatewayIp;
+   @Named("ip_version")
+   private Integer ipVersion;
+   private String cidr;
+   @Named("enable_dhcp")
+   private Boolean enableDhcp;
+   @Named("dns_nameservers")
+   private ImmutableSet<String> dnsNameServers;
+   @Named("host_routes")
+   private ImmutableSet<HostRoute> hostRoutes;
+   @Named("ipv6_address_mode")
+   private IPv6DHCPMode ipv6AddressMode;
+   @Named("ipv6_ra_mode")
+   private IPv6DHCPMode ipv6RaMode;
+
+   @ConstructorProperties({"id", "name", "network_id", "tenant_id", "allocation_pools", "gateway_ip", "ip_version",
+         "cidr", "enable_dhcp", "dns_nameservers", "host_routes", "ipv6_address_mode", "ipv6_ra_mode"})
+   private Subnet(String id, String name, String networkId, String tenantId, ImmutableSet<AllocationPool> allocationPools,
+         String gatewayIp, Integer ipVersion, String cidr, Boolean enableDhcp, ImmutableSet<String> dnsNameServers, ImmutableSet<HostRoute> hostRoutes,
+         IPv6DHCPMode ipv6AddressMode, IPv6DHCPMode ipv6RaMode) {
+      this.id = id;
+      this.name = name;
+      this.networkId = networkId;
+      this.tenantId = tenantId;
+      this.allocationPools = allocationPools;
+      this.gatewayIp = gatewayIp;
+      this.ipVersion = ipVersion;
+      this.cidr = cidr;
+      this.enableDhcp = enableDhcp;
+      this.dnsNameServers = dnsNameServers;
+      this.hostRoutes = hostRoutes;
+      this.ipv6AddressMode = ipv6AddressMode;
+      this.ipv6RaMode = ipv6RaMode;
+   }
+
+   /**
+    * Default constructor.
+    */
+   private Subnet() {}
+
+   /**
+    * Copy constructor
+    * @param subnet
+    */
+   private Subnet(Subnet subnet) {
+      this(subnet.id,
+            subnet.name,
+            subnet.networkId,
+            subnet.tenantId,
+            subnet.allocationPools,
+            subnet.gatewayIp,
+            subnet.ipVersion,
+            subnet.cidr,
+            subnet.enableDhcp,
+            subnet.dnsNameServers,
+            subnet.hostRoutes,
+            subnet.ipv6AddressMode,
+            subnet.ipv6RaMode);
+   }
+
+   /**
+    * @return the id of the subnet
+    */
+   @Nullable
+   public String getId() {
+      return this.id;
+   }
+
+   /**
+    * @return the name of the subnet
+    */
+   @Nullable
+   public String getName() {
+      return this.name;
+   }
+
+   /**
+    * @return the id of the network this subnet is associated with.
+    */
+   @Nullable
+   public String getNetworkId() {
+      return networkId;
+   }
+
+   /**
+    * @return the id of the tenant where this entity is associated with.
+    */
+   @Nullable
+   public String getTenantId() {
+      return tenantId;
+   }
+
+   /**
+    * @return the sub-ranges of CIDR available for dynamic allocation to ports.
+    */
+   @Nullable
+   public ImmutableSet<AllocationPool> getAllocationPools() {
+      return allocationPools;
+   }
+
+   /**
+    * @return the default gateway used by devices in this subnet.
+    */
+   @Nullable
+   public String getGatewayIp() {
+      return gatewayIp;
+   }
+
+   /**
+    * @return the IP version used by this subnet.
+    */
+   @Nullable
+   public Integer getIpVersion() {
+      return ipVersion;
+   }
+
+   /**
+    * @return the CIDR representing the IP range for this subnet, based on IP version.
+    */
+   @Nullable
+   public String getCidr() {
+      return cidr;
+   }
+
+   /**
+    * @return true if DHCP is enabled for this subnet, false if not.
+    */
+   @Nullable
+   public Boolean getEnableDhcp() {
+      return enableDhcp;
+   }
+
+   /**
+    * @return Configurable maximum amount of name servers per subnet. The default is 5.
+    */
+   @Nullable
+   public ImmutableSet<String> getDnsNameservers() {
+      return dnsNameServers;
+   }
+
+   /**
+    * @return Configurable maximum amount of routes per subnet. The default is 20.
+    */
+   @Nullable
+   public ImmutableSet<HostRoute> getHostRoutes() {
+      return hostRoutes;
+   }
+
+   /**
+    * @return The IP v6 Address Mode.
+    */
+   @Nullable
+   public IPv6DHCPMode getIPv6AddressMode() {
+      return ipv6AddressMode;
+   }
+
+   /**
+    * @return The IP v6 Router Advertisement mode.
+    */
+   @Nullable
+   public IPv6DHCPMode getIPv6RAMode() {
+      return ipv6RaMode;
+   }
+
+   @Override
+   public int hashCode() {
+      return Objects.hashCode(id, name, networkId, tenantId, allocationPools, gatewayIp,
+            ipVersion, cidr, enableDhcp, dnsNameServers, hostRoutes,
+            ipv6AddressMode, ipv6RaMode);
+   }
+
+   @Override
+   public boolean equals(Object o) {
+      if (this == o)
+         return true;
+      if (o == null || getClass() != o.getClass())
+         return false;
+
+      Subnet that = (Subnet) o;
+
+      return Objects.equal(this.id, that.id) &&
+            Objects.equal(this.name, that.name) &&
+            Objects.equal(this.networkId, that.networkId) &&
+            Objects.equal(this.tenantId, that.tenantId) &&
+            Objects.equal(this.allocationPools, that.allocationPools) &&
+            Objects.equal(this.gatewayIp, that.gatewayIp) &&
+            Objects.equal(this.ipVersion, that.ipVersion) &&
+            Objects.equal(this.cidr, that.cidr) &&
+            Objects.equal(this.enableDhcp, that.enableDhcp) &&
+            Objects.equal(this.dnsNameServers, that.dnsNameServers) &&
+            Objects.equal(this.hostRoutes, that.hostRoutes) &&
+            Objects.equal(this.ipv6AddressMode, that.ipv6AddressMode) &&
+            Objects.equal(this.ipv6RaMode, that.ipv6RaMode);
+   }
+
+   @Override
+   public String toString() {
+      return Objects.toStringHelper(this)
+            .add("id", id)
+            .add("name", name)
+            .add("networkId", networkId)
+            .add("tenantId", tenantId)
+            .add("allocationPools", allocationPools)
+            .add("gatewayIp", gatewayIp)
+            .add("ipVersion", ipVersion)
+            .add("cidr", cidr)
+            .add("enableDhcp", enableDhcp)
+            .add("dnsNameServers", dnsNameServers)
+            .add("hostRoutes", hostRoutes)
+            .add("ipv6AddressMode", ipv6AddressMode)
+            .add("ipv6RaMode", ipv6RaMode)
+            .toString();
+   }
+
+   /*
+    * Methods to get the Create and Update builders follow
+    */
+
+   /**
+    * @return the Builder for creating a new Router
+    */
+   public static CreateBuilder createOptions(String networkId, String cidr) {
+      return new CreateBuilder(networkId, cidr);
+   }
+
+   /**
+    * @return the Builder for updating a Router
+    */
+   public static UpdateBuilder updateOptions() {
+      return new UpdateBuilder();
+   }
+
+   private static abstract class Builder<ParameterizedBuilderType> {
+      protected Subnet subnet;
+
+      /**
+       * No-parameters constructor used when updating.
+       */
+      private Builder() {
+         subnet = new Subnet();
+      }
+
+      protected abstract ParameterizedBuilderType self();
+
+      /**
+       * @see Subnet#getName()
+       */
+      public ParameterizedBuilderType name(String name) {
+         subnet.name = name;
+         return self();
+      }
+
+      /**
+       * @see Subnet#getNetworkId()
+       */
+      public ParameterizedBuilderType networkId(String networkId) {
+         subnet.networkId = networkId;
+         return self();
+      }
+
+      /**
+       * Only administrators can specify a tenant ID that is not their own.
+       * As it is optional, this is usually omitted in requests.
+       * @see Subnet#getTenantId()
+       */
+      public ParameterizedBuilderType tenantId(String tenantId) {
+         subnet.tenantId = tenantId;
+         return self();
+      }
+
+      /**
+       * @see Subnet#getAllocationPools()
+       */
+      public ParameterizedBuilderType allocationPools(Collection<AllocationPool> allocationPools) {
+         subnet.allocationPools = ImmutableSet.copyOf(allocationPools);
+         return self();
+      }
+
+      /**
+       * @see Subnet#getGatewayIp()
+       */
+      public ParameterizedBuilderType gatewayIp(String gatewayIp) {
+         subnet.gatewayIp = gatewayIp;
+         return self();
+      }
+
+      /**
+       * @see Subnet#getIpVersion()
+       */
+      public ParameterizedBuilderType ipVersion(int ipVersion) {
+         subnet.ipVersion = ipVersion;
+         return self();
+      }
+
+      /**
+       * @see Subnet#getCidr()
+       */
+      public ParameterizedBuilderType cidr(String cidr) {
+         subnet.cidr = cidr;
+         return self();
+      }
+
+      /**
+       * @see Subnet#getEnableDhcp()
+       */
+      public ParameterizedBuilderType enableDhcp(Boolean enableDhcp) {
+         subnet.enableDhcp = enableDhcp;
+         return self();
+      }
+
+      /**
+       * @see Subnet#getDnsNameservers()
+       */
+      public ParameterizedBuilderType dnsNameServers(ImmutableSet<String> dnsNameServers) {
+         subnet.dnsNameServers = dnsNameServers;
+         return self();
+      }
+
+      /**
+       * @see Subnet#getHostRoutes()
+       */
+      public ParameterizedBuilderType hostRoutes(ImmutableSet<HostRoute> hostRoutes) {
+         subnet.hostRoutes = hostRoutes;
+         return self();
+      }
+
+      /**
+       * @see Subnet#getIPv6RAMode()
+       */
+      public ParameterizedBuilderType ipv6RaMode(IPv6DHCPMode ipv6RaMode) {
+         subnet.ipv6RaMode = ipv6RaMode;
+         return self();
+      }
+
+      /**
+       * @see Subnet#getIPv6AddressMode()
+       */
+      public ParameterizedBuilderType ipv6AddressMode(IPv6DHCPMode ipv6AddressMode) {
+         subnet.ipv6AddressMode = ipv6AddressMode;
+         return self();
+      }
+   }
+
+   /**
+    * Create and Update builders (inheriting from Builder)
+    */
+   public static class CreateBuilder extends Builder<CreateBuilder> {
+      /**
+       *
+       * Supply required properties for creating a Builder
+       */
+      private CreateBuilder(String networkId, String cidr) {
+         subnet.networkId = networkId;
+         subnet.cidr = cidr;
+      }
+
+      /**
+       * @return a CreateOptions constructed with this Builder.
+       */
+      public CreateOptions build() {
+         return new CreateOptions(subnet);
+      }
+
+      protected CreateBuilder self() {
+         return this;
+      }
+   }
+
+   /**
+    * Create and Update builders (inheriting from Builder)
+    */
+   public static class UpdateBuilder extends Builder<UpdateBuilder> {
+      /**
+       * Supply required properties for updating a Builder
+       */
+      private UpdateBuilder() {
+      }
+
+      /**
+       * @return a UpdateOptions constructed with this Builder.
+       */
+      public UpdateOptions build() {
+         return new UpdateOptions(subnet);
+      }
+
+      protected UpdateBuilder self() {
+         return this;
+      }
+   }
+
+   /**
+    * Create and Update options - extend the domain class, passed to API update and create calls.
+    * Essentially the same as the domain class. Ensure validation and safe typing.
+    */
+   public static class CreateOptions extends Subnet {
+      /**
+       * Copy constructor
+       */
+      private CreateOptions(Subnet subnet) {
+         super(subnet);
+         checkNotNull(subnet.networkId, "networkId should not be null");
+         checkNotNull(subnet.cidr, "cidr should not be null");
+      }
+   }
+
+   /**
+    * Create and Update options - extend the domain class, passed to API update and create calls.
+    * Essentially the same as the domain class. Ensure validation and safe typing.
+    */
+   public static class UpdateOptions extends Subnet {
+      /**
+       * Copy constructor
+       */
+      private UpdateOptions(Subnet subnet) {
+         super(subnet);
+      }
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/9c4bd944/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/Subnets.java
----------------------------------------------------------------------
diff --git a/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/Subnets.java b/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/Subnets.java
new file mode 100644
index 0000000..ac36a2b
--- /dev/null
+++ b/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/Subnets.java
@@ -0,0 +1,35 @@
+/*
+ * 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 com.google.common.collect.ImmutableSet;
+import org.jclouds.openstack.v2_0.domain.Link;
+import org.jclouds.openstack.v2_0.domain.PaginatedCollection;
+
+import java.beans.ConstructorProperties;
+
+/**
+ * A collection of Networks
+ */
+public class Subnets extends PaginatedCollection<Subnet> {
+   public static final Subnets EMPTY = new Subnets(ImmutableSet.<Subnet> of(), ImmutableSet.<Link> of());
+
+   @ConstructorProperties({ "subnets", "subnets_links" })
+   protected Subnets(Iterable<Subnet> subnets, Iterable<Link> subnetsLinks) {
+      super(subnets, subnetsLinks);
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/9c4bd944/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/VIFType.java
----------------------------------------------------------------------
diff --git a/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/VIFType.java b/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/VIFType.java
new file mode 100644
index 0000000..0c53e77
--- /dev/null
+++ b/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/VIFType.java
@@ -0,0 +1,62 @@
+/*
+ * 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;
+
+public enum VIFType {
+   UNBOUND("unbound"),
+   BINDING_FAILED("binding_failed"),
+   IOVISOR("iovisor"),
+   OVS("ovs"),
+   BRIDGE("bridge"),
+   _802_QBG("802.1qbg"),
+   _802_QBH("802.1qbh"),
+   HYPERV("hyperv"),
+   MIDONET("midonet"),
+   MLNX_DIRECT("mlnx_direct"),
+   MLNX_HOSTDEV("hostdev"),
+   OTHER("other"),
+   /**
+    * Used by jclouds when the service returns an unknown value other than null.
+    */
+   UNRECOGNIZED("unrecognized");
+
+   private String name;
+
+   private VIFType(String name) {
+      this.name = name;
+   }
+
+   public String toString() {
+      return name;
+   }
+
+   /**
+    * This provides GSON enum support in jclouds.
+    * */
+   public static VIFType fromValue(String name){
+      if (name != null) {
+         for (VIFType value : VIFType.values()) {
+            if (name.equalsIgnoreCase(value.name)) {
+               return value;
+            }
+         }
+         return UNRECOGNIZED;
+      }
+      return null;
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/9c4bd944/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/VNICType.java
----------------------------------------------------------------------
diff --git a/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/VNICType.java b/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/VNICType.java
new file mode 100644
index 0000000..b67063d
--- /dev/null
+++ b/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/VNICType.java
@@ -0,0 +1,56 @@
+/*
+ * 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;
+
+/**
+ * Enumerates supported VNIC types.
+ */
+public enum VNICType {
+   NORMAL("normal"),
+   DIRECT("direct"),
+   MACVTAP("macvtap"),
+   /**
+    * Used by jclouds when the service returns an unknown value other than null.
+    */
+   UNRECOGNIZED("unrecognized");
+
+   private String name;
+
+   private VNICType(String name) {
+      this.name = name;
+   }
+
+   public String toString() {
+      return name;
+   }
+
+   /**
+    * This provides GSON enum support in jclouds.
+    * */
+   public static VNICType fromValue(String name){
+      if (name != null) {
+         for (VNICType value : VNICType.values()) {
+            if (name.equalsIgnoreCase(value.name)) {
+               return value;
+            }
+         }
+         return UNRECOGNIZED;
+      }
+      return null;
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/9c4bd944/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/extensions/RouterApi.java
----------------------------------------------------------------------
diff --git a/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/extensions/RouterApi.java b/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/extensions/RouterApi.java
new file mode 100644
index 0000000..1012117
--- /dev/null
+++ b/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/extensions/RouterApi.java
@@ -0,0 +1,197 @@
+/**
+ * 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.extensions;
+
+import com.google.common.annotations.Beta;
+import org.jclouds.Fallbacks;
+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.Router;
+import org.jclouds.openstack.neutron.v2.domain.RouterInterface;
+import org.jclouds.openstack.neutron.v2.domain.Routers;
+import org.jclouds.openstack.neutron.v2.fallbacks.EmptyRoutersFallback;
+import org.jclouds.openstack.neutron.v2.functions.ParseRouters;
+import org.jclouds.openstack.neutron.v2.functions.RouterToPagedIterable;
+import org.jclouds.openstack.neutron.v2.options.EmptyOptions;
+import org.jclouds.openstack.v2_0.options.PaginationOptions;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.MapBinder;
+import org.jclouds.rest.annotations.PayloadParam;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.ResponseParser;
+import org.jclouds.rest.annotations.SelectJson;
+import org.jclouds.rest.annotations.Transform;
+import org.jclouds.rest.annotations.WrapWith;
+
+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;
+
+/**
+ * Provides synchronous access to Router operations on the OpenStack Neutron API.
+ * <p/>
+ * A logical entity for forwarding packets across internal subnets and NATting them on external
+ * networks through an appropriate external gateway.
+ *
+ * @see <a href=
+ *      "http://docs.openstack.org/api/openstack-network/2.0/content/router_ext.html">api doc</a>
+ */
+@Beta
+@Path("/v2.0/routers")
+@RequestFilters(AuthenticateRequest.class)
+@Consumes(MediaType.APPLICATION_JSON)
+public interface RouterApi {
+
+   /**
+    * Returns the list of all routers currently defined in Neutron for the current tenant. The list provides the unique
+    * identifier of each router configured for the tenant
+    *
+    * @return the list of all router references configured for the tenant.
+    */
+   @Named("router:list")
+   @GET
+   @Transform(RouterToPagedIterable.class)
+   @ResponseParser(ParseRouters.class)
+   @Fallback(Fallbacks.EmptyPagedIterableOnNotFoundOr404.class)
+   PagedIterable<Router> list();
+
+   /**
+    * @see <a href="http://docs.openstack.org/api/openstack-network/2.0/content/pagination.html">api doc</a>
+    */
+   @Named("router:list")
+   @GET
+   @ResponseParser(ParseRouters.class)
+   @Fallback(EmptyRoutersFallback.class)
+   Routers list(PaginationOptions options);
+
+   /**
+    * Returns a Routers collection that should contain a single router with the id requested.
+    *
+    * @param id the id of the router to return
+    * @return Routers collection or empty if not found
+    */
+   @Named("router:get")
+   @GET
+   @Path("/{id}")
+   @SelectJson("router")
+   @Fallback(Fallbacks.NullOnNotFoundOr404.class)
+   @Nullable
+   Router get(@PathParam("id") String id);
+
+   /**
+    * Create a new router
+    *
+    * @param router Options for creating a router
+    * @return the newly created router
+    */
+   @Named("router:create")
+   @POST
+   @SelectJson("router")
+   Router create(@WrapWith("router") Router.CreateOptions router);
+
+   /**
+    * Update a router
+    *
+    * @param id the id of the router to update
+    * @param router Contains only the attributes to update
+    * @return The modified router
+    */
+   @Named("router:update")
+   @PUT
+   @Path("/{id}")
+   @SelectJson("router")
+   @Fallback(Fallbacks.NullOnNotFoundOr404.class)
+   @Nullable
+   Router update(@PathParam("id") String id, @WrapWith("router") Router.UpdateOptions router);
+
+   /**
+    * Deletes the specified router
+    *
+    * @param id the id of the router to delete
+    * @return true if delete successful, false if not
+    */
+   @Named("router:delete")
+   @DELETE
+   @Path("/{id}")
+   @Fallback(Fallbacks.FalseOnNotFoundOr404.class)
+   boolean delete(@PathParam("id") String id);
+
+   /**
+    * Add a interface to a router to connect to the specified subnet
+    *
+    * @param routerId the id of the router to create the interface at
+    * @param subnetId the id of the subnet to connect with the interface
+    * @return the newly-created router interface
+    */
+   @Named("router:addInterfaceForSubnet")
+   @PUT
+   @Path("/{id}/add_router_interface")
+   @MapBinder(EmptyOptions.class)
+   @Fallback(Fallbacks.NullOnNotFoundOr404.class)
+   @Nullable
+   RouterInterface addInterfaceForSubnet(@PathParam("id") String routerId, @PayloadParam("subnet_id") String subnetId);
+
+   /**
+    * Add a interface to a router to connect to the specified port
+    *
+    * @param routerId the id of the router to create the interface at
+    * @param portId the id of the port to connect with the interface
+    * @return the newly-created router interface
+    */
+   @Named("router:addInterfaceForPort")
+   @PUT
+   @Path("/{id}/add_router_interface")
+   @MapBinder(EmptyOptions.class)
+   @Fallback(Fallbacks.NullOnNotFoundOr404.class)
+   @Nullable
+   RouterInterface addInterfaceForPort(@PathParam("id") String routerId, @PayloadParam("port_id") String portId);
+
+   /**
+    * Remove the interface where the specified subnet is connected to
+    *
+    * @param routerId the id of the router to remove the interface from
+    * @param subnetId the id of the subnet to disconnect from the interface
+    */
+   @Named("router:removeInterfaceForSubnet")
+   @PUT
+   @Path("/{id}/remove_router_interface")
+   @MapBinder(EmptyOptions.class)
+   @Fallback(Fallbacks.FalseOnNotFoundOr404.class)
+   boolean removeInterfaceForSubnet(@PathParam("id") String routerId, @PayloadParam("subnet_id") String subnetId);
+
+   /**
+    * Remove the interface where the specified port is connected to
+    *
+    * @param routerId the id of the router to remove the interface from
+    * @param portId the id of the port to disconnect from the interface
+    */
+   @Named("router:removeInterfaceForPort")
+   @PUT
+   @Path("/{id}/remove_router_interface")
+   @MapBinder(EmptyOptions.class)
+   @Fallback(Fallbacks.FalseOnNotFoundOr404.class)
+   boolean removeInterfaceForPort(@PathParam("id") String routerId, @PayloadParam("port_id") String portId);
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/9c4bd944/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/fallbacks/EmptyNetworksFallback.java
----------------------------------------------------------------------
diff --git a/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/fallbacks/EmptyNetworksFallback.java b/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/fallbacks/EmptyNetworksFallback.java
new file mode 100644
index 0000000..3a859a9
--- /dev/null
+++ b/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/fallbacks/EmptyNetworksFallback.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.Networks;
+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 EmptyNetworksFallback implements Fallback<Networks> {
+
+   public ListenableFuture<Networks> create(Throwable t) throws Exception {
+      return immediateFuture(createOrPropagate(t));
+   }
+
+   @Override
+   public Networks createOrPropagate(Throwable t) throws Exception {
+      if ((getFirstThrowableOfType(checkNotNull(t, "throwable"), ResourceNotFoundException.class) != null)
+            || contains404(t)) {
+         return Networks.EMPTY;
+      }
+      throw propagate(t);
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/9c4bd944/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/fallbacks/EmptyPortsFallback.java
----------------------------------------------------------------------
diff --git a/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/fallbacks/EmptyPortsFallback.java b/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/fallbacks/EmptyPortsFallback.java
new file mode 100644
index 0000000..2ca5c84
--- /dev/null
+++ b/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/fallbacks/EmptyPortsFallback.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.Ports;
+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 EmptyPortsFallback implements Fallback<Ports> {
+
+   public ListenableFuture<Ports> create(Throwable t) throws Exception {
+      return immediateFuture(createOrPropagate(t));
+   }
+
+   @Override
+   public Ports createOrPropagate(Throwable t) throws Exception {
+      if ((getFirstThrowableOfType(checkNotNull(t, "throwable"), ResourceNotFoundException.class) != null)
+            || contains404(t)) {
+         return Ports.EMPTY;
+      }
+      throw propagate(t);
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/9c4bd944/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/fallbacks/EmptyRoutersFallback.java
----------------------------------------------------------------------
diff --git a/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/fallbacks/EmptyRoutersFallback.java b/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/fallbacks/EmptyRoutersFallback.java
new file mode 100644
index 0000000..7019510
--- /dev/null
+++ b/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/fallbacks/EmptyRoutersFallback.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.Routers;
+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 EmptyRoutersFallback implements Fallback<Routers> {
+
+   public ListenableFuture<Routers> create(Throwable t) throws Exception {
+      return immediateFuture(createOrPropagate(t));
+   }
+
+   @Override
+   public Routers createOrPropagate(Throwable t) throws Exception {
+      if ((getFirstThrowableOfType(checkNotNull(t, "throwable"), ResourceNotFoundException.class) != null)
+            || contains404(t)) {
+         return Routers.EMPTY;
+      }
+      throw propagate(t);
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/9c4bd944/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/fallbacks/EmptySubnetsFallback.java
----------------------------------------------------------------------
diff --git a/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/fallbacks/EmptySubnetsFallback.java b/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/fallbacks/EmptySubnetsFallback.java
new file mode 100644
index 0000000..6f86023
--- /dev/null
+++ b/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/fallbacks/EmptySubnetsFallback.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.Subnets;
+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 EmptySubnetsFallback implements Fallback<Subnets> {
+
+   public ListenableFuture<Subnets> create(Throwable t) throws Exception {
+      return immediateFuture(createOrPropagate(t));
+   }
+
+   @Override
+   public Subnets createOrPropagate(Throwable t) throws Exception {
+      if ((getFirstThrowableOfType(checkNotNull(t, "throwable"), ResourceNotFoundException.class) != null)
+            || contains404(t)) {
+         return Subnets.EMPTY;
+      }
+      throw propagate(t);
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/9c4bd944/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/features/NetworkApi.java
----------------------------------------------------------------------
diff --git a/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/features/NetworkApi.java b/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/features/NetworkApi.java
new file mode 100644
index 0000000..cd02cac
--- /dev/null
+++ b/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/features/NetworkApi.java
@@ -0,0 +1,152 @@
+/**
+ * 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.features;
+
+import com.google.common.annotations.Beta;
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.ImmutableList;
+import org.jclouds.Fallbacks;
+import org.jclouds.Fallbacks.EmptyPagedIterableOnNotFoundOr404;
+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.Network;
+import org.jclouds.openstack.neutron.v2.domain.Networks;
+import org.jclouds.openstack.neutron.v2.fallbacks.EmptyNetworksFallback;
+import org.jclouds.openstack.neutron.v2.functions.NetworksToPagedIterable;
+import org.jclouds.openstack.neutron.v2.functions.ParseNetworks;
+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 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.Produces;
+import javax.ws.rs.core.MediaType;
+
+/**
+ * Provides synchronous access to Network operations on the openstack Neutron API.
+ * <p/>
+ * Each tenant can define one or more networks. A network is a virtual isolated layer-2 broadcast domain reserved to the
+ * tenant. A tenant can create several ports for a network, and plug virtual interfaces into these ports.
+ *
+ * @see <a href=
+ *      "http://docs.openstack.org/api/openstack-network/2.0/content/Networks.html">api doc</a>
+ */
+@Beta
+@Path("/v2.0/networks")
+@RequestFilters(AuthenticateRequest.class)
+@Consumes(MediaType.APPLICATION_JSON)
+@Produces(MediaType.APPLICATION_JSON)
+public interface NetworkApi {
+
+   /**
+    * Returns all networks currently defined in Neutron for the current tenant.
+    *
+    * @return the list of all networks configured for the tenant
+    */
+   @Named("network:list")
+   @GET
+   @ResponseParser(ParseNetworks.class)
+   @Transform(NetworksToPagedIterable.class)
+   @Fallback(EmptyPagedIterableOnNotFoundOr404.class)
+   PagedIterable<Network> list();
+
+   /**
+    * @see <a href="http://docs.openstack.org/api/openstack-network/2.0/content/pagination.html">api doc</a>
+    */
+   @Named("network:list")
+   @GET
+   @ResponseParser(ParseNetworks.class)
+   @Fallback(EmptyNetworksFallback.class)
+   Networks list(PaginationOptions options);
+
+   /**
+    * Return a specific network
+    *
+    * @param id the id of the network to return
+    * @return Network or null if not found
+    */
+   @Named("network:get")
+   @GET
+   @Path("/{id}")
+   @SelectJson("network")
+   @Fallback(Fallbacks.NullOnNotFoundOr404.class)
+   @Nullable
+   Network get(@PathParam("id") String id);
+
+   /**
+    * Create a new network with the specified type
+    *
+    * @param network Describes the network to be created.
+    * @return a reference of the newly-created network
+    */
+   @Named("network:create")
+   @POST
+   @SelectJson("network")
+   Network create(@WrapWith("network") Network.CreateOptions network);
+
+   /**
+    * Create multiple networks
+    *
+    * @param networks the bulk of networks to create
+    * @return list of references of the newly-created networks
+    */
+   @Named("network:createBulk")
+   @POST
+   @SelectJson("networks")
+   FluentIterable<Network> createBulk(@WrapWith("networks") ImmutableList<Network.CreateOptions> networks);
+
+   /**
+    * Update a network
+    *
+    * @param id the id of the network to update
+    * @param network the network to update
+    * @return true if update successful, false if not
+    */
+   @Named("network:update")
+   @PUT
+   @Path("/{id}")
+   @SelectJson("network")
+   @Fallback(Fallbacks.NullOnNotFoundOr404.class)
+   @Nullable
+   Network update(@PathParam("id") String id, @WrapWith("network") Network.UpdateOptions network);
+
+   /**
+    * Deletes the specified network
+    *
+    * @param id the id of the network to delete
+    * @return true if delete was successful, false if not
+    */
+   @Named("network:delete")
+   @DELETE
+   @Path("/{id}")
+   @Fallback(Fallbacks.FalseOnNotFoundOr404.class)
+   boolean delete(@PathParam("id") String id);
+}