You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by hu...@apache.org on 2013/12/19 15:08:05 UTC

[1/2] Adding OpenDayLight Neutron API. It includes 24 unit tests and 3 integration tests. Everythin passed the build.

Updated Branches:
  refs/heads/opendaylight 30d46fd2f -> b7d7342cd


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b7d7342c/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/resources/NeutronPortsNorthboundAction.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/resources/NeutronPortsNorthboundAction.java b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/resources/NeutronPortsNorthboundAction.java
new file mode 100644
index 0000000..6ff1691
--- /dev/null
+++ b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/resources/NeutronPortsNorthboundAction.java
@@ -0,0 +1,111 @@
+//
+// 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.apache.cloudstack.network.opendaylight.api.resources;
+
+import java.io.UnsupportedEncodingException;
+import java.lang.reflect.Type;
+import java.net.URL;
+import java.text.MessageFormat;
+import java.util.Collections;
+
+import org.apache.cloudstack.network.opendaylight.api.NeutronRestApiException;
+import org.apache.cloudstack.network.opendaylight.api.enums.NeutronNorthboundEnum;
+import org.apache.cloudstack.network.opendaylight.api.model.NeutronPortWrapper;
+import org.apache.cloudstack.network.opendaylight.api.model.NeutronPortsList;
+import org.apache.commons.httpclient.methods.StringRequestEntity;
+
+import com.google.gson.FieldNamingPolicy;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.reflect.TypeToken;
+
+public class NeutronPortsNorthboundAction extends Action {
+
+    private final Gson gsonNeutronPort;
+
+    public NeutronPortsNorthboundAction(final URL url, final String username, final String password) {
+        super(url, username, password);
+        gsonNeutronPort = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES).create();
+    }
+
+    @SuppressWarnings("unchecked")
+    public <T> T listAllPorts() throws NeutronRestApiException {
+        String uri = NeutronNorthboundEnum.PORTS_URI.getUri();
+        String bodystring = executeGet(uri, Collections.<String, String> emptyMap());
+
+        Type returnType = new TypeToken<NeutronPortsList<NeutronPortWrapper>>() {
+        }.getType();
+
+        T returnValue = (T) gsonNeutronPort.fromJson(bodystring, returnType);
+
+        return returnValue;
+    }
+
+    @SuppressWarnings("unchecked")
+    public <T> T findPortById(final String portId) throws NeutronRestApiException {
+        String uri = NeutronNorthboundEnum.PORTS_PARAM_URI.getUri();
+        uri = MessageFormat.format(uri, portId);
+
+        String bodystring = executeGet(uri, Collections.<String, String> emptyMap());
+
+        Type returnType = new TypeToken<NeutronPortWrapper>() {
+        }.getType();
+
+        T returnValue = (T) gsonNeutronPort.fromJson(bodystring, returnType);
+
+        return returnValue;
+    }
+
+    @SuppressWarnings("unchecked")
+    public <T> T createNeutronPort(final NeutronPortWrapper newPortWrapper) throws NeutronRestApiException {
+        try {
+            String uri = NeutronNorthboundEnum.PORTS_URI.getUri();
+            StringRequestEntity entity = new StringRequestEntity(gsonNeutronPort.toJson(newPortWrapper), JSON_CONTENT_TYPE, null);
+
+            String bodystring = executePost(uri, entity);
+
+            T result = (T) gsonNeutronPort.fromJson(bodystring, TypeToken.get(NeutronPortWrapper.class).getType());
+
+            return result;
+        } catch (UnsupportedEncodingException e) {
+            throw new NeutronRestApiException("Failed to encode json request body", e);
+        }
+    }
+
+    public <T> void updateNeutronPort(final String portId, final NeutronPortWrapper newPortWrapper) throws NeutronRestApiException {
+        try {
+            String uri = NeutronNorthboundEnum.PORTS_PARAM_URI.getUri();
+            uri = MessageFormat.format(uri, portId);
+
+            StringRequestEntity entity = new StringRequestEntity(gsonNeutronPort.toJson(newPortWrapper), JSON_CONTENT_TYPE, null);
+
+            executePut(uri, entity);
+        } catch (UnsupportedEncodingException e) {
+            throw new NeutronRestApiException("Failed to encode json request body", e);
+        }
+    }
+
+    public <T> void deleteNeutronPort(final String portId) throws NeutronRestApiException {
+        String uri = NeutronNorthboundEnum.PORTS_PARAM_URI.getUri();
+        uri = MessageFormat.format(uri, portId);
+
+        executeDelete(uri);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b7d7342c/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/responses/OpenDaylightControllerResponse.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/responses/OpenDaylightControllerResponse.java b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/responses/OpenDaylightControllerResponse.java
new file mode 100644
index 0000000..98c644a
--- /dev/null
+++ b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/responses/OpenDaylightControllerResponse.java
@@ -0,0 +1,26 @@
+//
+// 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.apache.cloudstack.network.opendaylight.api.responses;
+
+import org.apache.cloudstack.api.BaseResponse;
+
+public class OpenDaylightControllerResponse extends BaseResponse {
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b7d7342c/plugins/network-elements/opendaylight/src/test/java/org/apache/cloudstack/network/opendaylight/api/test/NeutronEnumsTest.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/opendaylight/src/test/java/org/apache/cloudstack/network/opendaylight/api/test/NeutronEnumsTest.java b/plugins/network-elements/opendaylight/src/test/java/org/apache/cloudstack/network/opendaylight/api/test/NeutronEnumsTest.java
new file mode 100644
index 0000000..1edf93b
--- /dev/null
+++ b/plugins/network-elements/opendaylight/src/test/java/org/apache/cloudstack/network/opendaylight/api/test/NeutronEnumsTest.java
@@ -0,0 +1,85 @@
+//
+// 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.apache.cloudstack.network.opendaylight.api.test;
+
+import java.text.MessageFormat;
+
+import junit.framework.Assert;
+
+import org.apache.cloudstack.network.opendaylight.api.NeutronRestApiException;
+import org.apache.cloudstack.network.opendaylight.api.enums.NeutronNorthboundEnum;
+import org.junit.Test;
+
+public class NeutronEnumsTest {
+
+    @Test
+    public <T> void enumsUrlFormatTest1() throws NeutronRestApiException {
+        String netUrl = NeutronNorthboundEnum.NETWORK_PARAM_URI.getUri();
+        netUrl = MessageFormat.format(netUrl, netId);
+
+        Assert.assertEquals(NETWORK_PARAM_URI, netUrl);
+    }
+
+    @Test
+    public <T> void enumsUrlFormatTest2() throws NeutronRestApiException {
+        String portUrl = NeutronNorthboundEnum.PORTS_PARAM_URI.getUri();
+        portUrl = MessageFormat.format(portUrl, portId);
+
+        Assert.assertEquals(PORTS_PARAM_URI, portUrl);
+    }
+
+    @Test
+    public <T> void enumsUrlFormatTest3() throws NeutronRestApiException {
+        String nodedelUrl = NeutronNorthboundEnum.NODE_PARAM_URI.getUri();
+        nodedelUrl = MessageFormat.format(nodedelUrl, "test", nodeId);
+
+        Assert.assertEquals(NODE_PARAM_URI, nodedelUrl);
+    }
+
+    @Test
+    public <T> void enumsUrlFormatTest4() throws NeutronRestApiException {
+        String nodeV1Url = NeutronNorthboundEnum.NODE_PORT_PER_NODE_URI.getUri();
+        nodeV1Url = MessageFormat.format(nodeV1Url, nodeId, ip, String.valueOf(port));
+
+        Assert.assertEquals(NODE_PORT_PER_NODE_URI, nodeV1Url);
+    }
+
+    @Test
+    public <T> void enumsUrlFormatTest5() throws NeutronRestApiException {
+        String nodeV2Url = NeutronNorthboundEnum.NODE_PORT_PER_TYPE_URI.getUri();
+        nodeV2Url = MessageFormat.format(nodeV2Url, "test", nodeId, ip, String.valueOf(port));
+
+        Assert.assertEquals(NODE_PORT_PER_TYPE_URI, nodeV2Url);
+    }
+
+    static String NETWORK_PARAM_URI = "/controller/nb/v2/neutron/networks/0AACEED5-A688-429A-92FC-E1C9E4EEEE98";
+
+    static String PORTS_PARAM_URI = "/controller/nb/v2/neutron/ports/F4267875-0C85-4829-8434-901A08691C6E";
+
+    static String NODE_PARAM_URI = "/controller/nb/v2/connectionmanager/node/test/ca31aa7f-84c7-416d-bc00-1f84927367e0";
+    static String NODE_PORT_PER_NODE_URI = "/controller/nb/v2/connectionmanager/node/ca31aa7f-84c7-416d-bc00-1f84927367e0/address/1.1.1.1/port/6400";
+    static String NODE_PORT_PER_TYPE_URI = "/controller/nb/v2/connectionmanager/node/test/ca31aa7f-84c7-416d-bc00-1f84927367e0/address/1.1.1.1/port/6400";
+
+    static String netId = "0AACEED5-A688-429A-92FC-E1C9E4EEEE98";
+    static String portId = "F4267875-0C85-4829-8434-901A08691C6E";
+    static String nodeId = "ca31aa7f-84c7-416d-bc00-1f84927367e0";
+    static String ip = "1.1.1.1";
+    static int port = 6400;
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b7d7342c/plugins/network-elements/opendaylight/src/test/java/org/apache/cloudstack/network/opendaylight/api/test/NeutronNetworkAdapterTest.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/opendaylight/src/test/java/org/apache/cloudstack/network/opendaylight/api/test/NeutronNetworkAdapterTest.java b/plugins/network-elements/opendaylight/src/test/java/org/apache/cloudstack/network/opendaylight/api/test/NeutronNetworkAdapterTest.java
new file mode 100644
index 0000000..9d0adad
--- /dev/null
+++ b/plugins/network-elements/opendaylight/src/test/java/org/apache/cloudstack/network/opendaylight/api/test/NeutronNetworkAdapterTest.java
@@ -0,0 +1,88 @@
+//
+// 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.apache.cloudstack.network.opendaylight.api.test;
+
+import java.io.UnsupportedEncodingException;
+import java.util.UUID;
+
+import junit.framework.Assert;
+
+import org.apache.commons.httpclient.methods.StringRequestEntity;
+import org.junit.Test;
+
+import com.google.gson.FieldNamingPolicy;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.reflect.TypeToken;
+
+import org.apache.cloudstack.network.opendaylight.api.NeutronRestApiException;
+import org.apache.cloudstack.network.opendaylight.api.model.NeutronNetwork;
+import org.apache.cloudstack.network.opendaylight.api.model.NeutronNetworkWrapper;
+
+public class NeutronNetworkAdapterTest {
+
+    private final Gson gsonNeutronNetwork = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES).create();
+
+    @Test
+    public void gsonNeutronNetworkMarshalingTest() throws NeutronRestApiException {
+        NeutronNetwork network = new NeutronNetwork();
+        network.setId(UUID.fromString("ca31aa7f-84c7-416d-bc00-1f84927367e0"));
+        network.setName("test_gre");
+        network.setNetworkType("test");
+        network.setSegmentationId(1001);
+        network.setShared(true);
+        network.setTenantId("wilder");
+
+        NeutronNetworkWrapper networkWrapper = new NeutronNetworkWrapper();
+        networkWrapper.setNetwork(network);
+
+        StringRequestEntity entity;
+        try {
+            entity = new StringRequestEntity(gsonNeutronNetwork.toJson(networkWrapper), "application/json", null);
+
+            String actual = entity.getContent();
+            Assert.assertEquals(jsonString, actual);
+        } catch (UnsupportedEncodingException e) {
+            Assert.fail(e.getMessage());
+        }
+    }
+
+    @Test
+    public <T> void gsonNeutronNetworkUnmarshalingTest() throws NeutronRestApiException {
+        NeutronNetwork network = new NeutronNetwork();
+        network.setId(UUID.fromString("ca31aa7f-84c7-416d-bc00-1f84927367e0"));
+        network.setName("test_gre");
+        network.setNetworkType("test");
+        network.setSegmentationId(1001);
+        network.setShared(true);
+        network.setTenantId("wilder");
+
+        NeutronNetworkWrapper networkWrapper = new NeutronNetworkWrapper();
+        networkWrapper.setNetwork(network);
+
+        NeutronNetworkWrapper returnValue = (NeutronNetworkWrapper) gsonNeutronNetwork.fromJson(jsonString, TypeToken.get(networkWrapper.getClass()).getType());
+
+        Assert.assertNotNull(returnValue);
+        Assert.assertEquals("test_gre", returnValue.getNetwork().getName());
+    }
+
+    static String jsonString = "{\"network\":{\"id\":\"ca31aa7f-84c7-416d-bc00-1f84927367e0\",\"name\":"
+            + "\"test_gre\",\"shared\":true,\"tenant_id\":\"wilder\",\"provider:network_type\":\"test\",\"provider:segmentation_id\":1001}}";
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b7d7342c/plugins/network-elements/opendaylight/src/test/java/org/apache/cloudstack/network/opendaylight/api/test/NeutronNodeAdapterTest.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/opendaylight/src/test/java/org/apache/cloudstack/network/opendaylight/api/test/NeutronNodeAdapterTest.java b/plugins/network-elements/opendaylight/src/test/java/org/apache/cloudstack/network/opendaylight/api/test/NeutronNodeAdapterTest.java
new file mode 100644
index 0000000..d7437fe
--- /dev/null
+++ b/plugins/network-elements/opendaylight/src/test/java/org/apache/cloudstack/network/opendaylight/api/test/NeutronNodeAdapterTest.java
@@ -0,0 +1,74 @@
+//
+// 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.apache.cloudstack.network.opendaylight.api.test;
+
+import java.io.UnsupportedEncodingException;
+
+import junit.framework.Assert;
+
+import org.apache.cloudstack.network.opendaylight.api.NeutronRestApiException;
+import org.apache.cloudstack.network.opendaylight.api.model.NeutronNode;
+import org.apache.cloudstack.network.opendaylight.api.model.NeutronNodeWrapper;
+import org.apache.commons.httpclient.methods.StringRequestEntity;
+import org.junit.Test;
+
+import com.google.gson.FieldNamingPolicy;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.reflect.TypeToken;
+
+public class NeutronNodeAdapterTest {
+
+    private final Gson gsonNeutronNode = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES).create();
+
+    @Test
+    public void gsonNeutronPortMarshalingTest() throws NeutronRestApiException {
+        NeutronNode node = new NeutronNode("node-test", "test");
+        NeutronNodeWrapper nodeWrapper = new NeutronNodeWrapper(node);
+
+        StringRequestEntity entity;
+        try {
+            entity = new StringRequestEntity(gsonNeutronNode.toJson(nodeWrapper), "application/json", null);
+
+            String actual = entity.getContent();
+            Assert.assertEquals(jsonString, actual);
+        } catch (UnsupportedEncodingException e) {
+            Assert.fail(e.getMessage());
+        }
+    }
+
+    @Test
+    public <T> void gsonNeutronPortUnmarshalingTest() throws NeutronRestApiException {
+        NeutronNodeWrapper returnValue = (NeutronNodeWrapper) gsonNeutronNode.fromJson(jsonString, TypeToken.get(NeutronNodeWrapper.class).getType());
+
+        Assert.assertNotNull(returnValue);
+        Assert.assertEquals("node-test", returnValue.getNode().getId().toString());
+    }
+
+    @Test
+    public <T> void gsonNeutronPortUnmarshalingNullTest() throws NeutronRestApiException {
+        String json = null;
+        NeutronNodeWrapper returnValue = (NeutronNodeWrapper) gsonNeutronNode.fromJson(json, TypeToken.get(NeutronNodeWrapper.class).getType());
+
+        Assert.assertNull(returnValue);
+    }
+
+    static String jsonString = "{\"node\":{\"id\":\"node-test\",\"type\":\"test\"}}";
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b7d7342c/plugins/network-elements/opendaylight/src/test/java/org/apache/cloudstack/network/opendaylight/api/test/NeutronPortAdapterTest.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/opendaylight/src/test/java/org/apache/cloudstack/network/opendaylight/api/test/NeutronPortAdapterTest.java b/plugins/network-elements/opendaylight/src/test/java/org/apache/cloudstack/network/opendaylight/api/test/NeutronPortAdapterTest.java
new file mode 100644
index 0000000..4d88344
--- /dev/null
+++ b/plugins/network-elements/opendaylight/src/test/java/org/apache/cloudstack/network/opendaylight/api/test/NeutronPortAdapterTest.java
@@ -0,0 +1,95 @@
+//
+// 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.apache.cloudstack.network.opendaylight.api.test;
+
+import java.io.UnsupportedEncodingException;
+import java.util.UUID;
+
+import junit.framework.Assert;
+
+import org.apache.cloudstack.network.opendaylight.api.NeutronRestApiException;
+import org.apache.cloudstack.network.opendaylight.api.model.NeutronPort;
+import org.apache.cloudstack.network.opendaylight.api.model.NeutronPortWrapper;
+import org.apache.commons.httpclient.methods.StringRequestEntity;
+import org.junit.Test;
+
+import com.google.gson.FieldNamingPolicy;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.reflect.TypeToken;
+
+public class NeutronPortAdapterTest {
+
+    private final Gson gsonNeutronPort = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES).create();
+
+    @Test
+    public void gsonNeutronPortMarshalingTest() throws NeutronRestApiException {
+        NeutronPort port = new NeutronPort();
+
+        port.setId(UUID.fromString("ca31aa7f-84c7-416d-bc00-1f84927367e0"));
+        port.setName("test_gre");
+        port.setAdminStateUp(true);
+        port.setDeviceId(UUID.fromString("ca31aa7f-84c7-416d-bc00-1f84927367e0"));
+        port.setMacAddress("ca31aa7f-84c7-416d-bc00-1f84927367e0");
+        port.setNetworkId(UUID.fromString("ca31aa7f-84c7-416d-bc00-1f84927367e0"));
+        port.setStatus("ACTIVE");
+        port.setTenantId("wilder");
+
+        NeutronPortWrapper portWrapper = new NeutronPortWrapper();
+        portWrapper.setPort(port);
+
+        StringRequestEntity entity;
+        try {
+            entity = new StringRequestEntity(gsonNeutronPort.toJson(portWrapper), "application/json", null);
+
+            String actual = entity.getContent();
+
+            Assert.assertEquals(jsonString, actual);
+        } catch (UnsupportedEncodingException e) {
+            Assert.fail(e.getMessage());
+        }
+    }
+
+    @Test
+    public <T> void gsonNeutronPortUnmarshalingTest() throws NeutronRestApiException {
+        NeutronPort port = new NeutronPort();
+
+        port.setId(UUID.fromString("ca31aa7f-84c7-416d-bc00-1f84927367e0"));
+        port.setName("test_gre");
+        port.setAdminStateUp(true);
+        port.setDeviceId(UUID.fromString("ca31aa7f-84c7-416d-bc00-1f84927367e0"));
+        port.setMacAddress("ca31aa7f-84c7-416d-bc00-1f84927367e0");
+        port.setNetworkId(UUID.fromString("ca31aa7f-84c7-416d-bc00-1f84927367e0"));
+        port.setStatus("ACTIVE");
+        port.setTenantId("wilder");
+
+        NeutronPortWrapper portWrapper = new NeutronPortWrapper();
+        portWrapper.setPort(port);
+
+        NeutronPortWrapper returnValue = (NeutronPortWrapper) gsonNeutronPort.fromJson(jsonString, TypeToken.get(portWrapper.getClass()).getType());
+
+        Assert.assertNotNull(returnValue);
+        Assert.assertEquals("ca31aa7f-84c7-416d-bc00-1f84927367e0", returnValue.getPort().getMacAddress());
+    }
+
+    static String jsonString = "{\"port\":{\"id\":\"ca31aa7f-84c7-416d-bc00-1f84927367e0\",\"name\":\"test_gre\",\"tenant_id\":\"wilder\",\"network_id\":"
+            + "\"ca31aa7f-84c7-416d-bc00-1f84927367e0\",\"mac_address\":\"ca31aa7f-84c7-416d-bc00-1f84927367e0\",\"device_id\":\"ca31aa7f-84c7-416d-bc00-1f84927367e0\","
+            + "\"admin_state_up\":true,\"status\":\"ACTIVE\"}}";
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b7d7342c/plugins/network-elements/opendaylight/src/test/java/org/apache/cloudstack/network/opendaylight/api/test/NeutronRestApiIT.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/opendaylight/src/test/java/org/apache/cloudstack/network/opendaylight/api/test/NeutronRestApiIT.java b/plugins/network-elements/opendaylight/src/test/java/org/apache/cloudstack/network/opendaylight/api/test/NeutronRestApiIT.java
new file mode 100644
index 0000000..89f4b41
--- /dev/null
+++ b/plugins/network-elements/opendaylight/src/test/java/org/apache/cloudstack/network/opendaylight/api/test/NeutronRestApiIT.java
@@ -0,0 +1,95 @@
+//
+// 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.apache.cloudstack.network.opendaylight.api.test;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.List;
+
+import junit.framework.Assert;
+
+import org.apache.cloudstack.network.opendaylight.api.NeutronRestApiException;
+import org.apache.cloudstack.network.opendaylight.api.model.NeutronNetworkWrapper;
+import org.apache.cloudstack.network.opendaylight.api.model.NeutronNetworksList;
+import org.apache.cloudstack.network.opendaylight.api.model.NeutronNodeWrapper;
+import org.apache.cloudstack.network.opendaylight.api.model.NeutronNodesList;
+import org.apache.cloudstack.network.opendaylight.api.model.NeutronPortWrapper;
+import org.apache.cloudstack.network.opendaylight.api.model.NeutronPortsList;
+import org.apache.cloudstack.network.opendaylight.api.resources.NeutronNetworksNorthboundAction;
+import org.apache.cloudstack.network.opendaylight.api.resources.NeutronNodesNorthboundAction;
+import org.apache.cloudstack.network.opendaylight.api.resources.NeutronPortsNorthboundAction;
+import org.junit.Test;
+
+public class NeutronRestApiIT {
+
+    @Test
+    public void neutronListAllNodes() throws NeutronRestApiException {
+        URL url;
+        try {
+            url = new URL("http://178.237.34.233:8080");
+
+            NeutronNodesNorthboundAction neutron = new NeutronNodesNorthboundAction(url, "admin", "admin");
+            NeutronNodesList<NeutronNodeWrapper> results = neutron.listAllNodes();
+
+            Assert.assertNotNull(results);
+
+        } catch (MalformedURLException e) {
+            Assert.fail("Should not fail here.");
+        }
+    }
+
+    @Test
+    public void neutronListAllNetworks() throws NeutronRestApiException {
+        URL url;
+        try {
+            url = new URL("http://178.237.34.233:8080");
+
+            NeutronNetworksNorthboundAction neutron = new NeutronNetworksNorthboundAction(url, "admin", "admin");
+            NeutronNetworksList<NeutronNetworkWrapper> results = neutron.listAllNetworks();
+
+            Assert.assertNotNull(results);
+
+            List<NeutronNetworkWrapper> networks = results.getNetworks();
+            Assert.assertNotNull(networks);
+
+        } catch (MalformedURLException e) {
+            Assert.fail("Should not fail here.");
+        }
+    }
+
+    @Test
+    public void neutronListAllPorts() throws NeutronRestApiException {
+        URL url;
+        try {
+            url = new URL("http://178.237.34.233:8080");
+
+            NeutronPortsNorthboundAction neutron = new NeutronPortsNorthboundAction(url, "admin", "admin");
+            NeutronPortsList<NeutronPortWrapper> results = neutron.listAllPorts();
+
+            Assert.assertNotNull(results);
+
+            List<NeutronPortWrapper> networks = results.getPorts();
+            Assert.assertNotNull(networks);
+
+        } catch (MalformedURLException e) {
+            Assert.fail("Should not fail here.");
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b7d7342c/plugins/network-elements/opendaylight/src/test/java/org/apache/cloudstack/network/opendaylight/api/test/NeutronRestApiTest.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/opendaylight/src/test/java/org/apache/cloudstack/network/opendaylight/api/test/NeutronRestApiTest.java b/plugins/network-elements/opendaylight/src/test/java/org/apache/cloudstack/network/opendaylight/api/test/NeutronRestApiTest.java
new file mode 100644
index 0000000..aee15b3
--- /dev/null
+++ b/plugins/network-elements/opendaylight/src/test/java/org/apache/cloudstack/network/opendaylight/api/test/NeutronRestApiTest.java
@@ -0,0 +1,254 @@
+//
+// 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.apache.cloudstack.network.opendaylight.api.test;
+
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.UUID;
+
+import junit.framework.Assert;
+
+import org.apache.cloudstack.network.opendaylight.api.NeutronRestApi;
+import org.apache.cloudstack.network.opendaylight.api.NeutronRestApiException;
+import org.apache.cloudstack.network.opendaylight.api.NeutronRestFactory;
+import org.apache.cloudstack.network.opendaylight.api.model.NeutronNetwork;
+import org.apache.cloudstack.network.opendaylight.api.model.NeutronNetworkWrapper;
+import org.apache.cloudstack.network.opendaylight.api.resources.NeutronNetworksNorthboundAction;
+import org.apache.cloudstack.network.opendaylight.api.resources.NeutronNodesNorthboundAction;
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.HttpException;
+import org.apache.commons.httpclient.HttpMethodBase;
+import org.apache.commons.httpclient.methods.DeleteMethod;
+import org.apache.commons.httpclient.methods.GetMethod;
+import org.apache.commons.httpclient.methods.PostMethod;
+import org.apache.commons.httpclient.methods.PutMethod;
+import org.junit.Test;
+
+public class NeutronRestApiTest {
+
+    NeutronRestFactory factory = NeutronRestFactory.getInstance();
+
+    NeutronRestApi httpGet = factory.getNeutronApi(GetMethod.class);
+    NeutronRestApi httpPost = factory.getNeutronApi(PostMethod.class);
+    NeutronRestApi httpPut = factory.getNeutronApi(PutMethod.class);
+    NeutronRestApi httpDelete = factory.getNeutronApi(DeleteMethod.class);
+
+    @Test
+    public void resourceHttpGetInstances() throws NeutronRestApiException {
+        NeutronRestApi newHttpGet = factory.getNeutronApi(GetMethod.class);
+        assertTrue(httpGet == newHttpGet);
+    }
+
+    @Test
+    public void resourceHttpPostInstances() throws NeutronRestApiException {
+        NeutronRestApi newHttpPost = factory.getNeutronApi(PostMethod.class);
+        assertTrue(httpPost == newHttpPost);
+    }
+
+    @Test
+    public void resourceHttpPutInstances() throws NeutronRestApiException {
+        NeutronRestApi newHttpPut = factory.getNeutronApi(PutMethod.class);
+        assertTrue(httpPut == newHttpPut);
+    }
+
+    @Test
+    public void resourceHttpDeleteInstances() throws NeutronRestApiException {
+        NeutronRestApi newHttpDelete = factory.getNeutronApi(DeleteMethod.class);
+        assertTrue(httpDelete == newHttpDelete);
+    }
+
+    @Test(expected = NeutronRestApiException.class)
+    public void neutronNetworksFail() throws NeutronRestApiException {
+        URL url;
+        try {
+            url = new URL("http://localhost:8080");
+
+            NeutronNetworksNorthboundAction neutron = new NeutronNetworksNorthboundAction(url, "admin", "admin");
+            neutron.listAllNetworks();
+        } catch (MalformedURLException e) {
+            Assert.fail("Should not fail here.");
+        }
+    }
+
+    @Test(expected = NeutronRestApiException.class)
+    public void neutronFindNetworkByIdFail() throws NeutronRestApiException {
+        URL url;
+        try {
+            url = new URL("http://localhost:8080");
+
+            NeutronNetworksNorthboundAction neutron = new NeutronNetworksNorthboundAction(url, "admin", "admin");
+            neutron.findNetworkById("0AACEED5-A688-429A-92FC-E1C9E4EEEE98");
+        } catch (MalformedURLException e) {
+            Assert.fail("Should not fail here.");
+        }
+    }
+
+    @Test(expected = NeutronRestApiException.class)
+    public void neutronNodesFail() throws NeutronRestApiException {
+        URL url;
+        try {
+            url = new URL("http://localhost:8080");
+
+            NeutronNodesNorthboundAction neutron = new NeutronNodesNorthboundAction(url, "admin", "admin");
+            neutron.listAllNodes();
+        } catch (MalformedURLException e) {
+            Assert.fail("Should not fail here.");
+        }
+    }
+
+    /*
+     * Test fails because there is no controller. It's used only to test that
+     * the HTTP methods are correct.
+     */
+    @Test(expected = NeutronRestApiException.class)
+    public void neutronHTTPDeleteMethod() throws NeutronRestApiException {
+        URL url;
+        try {
+            url = new URL("http://127.0.0.1:8080");
+
+            NeutronNetworksNorthboundAction neutron = new NeutronNetworksNorthboundAction(url, "admin", "admin");
+            neutron.deleteNeutronNetwork("0AACEED5-A688-429A-92FC-E1C9E4EEEE98");
+        } catch (MalformedURLException e) {
+            Assert.fail("Should not fail here.");
+        }
+    }
+
+    /*
+     * Test fails because there is no controller. It's used only to test that
+     * the HTTP methods are correct.
+     */
+    @Test(expected = NeutronRestApiException.class)
+    public void neutronHTTPGetMethod() throws NeutronRestApiException {
+        URL url;
+        try {
+            url = new URL("http://localhost:8080");
+
+            NeutronNetworksNorthboundAction neutron = new NeutronNetworksNorthboundAction(url, "admin", "admin");
+            neutron.listAllNetworks();
+        } catch (MalformedURLException e) {
+            Assert.fail("Should not fail here.");
+        }
+    }
+
+    /*
+     * Test fails because there is no controller. It's used only to test that
+     * the HTTP methods are correct.
+     */
+    @Test(expected = NeutronRestApiException.class)
+    public void neutronHTTPPostMethod() throws NeutronRestApiException {
+        URL url;
+        try {
+            url = new URL("http://localhost:8080");
+
+            NeutronNetwork network = new NeutronNetwork();
+            network.setId(UUID.fromString("ca31aa7f-84c7-416d-bc00-1f84927367e0"));
+            network.setName("test_gre");
+            network.setNetworkType("test");
+            network.setSegmentationId(1001);
+            network.setShared(true);
+            network.setTenantId("wilder");
+
+            NeutronNetworkWrapper networkWrapper = new NeutronNetworkWrapper();
+            networkWrapper.setNetwork(network);
+
+            NeutronNetworksNorthboundAction neutron = new NeutronNetworksNorthboundAction(url, "admin", "admin");
+            neutron.createNeutronNetwork(networkWrapper);
+
+        } catch (MalformedURLException e) {
+            Assert.fail("Should not fail here.");
+        }
+    }
+
+    /*
+     * Test fails because there is no controller. It's used only to test that
+     * the HTTP methods are correct.
+     */
+    @Test(expected = NeutronRestApiException.class)
+    public void neutronHTTPPutMethod() throws NeutronRestApiException {
+        URL url;
+        try {
+            url = new URL("http://localhost:8080");
+
+            NeutronNetwork network = new NeutronNetwork();
+            network.setId(UUID.fromString("ca31aa7f-84c7-416d-bc00-1f84927367e0"));
+            network.setName("test_gre");
+            network.setNetworkType("test");
+            network.setSegmentationId(1001);
+            network.setShared(true);
+            network.setTenantId("wilder");
+
+            NeutronNetworkWrapper networkWrapper = new NeutronNetworkWrapper();
+            networkWrapper.setNetwork(network);
+
+            NeutronNetworksNorthboundAction neutron = new NeutronNetworksNorthboundAction(url, "admin", "admin");
+            neutron.updateNeutronNetwork("ca31aa7f-84c7-416d-bc00-1f84927367e0", networkWrapper);
+
+        } catch (MalformedURLException e) {
+            Assert.fail("Should not fail here.");
+        }
+    }
+
+    /*
+     * Test fails because there is no controller. It's used only to test that
+     * the HTTP methods are correct.
+     */
+    @Test(expected = NeutronRestApiException.class)
+    public void neutronHTTPPutUriMethod() throws NeutronRestApiException {
+        URL url;
+        try {
+            url = new URL("http://localhost:8080");
+
+            NeutronNodesNorthboundAction neutron = new NeutronNodesNorthboundAction(url, "admin", "admin");
+            neutron.updateNeutronNodeV1("ca31aa7f-84c7-416d-bc00-1f84927367e0", "1.1.1.1.", 6400);
+
+        } catch (MalformedURLException e) {
+            Assert.fail("Should not fail here.");
+        }
+    }
+
+    static String networkJSON = "{" + "\"networks\": [" + "{" + "\"network\": {" + "\"segmentation_id\": 100," + "\"shared\": false," + "\"name\": \"net_test\","
+            + "\"network_type\": \"test\"," + "\"tenant_id\": \"t\"," + "\"id\": \"0AACEED5-A688-429A-92FC-E1C9E4EEEE98\"," + "\"status\": \"ACTIVE\"" + "}" + "}" + "]" + "}";
+}
+
+class NeutronRestApiMock extends NeutronRestApi {
+
+    HttpClient client = mock(HttpClient.class);
+
+    NeutronRestApiMock(final Class<? extends HttpMethodBase> httpClazz) {
+        super(httpClazz);
+    }
+
+    @Override
+    public void executeMethod(final HttpMethodBase method) throws NeutronRestApiException {
+        try {
+            client.executeMethod(method);
+        } catch (HttpException e) {
+            method.releaseConnection();
+            throw new NeutronRestApiException("API call to Neutron NVP Controller Failed", e);
+        } catch (IOException e) {
+            method.releaseConnection();
+            throw new NeutronRestApiException("API call to Neutron NVP Controller Failed", e);
+        }
+    }
+}
\ No newline at end of file


[2/2] git commit: updated refs/heads/opendaylight to b7d7342

Posted by hu...@apache.org.
Adding OpenDayLight Neutron API. It includes 24 unit tests and 3 integration tests. Everythin passed the build.

Signed-off-by: Hugo Trippaers <ht...@schubergphilis.com>


Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/b7d7342c
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/b7d7342c
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/b7d7342c

Branch: refs/heads/opendaylight
Commit: b7d7342cd787af27a7f52a03356e9218a19c0030
Parents: 30d46fd
Author: wrodrigues <wr...@schubergphilis.com>
Authored: Thu Dec 19 14:30:01 2013 +0100
Committer: Hugo Trippaers <ht...@schubergphilis.com>
Committed: Thu Dec 19 14:44:31 2013 +0100

----------------------------------------------------------------------
 .../api/NeutronInvalidCredentialsException.java |  38 +++
 .../opendaylight/api/NeutronRestApi.java        | 217 ++++++++++++++
 .../api/NeutronRestApiException.java            |  38 +++
 .../opendaylight/api/NeutronRestFactory.java    |  55 ++++
 .../commands/AddOpenDaylightControllerCmd.java  | 114 ++++++++
 .../DeleteOpenDaylightControllerCmd.java        |  99 +++++++
 .../api/enums/NeutronNorthboundEnum.java        |  44 +++
 .../opendaylight/api/model/NeutronNetwork.java  | 213 ++++++++++++++
 .../api/model/NeutronNetworkWrapper.java        |  70 +++++
 .../api/model/NeutronNetworksList.java          |  42 +++
 .../opendaylight/api/model/NeutronNode.java     |  98 +++++++
 .../api/model/NeutronNodeWrapper.java           |  65 +++++
 .../api/model/NeutronNodesList.java             |  42 +++
 .../opendaylight/api/model/NeutronPort.java     | 265 +++++++++++++++++
 .../api/model/NeutronPortWrapper.java           |  70 +++++
 .../api/model/NeutronPortsList.java             |  42 +++
 .../opendaylight/api/resources/Action.java      | 287 +++++++++++++++++++
 .../NeutronNetworksNorthboundAction.java        | 111 +++++++
 .../resources/NeutronNodesNorthboundAction.java |  89 ++++++
 .../resources/NeutronPortsNorthboundAction.java | 111 +++++++
 .../OpenDaylightControllerResponse.java         |  26 ++
 .../opendaylight/api/test/NeutronEnumsTest.java |  85 ++++++
 .../api/test/NeutronNetworkAdapterTest.java     |  88 ++++++
 .../api/test/NeutronNodeAdapterTest.java        |  74 +++++
 .../api/test/NeutronPortAdapterTest.java        |  95 ++++++
 .../opendaylight/api/test/NeutronRestApiIT.java |  95 ++++++
 .../api/test/NeutronRestApiTest.java            | 254 ++++++++++++++++
 27 files changed, 2827 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b7d7342c/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/NeutronInvalidCredentialsException.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/NeutronInvalidCredentialsException.java b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/NeutronInvalidCredentialsException.java
new file mode 100644
index 0000000..f46e0b6
--- /dev/null
+++ b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/NeutronInvalidCredentialsException.java
@@ -0,0 +1,38 @@
+//
+// 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.apache.cloudstack.network.opendaylight.api;
+
+public class NeutronInvalidCredentialsException extends Exception {
+
+    public NeutronInvalidCredentialsException() {
+    }
+
+    public NeutronInvalidCredentialsException(final String message) {
+        super(message);
+    }
+
+    public NeutronInvalidCredentialsException(final Throwable cause) {
+        super(cause);
+    }
+
+    public NeutronInvalidCredentialsException(final String message, final Throwable cause) {
+        super(message, cause);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b7d7342c/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/NeutronRestApi.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/NeutronRestApi.java b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/NeutronRestApi.java
new file mode 100644
index 0000000..2d0c532
--- /dev/null
+++ b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/NeutronRestApi.java
@@ -0,0 +1,217 @@
+//
+// 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.apache.cloudstack.network.opendaylight.api;
+
+import java.io.IOException;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.MalformedURLException;
+import java.net.Socket;
+import java.net.URL;
+import java.net.UnknownHostException;
+import java.security.KeyManagementException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.X509Certificate;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
+
+import org.apache.commons.httpclient.ConnectTimeoutException;
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.HttpException;
+import org.apache.commons.httpclient.HttpMethodBase;
+import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
+import org.apache.commons.httpclient.cookie.CookiePolicy;
+import org.apache.commons.httpclient.params.HttpConnectionParams;
+import org.apache.commons.httpclient.protocol.Protocol;
+import org.apache.commons.httpclient.protocol.ProtocolSocketFactory;
+import org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory;
+import org.apache.log4j.Logger;
+
+public class NeutronRestApi {
+
+    private static final Logger s_logger = Logger.getLogger(NeutronRestApi.class);
+    private static final MultiThreadedHttpConnectionManager s_httpClientManager = new MultiThreadedHttpConnectionManager();
+
+    private static final String PROTOCOL = "https";
+    private static final int HTTPS_PORT = 443;
+
+    private final HttpClient client;
+
+    private Class<? extends HttpMethodBase> httpClazz;
+
+    protected NeutronRestApi(final Class<? extends HttpMethodBase> httpClazz) {
+        this(httpClazz, PROTOCOL, HTTPS_PORT);
+    }
+
+    protected NeutronRestApi(final Class<? extends HttpMethodBase> httpClazz, final String protocol, final int port) {
+        client = createHttpClient();
+        client.getParams().setCookiePolicy(CookiePolicy.BROWSER_COMPATIBILITY);
+        this.httpClazz = httpClazz;
+
+        try {
+            // Cast to ProtocolSocketFactory to avoid the deprecated constructor
+            // with the SecureProtocolSocketFactory parameter
+            Protocol.registerProtocol(protocol, new Protocol(protocol, (ProtocolSocketFactory) new TrustingProtocolSocketFactory(), HTTPS_PORT));
+        } catch (IOException e) {
+            s_logger.warn("Failed to register the TrustingProtocolSocketFactory, falling back to default SSLSocketFactory", e);
+        }
+    }
+
+    public Class<? extends HttpMethodBase> getHttpClazz() {
+        return httpClazz;
+    }
+
+    public HttpMethodBase createMethod(final URL neutronUrl, final String uri) throws NeutronRestApiException {
+        String url;
+        try {
+            String formattedUrl = neutronUrl.toString() + uri;
+            url = new URL(formattedUrl).toString();
+
+            Constructor<? extends HttpMethodBase> httpMethodConstructor = httpClazz.getConstructor(String.class);
+            HttpMethodBase httpMethod = httpMethodConstructor.newInstance(url);
+
+            return httpMethod;
+        } catch (MalformedURLException e) {
+            String error = "Unable to build Neutron API URL";
+            s_logger.error(error, e);
+            throw new NeutronRestApiException(error, e);
+        } catch (NoSuchMethodException e) {
+            String error = "Unable to build Neutron API URL due to reflection error";
+            s_logger.error(error, e);
+            throw new NeutronRestApiException(error, e);
+        } catch (SecurityException e) {
+            String error = "Unable to build Neutron API URL due to security violation";
+            s_logger.error(error, e);
+            throw new NeutronRestApiException(error, e);
+        } catch (InstantiationException e) {
+            String error = "Unable to build Neutron API due to instantiation error";
+            s_logger.error(error, e);
+            throw new NeutronRestApiException(error, e);
+        } catch (IllegalAccessException e) {
+            String error = "Unable to build Neutron API URL due to absence of access modifier";
+            s_logger.error(error, e);
+            throw new NeutronRestApiException(error, e);
+        } catch (IllegalArgumentException e) {
+            String error = "Unable to build Neutron API URL due to wrong argument in constructor";
+            s_logger.error(error, e);
+            throw new NeutronRestApiException(error, e);
+        } catch (InvocationTargetException e) {
+            String error = "Unable to build Neutron API URL due to target error";
+            s_logger.error(error, e);
+            throw new NeutronRestApiException(error, e);
+        }
+    }
+
+    public void executeMethod(final HttpMethodBase method) throws NeutronRestApiException {
+        try {
+            client.executeMethod(method);
+        } catch (HttpException e) {
+            s_logger.error("HttpException caught while trying to connect to the Neutron Controller", e);
+            method.releaseConnection();
+            throw new NeutronRestApiException("API call to Neutron Controller Failed", e);
+        } catch (IOException e) {
+            s_logger.error("IOException caught while trying to connect to the Neutron Controller", e);
+            method.releaseConnection();
+            throw new NeutronRestApiException("API call to Neutron Controller Failed", e);
+        }
+    }
+
+    /*
+     * This factory method is protected so we can extend this in the unit tests.
+     */
+    protected HttpClient createHttpClient() {
+        return new HttpClient(s_httpClientManager);
+    }
+
+    /*
+     * It uses a self-signed certificate. The TrustingProtocolSocketFactory will
+     * accept any provided certificate when making an SSL connection to the SDN
+     * Manager
+     */
+    private class TrustingProtocolSocketFactory implements SecureProtocolSocketFactory {
+
+        private SSLSocketFactory ssf;
+
+        public TrustingProtocolSocketFactory() throws IOException {
+            // Create a trust manager that does not validate certificate chains
+            TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
+                @Override
+                public X509Certificate[] getAcceptedIssuers() {
+                    return null;
+                }
+
+                @Override
+                public void checkClientTrusted(final X509Certificate[] certs, final String authType) {
+                    // Trust always
+                }
+
+                @Override
+                public void checkServerTrusted(final X509Certificate[] certs, final String authType) {
+                    // Trust always
+                }
+            } };
+
+            try {
+                // Install the all-trusting trust manager
+                SSLContext sc = SSLContext.getInstance("SSL");
+                sc.init(null, trustAllCerts, new java.security.SecureRandom());
+                ssf = sc.getSocketFactory();
+            } catch (KeyManagementException e) {
+                throw new IOException(e);
+            } catch (NoSuchAlgorithmException e) {
+                throw new IOException(e);
+            }
+        }
+
+        @Override
+        public Socket createSocket(final String host, final int port) throws IOException {
+            return ssf.createSocket(host, port);
+        }
+
+        @Override
+        public Socket createSocket(final String address, final int port, final InetAddress localAddress, final int localPort) throws IOException, UnknownHostException {
+            return ssf.createSocket(address, port, localAddress, localPort);
+        }
+
+        @Override
+        public Socket createSocket(final Socket socket, final String host, final int port, final boolean autoClose) throws IOException, UnknownHostException {
+            return ssf.createSocket(socket, host, port, autoClose);
+        }
+
+        @Override
+        public Socket createSocket(final String host, final int port, final InetAddress localAddress, final int localPort, final HttpConnectionParams params) throws IOException,
+                UnknownHostException, ConnectTimeoutException {
+            int timeout = params.getConnectionTimeout();
+            if (timeout == 0) {
+                return createSocket(host, port, localAddress, localPort);
+            } else {
+                Socket s = ssf.createSocket();
+                s.bind(new InetSocketAddress(localAddress, localPort));
+                s.connect(new InetSocketAddress(host, port), timeout);
+                return s;
+            }
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b7d7342c/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/NeutronRestApiException.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/NeutronRestApiException.java b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/NeutronRestApiException.java
new file mode 100644
index 0000000..58bcd0d
--- /dev/null
+++ b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/NeutronRestApiException.java
@@ -0,0 +1,38 @@
+//
+// 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.apache.cloudstack.network.opendaylight.api;
+
+public class NeutronRestApiException extends Exception {
+
+    public NeutronRestApiException() {
+    }
+
+    public NeutronRestApiException(final String message) {
+        super(message);
+    }
+
+    public NeutronRestApiException(final Throwable cause) {
+        super(cause);
+    }
+
+    public NeutronRestApiException(final String message, final Throwable cause) {
+        super(message, cause);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b7d7342c/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/NeutronRestFactory.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/NeutronRestFactory.java b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/NeutronRestFactory.java
new file mode 100644
index 0000000..10ac5e0
--- /dev/null
+++ b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/NeutronRestFactory.java
@@ -0,0 +1,55 @@
+//
+// 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.apache.cloudstack.network.opendaylight.api;
+
+import java.util.Hashtable;
+import java.util.Map;
+
+import org.apache.commons.httpclient.HttpMethodBase;
+
+public class NeutronRestFactory {
+
+    private Map<String, NeutronRestApi> flyweight = new Hashtable<String, NeutronRestApi>();
+
+    private static NeutronRestFactory instance;
+
+    static {
+        instance = new NeutronRestFactory();
+    }
+
+    private NeutronRestFactory() {
+    }
+
+    public static NeutronRestFactory getInstance() {
+        return instance;
+    }
+
+    public NeutronRestApi getNeutronApi(final Class<? extends HttpMethodBase> clazz) {
+        if (!flyweight.containsKey(clazz.getName())) {
+            NeutronRestApi api = new NeutronRestApi(clazz);
+            addNeutronApi(api);
+        }
+        return flyweight.get(clazz.getName());
+    }
+
+    public void addNeutronApi(final NeutronRestApi api) {
+        flyweight.put(api.getHttpClazz().getName(), api);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b7d7342c/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/commands/AddOpenDaylightControllerCmd.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/commands/AddOpenDaylightControllerCmd.java b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/commands/AddOpenDaylightControllerCmd.java
new file mode 100644
index 0000000..dca8007
--- /dev/null
+++ b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/commands/AddOpenDaylightControllerCmd.java
@@ -0,0 +1,114 @@
+//
+// 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.apache.cloudstack.network.opendaylight.api.commands;
+
+import javax.inject.Inject;
+
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.BaseAsyncCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.PhysicalNetworkResponse;
+import org.apache.cloudstack.context.CallContext;
+import org.apache.cloudstack.network.opendaylight.agent.OpenDaylightControllerResourceManager;
+import org.apache.cloudstack.network.opendaylight.api.responses.OpenDaylightControllerResponse;
+
+import com.cloud.event.EventTypes;
+import com.cloud.exception.ConcurrentOperationException;
+import com.cloud.exception.InsufficientCapacityException;
+import com.cloud.exception.NetworkRuleConflictException;
+import com.cloud.exception.ResourceAllocationException;
+import com.cloud.exception.ResourceUnavailableException;
+
+@APICommand(name = "addOpenDaylightController", responseObject = OpenDaylightControllerResponse.class, description = "Adds an OpenDyalight controler")
+public class AddOpenDaylightControllerCmd extends BaseAsyncCmd {
+
+    @Inject
+    private OpenDaylightControllerResourceManager resourceManager;
+
+    /////////////////////////////////////////////////////
+    //////////////// API parameters /////////////////////
+    /////////////////////////////////////////////////////
+
+    @Parameter(name = ApiConstants.PHYSICAL_NETWORK_ID, type = CommandType.UUID, entityType = PhysicalNetworkResponse.class, required = true,
+            description = "the Physical Network ID")
+    private Long physicalNetworkId;
+
+    @Parameter(name = ApiConstants.URL, type = CommandType.STRING, required = true, description = "Api URL of the OpenDaylight Controller.")
+    private String url;
+
+    @Parameter(name = ApiConstants.USERNAME, type = CommandType.STRING, required = true, description = "Username to access the OpenDaylight API")
+    private String username;
+
+    @Parameter(name = ApiConstants.PASSWORD, type = CommandType.STRING, required = true, description = "Credential to access the OpenDaylight API")
+    private String password;
+
+    /////////////////////////////////////////////////////
+    /////////////////// Accessors ///////////////////////
+    /////////////////////////////////////////////////////
+
+    @Override
+    public String getCommandName() {
+        return "addOpenDaylightController";
+    }
+
+    @Override
+    public long getEntityOwnerId() {
+        return CallContext.current().getCallingAccount().getId();
+    }
+
+    @Override
+    public String getEventType() {
+        return EventTypes.EVENT_EXTERNAL_OPENDAYLIGHT_ADD_CONTROLLER;
+    }
+
+    @Override
+    public String getEventDescription() {
+        return "Adding OpenDaylight controller";
+    }
+
+    public Long getPhysicalNetworkId() {
+        return physicalNetworkId;
+    }
+
+    public String getUrl() {
+        return url;
+    }
+
+    public String getUsername() {
+        return username;
+    }
+
+    public String getPassword() {
+        return password;
+    }
+
+    /////////////////////////////////////////////////////
+    /////////////// API Implementation///////////////////
+    /////////////////////////////////////////////////////
+
+    @Override
+    public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException,
+    NetworkRuleConflictException {
+        resourceManager.addController(this);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b7d7342c/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/commands/DeleteOpenDaylightControllerCmd.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/commands/DeleteOpenDaylightControllerCmd.java b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/commands/DeleteOpenDaylightControllerCmd.java
new file mode 100644
index 0000000..7359ce9
--- /dev/null
+++ b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/commands/DeleteOpenDaylightControllerCmd.java
@@ -0,0 +1,99 @@
+//
+// 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.apache.cloudstack.network.opendaylight.api.commands;
+
+import javax.inject.Inject;
+
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseAsyncCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.SuccessResponse;
+import org.apache.cloudstack.context.CallContext;
+import org.apache.cloudstack.network.opendaylight.agent.OpenDaylightControllerResourceManager;
+import org.apache.cloudstack.network.opendaylight.api.responses.OpenDaylightControllerResponse;
+
+import com.cloud.event.EventTypes;
+import com.cloud.exception.ConcurrentOperationException;
+import com.cloud.exception.InsufficientCapacityException;
+import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.exception.NetworkRuleConflictException;
+import com.cloud.exception.ResourceAllocationException;
+import com.cloud.exception.ResourceUnavailableException;
+
+@APICommand(name = "deleteOpenDaylightController", responseObject = OpenDaylightControllerResponse.class, description = "Removes an OpenDyalight controler")
+public class DeleteOpenDaylightControllerCmd extends BaseAsyncCmd {
+    @Inject
+    private OpenDaylightControllerResourceManager resourceManager;
+
+    /////////////////////////////////////////////////////
+    //////////////// API parameters /////////////////////
+    /////////////////////////////////////////////////////
+
+    @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = OpenDaylightControllerResponse.class, required = true, description = "OpenDaylight Controller ID")
+    private Long id;
+
+    /////////////////////////////////////////////////////
+    /////////////////// Accessors ///////////////////////
+    /////////////////////////////////////////////////////
+
+    public Long getId() {
+        return id;
+    }
+
+    @Override
+    public String getEventType() {
+        return EventTypes.EVENT_EXTERNAL_OPENDAYLIGHT_DELETE_CONTROLLER;
+    }
+
+    @Override
+    public String getEventDescription() {
+        return "Deleted OpenDaylight Controller";
+    }
+
+    @Override
+    public String getCommandName() {
+        return "deleteOpenDaylightController";
+    }
+
+    @Override
+    public long getEntityOwnerId() {
+        return CallContext.current().getCallingAccount().getId();
+    }
+
+    /////////////////////////////////////////////////////
+    /////////////// API Implementation///////////////////
+    /////////////////////////////////////////////////////
+    @Override
+    public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException,
+    NetworkRuleConflictException {
+        try {
+            resourceManager.deleteController(this);
+            SuccessResponse response = new SuccessResponse(getCommandName());
+            response.setResponseName(getCommandName());
+            setResponseObject(response); //FIXME
+        } catch (InvalidParameterValueException e) {
+            throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to delete OpenDaylight controller.");
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b7d7342c/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/enums/NeutronNorthboundEnum.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/enums/NeutronNorthboundEnum.java b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/enums/NeutronNorthboundEnum.java
new file mode 100644
index 0000000..8411e23
--- /dev/null
+++ b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/enums/NeutronNorthboundEnum.java
@@ -0,0 +1,44 @@
+//
+// 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.apache.cloudstack.network.opendaylight.api.enums;
+
+public enum NeutronNorthboundEnum {
+
+    NETWORKS_URI("/controller/nb/v2/neutron/networks"),
+    NETWORK_PARAM_URI("/controller/nb/v2/neutron/networks/{0}"),
+
+    PORTS_URI("/controller/nb/v2/neutron/ports"),
+    PORTS_PARAM_URI("/controller/nb/v2/neutron/ports/{0}"),
+
+    NODES_URI("/controller/nb/v2/connectionmanager/nodes"),
+    NODE_PARAM_URI("/controller/nb/v2/connectionmanager/node/{0}/{1}"),
+    NODE_PORT_PER_NODE_URI("/controller/nb/v2/connectionmanager/node/{0}/address/{1}/port/{2}"),
+    NODE_PORT_PER_TYPE_URI("/controller/nb/v2/connectionmanager/node/{0}/{1}/address/{2}/port/{3}");
+
+    private String uri;
+
+    private NeutronNorthboundEnum(String uri) {
+        this.uri = uri;
+    }
+
+    public String getUri() {
+        return uri;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b7d7342c/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/model/NeutronNetwork.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/model/NeutronNetwork.java b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/model/NeutronNetwork.java
new file mode 100644
index 0000000..7d1ebf0
--- /dev/null
+++ b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/model/NeutronNetwork.java
@@ -0,0 +1,213 @@
+//
+// 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.apache.cloudstack.network.opendaylight.api.model;
+
+import java.util.UUID;
+
+import com.google.gson.annotations.SerializedName;
+
+public class NeutronNetwork {
+
+    private UUID id;
+    private String name;
+    private boolean shared;
+    private String tenantId;
+    @SerializedName("provider:network_type")
+    private String networkType;
+    @SerializedName("provider:segmentation_id")
+    private Integer segmentationId;
+
+    public NeutronNetwork() {
+    }
+
+    public NeutronNetwork(final UUID id, final String name, final boolean shared, final String tenantId, final String networkType, final Integer segmentationId) {
+        this.id = id;
+        this.name = name;
+        this.shared = shared;
+        this.tenantId = tenantId;
+        this.networkType = networkType;
+        this.segmentationId = segmentationId;
+    }
+
+    public UUID getId() {
+        return id;
+    }
+
+    public void setId(final UUID uuid) {
+        id = uuid;
+    }
+
+    public String getNetworkType() {
+        return networkType;
+    }
+
+    public void setNetworkType(final String networkType) {
+        this.networkType = networkType;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(final String name) {
+        this.name = name;
+    }
+
+    public boolean isShared() {
+        return shared;
+    }
+
+    public void setShared(final boolean shared) {
+        this.shared = shared;
+    }
+
+    public Integer getSegmentationId() {
+        return segmentationId;
+    }
+
+    public void setSegmentationId(final Integer segmentationId) {
+        this.segmentationId = segmentationId;
+    }
+
+    public String getTenantId() {
+        return tenantId;
+    }
+
+    public void setTenantId(final String tenantId) {
+        this.tenantId = tenantId;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + (name == null ? 0 : name.hashCode());
+        result = prime * result + (networkType == null ? 0 : networkType.hashCode());
+        result = prime * result + (segmentationId == null ? 0 : segmentationId.hashCode());
+        result = prime * result + (shared ? 1231 : 1237);
+        result = prime * result + (tenantId == null ? 0 : tenantId.hashCode());
+        result = prime * result + (id == null ? 0 : id.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(final Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        NeutronNetwork other = (NeutronNetwork) obj;
+        if (name == null) {
+            if (other.name != null) {
+                return false;
+            }
+        } else if (!name.equals(other.name)) {
+            return false;
+        }
+        if (networkType == null) {
+            if (other.networkType != null) {
+                return false;
+            }
+        } else if (!networkType.equals(other.networkType)) {
+            return false;
+        }
+        if (segmentationId == null) {
+            if (other.segmentationId != null) {
+                return false;
+            }
+        } else if (!segmentationId.equals(other.segmentationId)) {
+            return false;
+        }
+        if (shared != other.shared) {
+            return false;
+        }
+        if (tenantId == null) {
+            if (other.tenantId != null) {
+                return false;
+            }
+        } else if (!tenantId.equals(other.tenantId)) {
+            return false;
+        }
+        if (id == null) {
+            if (other.id != null) {
+                return false;
+            }
+        } else if (!id.equals(other.id)) {
+            return false;
+        }
+        return true;
+    }
+
+    public boolean equalsIgnoreUuid(final Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        NeutronNetwork other = (NeutronNetwork) obj;
+        if (name == null) {
+            if (other.name != null) {
+                return false;
+            }
+        } else if (!name.equals(other.name)) {
+            return false;
+        }
+        if (networkType == null) {
+            if (other.networkType != null) {
+                return false;
+            }
+        } else if (!networkType.equals(other.networkType)) {
+            return false;
+        }
+        if (segmentationId == null) {
+            if (other.segmentationId != null) {
+                return false;
+            }
+        } else if (!segmentationId.equals(other.segmentationId)) {
+            return false;
+        }
+        if (shared != other.shared) {
+            return false;
+        }
+        if (tenantId == null) {
+            if (other.tenantId != null) {
+                return false;
+            }
+        } else if (!tenantId.equals(other.tenantId)) {
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        return "NeutronNetwork [uuid=" + id + ", networkType=" + networkType + ", name=" + name + ", shared=" + shared + ", segmentationId=" + segmentationId + ", tenantId="
+                + tenantId + "]";
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b7d7342c/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/model/NeutronNetworkWrapper.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/model/NeutronNetworkWrapper.java b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/model/NeutronNetworkWrapper.java
new file mode 100644
index 0000000..be1d85e
--- /dev/null
+++ b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/model/NeutronNetworkWrapper.java
@@ -0,0 +1,70 @@
+//
+// 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.apache.cloudstack.network.opendaylight.api.model;
+
+public class NeutronNetworkWrapper {
+
+    private NeutronNetwork network;
+
+    public NeutronNetworkWrapper() {
+    }
+
+    public NeutronNetworkWrapper(final NeutronNetwork network) {
+        this.network = network;
+    }
+
+    public NeutronNetwork getNetwork() {
+        return network;
+    }
+
+    public void setNetwork(final NeutronNetwork network) {
+        this.network = network;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + (network == null ? 0 : network.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(final Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        NeutronNetworkWrapper other = (NeutronNetworkWrapper) obj;
+        if (network == null) {
+            if (other.network != null) {
+                return false;
+            }
+        } else if (!network.equals(other.network)) {
+            return false;
+        }
+        return true;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b7d7342c/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/model/NeutronNetworksList.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/model/NeutronNetworksList.java b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/model/NeutronNetworksList.java
new file mode 100644
index 0000000..1f9ab59
--- /dev/null
+++ b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/model/NeutronNetworksList.java
@@ -0,0 +1,42 @@
+//
+// 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.apache.cloudstack.network.opendaylight.api.model;
+
+import java.util.List;
+
+public class NeutronNetworksList<T> {
+
+    private List<T> networks;
+
+    public NeutronNetworksList() {
+    }
+
+    public NeutronNetworksList(final List<T> networks) {
+        this.networks = networks;
+    }
+
+    public List<T> getNetworks() {
+        return networks;
+    }
+
+    public void setNetworks(final List<T> networks) {
+        this.networks = networks;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b7d7342c/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/model/NeutronNode.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/model/NeutronNode.java b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/model/NeutronNode.java
new file mode 100644
index 0000000..d5b1437
--- /dev/null
+++ b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/model/NeutronNode.java
@@ -0,0 +1,98 @@
+//
+// 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.apache.cloudstack.network.opendaylight.api.model;
+
+
+public class NeutronNode {
+
+    private String id;
+    private String type;
+
+    public NeutronNode() {
+    }
+
+    public NeutronNode(final String id, final String type) {
+        this.id = id;
+        this.type = type;
+    }
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(final String id) {
+        this.id = id;
+    }
+
+    public String getType() {
+        return type;
+    }
+
+    public void setType(final String type) {
+        this.type = type;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + (id == null ? 0 : id.hashCode());
+        result = prime * result + (type == null ? 0 : type.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(final Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        NeutronNode other = (NeutronNode) obj;
+        if (id == null) {
+            if (other.id != null)
+                return false;
+        } else if (!id.equals(other.id))
+            return false;
+        if (type == null) {
+            if (other.type != null)
+                return false;
+        } else if (!type.equals(other.type))
+            return false;
+        return true;
+    }
+
+    public boolean equalsIgnoreUuid(final Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        NeutronNode other = (NeutronNode) obj;
+        if (type == null) {
+            if (other.type != null)
+                return false;
+        } else if (!type.equals(other.type))
+            return false;
+        return true;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b7d7342c/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/model/NeutronNodeWrapper.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/model/NeutronNodeWrapper.java b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/model/NeutronNodeWrapper.java
new file mode 100644
index 0000000..4dcb4c9
--- /dev/null
+++ b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/model/NeutronNodeWrapper.java
@@ -0,0 +1,65 @@
+//
+// 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.apache.cloudstack.network.opendaylight.api.model;
+
+public class NeutronNodeWrapper {
+
+    private NeutronNode node;
+
+    public NeutronNodeWrapper() {
+    }
+
+    public NeutronNodeWrapper(final NeutronNode node) {
+        this.node = node;
+    }
+
+    public NeutronNode getNode() {
+        return node;
+    }
+
+    public void setNode(final NeutronNode node) {
+        this.node = node;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + (node == null ? 0 : node.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(final Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        NeutronNodeWrapper other = (NeutronNodeWrapper) obj;
+        if (node == null) {
+            if (other.node != null)
+                return false;
+        } else if (!node.equals(other.node))
+            return false;
+        return true;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b7d7342c/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/model/NeutronNodesList.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/model/NeutronNodesList.java b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/model/NeutronNodesList.java
new file mode 100644
index 0000000..a935bef
--- /dev/null
+++ b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/model/NeutronNodesList.java
@@ -0,0 +1,42 @@
+//
+// 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.apache.cloudstack.network.opendaylight.api.model;
+
+import java.util.List;
+
+public class NeutronNodesList<T> {
+
+    private List<T> nodes;
+
+    public NeutronNodesList() {
+    }
+
+    public NeutronNodesList(final List<T> nodes) {
+        this.nodes = nodes;
+    }
+
+    public List<T> getNodes() {
+        return nodes;
+    }
+
+    public void setNodes(final List<T> nodes) {
+        this.nodes = nodes;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b7d7342c/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/model/NeutronPort.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/model/NeutronPort.java b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/model/NeutronPort.java
new file mode 100644
index 0000000..9824fee
--- /dev/null
+++ b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/model/NeutronPort.java
@@ -0,0 +1,265 @@
+//
+// 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.apache.cloudstack.network.opendaylight.api.model;
+
+import java.util.List;
+import java.util.UUID;
+
+public class NeutronPort {
+
+    private UUID id;
+    private String name;
+    private String tenantId;
+    private UUID networkId;
+    private String macAddress;
+    private UUID deviceId;
+    private boolean adminStateUp;
+    private String status;
+    private List<String> fixedIps;
+
+    public NeutronPort() {
+    }
+
+    public NeutronPort(final UUID id, final String name, final String tenantId, final UUID networkId, final String macAddress, final UUID deviceId, final boolean adminStateUp,
+            final String status, final List<String> fixedIps) {
+        this.id = id;
+        this.name = name;
+        this.tenantId = tenantId;
+        this.networkId = networkId;
+        this.macAddress = macAddress;
+        this.deviceId = deviceId;
+        this.adminStateUp = adminStateUp;
+        this.status = status;
+        this.fixedIps = fixedIps;
+    }
+
+    public UUID getId() {
+        return id;
+    }
+
+    public void setId(final UUID uuid) {
+        id = uuid;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(final String name) {
+        this.name = name;
+    }
+
+    public String getTenantId() {
+        return tenantId;
+    }
+
+    public void setTenantId(final String tenantId) {
+        this.tenantId = tenantId;
+    }
+
+    public UUID getNetworkId() {
+        return networkId;
+    }
+
+    public void setNetworkId(final UUID networkId) {
+        this.networkId = networkId;
+    }
+
+    public String getMacAddress() {
+        return macAddress;
+    }
+
+    public void setMacAddress(final String macAddress) {
+        this.macAddress = macAddress;
+    }
+
+    public UUID getDeviceId() {
+        return deviceId;
+    }
+
+    public void setDeviceId(final UUID deviceId) {
+        this.deviceId = deviceId;
+    }
+
+    public boolean isAdminStateUp() {
+        return adminStateUp;
+    }
+
+    public void setAdminStateUp(final boolean adminStateUp) {
+        this.adminStateUp = adminStateUp;
+    }
+
+    public String getStatus() {
+        return status;
+    }
+
+    public void setStatus(final String status) {
+        this.status = status;
+    }
+
+    public List<String> getFixedIps() {
+        return fixedIps;
+    }
+
+    public void setFixedIps(final List<String> fixedIps) {
+        this.fixedIps = fixedIps;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + (adminStateUp ? 1231 : 1237);
+        result = prime * result + (deviceId == null ? 0 : deviceId.hashCode());
+        result = prime * result + (macAddress == null ? 0 : macAddress.hashCode());
+        result = prime * result + (name == null ? 0 : name.hashCode());
+        result = prime * result + (networkId == null ? 0 : networkId.hashCode());
+        result = prime * result + (status == null ? 0 : status.hashCode());
+        result = prime * result + (tenantId == null ? 0 : tenantId.hashCode());
+        result = prime * result + (id == null ? 0 : id.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(final Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        NeutronPort other = (NeutronPort) obj;
+        if (adminStateUp != other.adminStateUp) {
+            return false;
+        }
+        if (deviceId == null) {
+            if (other.deviceId != null) {
+                return false;
+            }
+        } else if (!deviceId.equals(other.deviceId)) {
+            return false;
+        }
+        if (macAddress == null) {
+            if (other.macAddress != null) {
+                return false;
+            }
+        } else if (!macAddress.equals(other.macAddress)) {
+            return false;
+        }
+        if (name == null) {
+            if (other.name != null) {
+                return false;
+            }
+        } else if (!name.equals(other.name)) {
+            return false;
+        }
+        if (networkId == null) {
+            if (other.networkId != null) {
+                return false;
+            }
+        } else if (!networkId.equals(other.networkId)) {
+            return false;
+        }
+        if (status == null) {
+            if (other.status != null) {
+                return false;
+            }
+        } else if (!status.equals(other.status)) {
+            return false;
+        }
+        if (tenantId == null) {
+            if (other.tenantId != null) {
+                return false;
+            }
+        } else if (!tenantId.equals(other.tenantId)) {
+            return false;
+        }
+        if (id == null) {
+            if (other.id != null) {
+                return false;
+            }
+        } else if (!id.equals(other.id)) {
+            return false;
+        }
+        return true;
+    }
+
+    public boolean equalsIgnoreUuid(final Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        NeutronPort other = (NeutronPort) obj;
+        if (adminStateUp != other.adminStateUp) {
+            return false;
+        }
+        if (deviceId == null) {
+            if (other.deviceId != null) {
+                return false;
+            }
+        } else if (!deviceId.equals(other.deviceId)) {
+            return false;
+        }
+        if (macAddress == null) {
+            if (other.macAddress != null) {
+                return false;
+            }
+        } else if (!macAddress.equals(other.macAddress)) {
+            return false;
+        }
+        if (name == null) {
+            if (other.name != null) {
+                return false;
+            }
+        } else if (!name.equals(other.name)) {
+            return false;
+        }
+        if (networkId == null) {
+            if (other.networkId != null) {
+                return false;
+            }
+        } else if (!networkId.equals(other.networkId)) {
+            return false;
+        }
+        if (status == null) {
+            if (other.status != null) {
+                return false;
+            }
+        } else if (!status.equals(other.status)) {
+            return false;
+        }
+        if (tenantId == null) {
+            if (other.tenantId != null) {
+                return false;
+            }
+        } else if (!tenantId.equals(other.tenantId)) {
+            return false;
+        }
+        return true;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b7d7342c/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/model/NeutronPortWrapper.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/model/NeutronPortWrapper.java b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/model/NeutronPortWrapper.java
new file mode 100644
index 0000000..be7817f
--- /dev/null
+++ b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/model/NeutronPortWrapper.java
@@ -0,0 +1,70 @@
+//
+// 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.apache.cloudstack.network.opendaylight.api.model;
+
+public class NeutronPortWrapper {
+
+    private NeutronPort port;
+
+    public NeutronPortWrapper() {
+    }
+
+    public NeutronPortWrapper(final NeutronPort port) {
+        this.port = port;
+    }
+
+    public NeutronPort getPort() {
+        return port;
+    }
+
+    public void setPort(final NeutronPort port) {
+        this.port = port;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + (port == null ? 0 : port.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(final Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        NeutronPortWrapper other = (NeutronPortWrapper) obj;
+        if (port == null) {
+            if (other.port != null) {
+                return false;
+            }
+        } else if (!port.equals(other.port)) {
+            return false;
+        }
+        return true;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b7d7342c/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/model/NeutronPortsList.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/model/NeutronPortsList.java b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/model/NeutronPortsList.java
new file mode 100644
index 0000000..1e6518c
--- /dev/null
+++ b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/model/NeutronPortsList.java
@@ -0,0 +1,42 @@
+//
+// 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.apache.cloudstack.network.opendaylight.api.model;
+
+import java.util.List;
+
+public class NeutronPortsList<T> {
+
+    private List<T> ports;
+
+    public NeutronPortsList() {
+    }
+
+    public NeutronPortsList(final List<T> ports) {
+        this.ports = ports;
+    }
+
+    public List<T> getPorts() {
+        return ports;
+    }
+
+    public void setPorts(final List<T> ports) {
+        this.ports = ports;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b7d7342c/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/resources/Action.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/resources/Action.java b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/resources/Action.java
new file mode 100644
index 0000000..fb764ba
--- /dev/null
+++ b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/resources/Action.java
@@ -0,0 +1,287 @@
+//
+// 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.apache.cloudstack.network.opendaylight.api.resources;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.apache.cloudstack.network.opendaylight.api.NeutronInvalidCredentialsException;
+import org.apache.cloudstack.network.opendaylight.api.NeutronRestApi;
+import org.apache.cloudstack.network.opendaylight.api.NeutronRestApiException;
+import org.apache.cloudstack.network.opendaylight.api.NeutronRestFactory;
+import org.apache.commons.codec.binary.Base64;
+import org.apache.commons.httpclient.HttpMethodBase;
+import org.apache.commons.httpclient.HttpStatus;
+import org.apache.commons.httpclient.NameValuePair;
+import org.apache.commons.httpclient.methods.DeleteMethod;
+import org.apache.commons.httpclient.methods.GetMethod;
+import org.apache.commons.httpclient.methods.PostMethod;
+import org.apache.commons.httpclient.methods.PutMethod;
+import org.apache.commons.httpclient.methods.StringRequestEntity;
+import org.apache.log4j.Logger;
+
+public abstract class Action {
+
+    private static final Logger s_logger = Logger.getLogger(Action.class);
+    private static final int BODY_RESP_MAX_LEN = 1024;
+
+    // private static final String DEFAULT
+
+    protected static final String TEXT_HTML_CONTENT_TYPE = "text/html";
+    protected static final String JSON_CONTENT_TYPE = "application/json";
+    protected static final String CONTENT_TYPE = "Content-Type";
+
+    private final URL url;
+    private final String username;
+    private final String password;
+
+    public Action(final URL url, final String username, final String password) {
+
+        this.url = url;
+        this.username = username;
+        this.password = password;
+    }
+
+    public String executeGet(final String uri, final Map<String, String> parameters) throws NeutronRestApiException {
+        try {
+            validateCredentials();
+        } catch (NeutronInvalidCredentialsException e) {
+            throw new NeutronRestApiException("Invalid credentials!", e);
+        }
+
+        NeutronRestFactory factory = NeutronRestFactory.getInstance();
+
+        NeutronRestApi neutronRestApi = factory.getNeutronApi(GetMethod.class);
+        GetMethod getMethod = (GetMethod) neutronRestApi.createMethod(url, uri);
+
+        try {
+            getMethod.setRequestHeader(CONTENT_TYPE, JSON_CONTENT_TYPE);
+
+            String encodedCredentials = encodeCredentials();
+            getMethod.setRequestHeader("Authorization", "Basic " + encodedCredentials);
+
+            if (parameters != null && !parameters.isEmpty()) {
+                List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(parameters.size());
+                for (Entry<String, String> e : parameters.entrySet()) {
+                    nameValuePairs.add(new NameValuePair(e.getKey(), e.getValue()));
+                }
+                getMethod.setQueryString(nameValuePairs.toArray(new NameValuePair[0]));
+            }
+
+            neutronRestApi.executeMethod(getMethod);
+
+            if (getMethod.getStatusCode() != HttpStatus.SC_OK) {
+                String errorMessage = responseToErrorMessage(getMethod);
+                getMethod.releaseConnection();
+                s_logger.error("Failed to retrieve object : " + errorMessage);
+                throw new NeutronRestApiException("Failed to retrieve object : " + errorMessage);
+            }
+
+            return getMethod.getResponseBodyAsString();
+
+        } catch (NeutronRestApiException e) {
+            s_logger.error("NeutronRestApiException caught while trying to execute HTTP Method on the Neutron Controller", e);
+            throw new NeutronRestApiException("API call to Neutron Controller Failed", e);
+        } catch (IOException e) {
+            throw new NeutronRestApiException(e);
+        } finally {
+            getMethod.releaseConnection();
+        }
+    }
+
+    protected String executePost(final String uri, final StringRequestEntity entity) throws NeutronRestApiException {
+        try {
+            validateCredentials();
+        } catch (NeutronInvalidCredentialsException e) {
+            throw new NeutronRestApiException("Invalid credentials!", e);
+        }
+
+        NeutronRestFactory factory = NeutronRestFactory.getInstance();
+
+        NeutronRestApi neutronRestApi = factory.getNeutronApi(PostMethod.class);
+        PostMethod postMethod = (PostMethod) neutronRestApi.createMethod(url, uri);
+
+        try {
+            postMethod.setRequestHeader(CONTENT_TYPE, JSON_CONTENT_TYPE);
+            postMethod.setRequestEntity(entity);
+
+            String encodedCredentials = encodeCredentials();
+            postMethod.setRequestHeader("Authorization", "Basic " + encodedCredentials);
+
+            neutronRestApi.executeMethod(postMethod);
+
+            if (postMethod.getStatusCode() != HttpStatus.SC_CREATED) {
+                String errorMessage = responseToErrorMessage(postMethod);
+                postMethod.releaseConnection();
+                s_logger.error("Failed to create object : " + errorMessage);
+                throw new NeutronRestApiException("Failed to create object : " + errorMessage);
+            }
+
+            return postMethod.getResponseBodyAsString();
+        } catch (NeutronRestApiException e) {
+            s_logger.error("NeutronRestApiException caught while trying to execute HTTP Method on the Neutron Controller", e);
+            throw new NeutronRestApiException("API call to Neutron Controller Failed", e);
+        } catch (IOException e) {
+            throw new NeutronRestApiException("Failed to load json response body", e);
+        } finally {
+            postMethod.releaseConnection();
+        }
+    }
+
+    protected void executePut(final String uri, final StringRequestEntity entity) throws NeutronRestApiException {
+        try {
+            validateCredentials();
+        } catch (NeutronInvalidCredentialsException e) {
+            throw new NeutronRestApiException("Invalid credentials!", e);
+        }
+
+        NeutronRestFactory factory = NeutronRestFactory.getInstance();
+
+        NeutronRestApi neutronRestApi = factory.getNeutronApi(PutMethod.class);
+        PutMethod putMethod = (PutMethod) neutronRestApi.createMethod(url, uri);
+
+        try {
+            putMethod.setRequestHeader(CONTENT_TYPE, JSON_CONTENT_TYPE);
+            putMethod.setRequestEntity(entity);
+
+            String encodedCredentials = encodeCredentials();
+            putMethod.setRequestHeader("Authorization", "Basic " + encodedCredentials);
+
+            neutronRestApi.executeMethod(putMethod);
+
+            if (putMethod.getStatusCode() != HttpStatus.SC_OK) {
+                String errorMessage = responseToErrorMessage(putMethod);
+                putMethod.releaseConnection();
+                s_logger.error("Failed to update object : " + errorMessage);
+                throw new NeutronRestApiException("Failed to create object : " + errorMessage);
+            }
+        } catch (NeutronRestApiException e) {
+            s_logger.error("NeutronRestApiException caught while trying to execute HTTP Method on the Neutron Controller", e);
+            throw new NeutronRestApiException("API call to Neutron Controller Failed", e);
+        } finally {
+            putMethod.releaseConnection();
+        }
+    }
+
+    protected String executePut(final String uri) throws NeutronRestApiException {
+        try {
+            validateCredentials();
+        } catch (NeutronInvalidCredentialsException e) {
+            throw new NeutronRestApiException("Invalid credentials!", e);
+        }
+
+        NeutronRestFactory factory = NeutronRestFactory.getInstance();
+
+        NeutronRestApi neutronRestApi = factory.getNeutronApi(PutMethod.class);
+        PutMethod putMethod = (PutMethod) neutronRestApi.createMethod(url, uri);
+
+        try {
+            String encodedCredentials = encodeCredentials();
+            putMethod.setRequestHeader("Authorization", "Basic " + encodedCredentials);
+
+            neutronRestApi.executeMethod(putMethod);
+
+            if (putMethod.getStatusCode() != HttpStatus.SC_OK) {
+                String errorMessage = responseToErrorMessage(putMethod);
+                putMethod.releaseConnection();
+                s_logger.error("Failed to update object : " + errorMessage);
+                throw new NeutronRestApiException("Failed to create object : " + errorMessage);
+            }
+
+            return putMethod.getResponseBodyAsString();
+        } catch (NeutronRestApiException e) {
+            s_logger.error("NeutronRestApiException caught while trying to execute HTTP Method on the Neutron Controller", e);
+            throw new NeutronRestApiException("API call to Neutron Controller Failed", e);
+        } catch (IOException e) {
+            throw new NeutronRestApiException("Failed to load json response body", e);
+        } finally {
+            putMethod.releaseConnection();
+        }
+    }
+
+    protected void executeDelete(final String uri) throws NeutronRestApiException {
+        try {
+            validateCredentials();
+        } catch (NeutronInvalidCredentialsException e) {
+            throw new NeutronRestApiException("Invalid credentials!", e);
+        }
+
+        NeutronRestFactory factory = NeutronRestFactory.getInstance();
+
+        NeutronRestApi neutronRestApi = factory.getNeutronApi(DeleteMethod.class);
+        DeleteMethod deleteMethod = (DeleteMethod) neutronRestApi.createMethod(url, uri);
+
+        try {
+            deleteMethod.setRequestHeader(CONTENT_TYPE, JSON_CONTENT_TYPE);
+
+            String encodedCredentials = encodeCredentials();
+            deleteMethod.setRequestHeader("Authorization", "Basic " + encodedCredentials);
+
+            neutronRestApi.executeMethod(deleteMethod);
+
+            if (deleteMethod.getStatusCode() != HttpStatus.SC_NO_CONTENT) {
+                String errorMessage = responseToErrorMessage(deleteMethod);
+                deleteMethod.releaseConnection();
+                s_logger.error("Failed to update object : " + errorMessage);
+                throw new NeutronRestApiException("Failed to create object : " + errorMessage);
+            }
+        } catch (NeutronRestApiException e) {
+            s_logger.error("NeutronRestApiException caught while trying to execute HTTP Method on the Neutron Controller", e);
+            throw new NeutronRestApiException("API call to Neutron Controller Failed", e);
+        } finally {
+            deleteMethod.releaseConnection();
+        }
+    }
+
+    private void validateCredentials() throws NeutronInvalidCredentialsException {
+        if (username == null || username.isEmpty() || password == null || password.isEmpty()) {
+            throw new NeutronInvalidCredentialsException("Credentials are null or empty");
+        }
+    }
+
+    private String encodeCredentials() {
+        String authString = username + ":" + password;
+        byte[] authEncBytes = Base64.encodeBase64(authString.getBytes());
+        String authStringEnc = new String(authEncBytes);
+        return authStringEnc;
+    }
+
+    private String responseToErrorMessage(final HttpMethodBase method) {
+        assert method.isRequestSent() : "no use getting an error message unless the request is sent";
+
+        if (TEXT_HTML_CONTENT_TYPE.equals(method.getResponseHeader(CONTENT_TYPE).getValue())) {
+            // The error message is the response content
+            // Safety margin of 1024 characters, anything longer is probably
+            // useless and will clutter the logs
+            try {
+                return method.getResponseBodyAsString(BODY_RESP_MAX_LEN);
+            } catch (IOException e) {
+                s_logger.debug("Error while loading response body", e);
+            }
+        }
+
+        // The default
+        return method.getStatusText();
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b7d7342c/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/resources/NeutronNetworksNorthboundAction.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/resources/NeutronNetworksNorthboundAction.java b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/resources/NeutronNetworksNorthboundAction.java
new file mode 100644
index 0000000..2d4f7c9
--- /dev/null
+++ b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/resources/NeutronNetworksNorthboundAction.java
@@ -0,0 +1,111 @@
+//
+// 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.apache.cloudstack.network.opendaylight.api.resources;
+
+import java.io.UnsupportedEncodingException;
+import java.lang.reflect.Type;
+import java.net.URL;
+import java.text.MessageFormat;
+import java.util.Collections;
+
+import org.apache.cloudstack.network.opendaylight.api.NeutronRestApiException;
+import org.apache.cloudstack.network.opendaylight.api.enums.NeutronNorthboundEnum;
+import org.apache.cloudstack.network.opendaylight.api.model.NeutronNetworkWrapper;
+import org.apache.cloudstack.network.opendaylight.api.model.NeutronNetworksList;
+import org.apache.commons.httpclient.methods.StringRequestEntity;
+
+import com.google.gson.FieldNamingPolicy;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.reflect.TypeToken;
+
+public class NeutronNetworksNorthboundAction extends Action {
+
+    private final Gson gsonNeutronNetwork;
+
+    public NeutronNetworksNorthboundAction(final URL url, final String username, final String password) {
+        super(url, username, password);
+        gsonNeutronNetwork = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES).create();
+    }
+
+    @SuppressWarnings("unchecked")
+    public <T> T listAllNetworks() throws NeutronRestApiException {
+        String uri = NeutronNorthboundEnum.NETWORKS_URI.getUri();
+        String bodystring = executeGet(uri, Collections.<String, String> emptyMap());
+
+        Type returnType = new TypeToken<NeutronNetworksList<NeutronNetworkWrapper>>() {
+        }.getType();
+
+        T returnValue = (T) gsonNeutronNetwork.fromJson(bodystring, returnType);
+
+        return returnValue;
+    }
+
+    @SuppressWarnings("unchecked")
+    public <T> T findNetworkById(final String networkId) throws NeutronRestApiException {
+        String uri = NeutronNorthboundEnum.NETWORK_PARAM_URI.getUri();
+        uri = MessageFormat.format(uri, networkId);
+
+        String bodystring = executeGet(uri, Collections.<String, String> emptyMap());
+
+        Type returnType = new TypeToken<NeutronNetworkWrapper>() {
+        }.getType();
+
+        T returnValue = (T) gsonNeutronNetwork.fromJson(bodystring, returnType);
+
+        return returnValue;
+    }
+
+    @SuppressWarnings("unchecked")
+    public <T> T createNeutronNetwork(final NeutronNetworkWrapper newNetworkWrapper) throws NeutronRestApiException {
+        try {
+            String uri = NeutronNorthboundEnum.NETWORKS_URI.getUri();
+            StringRequestEntity entity = new StringRequestEntity(gsonNeutronNetwork.toJson(newNetworkWrapper), JSON_CONTENT_TYPE, null);
+
+            String bodystring = executePost(uri, entity);
+
+            T result = (T) gsonNeutronNetwork.fromJson(bodystring, TypeToken.get(NeutronNetworkWrapper.class).getType());
+
+            return result;
+        } catch (UnsupportedEncodingException e) {
+            throw new NeutronRestApiException("Failed to encode json request body", e);
+        }
+    }
+
+    public <T> void updateNeutronNetwork(final String networkId, final NeutronNetworkWrapper newNetworkWrapper) throws NeutronRestApiException {
+        try {
+            String uri = NeutronNorthboundEnum.NETWORK_PARAM_URI.getUri();
+            uri = MessageFormat.format(uri, networkId);
+
+            StringRequestEntity entity = new StringRequestEntity(gsonNeutronNetwork.toJson(newNetworkWrapper), JSON_CONTENT_TYPE, null);
+
+            executePut(uri, entity);
+        } catch (UnsupportedEncodingException e) {
+            throw new NeutronRestApiException("Failed to encode json request body", e);
+        }
+    }
+
+    public <T> void deleteNeutronNetwork(final String networkId) throws NeutronRestApiException {
+        String uri = NeutronNorthboundEnum.NETWORK_PARAM_URI.getUri();
+        uri = MessageFormat.format(uri, networkId);
+
+        executeDelete(uri);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b7d7342c/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/resources/NeutronNodesNorthboundAction.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/resources/NeutronNodesNorthboundAction.java b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/resources/NeutronNodesNorthboundAction.java
new file mode 100644
index 0000000..891ca16
--- /dev/null
+++ b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/resources/NeutronNodesNorthboundAction.java
@@ -0,0 +1,89 @@
+//
+// 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.apache.cloudstack.network.opendaylight.api.resources;
+
+import java.lang.reflect.Type;
+import java.net.URL;
+import java.text.MessageFormat;
+import java.util.Collections;
+
+import org.apache.cloudstack.network.opendaylight.api.NeutronRestApiException;
+import org.apache.cloudstack.network.opendaylight.api.enums.NeutronNorthboundEnum;
+import org.apache.cloudstack.network.opendaylight.api.model.NeutronNodeWrapper;
+import org.apache.cloudstack.network.opendaylight.api.model.NeutronNodesList;
+
+import com.google.gson.FieldNamingPolicy;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.reflect.TypeToken;
+
+public class NeutronNodesNorthboundAction extends Action {
+
+    private final Gson gsonNeutronNode;
+
+    public NeutronNodesNorthboundAction(final URL url, final String username, final String password) {
+        super(url, username, password);
+        gsonNeutronNode = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES).create();
+    }
+
+    @SuppressWarnings("unchecked")
+    public <T> T listAllNodes() throws NeutronRestApiException {
+        String uri = NeutronNorthboundEnum.PORTS_URI.getUri();
+        String bodystring = executeGet(uri, Collections.<String, String> emptyMap());
+
+        Type returnType = new TypeToken<NeutronNodesList<NeutronNodeWrapper>>() {
+        }.getType();
+
+        T returnValue = (T) gsonNeutronNode.fromJson(bodystring, returnType);
+
+        return returnValue;
+    }
+
+    public <T> void deleteNode(final String nodeType, final String nodeId) throws NeutronRestApiException {
+        String uri = NeutronNorthboundEnum.NETWORK_PARAM_URI.getUri();
+        uri = MessageFormat.format(uri, nodeType, nodeId);
+
+        executeDelete(uri);
+    }
+
+    @SuppressWarnings("unchecked")
+    public <T> T updateNeutronNodeV1(final String nodeId, final String ipAddress, final int port) throws NeutronRestApiException {
+        String uri = NeutronNorthboundEnum.NODE_PORT_PER_NODE_URI.getUri();
+        uri = MessageFormat.format(uri, nodeId, ipAddress, String.valueOf(port));
+
+        String bodystring = executePut(uri);
+
+        T result = (T) gsonNeutronNode.fromJson(bodystring, TypeToken.get(NeutronNodeWrapper.class).getType());
+
+        return result;
+    }
+
+    @SuppressWarnings("unchecked")
+    public <T> T updateNeutronNodeV2(final String nodeType, final String nodeId, final String ipAddress, final int port) throws NeutronRestApiException {
+        String uri = NeutronNorthboundEnum.NODE_PORT_PER_TYPE_URI.getUri();
+        uri = MessageFormat.format(uri, nodeType, nodeId, ipAddress, String.valueOf(port));
+
+        String bodystring = executePut(uri);
+
+        T result = (T) gsonNeutronNode.fromJson(bodystring, TypeToken.get(NeutronNodeWrapper.class).getType());
+
+        return result;
+    }
+}
\ No newline at end of file