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 2014/01/08 17:09:22 UTC

[01/11] Add a network plugin for OpenDaylight

Updated Branches:
  refs/heads/master cbe2560a7 -> 612a41e3f


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1f9528ba/plugins/network-elements/opendaylight/src/main/resources/META-INF/cloudstack/opendaylight/module.properties
----------------------------------------------------------------------
diff --git a/plugins/network-elements/opendaylight/src/main/resources/META-INF/cloudstack/opendaylight/module.properties b/plugins/network-elements/opendaylight/src/main/resources/META-INF/cloudstack/opendaylight/module.properties
new file mode 100644
index 0000000..36d2331
--- /dev/null
+++ b/plugins/network-elements/opendaylight/src/main/resources/META-INF/cloudstack/opendaylight/module.properties
@@ -0,0 +1,21 @@
+#
+# 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.
+#
+
+name=opendaylight
+parent=network

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1f9528ba/plugins/network-elements/opendaylight/src/main/resources/META-INF/cloudstack/opendaylight/spring-opendaylight-context.xml
----------------------------------------------------------------------
diff --git a/plugins/network-elements/opendaylight/src/main/resources/META-INF/cloudstack/opendaylight/spring-opendaylight-context.xml b/plugins/network-elements/opendaylight/src/main/resources/META-INF/cloudstack/opendaylight/spring-opendaylight-context.xml
new file mode 100644
index 0000000..76b6a92
--- /dev/null
+++ b/plugins/network-elements/opendaylight/src/main/resources/META-INF/cloudstack/opendaylight/spring-opendaylight-context.xml
@@ -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.
+
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xmlns:context="http://www.springframework.org/schema/context"
+       xmlns:aop="http://www.springframework.org/schema/aop"
+       xsi:schemaLocation="http://www.springframework.org/schema/beans
+                      http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
+                      http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
+                      http://www.springframework.org/schema/context
+                      http://www.springframework.org/schema/context/spring-context-3.0.xsd"
+                      >
+
+    <bean id="OpendaylightGuestNetworkGuru" class="org.apache.cloudstack.network.opendaylight.OpendaylightGuestNetworkGuru">
+        <property name="name" value="OpendaylightGuestNetworkGuru" />
+    </bean>
+    <bean id="OpendaylightElement" class="org.apache.cloudstack.network.opendaylight.OpendaylightElement">
+        <property name="name" value="OpendaylightElement" />
+    </bean>
+    <bean id="OpenDaylightControllerResourceManager" class="org.apache.cloudstack.network.opendaylight.agent.OpenDaylightControllerResourceManagerImpl"/>
+    <bean id="OpenDaylightControllerMappingDao" class="org.apache.cloudstack.network.opendaylight.dao.OpenDaylightControllerMappingDaoImpl" />
+
+</beans>
+

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1f9528ba/plugins/pom.xml
----------------------------------------------------------------------
diff --git a/plugins/pom.xml b/plugins/pom.xml
index 8ec6a71..85a7bbe 100755
--- a/plugins/pom.xml
+++ b/plugins/pom.xml
@@ -51,6 +51,7 @@
     <module>network-elements/bigswitch-vns</module>
     <module>network-elements/midonet</module>
     <module>network-elements/stratosphere-ssp</module>
+    <module>network-elements/opendaylight</module>
     <module>storage-allocators/random</module>
     <module>user-authenticators/ldap</module>
     <module>user-authenticators/md5</module>


[05/11] git commit: updated refs/heads/master to 612a41e

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/f3f93a96
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/f3f93a96
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/f3f93a96

Branch: refs/heads/master
Commit: f3f93a96f549203e00046bd681ddc87e174c2a6b
Parents: 850bc9f
Author: wrodrigues <wr...@schubergphilis.com>
Authored: Thu Dec 19 14:30:01 2013 +0100
Committer: Hugo Trippaers <ht...@schubergphilis.com>
Committed: Wed Jan 8 16:00:39 2014 +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/f3f93a96/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/f3f93a96/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/f3f93a96/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/f3f93a96/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/f3f93a96/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/f3f93a96/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/f3f93a96/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/f3f93a96/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/f3f93a96/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/f3f93a96/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/f3f93a96/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/f3f93a96/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/f3f93a96/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/f3f93a96/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/f3f93a96/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/f3f93a96/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/f3f93a96/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/f3f93a96/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/f3f93a96/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


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

Posted by hu...@apache.org.
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f3f93a96/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/f3f93a96/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/f3f93a96/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/f3f93a96/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/f3f93a96/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/f3f93a96/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/f3f93a96/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/f3f93a96/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


[08/11] git commit: updated refs/heads/master to 612a41e

Posted by hu...@apache.org.
Apply some formatting to system.js


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

Branch: refs/heads/master
Commit: 0ba1abe2627bd05c64aabf25142b266837c6e044
Parents: 8ddcc9b
Author: Hugo Trippaers <ht...@schubergphilis.com>
Authored: Wed Jan 8 16:04:44 2014 +0100
Committer: Hugo Trippaers <ht...@schubergphilis.com>
Committed: Wed Jan 8 16:04:44 2014 +0100

----------------------------------------------------------------------
 ui/scripts/system.js | 8437 +++++++++++++++++++++++----------------------
 1 file changed, 4254 insertions(+), 4183 deletions(-)
----------------------------------------------------------------------



[06/11] git commit: updated refs/heads/master to 612a41e

Posted by hu...@apache.org.
Set unique gre key for every network.

Set interface id to nic uuid when creating the vif.


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

Branch: refs/heads/master
Commit: 8ddcc9ba808041fbf42fc45f478574502dcad256
Parents: f3f93a9
Author: Hugo Trippaers <ht...@schubergphilis.com>
Authored: Fri Jan 3 10:49:03 2014 +0100
Committer: Hugo Trippaers <ht...@schubergphilis.com>
Committed: Wed Jan 8 16:00:59 2014 +0100

----------------------------------------------------------------------
 .../hypervisor/kvm/resource/OvsVifDriver.java   |  2 +-
 .../agent/OpenDaylightControllerResource.java   | 25 +++++++++++++++++++-
 .../NeutronNetworksNorthboundAction.java        | 12 ++++++----
 3 files changed, 32 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8ddcc9ba/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/OvsVifDriver.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/OvsVifDriver.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/OvsVifDriver.java
index 79606b3..c64a472 100644
--- a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/OvsVifDriver.java
+++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/OvsVifDriver.java
@@ -83,7 +83,7 @@ public class OvsVifDriver extends VifDriverBase {
                     intf.defBridgeNet(_pifs.get("private"), null, nic.getMac(), getGuestNicModel(guestOsType), networkRateKBps);
                     intf.setVlanTag(Integer.parseInt(vlanId));
                 }
-            } else if (nic.getBroadcastType() == Networks.BroadcastDomainType.Lswitch) {
+            } else if (nic.getBroadcastType() == Networks.BroadcastDomainType.Lswitch || nic.getBroadcastType() == Networks.BroadcastDomainType.OpenDaylight) {
                 s_logger.debug("nic " + nic + " needs to be connected to LogicalSwitch " + logicalSwitchUuid);
                 intf.setVirtualPortInterfaceId(nic.getUuid());
                 String brName = (trafficLabel != null && !trafficLabel.isEmpty()) ? _pifs.get(trafficLabel) : _pifs.get("private");

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8ddcc9ba/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/OpenDaylightControllerResource.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/OpenDaylightControllerResource.java b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/OpenDaylightControllerResource.java
index 5c1e1e4..c2b7a67 100644
--- a/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/OpenDaylightControllerResource.java
+++ b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/OpenDaylightControllerResource.java
@@ -26,6 +26,7 @@ import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Map.Entry;
+import java.util.Random;
 import java.util.UUID;
 
 import javax.naming.ConfigurationException;
@@ -46,6 +47,7 @@ import org.apache.cloudstack.network.opendaylight.agent.responses.DestroyPortAns
 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;
+import org.apache.cloudstack.network.opendaylight.api.model.NeutronNetworksList;
 import org.apache.cloudstack.network.opendaylight.api.model.NeutronNode;
 import org.apache.cloudstack.network.opendaylight.api.model.NeutronNodeWrapper;
 import org.apache.cloudstack.network.opendaylight.api.model.NeutronNodesList;
@@ -206,6 +208,27 @@ public class OpenDaylightControllerResource implements ServerResource {
 
     private Answer executeRequest(ConfigureNetworkCommand cmd) {
         NeutronNetworksNorthboundAction configureNetwork = new NeutronNetworksNorthboundAction(controllerUrl, controllerUsername, controllerPassword);
+
+        // Find free gre key
+        int gre_key = -1;
+        Random keyGenerator = new Random(System.currentTimeMillis());
+        try {
+            NeutronNetworksList<NeutronNetwork> networks = configureNetwork.listAllNetworks();
+            while (true) {
+                int i = keyGenerator.nextInt();
+                for (NeutronNetwork network : networks.getNetworks()) {
+                    if (network.getSegmentationId() == i) {
+                        continue;
+                    }
+                }
+                gre_key = i;
+                break;
+            }
+        } catch (NeutronRestApiException e) {
+            s_logger.error("Failed to list existing networks on the ODL Controller", e);
+            return new ConfigureNetworkAnswer(cmd, e);
+        }
+
         NeutronNetwork newNetwork = new NeutronNetwork();
 
         // Configuration from the command
@@ -215,7 +238,7 @@ public class OpenDaylightControllerResource implements ServerResource {
         // Static configuation
         newNetwork.setNetworkType("gre");
         newNetwork.setShared(false);
-        newNetwork.setSegmentationId(100);
+        newNetwork.setSegmentationId(gre_key);
         newNetwork.setId(UUID.randomUUID());
 
         NeutronNetworkWrapper wrapper = new NeutronNetworkWrapper();

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8ddcc9ba/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
index 2d4f7c9..3a8c187 100644
--- 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
@@ -25,10 +25,6 @@ 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;
@@ -36,6 +32,12 @@ 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.enums.NeutronNorthboundEnum;
+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.model.NeutronNetworksList;
+
 public class NeutronNetworksNorthboundAction extends Action {
 
     private final Gson gsonNeutronNetwork;
@@ -50,7 +52,7 @@ public class NeutronNetworksNorthboundAction extends Action {
         String uri = NeutronNorthboundEnum.NETWORKS_URI.getUri();
         String bodystring = executeGet(uri, Collections.<String, String> emptyMap());
 
-        Type returnType = new TypeToken<NeutronNetworksList<NeutronNetworkWrapper>>() {
+        Type returnType = new TypeToken<NeutronNetworksList<NeutronNetwork>>() {
         }.getType();
 
         T returnValue = (T) gsonNeutronNetwork.fromJson(bodystring, returnType);


[02/11] git commit: updated refs/heads/master to 612a41e

Posted by hu...@apache.org.
Add a network plugin for OpenDaylight

This plugin is a technology preview and designed to work with the OVSDB module


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

Branch: refs/heads/master
Commit: 1f9528bad3493f287bfd6dfc48dfd077697e7d1f
Parents: cbe2560
Author: Hugo Trippaers <ht...@schubergphilis.com>
Authored: Thu Dec 19 10:50:44 2013 +0100
Committer: Hugo Trippaers <ht...@schubergphilis.com>
Committed: Wed Jan 8 15:57:46 2014 +0100

----------------------------------------------------------------------
 LICENSE.header                                  |  16 +
 plugins/network-elements/opendaylight/pom.xml   | 132 ++++++++
 .../opendaylight/OpendaylightElement.java       | 174 ++++++++++
 .../OpendaylightGuestNetworkGuru.java           | 276 ++++++++++++++++
 .../agent/OpenDaylightControllerResource.java   | 321 +++++++++++++++++++
 .../OpenDaylightControllerResourceManager.java  |  34 ++
 ...enDaylightControllerResourceManagerImpl.java | 173 ++++++++++
 .../agent/commands/AddHypervisorCommand.java    |  58 ++++
 .../agent/commands/ConfigureNetworkCommand.java |  54 ++++
 .../agent/commands/ConfigurePortCommand.java    |  80 +++++
 .../agent/commands/DestroyNetworkCommand.java   |  45 +++
 .../agent/commands/DestroyPortCommand.java      |  50 +++
 .../StartupOpenDaylightControllerCommand.java   |  29 ++
 .../agent/responses/AddHypervisorAnswer.java    |  35 ++
 .../agent/responses/ConfigureNetworkAnswer.java |  43 +++
 .../agent/responses/ConfigurePortAnswer.java    |  35 ++
 .../agent/responses/DestroyNetworkAnswer.java   |  35 ++
 .../agent/responses/DestroyPortAnswer.java      |  35 ++
 .../dao/OpenDaylightControllerMappingDao.java   |  28 ++
 .../OpenDaylightControllerMappingDaoImpl.java   |  45 +++
 .../dao/OpenDaylightControllerVO.java           | 101 ++++++
 .../cloudstack/opendaylight/module.properties   |  21 ++
 .../spring-opendaylight-context.xml             |  42 +++
 plugins/pom.xml                                 |   1 +
 24 files changed, 1863 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1f9528ba/LICENSE.header
----------------------------------------------------------------------
diff --git a/LICENSE.header b/LICENSE.header
new file mode 100644
index 0000000..4eacb64
--- /dev/null
+++ b/LICENSE.header
@@ -0,0 +1,16 @@
+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.

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1f9528ba/plugins/network-elements/opendaylight/pom.xml
----------------------------------------------------------------------
diff --git a/plugins/network-elements/opendaylight/pom.xml b/plugins/network-elements/opendaylight/pom.xml
new file mode 100644
index 0000000..8c69b6e
--- /dev/null
+++ b/plugins/network-elements/opendaylight/pom.xml
@@ -0,0 +1,132 @@
+<!--
+
+    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.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <artifactId>cloud-plugin-network-opendaylight</artifactId>
+  <name>Apache CloudStack Plugin - Network Opendaylight</name>
+  <parent>
+    <groupId>org.apache.cloudstack</groupId>
+    <artifactId>cloudstack-plugins</artifactId>
+    <version>4.4.0-SNAPSHOT</version>
+    <relativePath>../../pom.xml</relativePath>
+  </parent>
+
+  <!-- not parenting to the maven-default pom, as we want this in services -->
+  <build>
+    <sourceDirectory>${basedir}/src/main/java</sourceDirectory>
+    <scriptSourceDirectory>${basedir}/src/main/scripts</scriptSourceDirectory>
+    <testSourceDirectory>${basedir}/src/test/java</testSourceDirectory>
+    <outputDirectory>${basedir}/target/classes</outputDirectory>
+    <testOutputDirectory>${basedir}/target/test-classes</testOutputDirectory>
+    <resources>
+      <resource>
+        <directory>${basedir}/src/main/resources</directory>
+      </resource>
+    </resources>
+    <testResources>
+      <testResource>
+        <directory>${basedir}/src/test/resources</directory>
+      </testResource>
+    </testResources>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-checkstyle-plugin</artifactId>
+        <dependencies>
+          <dependency>
+            <groupId>org.apache.cloudstack</groupId>
+            <artifactId>checkstyle</artifactId>
+            <version>${project.version}</version>
+          </dependency>
+        </dependencies>
+        <executions>
+          <execution>
+            <phase>process-classes</phase>
+            <goals>
+              <goal>check</goal>
+            </goals>
+          </execution>
+        </executions>
+        <configuration>
+          <failsOnError>true</failsOnError>
+          <configLocation>tooling/checkstyle.xml</configLocation>
+          <consoleOutput>true</consoleOutput>
+          <includeTestSourceDirectory>true</includeTestSourceDirectory>
+          <sourceDirectory>${project.basedir}</sourceDirectory>
+          <includes>**\/*.java,**\/*.xml,**\/*.ini,**\/*.sh,**\/*.bat</includes>
+          <excludes>**\/target\/,**\/bin\/</excludes>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>com.mycila.maven-license-plugin</groupId>
+        <artifactId>maven-license-plugin</artifactId>
+        <version>1.9.0</version>
+        <executions>
+          <execution>
+            <phase>process-classes</phase>
+            <goals>
+              <goal>format</goal>
+            </goals>
+          </execution>
+        </executions>
+        <configuration>
+          <strictCheck>true</strictCheck>
+          <aggregate>true</aggregate>
+          <header>../../../LICENSE.header</header>
+          <mapping>
+                <xml>XML_STYLE</xml>
+                <java>DOUBLESLASH_STYLE</java>
+                <clj>SEMICOLON_STYLE</clj>
+          </mapping>
+          <useDefaultExcludes>false</useDefaultExcludes>
+          <excludes>
+            <exclude>target/**</exclude>
+            <exclude>.settings/**</exclude>
+            <exclude>.checkstyle</exclude>
+            <exclude>.project</exclude>
+            <exclude>.classpath</exclude>
+          </excludes>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+  <profiles>
+    <profile>
+      <id>integration</id>
+      <build>
+        <plugins>
+          <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-failsafe-plugin</artifactId>
+            <executions>
+              <execution>
+                <goals>
+                  <goal>integration-test</goal>
+                  <goal>verify</goal>
+                </goals>
+              </execution>
+            </executions>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+  </profiles>
+</project>

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1f9528ba/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/OpendaylightElement.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/OpendaylightElement.java b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/OpendaylightElement.java
new file mode 100644
index 0000000..9761e74
--- /dev/null
+++ b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/OpendaylightElement.java
@@ -0,0 +1,174 @@
+//
+// 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;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.ejb.Local;
+import javax.inject.Inject;
+import javax.naming.ConfigurationException;
+
+import org.apache.log4j.Logger;
+import org.springframework.stereotype.Component;
+
+import org.apache.cloudstack.network.opendaylight.agent.commands.StartupOpenDaylightControllerCommand;
+
+import com.cloud.agent.api.StartupCommand;
+import com.cloud.deploy.DeployDestination;
+import com.cloud.exception.ConcurrentOperationException;
+import com.cloud.exception.InsufficientCapacityException;
+import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.host.Host;
+import com.cloud.host.HostVO;
+import com.cloud.network.Network;
+import com.cloud.network.Network.Capability;
+import com.cloud.network.Network.Provider;
+import com.cloud.network.Network.Service;
+import com.cloud.network.PhysicalNetworkServiceProvider;
+import com.cloud.network.element.ConnectivityProvider;
+import com.cloud.network.element.NetworkElement;
+import com.cloud.offering.NetworkOffering;
+import com.cloud.resource.ResourceManager;
+import com.cloud.resource.ResourceStateAdapter;
+import com.cloud.resource.ServerResource;
+import com.cloud.resource.UnableDeleteHostException;
+import com.cloud.utils.component.AdapterBase;
+import com.cloud.utils.exception.CloudRuntimeException;
+import com.cloud.vm.NicProfile;
+import com.cloud.vm.ReservationContext;
+import com.cloud.vm.VirtualMachineProfile;
+
+@Component
+@Local(value = {NetworkElement.class, ConnectivityProvider.class})
+public class OpendaylightElement extends AdapterBase implements ConnectivityProvider, ResourceStateAdapter {
+
+    private static final Logger s_logger = Logger.getLogger(OpendaylightElement.class);
+    private static final Map<Service, Map<Capability, String>> s_capabilities = setCapabilities();
+
+    @Inject
+    ResourceManager resourceManager;
+
+    @Override
+    public Map<Service, Map<Capability, String>> getCapabilities() {
+        return s_capabilities;
+    }
+
+    @Override
+    public Provider getProvider() {
+        return Provider.Opendaylight;
+    }
+
+    @Override
+    public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
+        boolean configured = super.configure(name, params);
+        if (configured)
+            resourceManager.registerResourceStateAdapter(name, this);
+        return configured;
+    }
+
+    @Override
+    public boolean implement(Network network, NetworkOffering offering, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException,
+    ResourceUnavailableException, InsufficientCapacityException {
+        // TODO Auto-generated method stub
+        return true;
+    }
+
+    @Override
+    public boolean prepare(Network network, NicProfile nic, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException,
+    ResourceUnavailableException, InsufficientCapacityException {
+        // TODO Auto-generated method stub
+        return true;
+    }
+
+    @Override
+    public boolean release(Network network, NicProfile nic, VirtualMachineProfile vm, ReservationContext context) throws ConcurrentOperationException,
+    ResourceUnavailableException {
+        // TODO Auto-generated method stub
+        return true;
+    }
+
+    @Override
+    public boolean shutdown(Network network, ReservationContext context, boolean cleanup) throws ConcurrentOperationException, ResourceUnavailableException {
+        return true;
+    }
+
+    @Override
+    public boolean destroy(Network network, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException {
+        return true;
+    }
+
+    @Override
+    public boolean isReady(PhysicalNetworkServiceProvider provider) {
+        return true;
+    }
+
+    @Override
+    public boolean shutdownProviderInstances(PhysicalNetworkServiceProvider provider, ReservationContext context) throws ConcurrentOperationException,
+    ResourceUnavailableException {
+        return true;
+    }
+
+    @Override
+    public boolean canEnableIndividualServices() {
+        return false;
+    }
+
+    @Override
+    public boolean verifyServicesCombination(Set<Service> services) {
+        if (services.contains(Service.Connectivity) && services.size() == 1)
+            return true;
+        return false;
+    }
+
+    @Override
+    public HostVO createHostVOForConnectedAgent(HostVO host, StartupCommand[] startup) {
+        if (!(startup[0] instanceof StartupOpenDaylightControllerCommand)) {
+            return null;
+        }
+        throw new CloudRuntimeException("createHostVOForConnectedAgent is not implemented for OpendaylightElement");
+    }
+
+    @Override
+    public HostVO createHostVOForDirectConnectAgent(HostVO host, StartupCommand[] startup, ServerResource resource, Map<String, String> details, List<String> hostTags) {
+        if (!(startup[0] instanceof StartupOpenDaylightControllerCommand)) {
+            return null;
+        }
+        host.setType(Host.Type.L2Networking);
+        return host;
+    }
+
+    @Override
+    public DeleteHostAnswer deleteHost(HostVO host, boolean isForced, boolean isForceDeleteStorage) throws UnableDeleteHostException {
+        return new DeleteHostAnswer(true);
+    }
+
+    private static Map<Service, Map<Capability, String>> setCapabilities() {
+        Map<Service, Map<Capability, String>> capabilities = new HashMap<Service, Map<Capability, String>>();
+
+        // L2 Support : SDN provisioning
+        capabilities.put(Service.Connectivity, null);
+
+        return capabilities;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1f9528ba/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/OpendaylightGuestNetworkGuru.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/OpendaylightGuestNetworkGuru.java b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/OpendaylightGuestNetworkGuru.java
new file mode 100644
index 0000000..0b547e7
--- /dev/null
+++ b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/OpendaylightGuestNetworkGuru.java
@@ -0,0 +1,276 @@
+//
+// 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;
+
+import java.util.List;
+import java.util.UUID;
+
+import javax.inject.Inject;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.network.opendaylight.agent.commands.AddHypervisorCommand;
+import org.apache.cloudstack.network.opendaylight.agent.commands.ConfigureNetworkCommand;
+import org.apache.cloudstack.network.opendaylight.agent.commands.ConfigurePortCommand;
+import org.apache.cloudstack.network.opendaylight.agent.commands.DestroyNetworkCommand;
+import org.apache.cloudstack.network.opendaylight.agent.commands.DestroyPortCommand;
+import org.apache.cloudstack.network.opendaylight.agent.responses.AddHypervisorAnswer;
+import org.apache.cloudstack.network.opendaylight.agent.responses.ConfigureNetworkAnswer;
+import org.apache.cloudstack.network.opendaylight.agent.responses.ConfigurePortAnswer;
+import org.apache.cloudstack.network.opendaylight.agent.responses.DestroyNetworkAnswer;
+import org.apache.cloudstack.network.opendaylight.agent.responses.DestroyPortAnswer;
+import org.apache.cloudstack.network.opendaylight.dao.OpenDaylightControllerMappingDao;
+import org.apache.cloudstack.network.opendaylight.dao.OpenDaylightControllerVO;
+
+import com.cloud.agent.AgentManager;
+import com.cloud.dc.DataCenter;
+import com.cloud.dc.DataCenter.NetworkType;
+import com.cloud.deploy.DeployDestination;
+import com.cloud.deploy.DeploymentPlan;
+import com.cloud.exception.InsufficientAddressCapacityException;
+import com.cloud.exception.InsufficientVirtualNetworkCapcityException;
+import com.cloud.network.Network;
+import com.cloud.network.Network.GuestType;
+import com.cloud.network.Network.Provider;
+import com.cloud.network.Network.Service;
+import com.cloud.network.Network.State;
+import com.cloud.network.NetworkModel;
+import com.cloud.network.NetworkProfile;
+import com.cloud.network.Networks.BroadcastDomainType;
+import com.cloud.network.PhysicalNetwork;
+import com.cloud.network.PhysicalNetwork.IsolationMethod;
+import com.cloud.network.dao.NetworkDao;
+import com.cloud.network.dao.NetworkVO;
+import com.cloud.network.dao.PhysicalNetworkDao;
+import com.cloud.network.dao.PhysicalNetworkVO;
+import com.cloud.network.guru.GuestNetworkGuru;
+import com.cloud.offering.NetworkOffering;
+import com.cloud.offerings.dao.NetworkOfferingServiceMapDao;
+import com.cloud.user.Account;
+import com.cloud.utils.exception.CloudRuntimeException;
+import com.cloud.vm.NicProfile;
+import com.cloud.vm.ReservationContext;
+import com.cloud.vm.VirtualMachineProfile;
+
+public class OpendaylightGuestNetworkGuru extends GuestNetworkGuru {
+    private static final Logger s_logger = Logger.getLogger(OpendaylightGuestNetworkGuru.class);
+
+    @Inject
+    protected NetworkOfferingServiceMapDao ntwkOfferingSrvcDao;
+    @Inject
+    PhysicalNetworkDao physicalNetworkDao;
+    @Inject
+    OpenDaylightControllerMappingDao openDaylightControllerMappingDao;
+    @Inject
+    NetworkModel networkModel;
+    @Inject
+    AgentManager agentManager;
+    @Inject
+    NetworkDao networkDao;
+
+    public OpendaylightGuestNetworkGuru() {
+        _isolationMethods = new IsolationMethod[] {IsolationMethod.ODL};
+    }
+
+    @Override
+    protected boolean canHandle(NetworkOffering offering, NetworkType networkType, PhysicalNetwork physicalNetwork) {
+        if (networkType == NetworkType.Advanced && isMyTrafficType(offering.getTrafficType()) && offering.getGuestType() == Network.GuestType.Isolated &&
+                isMyIsolationMethod(physicalNetwork) && ntwkOfferingSrvcDao.areServicesSupportedByNetworkOffering(offering.getId(), Service.Connectivity)
+                && ntwkOfferingSrvcDao.isProviderForNetworkOffering(offering.getId(), Provider.Opendaylight)) {
+            return true;
+        } else {
+            s_logger.trace("We only take care of Guest networks of type   " + GuestType.Isolated + " in zone of type " + NetworkType.Advanced);
+            return false;
+        }
+    }
+
+    @Override
+    public Network design(NetworkOffering offering, DeploymentPlan plan, Network userSpecified, Account owner) {
+        PhysicalNetworkVO physnet = physicalNetworkDao.findById(plan.getPhysicalNetworkId());
+        DataCenter dc = _dcDao.findById(plan.getDataCenterId());
+        if (!canHandle(offering, dc.getNetworkType(), physnet)) {
+            s_logger.debug("Refusing to design this network");
+            return null;
+        }
+
+        List<OpenDaylightControllerVO> devices = openDaylightControllerMappingDao.listByPhysicalNetwork(physnet.getId());
+        if (devices.isEmpty()) {
+            s_logger.error("No Controller on physical network " + physnet.getName());
+            return null;
+        }
+        s_logger.debug("Controller " + devices.get(0).getUuid() + " found on physical network " + physnet.getId());
+        s_logger.debug("Physical isolation type is ODL, asking GuestNetworkGuru to design this network");
+
+        NetworkVO networkObject = (NetworkVO)super.design(offering, plan, userSpecified, owner);
+        if (networkObject == null) {
+            return null;
+        }
+        // Override the broadcast domain type
+        networkObject.setBroadcastDomainType(BroadcastDomainType.OpenDaylight);
+
+        return networkObject;
+    }
+
+    @Override
+    public Network implement(Network network, NetworkOffering offering, DeployDestination dest, ReservationContext context) throws InsufficientVirtualNetworkCapcityException {
+        assert (network.getState() == State.Implementing) : "Why are we implementing " + network;
+
+        long dcId = dest.getDataCenter().getId();
+
+        //get physical network id
+        Long physicalNetworkId = network.getPhysicalNetworkId();
+
+        // physical network id can be null in Guest Network in Basic zone, so locate the physical network
+        if (physicalNetworkId == null) {
+            physicalNetworkId = networkModel.findPhysicalNetworkId(dcId, offering.getTags(), offering.getTrafficType());
+        }
+
+        NetworkVO implemented = new NetworkVO(network.getTrafficType(), network.getMode(), network.getBroadcastDomainType(), network.getNetworkOfferingId(), State.Allocated,
+                network.getDataCenterId(), physicalNetworkId);
+
+        if (network.getGateway() != null) {
+            implemented.setGateway(network.getGateway());
+        }
+
+        if (network.getCidr() != null) {
+            implemented.setCidr(network.getCidr());
+        }
+
+        // Name is either the given name or the uuid
+        String name = network.getName();
+        if (name == null || name.isEmpty()) {
+            name = ((NetworkVO)network).getUuid();
+        }
+
+        List<OpenDaylightControllerVO> devices = openDaylightControllerMappingDao.listByPhysicalNetwork(physicalNetworkId);
+        if (devices.isEmpty()) {
+            s_logger.error("No Controller on physical network " + physicalNetworkId);
+            return null;
+        }
+        OpenDaylightControllerVO controller = devices.get(0);
+
+        ConfigureNetworkCommand cmd = new ConfigureNetworkCommand(name, context.getAccount().getAccountName());
+        ConfigureNetworkAnswer answer = (ConfigureNetworkAnswer)agentManager.easySend(controller.getHostId(), cmd);
+
+        if (answer == null || !answer.getResult()) {
+            s_logger.error("ConfigureNetworkCommand failed");
+            return null;
+        }
+
+        implemented.setBroadcastUri(BroadcastDomainType.OpenDaylight.toUri(answer.getNetworkUuid()));
+        implemented.setBroadcastDomainType(BroadcastDomainType.OpenDaylight);
+        s_logger.info("Implemented OK, network linked to  = " + implemented.getBroadcastUri().toString());
+
+        return implemented;
+    }
+
+    @Override
+    public void reserve(NicProfile nic, Network network, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context)
+            throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException {
+        super.reserve(nic, network, vm, dest, context);
+
+        //get physical network id
+        Long physicalNetworkId = network.getPhysicalNetworkId();
+
+        List<OpenDaylightControllerVO> devices = openDaylightControllerMappingDao.listByPhysicalNetwork(physicalNetworkId);
+        if (devices.isEmpty()) {
+            s_logger.error("No Controller on physical network " + physicalNetworkId);
+            throw new InsufficientVirtualNetworkCapcityException("No OpenDaylight Controller configured for this network", dest.getPod().getId());
+        }
+        OpenDaylightControllerVO controller = devices.get(0);
+
+        AddHypervisorCommand addCmd = new AddHypervisorCommand(dest.getHost().getUuid(), dest.getHost().getPrivateIpAddress());
+        AddHypervisorAnswer addAnswer = (AddHypervisorAnswer)agentManager.easySend(controller.getHostId(), addCmd);
+        if (addAnswer == null || !addAnswer.getResult()) {
+            s_logger.error("Failed to add " + dest.getHost().getName() + " as a node to the controller");
+            throw new InsufficientVirtualNetworkCapcityException("Failed to add destination hypervisor to the OpenDaylight Controller", dest.getPod().getId());
+        }
+
+        ConfigurePortCommand cmd = new ConfigurePortCommand(UUID.fromString(nic.getUuid()), UUID.fromString(BroadcastDomainType.getValue(network.getBroadcastUri())), context
+                .getAccount().getAccountName(), nic.getMacAddress());
+        ConfigurePortAnswer answer = (ConfigurePortAnswer)agentManager.easySend(controller.getHostId(), cmd);
+
+        if (answer == null || !answer.getResult()) {
+            s_logger.error("ConfigureNetworkCommand failed");
+            throw new InsufficientVirtualNetworkCapcityException("Failed to configure the port on the OpenDaylight Controller", dest.getPod().getId());
+        }
+
+    }
+
+    @Override
+    public boolean release(NicProfile nic, VirtualMachineProfile vm, String reservationId) {
+        boolean success = super.release(nic, vm, reservationId);
+
+        if (success) {
+            //get physical network id
+            NetworkVO network = _networkDao.findById(nic.getNetworkId());
+            Long physicalNetworkId = network.getPhysicalNetworkId();
+
+            List<OpenDaylightControllerVO> devices = openDaylightControllerMappingDao.listByPhysicalNetwork(physicalNetworkId);
+            if (devices.isEmpty()) {
+                s_logger.error("No Controller on physical network " + physicalNetworkId);
+                throw new CloudRuntimeException("No OpenDaylight controller on this physical network");
+            }
+            OpenDaylightControllerVO controller = devices.get(0);
+
+            DestroyPortCommand cmd = new DestroyPortCommand(UUID.fromString(nic.getUuid()));
+            DestroyPortAnswer answer = (DestroyPortAnswer)agentManager.easySend(controller.getHostId(), cmd);
+
+            if (answer == null || !answer.getResult()) {
+                s_logger.error("DestroyPortCommand failed");
+                success = false;
+            }
+        }
+
+        return success;
+    }
+
+    @Override
+    public void shutdown(NetworkProfile profile, NetworkOffering offering) {
+        NetworkVO networkObject = networkDao.findById(profile.getId());
+        if (networkObject.getBroadcastDomainType() != BroadcastDomainType.OpenDaylight || networkObject.getBroadcastUri() == null) {
+            s_logger.warn("BroadcastUri is empty or incorrect for guestnetwork " + networkObject.getDisplayText());
+            return;
+        }
+
+        List<OpenDaylightControllerVO> devices = openDaylightControllerMappingDao.listByPhysicalNetwork(networkObject.getPhysicalNetworkId());
+        if (devices.isEmpty()) {
+            s_logger.error("No Controller on physical network " + networkObject.getPhysicalNetworkId());
+            return;
+        }
+        OpenDaylightControllerVO controller = devices.get(0);
+
+        DestroyNetworkCommand cmd = new DestroyNetworkCommand(BroadcastDomainType.getValue(networkObject.getBroadcastUri()));
+        DestroyNetworkAnswer answer = (DestroyNetworkAnswer)agentManager.easySend(controller.getHostId(), cmd);
+
+        if (answer == null || !answer.getResult()) {
+            s_logger.error("DestroyNetworkCommand failed");
+        }
+
+        super.shutdown(profile, offering);
+    }
+
+    @Override
+    public boolean trash(Network network, NetworkOffering offering) {
+        // TODO Auto-generated method stub
+        return super.trash(network, offering);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1f9528ba/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/OpenDaylightControllerResource.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/OpenDaylightControllerResource.java b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/OpenDaylightControllerResource.java
new file mode 100644
index 0000000..5c1e1e4
--- /dev/null
+++ b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/OpenDaylightControllerResource.java
@@ -0,0 +1,321 @@
+//
+// 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.agent;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.security.InvalidParameterException;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.UUID;
+
+import javax.naming.ConfigurationException;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.network.opendaylight.agent.commands.AddHypervisorCommand;
+import org.apache.cloudstack.network.opendaylight.agent.commands.ConfigureNetworkCommand;
+import org.apache.cloudstack.network.opendaylight.agent.commands.ConfigurePortCommand;
+import org.apache.cloudstack.network.opendaylight.agent.commands.DestroyNetworkCommand;
+import org.apache.cloudstack.network.opendaylight.agent.commands.DestroyPortCommand;
+import org.apache.cloudstack.network.opendaylight.agent.commands.StartupOpenDaylightControllerCommand;
+import org.apache.cloudstack.network.opendaylight.agent.responses.AddHypervisorAnswer;
+import org.apache.cloudstack.network.opendaylight.agent.responses.ConfigureNetworkAnswer;
+import org.apache.cloudstack.network.opendaylight.agent.responses.ConfigurePortAnswer;
+import org.apache.cloudstack.network.opendaylight.agent.responses.DestroyNetworkAnswer;
+import org.apache.cloudstack.network.opendaylight.agent.responses.DestroyPortAnswer;
+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;
+import org.apache.cloudstack.network.opendaylight.api.model.NeutronNode;
+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.NeutronPort;
+import org.apache.cloudstack.network.opendaylight.api.model.NeutronPortWrapper;
+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 com.cloud.agent.IAgentControl;
+import com.cloud.agent.api.Answer;
+import com.cloud.agent.api.Command;
+import com.cloud.agent.api.MaintainAnswer;
+import com.cloud.agent.api.MaintainCommand;
+import com.cloud.agent.api.PingCommand;
+import com.cloud.agent.api.ReadyAnswer;
+import com.cloud.agent.api.ReadyCommand;
+import com.cloud.agent.api.StartupCommand;
+import com.cloud.host.Host;
+import com.cloud.host.Host.Type;
+import com.cloud.resource.ServerResource;
+
+public class OpenDaylightControllerResource implements ServerResource {
+    private static final Logger s_logger = Logger.getLogger(OpenDaylightControllerResource.class);
+    private Map<String, Object> configuration = new HashMap<String, Object>();
+
+    private URL controllerUrl;
+    private String controllerUsername;
+    private String controllerPassword;
+
+    private int runLevel;
+
+    @Override
+    public String getName() {
+        if (configuration.containsKey("name"))
+            return (String)configuration.get("name");
+        else
+            return null;
+    }
+
+    @Override
+    public void setName(String name) {
+        configuration.put("name", name);
+    }
+
+    @Override
+    public void setConfigParams(Map<String, Object> params) {
+        for (Entry<String, Object> entry : params.entrySet()) {
+            configuration.put(entry.getKey(), entry.getValue());
+        }
+        updateConfiguration();
+    }
+
+    @Override
+    public Map<String, Object> getConfigParams() {
+        return Collections.unmodifiableMap(configuration);
+    }
+
+    @Override
+    public int getRunLevel() {
+        return runLevel;
+    }
+
+    @Override
+    public void setRunLevel(int level) {
+        runLevel = level;
+    }
+
+    @Override
+    public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
+        for (Entry<String, Object> entry : params.entrySet()) {
+            configuration.put(entry.getKey(), entry.getValue());
+        }
+        updateConfiguration();
+        return true;
+    }
+
+    @Override
+    public boolean start() {
+        return true;
+    }
+
+    @Override
+    public boolean stop() {
+        return true;
+    }
+
+    @Override
+    public Type getType() {
+        return Type.L2Networking;
+    }
+
+    @Override
+    public StartupCommand[] initialize() {
+        StartupOpenDaylightControllerCommand sc = new StartupOpenDaylightControllerCommand();
+        sc.setGuid((String)configuration.get("guid"));
+        sc.setName(getName());
+        sc.setDataCenter((String)configuration.get("zoneId"));
+        sc.setPod("");
+        sc.setPrivateIpAddress("");
+        sc.setStorageIpAddress("");
+        sc.setVersion(OpenDaylightControllerResource.class.getPackage().getImplementationVersion());
+        return new StartupCommand[] {sc};
+
+    }
+
+    @Override
+    public PingCommand getCurrentStatus(long id) {
+        return new PingCommand(Host.Type.L2Networking, id);
+    }
+
+    @Override
+    public Answer executeRequest(Command cmd) {
+        if (cmd instanceof ConfigureNetworkCommand) {
+            return executeRequest((ConfigureNetworkCommand)cmd);
+        } else if (cmd instanceof DestroyNetworkCommand) {
+            return executeRequest((DestroyNetworkCommand)cmd);
+        } else if (cmd instanceof ConfigurePortCommand) {
+            return executeRequest((ConfigurePortCommand)cmd);
+        } else if (cmd instanceof DestroyPortCommand) {
+            return executeRequest((DestroyPortCommand)cmd);
+        } else if (cmd instanceof AddHypervisorCommand) {
+            return executeRequest((AddHypervisorCommand)cmd);
+        } else if (cmd instanceof ReadyCommand) {
+            return executeRequest((ReadyCommand)cmd);
+        } else if (cmd instanceof MaintainCommand) {
+            return executeRequest((MaintainCommand)cmd);
+        } else {
+            return Answer.createUnsupportedCommandAnswer(cmd);
+        }
+    }
+
+    @Override
+    public void disconnected() {
+        s_logger.warn("OpenDaylightControllerResource is disconnected from the controller at " + controllerUrl);
+
+    }
+
+    @Override
+    public IAgentControl getAgentControl() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public void setAgentControl(IAgentControl agentControl) {
+        // TODO Auto-generated method stub
+
+    }
+
+    private Answer executeRequest(final ReadyCommand cmd) {
+        return new ReadyAnswer(cmd);
+    }
+
+    private Answer executeRequest(final MaintainCommand cmd) {
+        return new MaintainAnswer(cmd);
+    }
+
+    private Answer executeRequest(ConfigureNetworkCommand cmd) {
+        NeutronNetworksNorthboundAction configureNetwork = new NeutronNetworksNorthboundAction(controllerUrl, controllerUsername, controllerPassword);
+        NeutronNetwork newNetwork = new NeutronNetwork();
+
+        // Configuration from the command
+        newNetwork.setName(cmd.getName());
+        newNetwork.setTenantId(cmd.getTenantId());
+
+        // Static configuation
+        newNetwork.setNetworkType("gre");
+        newNetwork.setShared(false);
+        newNetwork.setSegmentationId(100);
+        newNetwork.setId(UUID.randomUUID());
+
+        NeutronNetworkWrapper wrapper = new NeutronNetworkWrapper();
+        wrapper.setNetwork(newNetwork);
+        try {
+            wrapper = configureNetwork.createNeutronNetwork(wrapper);
+        } catch (NeutronRestApiException e) {
+            s_logger.error("createNeutronNetwork failed", e);
+            return new ConfigureNetworkAnswer(cmd, e);
+        }
+
+        return new ConfigureNetworkAnswer(cmd, true, null, wrapper.getNetwork().getId().toString());
+    }
+
+    private Answer executeRequest(DestroyNetworkCommand cmd) {
+        NeutronNetworksNorthboundAction configureNetwork = new NeutronNetworksNorthboundAction(controllerUrl, controllerUsername, controllerPassword);
+        try {
+            configureNetwork.deleteNeutronNetwork(cmd.getNetworkUuid());
+        } catch (NeutronRestApiException e) {
+            s_logger.error("deleteNeutronNetwork failed", e);
+            return new DestroyNetworkAnswer(cmd, e);
+        }
+
+        return new DestroyNetworkAnswer(cmd, true, "Network " + cmd.getNetworkUuid() + " deleted");
+    }
+
+    private Answer executeRequest(ConfigurePortCommand cmd) {
+        NeutronPortsNorthboundAction configurePort = new NeutronPortsNorthboundAction(controllerUrl, controllerUsername, controllerPassword);
+        NeutronPort newPort = new NeutronPort();
+
+        // Configuration from the command
+        newPort.setId(cmd.getPortId());
+        newPort.setTenantId(cmd.getTennantId());
+        newPort.setAdminStateUp(true);
+        newPort.setName(cmd.getPortId().toString());
+        newPort.setNetworkId(cmd.getNetworkId());
+        newPort.setMacAddress(cmd.getMacAddress());
+        newPort.setDeviceId(UUID.randomUUID());
+
+        // Static valus
+        newPort.setStatus("ACTIVE");
+        newPort.setFixedIps(Collections.<String> emptyList());
+
+        NeutronPortWrapper portWrapper = new NeutronPortWrapper();
+        portWrapper.setPort(newPort);
+        try {
+            portWrapper = configurePort.createNeutronPort(portWrapper);
+        } catch (NeutronRestApiException e) {
+            s_logger.error("createPortCommand failed", e);
+            return new ConfigurePortAnswer(cmd, e);
+        }
+
+        return new ConfigurePortAnswer(cmd, true, "Port " + portWrapper.getPort().getId().toString() + " created");
+
+    }
+
+    private Answer executeRequest(DestroyPortCommand cmd) {
+        NeutronPortsNorthboundAction configurePort = new NeutronPortsNorthboundAction(controllerUrl, controllerUsername, controllerPassword);
+        try {
+            configurePort.deleteNeutronPort(cmd.getPortId().toString());
+        } catch (NeutronRestApiException e) {
+            s_logger.error("deleteNeutronPort failed", e);
+            return new DestroyPortAnswer(cmd, e);
+        }
+
+        return new DestroyPortAnswer(cmd, true, "Port " + cmd.getPortId().toString() + " deleted");
+    }
+
+    private Answer executeRequest(AddHypervisorCommand cmd) {
+        NeutronNodesNorthboundAction nodeActions = new NeutronNodesNorthboundAction(controllerUrl, controllerUsername, controllerPassword);
+        try {
+            NeutronNodesList<NeutronNodeWrapper> nodes = nodeActions.listAllNodes();
+            if (nodes.getNodes() != null) {
+                for (NeutronNodeWrapper nodeWrapper : nodes.getNodes()) {
+                    NeutronNode node = nodeWrapper.getNode();
+                    if (node.getId().equals(cmd.getHostId())) {
+                        return new AddHypervisorAnswer(cmd, true, "Hypervisor already connected");
+                    }
+                }
+            }
+
+            // Not found in the existing node list, add it
+            nodeActions.updateNeutronNodeV2("OVS", cmd.getHostId(), cmd.getIpAddress(), 6640);
+        } catch (NeutronRestApiException e) {
+            s_logger.error("Call to OpenDaylight failed", e);
+            return new AddHypervisorAnswer(cmd, e);
+        }
+        return new AddHypervisorAnswer(cmd, true, "Hypervisor " + cmd.getHostId() + " added");
+    }
+
+    private void updateConfiguration() {
+        if (!configuration.containsKey("url") || !configuration.containsKey("username") || !configuration.containsKey("password"))
+            throw new InvalidParameterException("OpenDaylightControllerResource needs a url, username and password.");
+        try {
+            controllerUrl = new URL((String)configuration.get("url"));
+        } catch (MalformedURLException e) {
+            throw new InvalidParameterException("OpenDaylightControllerResource found an invalid controller url");
+        }
+        controllerUsername = (String)configuration.get("username");
+        controllerPassword = (String)configuration.get("password");
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1f9528ba/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/OpenDaylightControllerResourceManager.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/OpenDaylightControllerResourceManager.java b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/OpenDaylightControllerResourceManager.java
new file mode 100644
index 0000000..1bc0e82
--- /dev/null
+++ b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/OpenDaylightControllerResourceManager.java
@@ -0,0 +1,34 @@
+//
+// 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.agent;
+
+import org.apache.cloudstack.network.opendaylight.api.commands.AddOpenDaylightControllerCmd;
+import org.apache.cloudstack.network.opendaylight.api.commands.DeleteOpenDaylightControllerCmd;
+import org.apache.cloudstack.network.opendaylight.dao.OpenDaylightControllerVO;
+
+import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.utils.component.PluggableService;
+
+public interface OpenDaylightControllerResourceManager extends PluggableService {
+
+    public OpenDaylightControllerVO addController(AddOpenDaylightControllerCmd cmd);
+
+    public void deleteController(DeleteOpenDaylightControllerCmd cmd) throws InvalidParameterValueException;
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1f9528ba/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/OpenDaylightControllerResourceManagerImpl.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/OpenDaylightControllerResourceManagerImpl.java b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/OpenDaylightControllerResourceManagerImpl.java
new file mode 100644
index 0000000..ad4db15
--- /dev/null
+++ b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/OpenDaylightControllerResourceManagerImpl.java
@@ -0,0 +1,173 @@
+//
+// 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.agent;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+import javax.inject.Inject;
+import javax.naming.ConfigurationException;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.network.ExternalNetworkDeviceManager.NetworkDevice;
+import org.apache.cloudstack.network.opendaylight.api.commands.AddOpenDaylightControllerCmd;
+import org.apache.cloudstack.network.opendaylight.api.commands.DeleteOpenDaylightControllerCmd;
+import org.apache.cloudstack.network.opendaylight.dao.OpenDaylightControllerMappingDao;
+import org.apache.cloudstack.network.opendaylight.dao.OpenDaylightControllerVO;
+
+import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.host.Host;
+import com.cloud.host.HostVO;
+import com.cloud.host.dao.HostDao;
+import com.cloud.network.Network;
+import com.cloud.network.Networks;
+import com.cloud.network.PhysicalNetworkServiceProvider;
+import com.cloud.network.dao.NetworkDao;
+import com.cloud.network.dao.NetworkVO;
+import com.cloud.network.dao.PhysicalNetworkDao;
+import com.cloud.network.dao.PhysicalNetworkServiceProviderDao;
+import com.cloud.network.dao.PhysicalNetworkServiceProviderVO;
+import com.cloud.network.dao.PhysicalNetworkVO;
+import com.cloud.resource.ResourceManager;
+import com.cloud.resource.ResourceState;
+import com.cloud.resource.ServerResource;
+import com.cloud.utils.db.Transaction;
+import com.cloud.utils.db.TransactionCallback;
+import com.cloud.utils.db.TransactionStatus;
+import com.cloud.utils.exception.CloudRuntimeException;
+
+public class OpenDaylightControllerResourceManagerImpl implements OpenDaylightControllerResourceManager {
+    private final static Logger s_logger = Logger.getLogger(OpenDaylightControllerResourceManagerImpl.class);
+
+    @Inject
+    HostDao hostDao;
+    @Inject
+    ResourceManager resourceManager;
+    @Inject
+    PhysicalNetworkDao physicalNetworkDao;
+    @Inject
+    PhysicalNetworkServiceProviderDao physicalNetworkServiceProviderDao;
+    @Inject
+    OpenDaylightControllerMappingDao openDaylightControllerMappingDao;
+    @Inject
+    NetworkDao networkDao;
+
+    @Override
+    public List<Class<?>> getCommands() {
+        List<Class<?>> commands = new ArrayList<Class<?>>();
+        commands.add(AddOpenDaylightControllerCmd.class);
+        return commands;
+    }
+
+    @Override
+    public OpenDaylightControllerVO addController(AddOpenDaylightControllerCmd cmd) {
+        ServerResource odlController = new OpenDaylightControllerResource();
+
+        final String deviceName = NetworkDevice.OpenDaylightController.getName();
+        NetworkDevice networkDevice = NetworkDevice.getNetworkDevice(deviceName);
+        final Long physicalNetworkId = cmd.getPhysicalNetworkId();
+        PhysicalNetworkVO physicalNetwork = physicalNetworkDao.findById(physicalNetworkId);
+        if (physicalNetwork == null) {
+            throw new InvalidParameterValueException("Could not find phyical network with ID: " + physicalNetworkId);
+        }
+        long zoneId = physicalNetwork.getDataCenterId();
+
+        final PhysicalNetworkServiceProviderVO ntwkSvcProvider = physicalNetworkServiceProviderDao.findByServiceProvider(physicalNetwork.getId(),
+                networkDevice.getNetworkServiceProvder());
+        if (ntwkSvcProvider == null) {
+            throw new CloudRuntimeException("Network Service Provider: " + networkDevice.getNetworkServiceProvder() + " is not enabled in the physical network: "
+                    + physicalNetworkId + "to add this device");
+        } else if (ntwkSvcProvider.getState() == PhysicalNetworkServiceProvider.State.Shutdown) {
+            throw new CloudRuntimeException("Network Service Provider: " + ntwkSvcProvider.getProviderName() + " is in shutdown state in the physical network: "
+                    + physicalNetworkId + "to add this device");
+        }
+
+        final Map<String, String> hostParams = new HashMap<String, String>();
+        hostParams.put("guid", UUID.randomUUID().toString());
+        hostParams.put("zoneId", String.valueOf(physicalNetwork.getDataCenterId()));
+        hostParams.put("physicalNetworkId", String.valueOf(physicalNetwork.getId()));
+        hostParams.put("name", "ODL Controller - " + hostParams.get("guid"));
+        hostParams.put("url", cmd.getUrl());
+        hostParams.put("username", cmd.getUsername());
+        hostParams.put("password", cmd.getPassword());
+
+        Map<String, Object> hostdetails = new HashMap<String, Object>();
+        hostdetails.putAll(hostParams);
+
+        try {
+            odlController.configure(hostParams.get("name"), hostdetails);
+            final Host host = resourceManager.addHost(zoneId, odlController, Host.Type.L2Networking, hostParams);
+            if (host != null) {
+                return Transaction.execute(new TransactionCallback<OpenDaylightControllerVO>() {
+                    @Override
+                    public OpenDaylightControllerVO doInTransaction(TransactionStatus status) {
+                        OpenDaylightControllerVO controller = new OpenDaylightControllerVO(host.getId(), physicalNetworkId, ntwkSvcProvider.getProviderName(), hostParams
+                                .get("name"));
+                        openDaylightControllerMappingDao.persist(controller);
+                        return controller;
+                    }
+                });
+            } else {
+                throw new CloudRuntimeException("Failed to create host object for ODL Controller");
+            }
+        } catch (ConfigurationException e) {
+            throw new CloudRuntimeException("Failed to add ODL Controller as a resource", e);
+        }
+    }
+
+    @Override
+    public void deleteController(DeleteOpenDaylightControllerCmd cmd) throws InvalidParameterValueException {
+        OpenDaylightControllerVO controller = openDaylightControllerMappingDao.findById(cmd.getId());
+        if (controller == null) {
+            throw new InvalidParameterValueException("No ODL Controller with id " + cmd.getId());
+        }
+
+        // Find the physical network we work for
+        Long physicalNetworkId = controller.getPhysicalNetworkId();
+        PhysicalNetworkVO physicalNetwork = physicalNetworkDao.findById(physicalNetworkId);
+        if (physicalNetwork != null) {
+            // Lets see if there are networks that use us
+            List<NetworkVO> networkList = networkDao.listByPhysicalNetwork(physicalNetworkId);
+
+            // Networks with broadcast type lswitch are ours
+            for (NetworkVO network : networkList) {
+                if (network.getBroadcastDomainType() == Networks.BroadcastDomainType.OpenDaylight) {
+                    if ((network.getState() != Network.State.Shutdown) && (network.getState() != Network.State.Destroy)) {
+                        throw new CloudRuntimeException("This Controller can not be deleted as there are one or more logical networks provisioned by cloudstack.");
+                    }
+                }
+            }
+        }
+
+        HostVO host = hostDao.findById(controller.getHostId());
+        Long hostId = host.getId();
+
+        host.setResourceState(ResourceState.Maintenance);
+        hostDao.update(hostId, host);
+        resourceManager.deleteHost(hostId, false, false);
+
+        openDaylightControllerMappingDao.remove(cmd.getId());
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1f9528ba/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/commands/AddHypervisorCommand.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/commands/AddHypervisorCommand.java b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/commands/AddHypervisorCommand.java
new file mode 100644
index 0000000..06e94b3
--- /dev/null
+++ b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/commands/AddHypervisorCommand.java
@@ -0,0 +1,58 @@
+//
+// 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.agent.commands;
+
+import com.cloud.agent.api.Command;
+
+public class AddHypervisorCommand extends Command {
+    private String hostId;
+    private String ipAddress;
+
+    public AddHypervisorCommand() {
+    }
+
+    public AddHypervisorCommand(String hostId, String ipAddress) {
+        this.hostId = hostId;
+        this.ipAddress = ipAddress;
+    }
+
+    public String getHostId() {
+        return hostId;
+    }
+
+    public void setHostId(String hostId) {
+        this.hostId = hostId;
+    }
+
+    public String getIpAddress() {
+        return ipAddress;
+    }
+
+    public void setIpAddress(String ipAddress) {
+        this.ipAddress = ipAddress;
+    }
+
+    @Override
+    public boolean executeInSequence() {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1f9528ba/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/commands/ConfigureNetworkCommand.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/commands/ConfigureNetworkCommand.java b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/commands/ConfigureNetworkCommand.java
new file mode 100644
index 0000000..bfbcde4
--- /dev/null
+++ b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/commands/ConfigureNetworkCommand.java
@@ -0,0 +1,54 @@
+//
+// 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.agent.commands;
+
+import com.cloud.agent.api.Command;
+
+public class ConfigureNetworkCommand extends Command {
+    private String name;
+    private String tenantId;
+
+    public ConfigureNetworkCommand(String name, String tenantId) {
+        this.name = name;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getTenantId() {
+        return tenantId;
+    }
+
+    public void setTenantId(String tennantId) {
+        tenantId = tennantId;
+    }
+
+    @Override
+    public boolean executeInSequence() {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1f9528ba/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/commands/ConfigurePortCommand.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/commands/ConfigurePortCommand.java b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/commands/ConfigurePortCommand.java
new file mode 100644
index 0000000..3d4d2a2
--- /dev/null
+++ b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/commands/ConfigurePortCommand.java
@@ -0,0 +1,80 @@
+//
+// 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.agent.commands;
+
+import java.util.UUID;
+
+import com.cloud.agent.api.Command;
+
+public class ConfigurePortCommand extends Command {
+    private UUID networkId;
+    private String tennantId;
+    private String macAddress;
+    private UUID portId;
+
+    public ConfigurePortCommand() {
+    }
+
+    public ConfigurePortCommand(UUID portId, UUID networkId, String tennantId, String macAddress) {
+        this.portId = portId;
+        this.networkId = networkId;
+        this.tennantId = tennantId;
+        this.macAddress = macAddress;
+    }
+
+    public UUID getNetworkId() {
+        return networkId;
+    }
+
+    public void setNetworkId(UUID networkId) {
+        this.networkId = networkId;
+    }
+
+    public String getTennantId() {
+        return tennantId;
+    }
+
+    public void setTennantId(String tennantId) {
+        this.tennantId = tennantId;
+    }
+
+    public String getMacAddress() {
+        return macAddress;
+    }
+
+    public void setMacAddress(String macAddress) {
+        this.macAddress = macAddress;
+    }
+
+    public UUID getPortId() {
+        return portId;
+    }
+
+    public void setPortId(UUID portId) {
+        this.portId = portId;
+    }
+
+    @Override
+    public boolean executeInSequence() {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1f9528ba/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/commands/DestroyNetworkCommand.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/commands/DestroyNetworkCommand.java b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/commands/DestroyNetworkCommand.java
new file mode 100644
index 0000000..6d1bc04
--- /dev/null
+++ b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/commands/DestroyNetworkCommand.java
@@ -0,0 +1,45 @@
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+
+package org.apache.cloudstack.network.opendaylight.agent.commands;
+
+import com.cloud.agent.api.Command;
+
+public class DestroyNetworkCommand extends Command {
+    private String networkUuid;
+
+    public DestroyNetworkCommand(String networkUuid) {
+        this.networkUuid = networkUuid;
+    }
+
+    public String getNetworkUuid() {
+        return networkUuid;
+    }
+
+    public void setNetworkUuid(String networkUuid) {
+        this.networkUuid = networkUuid;
+    }
+
+    @Override
+    public boolean executeInSequence() {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1f9528ba/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/commands/DestroyPortCommand.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/commands/DestroyPortCommand.java b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/commands/DestroyPortCommand.java
new file mode 100644
index 0000000..c0a8937
--- /dev/null
+++ b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/commands/DestroyPortCommand.java
@@ -0,0 +1,50 @@
+//
+// 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.agent.commands;
+
+import java.util.UUID;
+
+import com.cloud.agent.api.Command;
+
+public class DestroyPortCommand extends Command {
+    private UUID portId;
+
+    public DestroyPortCommand() {
+    }
+
+    public DestroyPortCommand(UUID portId) {
+        this.portId = portId;
+    }
+
+    public UUID getPortId() {
+        return portId;
+    }
+
+    public void setPortId(UUID portId) {
+        this.portId = portId;
+    }
+
+    @Override
+    public boolean executeInSequence() {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1f9528ba/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/commands/StartupOpenDaylightControllerCommand.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/commands/StartupOpenDaylightControllerCommand.java b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/commands/StartupOpenDaylightControllerCommand.java
new file mode 100644
index 0000000..de3a7a3
--- /dev/null
+++ b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/commands/StartupOpenDaylightControllerCommand.java
@@ -0,0 +1,29 @@
+//
+// 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.agent.commands;
+
+import com.cloud.agent.api.StartupCommand;
+import com.cloud.host.Host;
+
+public class StartupOpenDaylightControllerCommand extends StartupCommand {
+    public StartupOpenDaylightControllerCommand() {
+        super(Host.Type.L2Networking);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1f9528ba/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/responses/AddHypervisorAnswer.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/responses/AddHypervisorAnswer.java b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/responses/AddHypervisorAnswer.java
new file mode 100644
index 0000000..7986705
--- /dev/null
+++ b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/responses/AddHypervisorAnswer.java
@@ -0,0 +1,35 @@
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+
+package org.apache.cloudstack.network.opendaylight.agent.responses;
+
+import com.cloud.agent.api.Answer;
+import com.cloud.agent.api.Command;
+
+public class AddHypervisorAnswer extends Answer {
+
+    public AddHypervisorAnswer(Command command, boolean success, String details) {
+        super(command, success, details);
+    }
+
+    public AddHypervisorAnswer(Command command, Exception e) {
+        super(command, e);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1f9528ba/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/responses/ConfigureNetworkAnswer.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/responses/ConfigureNetworkAnswer.java b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/responses/ConfigureNetworkAnswer.java
new file mode 100644
index 0000000..81c4a6f
--- /dev/null
+++ b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/responses/ConfigureNetworkAnswer.java
@@ -0,0 +1,43 @@
+//
+// 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.agent.responses;
+
+import com.cloud.agent.api.Answer;
+import com.cloud.agent.api.Command;
+
+public class ConfigureNetworkAnswer extends Answer {
+    private String networkUuid;
+
+    public ConfigureNetworkAnswer(Command command, boolean success, String details, String networkUuid) {
+        this.networkUuid = networkUuid;
+    }
+
+    public ConfigureNetworkAnswer(Command command, boolean success, String details) {
+        super(command, success, details);
+    }
+
+    public ConfigureNetworkAnswer(Command command, Exception e) {
+        super(command, e);
+    }
+
+    public String getNetworkUuid() {
+        return networkUuid;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1f9528ba/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/responses/ConfigurePortAnswer.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/responses/ConfigurePortAnswer.java b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/responses/ConfigurePortAnswer.java
new file mode 100644
index 0000000..cf9acc1
--- /dev/null
+++ b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/responses/ConfigurePortAnswer.java
@@ -0,0 +1,35 @@
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+
+package org.apache.cloudstack.network.opendaylight.agent.responses;
+
+import com.cloud.agent.api.Answer;
+import com.cloud.agent.api.Command;
+
+public class ConfigurePortAnswer extends Answer {
+
+    public ConfigurePortAnswer(Command command, boolean success, String details) {
+        super(command, success, details);
+    }
+
+    public ConfigurePortAnswer(Command command, Exception e) {
+        super(command, e);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1f9528ba/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/responses/DestroyNetworkAnswer.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/responses/DestroyNetworkAnswer.java b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/responses/DestroyNetworkAnswer.java
new file mode 100644
index 0000000..10284b4
--- /dev/null
+++ b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/responses/DestroyNetworkAnswer.java
@@ -0,0 +1,35 @@
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+
+package org.apache.cloudstack.network.opendaylight.agent.responses;
+
+import com.cloud.agent.api.Answer;
+import com.cloud.agent.api.Command;
+
+public class DestroyNetworkAnswer extends Answer {
+
+    public DestroyNetworkAnswer(Command command, boolean success, String details) {
+        super(command, success, details);
+    }
+
+    public DestroyNetworkAnswer(Command command, Exception e) {
+        super(command, e);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1f9528ba/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/responses/DestroyPortAnswer.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/responses/DestroyPortAnswer.java b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/responses/DestroyPortAnswer.java
new file mode 100644
index 0000000..07bb0db
--- /dev/null
+++ b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/responses/DestroyPortAnswer.java
@@ -0,0 +1,35 @@
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+
+package org.apache.cloudstack.network.opendaylight.agent.responses;
+
+import com.cloud.agent.api.Answer;
+import com.cloud.agent.api.Command;
+
+public class DestroyPortAnswer extends Answer {
+
+    public DestroyPortAnswer(Command command, boolean success, String details) {
+        super(command, success, details);
+    }
+
+    public DestroyPortAnswer(Command command, Exception e) {
+        super(command, e);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1f9528ba/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/dao/OpenDaylightControllerMappingDao.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/dao/OpenDaylightControllerMappingDao.java b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/dao/OpenDaylightControllerMappingDao.java
new file mode 100644
index 0000000..8799982
--- /dev/null
+++ b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/dao/OpenDaylightControllerMappingDao.java
@@ -0,0 +1,28 @@
+//
+// 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.dao;
+
+import java.util.List;
+
+import com.cloud.utils.db.GenericDao;
+
+public interface OpenDaylightControllerMappingDao extends GenericDao<OpenDaylightControllerVO, Long> {
+    List<OpenDaylightControllerVO> listByPhysicalNetwork(long physicalNetworkId);
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1f9528ba/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/dao/OpenDaylightControllerMappingDaoImpl.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/dao/OpenDaylightControllerMappingDaoImpl.java b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/dao/OpenDaylightControllerMappingDaoImpl.java
new file mode 100644
index 0000000..1d0beca
--- /dev/null
+++ b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/dao/OpenDaylightControllerMappingDaoImpl.java
@@ -0,0 +1,45 @@
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+
+package org.apache.cloudstack.network.opendaylight.dao;
+
+import java.util.List;
+
+import com.cloud.utils.db.GenericDaoBase;
+import com.cloud.utils.db.SearchBuilder;
+import com.cloud.utils.db.SearchCriteria;
+import com.cloud.utils.db.SearchCriteria.Op;
+
+public class OpenDaylightControllerMappingDaoImpl extends GenericDaoBase<OpenDaylightControllerVO, Long> implements OpenDaylightControllerMappingDao {
+    private SearchBuilder<OpenDaylightControllerVO> physicalNetworkIdSearch;
+
+    public OpenDaylightControllerMappingDaoImpl() {
+        physicalNetworkIdSearch = createSearchBuilder();
+        physicalNetworkIdSearch.and("physicalNetworkId", physicalNetworkIdSearch.entity().getPhysicalNetworkId(), Op.EQ);
+        physicalNetworkIdSearch.done();
+    }
+
+    @Override
+    public List<OpenDaylightControllerVO> listByPhysicalNetwork(long physicalNetworkId) {
+        SearchCriteria<OpenDaylightControllerVO> sc = physicalNetworkIdSearch.create();
+        sc.setParameters("physicalNetworkId", physicalNetworkId);
+        return search(sc, null);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1f9528ba/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/dao/OpenDaylightControllerVO.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/dao/OpenDaylightControllerVO.java b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/dao/OpenDaylightControllerVO.java
new file mode 100644
index 0000000..61d5682
--- /dev/null
+++ b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/dao/OpenDaylightControllerVO.java
@@ -0,0 +1,101 @@
+//
+// 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.dao;
+
+import java.util.UUID;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+import org.apache.cloudstack.api.InternalIdentity;
+
+@Entity
+@Table(name = "external_opendaylight_controllers")
+public class OpenDaylightControllerVO implements InternalIdentity {
+    private static final long serialVersionUID = -575928081553194369L;
+
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    @Column(name = "id")
+    private long id;
+
+    @Column(name = "uuid")
+    private String uuid;
+
+    @Column(name = "host_id")
+    private long hostId;
+
+    @Column(name = "physical_network_id")
+    private long physicalNetworkId;
+
+    @Column(name = "provider_name")
+    private String providerName;
+
+    @Column(name = "device_name")
+    private String deviceName;
+
+    public OpenDaylightControllerVO() {
+        uuid = UUID.randomUUID().toString();
+    }
+
+    public OpenDaylightControllerVO(final long hostId, final long physicalNetworkId, final String providerName, final String deviceName) {
+        super();
+        this.hostId = hostId;
+        this.physicalNetworkId = physicalNetworkId;
+        this.providerName = providerName;
+        this.deviceName = deviceName;
+        uuid = UUID.randomUUID().toString();
+    }
+
+    @Override
+    public long getId() {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    public String getUuid() {
+        return uuid;
+    }
+
+    public void setUuid(String uuid) {
+        this.uuid = uuid;
+    }
+
+    public long getPhysicalNetworkId() {
+        return physicalNetworkId;
+    }
+
+    public long getHostId() {
+        return hostId;
+    }
+
+    public String getProviderName() {
+        return providerName;
+    }
+
+    public String getDeviceName() {
+        return deviceName;
+    }
+
+}


[03/11] git commit: updated refs/heads/master to 612a41e

Posted by hu...@apache.org.
Hook the OpenDaylight plugin into CloudStack


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

Branch: refs/heads/master
Commit: 850bc9fa826393c5ab110bf49138b4d0e1c1c313
Parents: 1f9528b
Author: Hugo Trippaers <ht...@schubergphilis.com>
Authored: Thu Dec 19 11:00:36 2013 +0100
Committer: Hugo Trippaers <ht...@schubergphilis.com>
Committed: Wed Jan 8 15:58:08 2014 +0100

----------------------------------------------------------------------
 api/src/com/cloud/event/EventTypes.java         |  10 ++
 api/src/com/cloud/network/Network.java          |   7 +-
 api/src/com/cloud/network/Networks.java         |   2 +-
 api/src/com/cloud/network/PhysicalNetwork.java  |   2 +-
 api/src/com/cloud/vm/NicProfile.java            | 102 ++++++++++---------
 .../network/ExternalNetworkDeviceManager.java   |   1 +
 client/pom.xml                                  |   5 +
 client/tomcatconf/commands.properties.in        |   3 +
 setup/db/db/schema-430to440.sql                 |  14 ++-
 9 files changed, 94 insertions(+), 52 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/850bc9fa/api/src/com/cloud/event/EventTypes.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/event/EventTypes.java b/api/src/com/cloud/event/EventTypes.java
index 5a342cd..e88f010 100755
--- a/api/src/com/cloud/event/EventTypes.java
+++ b/api/src/com/cloud/event/EventTypes.java
@@ -455,6 +455,11 @@ public class EventTypes {
     //Alert generation
     public static final String ALERT_GENERATE = "ALERT.GENERATE";
 
+    // OpenDaylight
+    public static final String EVENT_EXTERNAL_OPENDAYLIGHT_ADD_CONTROLLER = "PHYSICAL.ODLCONTROLLER.ADD";
+    public static final String EVENT_EXTERNAL_OPENDAYLIGHT_DELETE_CONTROLLER = "PHYSICAL.ODLCONTROLLER.DELETE";
+    public static final String EVENT_EXTERNAL_OPENDAYLIGHT_CONFIGURE_CONTROLLER = "PHYSICAL.ODLCONTROLLER.CONFIGURE";
+
     static {
 
         // TODO: need a way to force author adding event types to declare the entity details as well, with out braking
@@ -760,6 +765,11 @@ public class EventTypes {
         entityEventDetails.put(EVENT_AUTOSCALEVMGROUP_DISABLE, AutoScaleVmGroup.class.getName());
         entityEventDetails.put(EVENT_GUEST_VLAN_RANGE_DEDICATE, GuestVlan.class.getName());
         entityEventDetails.put(EVENT_DEDICATED_GUEST_VLAN_RANGE_RELEASE, GuestVlan.class.getName());
+
+        // OpenDaylight
+        entityEventDetails.put(EVENT_EXTERNAL_OPENDAYLIGHT_ADD_CONTROLLER, "OpenDaylightController");
+        entityEventDetails.put(EVENT_EXTERNAL_OPENDAYLIGHT_DELETE_CONTROLLER, "OpenDaylightController");
+        entityEventDetails.put(EVENT_EXTERNAL_OPENDAYLIGHT_CONFIGURE_CONTROLLER, "OpenDaylightController");
     }
 
     public static String getEntityForEvent(String eventName) {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/850bc9fa/api/src/com/cloud/network/Network.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/network/Network.java b/api/src/com/cloud/network/Network.java
index d19c999..d2c8ac0 100644
--- a/api/src/com/cloud/network/Network.java
+++ b/api/src/com/cloud/network/Network.java
@@ -47,9 +47,9 @@ public interface Network extends ControlledEntity, StateObject<Network.State>, I
         public static final Service Dns = new Service("Dns", Capability.AllowDnsSuffixModification);
         public static final Service Gateway = new Service("Gateway");
         public static final Service Firewall = new Service("Firewall", Capability.SupportedProtocols, Capability.MultipleIps, Capability.TrafficStatistics,
-            Capability.SupportedTrafficDirection, Capability.SupportedEgressProtocols);
+                Capability.SupportedTrafficDirection, Capability.SupportedEgressProtocols);
         public static final Service Lb = new Service("Lb", Capability.SupportedLBAlgorithms, Capability.SupportedLBIsolation, Capability.SupportedProtocols,
-            Capability.TrafficStatistics, Capability.LoadBalancingSupportedIps, Capability.SupportedStickinessMethods, Capability.ElasticLb, Capability.LbSchemes);
+                Capability.TrafficStatistics, Capability.LoadBalancingSupportedIps, Capability.SupportedStickinessMethods, Capability.ElasticLb, Capability.LbSchemes);
         public static final Service UserData = new Service("UserData");
         public static final Service SourceNat = new Service("SourceNat", Capability.SupportedSourceNatTypes, Capability.RedundantRouter);
         public static final Service StaticNat = new Service("StaticNat", Capability.ElasticIp);
@@ -128,6 +128,7 @@ public interface Network extends ControlledEntity, StateObject<Network.State>, I
         public static final Provider CiscoVnmc = new Provider("CiscoVnmc", true);
         // add new Ovs provider
         public static final Provider Ovs = new Provider("Ovs", false);
+        public static final Provider Opendaylight = new Provider("Opendaylight", false);
 
         private final String name;
         private final boolean isExternal;
@@ -213,7 +214,7 @@ public interface Network extends ControlledEntity, StateObject<Network.State>, I
 
         Allocated("Indicates the network configuration is in allocated but not setup"), Setup("Indicates the network configuration is setup"), Implementing(
                 "Indicates the network configuration is being implemented"), Implemented("Indicates the network configuration is in use"), Shutdown(
-                "Indicates the network configuration is being destroyed"), Destroy("Indicates that the network is destroyed");
+                        "Indicates the network configuration is being destroyed"), Destroy("Indicates that the network is destroyed");
 
         protected static final StateMachine2<State, Network.Event, Network> s_fsm = new StateMachine2<State, Network.Event, Network>();
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/850bc9fa/api/src/com/cloud/network/Networks.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/network/Networks.java b/api/src/com/cloud/network/Networks.java
index e4034a5..b2c04cd 100755
--- a/api/src/com/cloud/network/Networks.java
+++ b/api/src/com/cloud/network/Networks.java
@@ -94,7 +94,7 @@ public class Networks {
                 return uri.getSchemeSpecificPart();
             }
         },
-        Mido("mido", String.class), Pvlan("pvlan", String.class), Vxlan("vxlan", Long.class), UnDecided(null, null);
+        Mido("mido", String.class), Pvlan("pvlan", String.class), Vxlan("vxlan", Long.class), UnDecided(null, null), OpenDaylight("opendaylight", String.class);
 
         private final String scheme;
         private final Class<?> type;

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/850bc9fa/api/src/com/cloud/network/PhysicalNetwork.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/network/PhysicalNetwork.java b/api/src/com/cloud/network/PhysicalNetwork.java
index cfa236d..5c348c2 100644
--- a/api/src/com/cloud/network/PhysicalNetwork.java
+++ b/api/src/com/cloud/network/PhysicalNetwork.java
@@ -33,7 +33,7 @@ public interface PhysicalNetwork extends Identity, InternalIdentity {
     }
 
     public enum IsolationMethod {
-        VLAN, L3, GRE, STT, VNS, MIDO, SSP, VXLAN;
+        VLAN, L3, GRE, STT, VNS, MIDO, SSP, VXLAN, ODL;
     }
 
     public enum BroadcastDomainRange {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/850bc9fa/api/src/com/cloud/vm/NicProfile.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/vm/NicProfile.java b/api/src/com/cloud/vm/NicProfile.java
index ab18ca0..2058803 100644
--- a/api/src/com/cloud/vm/NicProfile.java
+++ b/api/src/com/cloud/vm/NicProfile.java
@@ -57,6 +57,7 @@ public class NicProfile implements InternalIdentity {
     String name;
     String requestedIpv4;
     String requestedIpv6;
+    String uuid;
 
     public String getDns1() {
         return dns1;
@@ -142,6 +143,10 @@ public class NicProfile implements InternalIdentity {
         this.format = format;
     }
 
+    public void setUuid(String uuid) {
+        this.uuid = uuid;
+    }
+
     public void setTrafficType(TrafficType trafficType) {
         this.trafficType = trafficType;
     }
@@ -215,29 +220,34 @@ public class NicProfile implements InternalIdentity {
         return strategy;
     }
 
+    public String getUuid() {
+        return uuid;
+    }
+
     public NicProfile(Nic nic, Network network, URI broadcastUri, URI isolationUri, Integer networkRate, boolean isSecurityGroupEnabled, String name) {
-        this.id = nic.getId();
-        this.networkId = network.getId();
-        this.gateway = nic.getGateway();
-        this.mode = network.getMode();
-        this.broadcastType = network.getBroadcastDomainType();
-        this.trafficType = network.getTrafficType();
-        this.ip4Address = nic.getIp4Address();
-        this.format = nic.getAddressFormat();
-        this.ip6Address = nic.getIp6Address();
-        this.macAddress = nic.getMacAddress();
-        this.reservationId = nic.getReservationId();
-        this.strategy = nic.getReservationStrategy();
-        this.deviceId = nic.getDeviceId();
-        this.defaultNic = nic.isDefaultNic();
+        id = nic.getId();
+        networkId = network.getId();
+        gateway = nic.getGateway();
+        mode = network.getMode();
+        broadcastType = network.getBroadcastDomainType();
+        trafficType = network.getTrafficType();
+        ip4Address = nic.getIp4Address();
+        format = nic.getAddressFormat();
+        ip6Address = nic.getIp6Address();
+        macAddress = nic.getMacAddress();
+        reservationId = nic.getReservationId();
+        strategy = nic.getReservationStrategy();
+        deviceId = nic.getDeviceId();
+        defaultNic = nic.isDefaultNic();
         this.broadcastUri = broadcastUri;
         this.isolationUri = isolationUri;
-        this.netmask = nic.getNetmask();
+        netmask = nic.getNetmask();
         this.isSecurityGroupEnabled = isSecurityGroupEnabled;
-        this.vmId = nic.getInstanceId();
+        vmId = nic.getInstanceId();
         this.name = name;
-        this.ip6Cidr = nic.getIp6Cidr();
-        this.ip6Gateway = nic.getIp6Gateway();
+        ip6Cidr = nic.getIp6Cidr();
+        ip6Gateway = nic.getIp6Gateway();
+        uuid = nic.getUuid();
 
         if (networkRate != null) {
             this.networkRate = networkRate;
@@ -245,7 +255,7 @@ public class NicProfile implements InternalIdentity {
     }
 
     public NicProfile(ReservationStrategy strategy, String ip4Address, String macAddress, String gateway, String netmask) {
-        this.format = AddressFormat.Ip4;
+        format = AddressFormat.Ip4;
         this.ip4Address = ip4Address;
         this.macAddress = macAddress;
         this.gateway = gateway;
@@ -274,11 +284,11 @@ public class NicProfile implements InternalIdentity {
     }
 
     public boolean isSecurityGroupEnabled() {
-        return this.isSecurityGroupEnabled;
+        return isSecurityGroupEnabled;
     }
 
     public void setSecurityGroupEnabled(boolean enabled) {
-        this.isSecurityGroupEnabled = enabled;
+        isSecurityGroupEnabled = enabled;
     }
 
     public String getRequestedIpv4() {
@@ -286,36 +296,36 @@ public class NicProfile implements InternalIdentity {
     }
 
     public void deallocate() {
-        this.gateway = null;
-        this.mode = null;
-        this.format = null;
-        this.broadcastType = null;
-        this.trafficType = null;
-        this.ip4Address = null;
-        this.ip6Address = null;
-        this.macAddress = null;
-        this.reservationId = null;
-        this.strategy = null;
-        this.deviceId = null;
-        this.broadcastUri = null;
-        this.isolationUri = null;
-        this.netmask = null;
-        this.dns1 = null;
-        this.dns2 = null;
+        gateway = null;
+        mode = null;
+        format = null;
+        broadcastType = null;
+        trafficType = null;
+        ip4Address = null;
+        ip6Address = null;
+        macAddress = null;
+        reservationId = null;
+        strategy = null;
+        deviceId = null;
+        broadcastUri = null;
+        isolationUri = null;
+        netmask = null;
+        dns1 = null;
+        dns2 = null;
     }
 
     @Override
     public String toString() {
         return new StringBuilder("NicProfile[").append(id)
-            .append("-")
-            .append(vmId)
-            .append("-")
-            .append(reservationId)
-            .append("-")
-            .append(ip4Address)
-            .append("-")
-            .append(broadcastUri)
-            .toString();
+                .append("-")
+                .append(vmId)
+                .append("-")
+                .append(reservationId)
+                .append("-")
+                .append(ip4Address)
+                .append("-")
+                .append(broadcastUri)
+                .toString();
     }
 
     public String getIp6Gateway() {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/850bc9fa/api/src/org/apache/cloudstack/network/ExternalNetworkDeviceManager.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/network/ExternalNetworkDeviceManager.java b/api/src/org/apache/cloudstack/network/ExternalNetworkDeviceManager.java
index 32f13f8..e73f526 100644
--- a/api/src/org/apache/cloudstack/network/ExternalNetworkDeviceManager.java
+++ b/api/src/org/apache/cloudstack/network/ExternalNetworkDeviceManager.java
@@ -45,6 +45,7 @@ public interface ExternalNetworkDeviceManager extends Manager {
         public static final NetworkDevice PaloAltoFirewall = new NetworkDevice("PaloAltoFirewall", Network.Provider.PaloAlto.getName());
         public static final NetworkDevice NiciraNvp = new NetworkDevice("NiciraNvp", Network.Provider.NiciraNvp.getName());
         public static final NetworkDevice CiscoVnmc = new NetworkDevice("CiscoVnmc", Network.Provider.CiscoVnmc.getName());
+        public static final NetworkDevice OpenDaylightController = new NetworkDevice("OpenDaylightController", Network.Provider.Opendaylight.getName());
 
         public NetworkDevice(String deviceName, String ntwkServiceprovider) {
             _name = deviceName;

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/850bc9fa/client/pom.xml
----------------------------------------------------------------------
diff --git a/client/pom.xml b/client/pom.xml
index 33d3f1e..abbc25d 100644
--- a/client/pom.xml
+++ b/client/pom.xml
@@ -132,6 +132,11 @@
     </dependency>
     <dependency>
       <groupId>org.apache.cloudstack</groupId>
+      <artifactId>cloud-plugin-network-opendaylight</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.cloudstack</groupId>
       <artifactId>cloud-plugin-hypervisor-xen</artifactId>
       <version>${project.version}</version>
     </dependency>

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/850bc9fa/client/tomcatconf/commands.properties.in
----------------------------------------------------------------------
diff --git a/client/tomcatconf/commands.properties.in b/client/tomcatconf/commands.properties.in
index a05310b..9f74fdb 100644
--- a/client/tomcatconf/commands.properties.in
+++ b/client/tomcatconf/commands.properties.in
@@ -706,3 +706,6 @@ importLdapUsers=3
 
 #### juniper-contrail commands
 createServiceInstance=1
+
+### OpenDaylight plugin commands
+addOpenDaylightController=1

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/850bc9fa/setup/db/db/schema-430to440.sql
----------------------------------------------------------------------
diff --git a/setup/db/db/schema-430to440.sql b/setup/db/db/schema-430to440.sql
index 17b4c6d..37be831 100644
--- a/setup/db/db/schema-430to440.sql
+++ b/setup/db/db/schema-430to440.sql
@@ -224,4 +224,16 @@ CREATE TABLE `cloud`.`user_details` (
   `display` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'True if the detail can be displayed to the end user',
   PRIMARY KEY (`id`),
   CONSTRAINT `fk_user_details__user_id` FOREIGN KEY `fk_user_details__user_id`(`user_id`) REFERENCES `user`(`id`) ON DELETE CASCADE
-) ENGINE=InnoDB DEFAULT CHARSET=utf8;
\ No newline at end of file
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+CREATE TABLE `cloud`.`external_opendaylight_controllers` (
+  `id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
+  `uuid` varchar(255) UNIQUE,
+  `physical_network_id` bigint unsigned NOT NULL COMMENT 'id of the physical network in to which the device is added',
+  `provider_name` varchar(255) NOT NULL COMMENT 'Service Provider name corresponding to this device',
+  `device_name` varchar(255) NOT NULL COMMENT 'name of the device',
+  `host_id` bigint unsigned NOT NULL COMMENT 'host id corresponding to the external device',
+  PRIMARY KEY (`id`),
+  CONSTRAINT `fk_external_opendaylight_devices__host_id` FOREIGN KEY (`host_id`) REFERENCES `host`(`id`) ON DELETE CASCADE,
+  CONSTRAINT `fk_external_opendaylight_devices__physical_network_id` FOREIGN KEY (`physical_network_id`) REFERENCES `physical_network`(`id`) ON DELETE CASCADE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;


[09/11] git commit: updated refs/heads/master to 612a41e

Posted by hu...@apache.org.
Apply two small fixes to system.js


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

Branch: refs/heads/master
Commit: 57da2bc784f125f61af4020d8589c690b89f058a
Parents: 0ba1abe
Author: Hugo Trippaers <ht...@schubergphilis.com>
Authored: Wed Jan 8 16:08:04 2014 +0100
Committer: Hugo Trippaers <ht...@schubergphilis.com>
Committed: Wed Jan 8 16:08:04 2014 +0100

----------------------------------------------------------------------
 ui/scripts/system.js | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/57da2bc7/ui/scripts/system.js
----------------------------------------------------------------------
diff --git a/ui/scripts/system.js b/ui/scripts/system.js
index 5145dcb..59aab8b 100644
--- a/ui/scripts/system.js
+++ b/ui/scripts/system.js
@@ -6524,7 +6524,7 @@
                                 }
                             }
                         }
-                    },
+                    }
                 }
             }
         },
@@ -14491,7 +14491,8 @@
                                                 id: 'zone',
                                                 description: _l('label.zone.wide')
                                             }
-                                            // { id: 'host', description: _l('label.host') }];
+                                            // { id: 'host', description: _l('label.host') }
+                                            ];
                                             
                                             args.response.success({
                                                 data: scope


[11/11] git commit: updated refs/heads/master to 612a41e

Posted by hu...@apache.org.
Add UI interface for managing the OpenDaylight provider and controllers.

Fix several bugs in the code related to the api handling.

Conflicts:
	ui/scripts/system.js

ui


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

Branch: refs/heads/master
Commit: 612a41e3f5b7f57b205ea84503d670793fb44c4f
Parents: e4cb9ce
Author: Hugo Trippaers <ht...@schubergphilis.com>
Authored: Sat Jan 4 17:00:42 2014 +0100
Committer: Hugo Trippaers <ht...@schubergphilis.com>
Committed: Wed Jan 8 17:08:37 2014 +0100

----------------------------------------------------------------------
 .../classes/resources/messages.properties       |   5 +
 client/tomcatconf/commands.properties.in        |   2 +
 .../OpenDaylightControllerResourceManager.java  |   8 ++
 ...enDaylightControllerResourceManagerImpl.java |  41 ++++++++
 .../ListOpenDaylightControllersCmd.java         | 104 +++++++++++++++++++
 .../OpenDaylightControllerResponse.java         |  47 +++++++++
 .../dao/OpenDaylightControllerVO.java           |   3 +-
 ui/dictionary.jsp                               |   5 +
 ui/scripts/system.js                            |  39 ++++++-
 ui/scripts/ui-custom/zoneWizard.js              |   5 +-
 10 files changed, 254 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/612a41e3/client/WEB-INF/classes/resources/messages.properties
----------------------------------------------------------------------
diff --git a/client/WEB-INF/classes/resources/messages.properties b/client/WEB-INF/classes/resources/messages.properties
index f4e6dc1..f186fbf 100644
--- a/client/WEB-INF/classes/resources/messages.properties
+++ b/client/WEB-INF/classes/resources/messages.properties
@@ -1267,6 +1267,11 @@ label.zoneWizard.trafficType.management=Management\: Traffic between CloudStack\
 label.zoneWizard.trafficType.public=Public\: Traffic between the internet and virtual machines in the cloud.
 label.zoneWizard.trafficType.storage=Storage\: Traffic between primary and secondary storage servers, such as VM templates and snapshots
 label.ldap.group.name=LDAP Group
+label.openDaylight=OpenDaylight
+label.opendaylight.controllers=OpenDaylight Controllers
+label.opendaylight.controllerdetail=OpenDaylight Controller Details
+label.add.OpenDaylight.device=Add OpenDaylight Controller
+label.delete.OpenDaylight.device=Delete OpenDaylight Controller
 managed.state=Managed State
 message.acquire.new.ip.vpc=Please confirm that you would like to acquire a new IP for this VPC.
 message.acquire.new.ip=Please confirm that you would like to acquire a new IP for this network.

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/612a41e3/client/tomcatconf/commands.properties.in
----------------------------------------------------------------------
diff --git a/client/tomcatconf/commands.properties.in b/client/tomcatconf/commands.properties.in
index 9f74fdb..189d087 100644
--- a/client/tomcatconf/commands.properties.in
+++ b/client/tomcatconf/commands.properties.in
@@ -709,3 +709,5 @@ createServiceInstance=1
 
 ### OpenDaylight plugin commands
 addOpenDaylightController=1
+deleteOpenDaylightController=1
+listOpenDaylightControllers=1

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/612a41e3/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/OpenDaylightControllerResourceManager.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/OpenDaylightControllerResourceManager.java b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/OpenDaylightControllerResourceManager.java
index 1bc0e82..5f6161a 100644
--- a/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/OpenDaylightControllerResourceManager.java
+++ b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/OpenDaylightControllerResourceManager.java
@@ -19,8 +19,12 @@
 
 package org.apache.cloudstack.network.opendaylight.agent;
 
+import java.util.List;
+
 import org.apache.cloudstack.network.opendaylight.api.commands.AddOpenDaylightControllerCmd;
 import org.apache.cloudstack.network.opendaylight.api.commands.DeleteOpenDaylightControllerCmd;
+import org.apache.cloudstack.network.opendaylight.api.commands.ListOpenDaylightControllersCmd;
+import org.apache.cloudstack.network.opendaylight.api.responses.OpenDaylightControllerResponse;
 import org.apache.cloudstack.network.opendaylight.dao.OpenDaylightControllerVO;
 
 import com.cloud.exception.InvalidParameterValueException;
@@ -31,4 +35,8 @@ public interface OpenDaylightControllerResourceManager extends PluggableService
     public OpenDaylightControllerVO addController(AddOpenDaylightControllerCmd cmd);
 
     public void deleteController(DeleteOpenDaylightControllerCmd cmd) throws InvalidParameterValueException;
+
+    public List<OpenDaylightControllerVO> listControllers(ListOpenDaylightControllersCmd cmd);
+
+    public OpenDaylightControllerResponse createResponseFromVO(OpenDaylightControllerVO controller);
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/612a41e3/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/OpenDaylightControllerResourceManagerImpl.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/OpenDaylightControllerResourceManagerImpl.java b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/OpenDaylightControllerResourceManagerImpl.java
index ad4db15..f4da02b 100644
--- a/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/OpenDaylightControllerResourceManagerImpl.java
+++ b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/OpenDaylightControllerResourceManagerImpl.java
@@ -33,15 +33,19 @@ import org.apache.log4j.Logger;
 import org.apache.cloudstack.network.ExternalNetworkDeviceManager.NetworkDevice;
 import org.apache.cloudstack.network.opendaylight.api.commands.AddOpenDaylightControllerCmd;
 import org.apache.cloudstack.network.opendaylight.api.commands.DeleteOpenDaylightControllerCmd;
+import org.apache.cloudstack.network.opendaylight.api.commands.ListOpenDaylightControllersCmd;
+import org.apache.cloudstack.network.opendaylight.api.responses.OpenDaylightControllerResponse;
 import org.apache.cloudstack.network.opendaylight.dao.OpenDaylightControllerMappingDao;
 import org.apache.cloudstack.network.opendaylight.dao.OpenDaylightControllerVO;
 
+import com.cloud.api.ApiDBUtils;
 import com.cloud.exception.InvalidParameterValueException;
 import com.cloud.host.Host;
 import com.cloud.host.HostVO;
 import com.cloud.host.dao.HostDao;
 import com.cloud.network.Network;
 import com.cloud.network.Networks;
+import com.cloud.network.PhysicalNetwork;
 import com.cloud.network.PhysicalNetworkServiceProvider;
 import com.cloud.network.dao.NetworkDao;
 import com.cloud.network.dao.NetworkVO;
@@ -77,6 +81,8 @@ public class OpenDaylightControllerResourceManagerImpl implements OpenDaylightCo
     public List<Class<?>> getCommands() {
         List<Class<?>> commands = new ArrayList<Class<?>>();
         commands.add(AddOpenDaylightControllerCmd.class);
+        commands.add(DeleteOpenDaylightControllerCmd.class);
+        commands.add(ListOpenDaylightControllersCmd.class);
         return commands;
     }
 
@@ -170,4 +176,39 @@ public class OpenDaylightControllerResourceManagerImpl implements OpenDaylightCo
         openDaylightControllerMappingDao.remove(cmd.getId());
     }
 
+    @Override
+    public List<OpenDaylightControllerVO> listControllers(ListOpenDaylightControllersCmd cmd) {
+        if (cmd.getId() != null) {
+            List<OpenDaylightControllerVO> foundControllers = new ArrayList<OpenDaylightControllerVO>();
+            OpenDaylightControllerVO controller = openDaylightControllerMappingDao.findById(cmd.getId());
+            if (controller != null) {
+                foundControllers.add(controller);
+            }
+            return foundControllers;
+        } else if (cmd.getPhysicalNetworkId() != null) {
+            return openDaylightControllerMappingDao.listByPhysicalNetwork(cmd.getPhysicalNetworkId());
+        }
+        return openDaylightControllerMappingDao.listAll();
+    }
+
+    @Override
+    public OpenDaylightControllerResponse createResponseFromVO(OpenDaylightControllerVO controller) {
+        OpenDaylightControllerResponse response = new OpenDaylightControllerResponse();
+        HostVO controllerHost = hostDao.findById(controller.getHostId());
+        hostDao.loadDetails(controllerHost);
+
+        PhysicalNetwork pnw = ApiDBUtils.findPhysicalNetworkById(controller.getPhysicalNetworkId());
+        if (pnw != null) {
+            response.setPhysicalNetworkId(pnw.getUuid());
+        }
+
+        response.setObjectName("opendaylightcontroller");
+        response.setId(controller.getUuid());
+        response.setUrl(controllerHost.getDetail("url"));
+        response.setName(controllerHost.getDetail("name"));
+        response.setUsername(controllerHost.getDetail("username"));
+
+        return response;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/612a41e3/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/commands/ListOpenDaylightControllersCmd.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/commands/ListOpenDaylightControllersCmd.java b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/commands/ListOpenDaylightControllersCmd.java
new file mode 100644
index 0000000..11f196b
--- /dev/null
+++ b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/api/commands/ListOpenDaylightControllersCmd.java
@@ -0,0 +1,104 @@
+//
+// 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 java.util.ArrayList;
+import java.util.List;
+
+import javax.inject.Inject;
+
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.ListResponse;
+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 org.apache.cloudstack.network.opendaylight.dao.OpenDaylightControllerVO;
+
+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 = "listOpenDaylightControllers", responseObject = OpenDaylightControllerResponse.class, description = "Lists OpenDyalight controllers")
+public class ListOpenDaylightControllersCmd extends BaseCmd {
+    @Inject
+    private OpenDaylightControllerResourceManager resourceManager;
+
+    /////////////////////////////////////////////////////
+    //////////////// API parameters /////////////////////
+    /////////////////////////////////////////////////////
+
+    @Parameter(name = ApiConstants.PHYSICAL_NETWORK_ID, type = CommandType.UUID, entityType = PhysicalNetworkResponse.class, required = false,
+            description = "the Physical Network ID")
+    private Long physicalNetworkId;
+
+    @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = OpenDaylightControllerResponse.class, required = false,
+            description = "the ID of a OpenDaylight Controller")
+    private Long Id;
+
+    /////////////////////////////////////////////////////
+    /////////////////// Accessors ///////////////////////
+    /////////////////////////////////////////////////////
+
+    @Override
+    public String getCommandName() {
+        return "listOpenDaylightControllers";
+    }
+
+    @Override
+    public long getEntityOwnerId() {
+        return CallContext.current().getCallingAccount().getId();
+    }
+
+    public Long getPhysicalNetworkId() {
+        return physicalNetworkId;
+    }
+
+    public Long getId() {
+        return Id;
+    }
+
+    /////////////////////////////////////////////////////
+    /////////////// API Implementation///////////////////
+    /////////////////////////////////////////////////////
+
+    @Override
+    public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException,
+    NetworkRuleConflictException {
+        List<OpenDaylightControllerVO> controllers = resourceManager.listControllers(this);
+
+        List<OpenDaylightControllerResponse> controllerList = new ArrayList<OpenDaylightControllerResponse>();
+        for (OpenDaylightControllerVO controller: controllers) {
+            OpenDaylightControllerResponse responseObject = resourceManager.createResponseFromVO(controller);
+            controllerList.add(responseObject);
+        }
+        ListResponse<OpenDaylightControllerResponse> responseList = new ListResponse<OpenDaylightControllerResponse>();
+        responseList.setResponseName(getCommandName());
+        responseList.setResponses(controllerList);
+        setResponseObject(responseList);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/612a41e3/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
index 98c644a..10c6f28 100644
--- 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
@@ -19,8 +19,55 @@
 
 package org.apache.cloudstack.network.opendaylight.api.responses;
 
+import com.google.gson.annotations.SerializedName;
+
+import org.apache.cloudstack.api.ApiConstants;
 import org.apache.cloudstack.api.BaseResponse;
+import org.apache.cloudstack.api.EntityReference;
+import org.apache.cloudstack.network.opendaylight.dao.OpenDaylightControllerVO;
+
+import com.cloud.serializer.Param;
 
+@EntityReference(value = OpenDaylightControllerVO.class)
 public class OpenDaylightControllerResponse extends BaseResponse {
+    @SerializedName(ApiConstants.ID)
+    @Param(description = "device id of the controller")
+    private String id;
+
+    @SerializedName(ApiConstants.PHYSICAL_NETWORK_ID)
+    @Param(description = "the physical network to which this controller belongs to")
+    private String physicalNetworkId;
+
+    @SerializedName(ApiConstants.NAME)
+    @Param(description = "the name assigned to the controller")
+    private String name;
+
+    @SerializedName(ApiConstants.URL)
+    @Param(description = "the url of the controller api")
+    private String url;
+
+    @SerializedName(ApiConstants.USERNAME)
+    @Param(description = "the username to authenticate to the controller")
+    private String username;
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public void setPhysicalNetworkId(String physicalNetworkId) {
+        this.physicalNetworkId = physicalNetworkId;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public void setUrl(String url) {
+        this.url = url;
+    }
+
+    public void setUsername(String username) {
+        this.username = username;
+    }
 
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/612a41e3/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/dao/OpenDaylightControllerVO.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/dao/OpenDaylightControllerVO.java b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/dao/OpenDaylightControllerVO.java
index 61d5682..b50cfda 100644
--- a/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/dao/OpenDaylightControllerVO.java
+++ b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/dao/OpenDaylightControllerVO.java
@@ -70,8 +70,7 @@ public class OpenDaylightControllerVO implements InternalIdentity {
 
     @Override
     public long getId() {
-        // TODO Auto-generated method stub
-        return 0;
+        return id;
     }
 
     public String getUuid() {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/612a41e3/ui/dictionary.jsp
----------------------------------------------------------------------
diff --git a/ui/dictionary.jsp b/ui/dictionary.jsp
index 8490f1b..16ecbab 100644
--- a/ui/dictionary.jsp
+++ b/ui/dictionary.jsp
@@ -1236,6 +1236,11 @@ dictionary = {
 'label.zone.step.4.title': '<fmt:message key="label.zone.step.4.title" />',
 'label.zone.wide': '<fmt:message key="label.zone.wide" />',
 'label.ldap.group.name': '<fmt:message key="label.ldap.group.name" />',
+'label.openDaylight': '<fmt:message key="OpenDaylight" />',
+'label.opendaylight.controllers': '<fmt:message key="OpenDaylight Controllers" />',
+'label.opendaylight.controllerdetail': '<fmt:message key="OpenDaylight Controller Details" />',
+'label.add.OpenDaylight.device': '<fmt:message key="Add OpenDaylight Controller" />',
+'label.delete.OpenDaylight.device': '<fmt:message key="Delete OpenDaylight Controller" />',
 'managed.state': '<fmt:message key="managed.state" />',
 'message.acquire.new.ip': '<fmt:message key="message.acquire.new.ip" />',
 'message.acquire.new.ip.vpc': '<fmt:message key="message.acquire.new.ip.vpc" />',

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/612a41e3/ui/scripts/system.js
----------------------------------------------------------------------
diff --git a/ui/scripts/system.js b/ui/scripts/system.js
index b06cb57..81c78d5 100644
--- a/ui/scripts/system.js
+++ b/ui/scripts/system.js
@@ -6619,7 +6619,7 @@
                                         },
                                         actions: {
                                             destroy: {
-                                                label: 'label.destroy.controller',
+                                                label: 'label.delete.OpenDaylight.device',
                                                 action: function (args) {
                                                     $.ajax({
                                                         url: createURL("deleteOpenDaylightController&id=" + args.data.id),
@@ -18105,6 +18105,33 @@
         });
     }
     
+    function addOpenDaylightController(args, physicalNetworkObj, apiCmd, apiCmdRes, apiCmdObj) {
+        var array1 =[];
+        array1.push("&physicalnetworkid=" + physicalNetworkObj.id);
+        array1.push("&username=" + todb(args.data.username));
+        array1.push("&password=" + todb(args.data.password));
+        array1.push("&url=" + todb(args.data.url));
+        
+        $.ajax({
+            url: createURL(apiCmd + array1.join("")),
+            dataType: "json",
+            type: "POST",
+            success: function (json) {
+                var jid = json[apiCmdRes].jobid;
+                args.response.success({
+                    _custom: {
+                        jobId: jid,
+                        getUpdatedItem: function (json) {
+                            var item = json.queryasyncjobresultresponse.jobresult[apiCmdObj];
+                            
+                            return item;
+                        }
+                    }
+                });
+            }
+        });
+    }
+    
     function addBigSwitchVnsDevice(args, physicalNetworkObj, apiCmd, apiCmdRes, apiCmdObj) {
         var array1 =[];
         array1.push("&physicalnetworkid=" + physicalNetworkObj.id);
@@ -18804,6 +18831,9 @@
                             case "Ovs":
                             nspMap[ "Ovs"] = items[i];
                             break;
+                            case "Opendaylight":
+                            nspMap[ "Opendaylight"] = items[i];
+                            break;
                         }
                     }
                 }
@@ -18844,6 +18874,11 @@
             id: 'Ovs',
             name: 'Ovs',
             state: nspMap.Ovs ? nspMap.Ovs.state: 'Disabled'
+        },
+        {
+            id: 'Opendaylight',
+            name: 'OpenDaylight (Experimental)',
+            state: nspMap.Opendaylight ? nspMap.Opendaylight.state: 'Disabled'
         }];
         
         $(window).trigger('cloudStack.system.serviceProviders.makeHarcodedArray', {
@@ -19011,4 +19046,4 @@
             }
         });
     }
-})($, cloudStack);
\ No newline at end of file
+})($, cloudStack);

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/612a41e3/ui/scripts/ui-custom/zoneWizard.js
----------------------------------------------------------------------
diff --git a/ui/scripts/ui-custom/zoneWizard.js b/ui/scripts/ui-custom/zoneWizard.js
index 28df193..99aa3b9 100644
--- a/ui/scripts/ui-custom/zoneWizard.js
+++ b/ui/scripts/ui-custom/zoneWizard.js
@@ -720,7 +720,10 @@
                             }).html('SSP'),
                             $('<option>').attr({
                                 value: 'VXLAN'
-                            }).html('VXLAN')
+                            }).html('VXLAN'),
+                            $('<option>').attr({
+                                value: 'ODL'
+                            }).html('ODL')
                         )
                     )
                 );


[07/11] Apply some formatting to system.js

Posted by hu...@apache.org.
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/0ba1abe2/ui/scripts/system.js
----------------------------------------------------------------------
diff --git a/ui/scripts/system.js b/ui/scripts/system.js
index 403fce0..5145dcb 100644
--- a/ui/scripts/system.js
+++ b/ui/scripts/system.js
@@ -15,30 +15,33 @@
 // specific language governing permissions and limitations
 // under the License.
 
-(function($, cloudStack) {
-
+(function ($, cloudStack) {
+    
     var zoneObjs, podObjs, clusterObjs, domainObjs, networkOfferingObjs, physicalNetworkObjs;
     var selectedClusterObj, selectedZoneObj, selectedPublicNetworkObj, selectedManagementNetworkObj, selectedPhysicalNetworkObj, selectedGuestNetworkObj;
-    var nspMap = {}; //from listNetworkServiceProviders API
-    var nspHardcodingArray = []; //for service providers listView (hardcoding, not from listNetworkServiceProviders API)
-
+    var nspMap = {
+    };
+    //from listNetworkServiceProviders API
+    var nspHardcodingArray =[]; //for service providers listView (hardcoding, not from listNetworkServiceProviders API)
+    
     // Add router type to virtual router
     // -- can be either Project, VPC, or System (standard)
-    var mapRouterType = function(index, router) {
+    var mapRouterType = function (index, router) {
         var routerType = _l('label.menu.system');
-
+        
         if (router.projectid) routerType = _l('label.project');
         if (router.vpcid) routerType = 'VPC';
-
+        
         return $.extend(router, {
             routerType: routerType
         });
     };
-
+    
     cloudStack.publicIpRangeAccount = {
-        dialog: function(args) {
-            return function(args) {
-                var data = args.data ? args.data : {};
+        dialog: function (args) {
+            return function (args) {
+                var data = args.data ? args.data: {
+                };
                 var fields = {
                     account: {
                         label: 'Account',
@@ -47,15 +50,15 @@
                     domainid: {
                         label: 'Domain',
                         defaultValue: data.domainid,
-                        select: function(args) {
+                        select: function (args) {
                             $.ajax({
                                 url: createURL('listDomains'),
                                 data: {
                                     listAll: true
                                 },
-                                success: function(json) {
+                                success: function (json) {
                                     args.response.success({
-                                        data: $.map(json.listdomainsresponse.domain, function(domain) {
+                                        data: $.map(json.listdomainsresponse.domain, function (domain) {
                                             return {
                                                 id: domain.id,
                                                 description: domain.path
@@ -68,17 +71,18 @@
                     }
                 };
                 var success = args.response.success;
-
-                if (args.$item) { // Account data is read-only after creation
+                
+                if (args.$item) {
+                    // Account data is read-only after creation
                     $.ajax({
                         url: createURL('listDomains'),
                         data: {
                             id: data.domainid,
                             listAll: true
                         },
-                        success: function(json) {
+                        success: function (json) {
                             var domain = json.listdomainsresponse.domain[0];
-
+                            
                             cloudStack.dialog.notice({
                                 message: '<ul><li>' + _l('label.account') + ': ' + data.account + '</li>' + '<li>' + _l('label.domain') + ': ' + domain.path + '</li></ul>'
                             });
@@ -91,9 +95,9 @@
                             desc: '(optional) Please specify an account to be associated with this IP range.',
                             fields: fields
                         },
-                        after: function(args) {
+                        after: function (args) {
                             var data = cloudStack.serializeForm(args.$form);
-
+                            
                             success({
                                 data: data
                             });
@@ -103,155 +107,158 @@
             };
         }
     };
-
-    var getTrafficType = function(physicalNetwork, typeID) {
-        var trafficType = {};
-
+    
+    var getTrafficType = function (physicalNetwork, typeID) {
+        var trafficType = {
+        };
+        
         $.ajax({
             url: createURL('listTrafficTypes'),
             data: {
                 physicalnetworkid: physicalNetwork.id
             },
             async: false,
-            success: function(json) {
+            success: function (json) {
                 trafficType = $.grep(
-                    json.listtraffictypesresponse.traffictype,
-                    function(trafficType) {
-                        return trafficType.traffictype == typeID;
-                    }
-                )[0];
+                json.listtraffictypesresponse.traffictype,
+                function (trafficType) {
+                    return trafficType.traffictype == typeID;
+                })[0];
             }
         });
-
+        
         if (trafficType.xennetworklabel == null || trafficType.xennetworklabel == 0)
-            trafficType.xennetworklabel = dictionary['label.network.label.display.for.blank.value'];
+        trafficType.xennetworklabel = dictionary[ 'label.network.label.display.for.blank.value'];
         if (trafficType.kvmnetworklabel == null || trafficType.kvmnetworklabel == 0)
-            trafficType.kvmnetworklabel = dictionary['label.network.label.display.for.blank.value'];
+        trafficType.kvmnetworklabel = dictionary[ 'label.network.label.display.for.blank.value'];
         if (trafficType.vmwarenetworklabel == null || trafficType.vmwarenetworklabel == 0)
-            trafficType.vmwarenetworklabel = dictionary['label.network.label.display.for.blank.value'];
+        trafficType.vmwarenetworklabel = dictionary[ 'label.network.label.display.for.blank.value'];
         if (trafficType.ovmnetworklabel == null || trafficType.ovmnetworklabel == 0)
-            trafficType.ovmnetworklabel = dictionary['label.network.label.display.for.blank.value'];
+        trafficType.ovmnetworklabel = dictionary[ 'label.network.label.display.for.blank.value'];
         if (trafficType.lxcnetworklabel == null || trafficType.lxcnetworklabel == 0)
-            trafficType.lxcnetworklabel = dictionary['label.network.label.display.for.blank.value'];
+        trafficType.lxcnetworklabel = dictionary[ 'label.network.label.display.for.blank.value'];
         if (trafficType.hypervnetworklabel == null || trafficType.hypervnetworklabel == 0)
-            trafficType.hypervnetworklabel = dictionary['label.network.label.display.for.blank.value'];
-                
+        trafficType.hypervnetworklabel = dictionary[ 'label.network.label.display.for.blank.value'];
+        
         return trafficType;
     };
-
-    var updateTrafficLabels = function(trafficType, labels, complete) {
-        var array1 = [];
-        if (labels.xennetworklabel != dictionary['label.network.label.display.for.blank.value'])
-            array1.push("&xennetworklabel=" + labels.xennetworklabel);
-        if (labels.kvmnetworklabel != dictionary['label.network.label.display.for.blank.value'])
-            array1.push("&kvmnetworklabel=" + labels.kvmnetworklabel);
-        if (labels.vmwarenetworklabel != dictionary['label.network.label.display.for.blank.value'])
-            array1.push("&vmwarenetworklabel=" + labels.vmwarenetworklabel);
-        if (labels.ovmnetworklabel != dictionary['label.network.label.display.for.blank.value'])
-            array1.push("&ovmnetworklabel=" + labels.ovmnetworklabel);
-        if (labels.lxcnetworklabel != dictionary['label.network.label.display.for.blank.value'])
-            array1.push("&lxcnetworklabel=" + labels.lxcnetworklabel);
-        if (labels.hypervnetworklabel != dictionary['label.network.label.display.for.blank.value'])
-            array1.push("&hypervnetworklabel=" + labels.hypervnetworklabel);        
+    
+    var updateTrafficLabels = function (trafficType, labels, complete) {
+        var array1 =[];
+        if (labels.xennetworklabel != dictionary[ 'label.network.label.display.for.blank.value'])
+        array1.push("&xennetworklabel=" + labels.xennetworklabel);
+        if (labels.kvmnetworklabel != dictionary[ 'label.network.label.display.for.blank.value'])
+        array1.push("&kvmnetworklabel=" + labels.kvmnetworklabel);
+        if (labels.vmwarenetworklabel != dictionary[ 'label.network.label.display.for.blank.value'])
+        array1.push("&vmwarenetworklabel=" + labels.vmwarenetworklabel);
+        if (labels.ovmnetworklabel != dictionary[ 'label.network.label.display.for.blank.value'])
+        array1.push("&ovmnetworklabel=" + labels.ovmnetworklabel);
+        if (labels.lxcnetworklabel != dictionary[ 'label.network.label.display.for.blank.value'])
+        array1.push("&lxcnetworklabel=" + labels.lxcnetworklabel);
+        if (labels.hypervnetworklabel != dictionary[ 'label.network.label.display.for.blank.value'])
+        array1.push("&hypervnetworklabel=" + labels.hypervnetworklabel);
         
         $.ajax({
             url: createURL('updateTrafficType' + array1.join("")),
             data: {
                 id: trafficType.id
             },
-            success: function(json) {
+            success: function (json) {
                 var jobID = json.updatetraffictyperesponse.jobid;
-
+                
                 cloudStack.ui.notifications.add({
-                        desc: 'Update traffic labels',
-                        poll: pollAsyncJobResult,
-                        section: 'System',
-                        _custom: {
-                            jobId: jobID
-                        }
-                    },
-                    complete ? complete : function() {}, {},
-                    function(data) {
-                        // Error
-                        cloudStack.dialog.notice({
-                            message: parseXMLHttpResponse(data)
-                        });
-                    }, {}
-                );
+                    desc: 'Update traffic labels',
+                    poll: pollAsyncJobResult,
+                    section: 'System',
+                    _custom: {
+                        jobId: jobID
+                    }
+                },
+                complete ? complete: function () {
+                },
+                {
+                },
+                function (data) {
+                    // Error
+                    cloudStack.dialog.notice({
+                        message: parseXMLHttpResponse(data)
+                    });
+                },
+                {
+                });
             }
         })
     };
-
+    
     function virtualRouterProviderActionFilter(args) {
-        var allowedActions = [];
+        var allowedActions =[];
         var jsonObj = args.context.item; //args.context.item == nspMap["virtualRouter"]
         if (jsonObj.state == "Enabled")
-            allowedActions.push("disable");
-        else if (jsonObj.state == "Disabled")
-            allowedActions.push("enable");
+        allowedActions.push("disable"); else if (jsonObj.state == "Disabled")
+        allowedActions.push("enable");
         return allowedActions;
     };
-
+    
     cloudStack.sections.system = {
         title: 'label.menu.infrastructure',
         id: 'system',
-
+        
         // System dashboard
         dashboard: {
-            dataProvider: function(args) {
+            dataProvider: function (args) {
                 var dataFns = {
-                    zoneCount: function(data) {
+                    zoneCount: function (data) {
                         $.ajax({
                             url: createURL('listZones'),
-                            success: function(json) {
+                            success: function (json) {
                                 dataFns.podCount($.extend(data, {
-                                    zoneCount: json.listzonesresponse.count ? json.listzonesresponse.count : 0,
+                                    zoneCount: json.listzonesresponse.count ? json.listzonesresponse.count: 0,
                                     zones: json.listzonesresponse.zone
                                 }));
                             }
                         });
                     },
-
-                    podCount: function(data) {
+                    
+                    podCount: function (data) {
                         $.ajax({
                             url: createURL('listPods'),
                             data: {
                                 page: 1,
                                 pagesize: 1 //specifying pagesize as 1 because we don't need any embedded objects to be returned here. The only thing we need from API response is "count" property.
                             },
-                            success: function(json) {
+                            success: function (json) {
                                 dataFns.clusterCount($.extend(data, {
-                                    podCount: json.listpodsresponse.count ? json.listpodsresponse.count : 0
+                                    podCount: json.listpodsresponse.count ? json.listpodsresponse.count: 0
                                 }));
                             }
                         });
                     },
-
-                    clusterCount: function(data) {
+                    
+                    clusterCount: function (data) {
                         $.ajax({
                             url: createURL('listClusters'),
                             data: {
                                 page: 1,
                                 pagesize: 1 //specifying pagesize as 1 because we don't need any embedded objects to be returned here. The only thing we need from API response is "count" property.
                             },
-                            success: function(json) {
+                            success: function (json) {
                                 dataFns.hostCount($.extend(data, {
-                                    clusterCount: json.listclustersresponse.count ? json.listclustersresponse.count : 0
+                                    clusterCount: json.listclustersresponse.count ? json.listclustersresponse.count: 0
                                 }));
-
+                                
                                 //comment the 4 lines above and uncomment the following 4 lines if listHosts API still responds slowly.
-
+                                
                                 /*
-                dataFns.primaryStorageCount($.extend(data, {
-                  clusterCount: json.listclustersresponse.count ?
-                    json.listclustersresponse.count : 0
-                }));
-                */
+                                dataFns.primaryStorageCount($.extend(data, {
+                                clusterCount: json.listclustersresponse.count ?
+                                json.listclustersresponse.count : 0
+                                }));
+                                 */
                             }
                         });
                     },
-
-                    hostCount: function(data) {
+                    
+                    hostCount: function (data) {
                         var data2 = {
                             type: 'routing',
                             page: 1,
@@ -260,15 +267,15 @@
                         $.ajax({
                             url: createURL('listHosts'),
                             data: data2,
-                            success: function(json) {
+                            success: function (json) {
                                 dataFns.primaryStorageCount($.extend(data, {
-                                    hostCount: json.listhostsresponse.count ? json.listhostsresponse.count : 0
+                                    hostCount: json.listhostsresponse.count ? json.listhostsresponse.count: 0
                                 }));
                             }
                         });
                     },
-
-                    primaryStorageCount: function(data) {
+                    
+                    primaryStorageCount: function (data) {
                         var data2 = {
                             page: 1,
                             pagesize: 1 //specifying pagesize as 1 because we don't need any embedded objects to be returned here. The only thing we need from API response is "count" property.
@@ -276,15 +283,15 @@
                         $.ajax({
                             url: createURL('listStoragePools'),
                             data: data2,
-                            success: function(json) {
+                            success: function (json) {
                                 dataFns.secondaryStorageCount($.extend(data, {
-                                    primaryStorageCount: json.liststoragepoolsresponse.count ? json.liststoragepoolsresponse.count : 0
+                                    primaryStorageCount: json.liststoragepoolsresponse.count ? json.liststoragepoolsresponse.count: 0
                                 }));
                             }
                         });
                     },
-
-                    secondaryStorageCount: function(data) {
+                    
+                    secondaryStorageCount: function (data) {
                         var data2 = {
                             type: 'SecondaryStorage',
                             page: 1,
@@ -293,30 +300,30 @@
                         $.ajax({
                             url: createURL('listImageStores'),
                             data: data2,
-                            success: function(json) {
+                            success: function (json) {
                                 dataFns.systemVmCount($.extend(data, {
-                                    secondaryStorageCount: json.listimagestoresresponse.imagestore ? json.listimagestoresresponse.count : 0
+                                    secondaryStorageCount: json.listimagestoresresponse.imagestore ? json.listimagestoresresponse.count: 0
                                 }));
                             }
                         });
                     },
-
-                    systemVmCount: function(data) {
+                    
+                    systemVmCount: function (data) {
                         $.ajax({
                             url: createURL('listSystemVms'),
                             data: {
                                 page: 1,
                                 pagesize: 1 //specifying pagesize as 1 because we don't need any embedded objects to be returned here. The only thing we need from API response is "count" property.
                             },
-                            success: function(json) {
+                            success: function (json) {
                                 dataFns.virtualRouterCount($.extend(data, {
-                                    systemVmCount: json.listsystemvmsresponse.count ? json.listsystemvmsresponse.count : 0
+                                    systemVmCount: json.listsystemvmsresponse.count ? json.listsystemvmsresponse.count: 0
                                 }));
                             }
                         });
                     },
-
-                    virtualRouterCount: function(data) {
+                    
+                    virtualRouterCount: function (data) {
                         var data2 = {
                             projectid: -1,
                             page: 1,
@@ -325,9 +332,9 @@
                         $.ajax({
                             url: createURL('listRouters'),
                             data: data2,
-                            success: function(json) {
-                                var total1 = json.listroutersresponse.count ? json.listroutersresponse.count : 0;
-
+                            success: function (json) {
+                                var total1 = json.listroutersresponse.count ? json.listroutersresponse.count: 0;
+                                
                                 var data3 = {
                                     listAll: true,
                                     page: 1,
@@ -336,8 +343,8 @@
                                 $.ajax({
                                     url: createURL('listRouters'),
                                     data: data3,
-                                    success: function(json) {
-                                        var total2 = json.listroutersresponse.count ? json.listroutersresponse.count : 0;
+                                    success: function (json) {
+                                        var total2 = json.listroutersresponse.count ? json.listroutersresponse.count: 0;
                                         dataFns.capacity($.extend(data, {
                                             virtualRouterCount: (total1 + total2)
                                         }));
@@ -346,28 +353,28 @@
                             }
                         });
                     },
-
-                    capacity: function(data) {
+                    
+                    capacity: function (data) {
                         if (data.zoneCount) {
                             $.ajax({
                                 url: createURL('listCapacity'),
-                                success: function(json) {
+                                success: function (json) {
                                     var capacities = json.listcapacityresponse.capacity;
-
-                                    var capacityTotal = function(id, converter) {
-                                        var capacity = $.grep(capacities, function(capacity) {
+                                    
+                                    var capacityTotal = function (id, converter) {
+                                        var capacity = $.grep(capacities, function (capacity) {
                                             return capacity.type == id;
                                         })[0];
-
-                                        var total = capacity ? capacity.capacitytotal : 0;
-
+                                        
+                                        var total = capacity ? capacity.capacitytotal: 0;
+                                        
                                         if (converter) {
                                             return converter(total);
                                         }
-
+                                        
                                         return total;
                                     };
-
+                                    
                                     dataFns.socketInfo($.extend(data, {
                                         cpuCapacityTotal: capacityTotal(1, cloudStack.converters.convertHz),
                                         memCapacityTotal: capacityTotal(0, cloudStack.converters.convertBytes),
@@ -383,106 +390,108 @@
                             }));
                         }
                     },
-
-                    socketInfo: function(data) {                    	
-                    	var socketCount = 0;                    	
-                    	$.ajax({
+                    
+                    socketInfo: function (data) {
+                        var socketCount = 0;
+                        $.ajax({
                             url: createURL('listHypervisors'),
                             async: false,
-                            success: function(json) {
+                            success: function (json) {
                                 args.response.success({
-                                    data: $(json.listhypervisorsresponse.hypervisor).map(function(index, hypervisor) {                                              	
-                                    	var totalHostCount = 0;                                                	
-                                    	var currentPage = 1;
-                                    	var returnedHostCount = 0;
-                                    	var returnedHostCpusocketsSum = 0;
-                                    	                                              	
-                                    	var callListHostsWithPage = function(setTotalHostCount) {                                                		
-                                    		$.ajax({
-                            					url: createURL('listHosts'),
-                                        		async: false,
-                                        		data: {
-                                        			type: 'routing',
-                                        			hypervisor: hypervisor.name,
-                                        			page: currentPage,
-                                        	        pagesize: pageSize //global variable
-                                        		},
-                                        		success: function(json) {                                          			
-                                        			if (json.listhostsresponse.count == undefined) {                                        				
-                                        				return;
-                                        			}
-                                        			                                        			
-                                        			if (setTotalHostCount) {
-                                        				totalHostCount = json.listhostsresponse.count;
-                                        			}                                                    			
-                                        			returnedHostCount += json.listhostsresponse.host.length;
-                                        			                                                    			
-                                        			var items = json.listhostsresponse.host;
-                                        			for (var i = 0; i < items.length; i++) {
-                                        				if (items[i].cpusockets != undefined && isNaN(items[i].cpusockets) == false) {
-                                        					returnedHostCpusocketsSum += items[i].cpusockets;
-                                        				} 
-                                        			}  
-                                        			
-                                        			if (returnedHostCount < totalHostCount) {
-                                        				currentPage++;
-                                        				callListHostsWithPage(false);
-                                        			}                                                    			
-                                        		}
-                            				});                                                		
-                                    	}
-                                    	
-                                    	callListHostsWithPage(true);
-                                    	                                    	
-                                    	socketCount += returnedHostCpusocketsSum;                                    	                                    	
+                                    data: $(json.listhypervisorsresponse.hypervisor).map(function (index, hypervisor) {
+                                        var totalHostCount = 0;
+                                        var currentPage = 1;
+                                        var returnedHostCount = 0;
+                                        var returnedHostCpusocketsSum = 0;
+                                        
+                                        var callListHostsWithPage = function (setTotalHostCount) {
+                                            $.ajax({
+                                                url: createURL('listHosts'),
+                                                async: false,
+                                                data: {
+                                                    type: 'routing',
+                                                    hypervisor: hypervisor.name,
+                                                    page: currentPage,
+                                                    pagesize: pageSize //global variable
+                                                },
+                                                success: function (json) {
+                                                    if (json.listhostsresponse.count == undefined) {
+                                                        return;
+                                                    }
+                                                    
+                                                    if (setTotalHostCount) {
+                                                        totalHostCount = json.listhostsresponse.count;
+                                                    }
+                                                    returnedHostCount += json.listhostsresponse.host.length;
+                                                    
+                                                    var items = json.listhostsresponse.host;
+                                                    for (var i = 0; i < items.length; i++) {
+                                                        if (items[i].cpusockets != undefined && isNaN(items[i].cpusockets) == false) {
+                                                            returnedHostCpusocketsSum += items[i].cpusockets;
+                                                        }
+                                                    }
+                                                    
+                                                    if (returnedHostCount < totalHostCount) {
+                                                        currentPage++;
+                                                        callListHostsWithPage(false);
+                                                    }
+                                                }
+                                            });
+                                        }
+                                        
+                                        callListHostsWithPage(true);
+                                        
+                                        socketCount += returnedHostCpusocketsSum;
                                     })
                                 });
                             }
                         });
-                    	
+                        
                         complete($.extend(data, {
                             socketCount: socketCount
                         }));
                     }
                 };
-
-                var complete = function(data) {
+                
+                var complete = function (data) {
                     args.response.success({
                         data: data
                     });
                 };
-
-                dataFns.zoneCount({});
+                
+                dataFns.zoneCount({
+                });
             }
         },
-
-        zoneDashboard: function(args) {
+        
+        zoneDashboard: function (args) {
             $.ajax({
                 url: createURL('listCapacity'),
                 data: {
                     zoneid: args.context.zones[0].id
                 },
-                success: function(json) {
+                success: function (json) {
                     var capacities = json.listcapacityresponse.capacity;
-                    var data = {};
-
-                    $(capacities).each(function() {
+                    var data = {
+                    };
+                    
+                    $(capacities).each(function () {
                         var capacity = this;
-
+                        
                         data[capacity.type] = {
                             used: cloudStack.converters.convertByType(capacity.type, capacity.capacityused),
                             total: cloudStack.converters.convertByType(capacity.type, capacity.capacitytotal),
                             percent: parseInt(capacity.percentused)
                         };
                     });
-
+                    
                     args.response.success({
                         data: data
                     });
                 }
             });
         },
-
+        
         // Network-as-a-service configuration
         naas: {
             providerListView: {
@@ -493,7 +502,7 @@
                     },
                     state: {
                         label: 'label.state',
-                        converter: function(str) {
+                        converter: function (str) {
                             // For localization
                             return str;
                         },
@@ -503,17 +512,16 @@
                         }
                     }
                 },
-                dataProvider: function(args) {
+                dataProvider: function (args) {
                     refreshNspData();
                     args.response.success({
                         data: nspHardcodingArray
                     })
                 },
-
-                detailView: function(args) {
+                
+                detailView: function (args) {
                     return cloudStack.sections.system.naas.networkProviders.types[
-                        args.context.networkProviders[0].id
-                    ];
+                    args.context.networkProviders[0].id];
                 }
             },
             mainNetworks: {
@@ -522,10 +530,10 @@
                         actions: {
                             edit: {
                                 label: 'label.edit',
-                                action: function(args) {
+                                action: function (args) {
                                     var trafficType = getTrafficType(selectedPhysicalNetworkObj, 'Public');
-
-                                    updateTrafficLabels(trafficType, args.data, function() {
+                                    
+                                    updateTrafficLabels(trafficType, args.data, function () {
                                         args.response.success();
                                     });
                                 }
@@ -534,14 +542,15 @@
                         tabs: {
                             details: {
                                 title: 'label.details',
-                                fields: [{
+                                fields:[ {
                                     traffictype: {
                                         label: 'label.traffic.type'
                                     },
                                     broadcastdomaintype: {
                                         label: 'label.broadcast.domain.type'
                                     }
-                                }, {
+                                },
+                                {
                                     xennetworklabel: {
                                         label: 'label.xen.traffic.label',
                                         isEditable: true
@@ -567,18 +576,18 @@
                                         isEditable: true
                                     }
                                 }],
-
-                                dataProvider: function(args) {
+                                
+                                dataProvider: function (args) {
                                     $.ajax({
                                         url: createURL("listNetworks&listAll=true&trafficType=Public&isSystem=true&zoneId=" + selectedZoneObj.id),
                                         dataType: "json",
                                         async: false,
-                                        success: function(json) {
+                                        success: function (json) {
                                             var trafficType = getTrafficType(selectedPhysicalNetworkObj, 'Public');
                                             var items = json.listnetworksresponse.network;
-
+                                            
                                             selectedPublicNetworkObj = items[0];
-
+                                            
                                             // Include traffic labels
                                             selectedPublicNetworkObj.xennetworklabel = trafficType.xennetworklabel;
                                             selectedPublicNetworkObj.kvmnetworklabel = trafficType.kvmnetworklabel;
@@ -594,10 +603,10 @@
                                     });
                                 }
                             },
-
+                            
                             ipAddresses: {
                                 title: 'label.ip.ranges',
-                                custom: function(args) {
+                                custom: function (args) {
                                     return $('<div></div>').multiEdit({
                                         context: args.context,
                                         noSelect: true,
@@ -637,108 +646,107 @@
                                         },
                                         add: {
                                             label: 'label.add',
-                                            action: function(args) {
-                                                var array1 = [];
+                                            action: function (args) {
+                                                var array1 =[];
                                                 array1.push("&zoneId=" + args.context.zones[0].id);
-
+                                                
                                                 if (args.data.vlan != null && args.data.vlan.length > 0)
-                                                    array1.push("&vlan=" + todb(args.data.vlan));
-                                                else
-                                                    array1.push("&vlan=untagged");
-
+                                                array1.push("&vlan=" + todb(args.data.vlan)); else
+                                                array1.push("&vlan=untagged");
+                                                
                                                 array1.push("&gateway=" + args.data.gateway);
                                                 array1.push("&netmask=" + args.data.netmask);
                                                 array1.push("&startip=" + args.data.startip);
                                                 if (args.data.endip != null && args.data.endip.length > 0)
-                                                    array1.push("&endip=" + args.data.endip);
-
+                                                array1.push("&endip=" + args.data.endip);
+                                                
                                                 if (args.data.account) {
                                                     array1.push("&account=" + args.data.account.account);
                                                     array1.push("&domainid=" + args.data.account.domainid);
                                                 }
-
-                                                array1.push("&forVirtualNetwork=true"); //indicates this new IP range is for public network, not guest network
-
+                                                
+                                                array1.push("&forVirtualNetwork=true");
+                                                //indicates this new IP range is for public network, not guest network
+                                                
                                                 $.ajax({
                                                     url: createURL("createVlanIpRange" + array1.join("")),
                                                     dataType: "json",
-                                                    success: function(json) {
+                                                    success: function (json) {
                                                         var item = json.createvlaniprangeresponse.vlan;
                                                         args.response.success({
                                                             data: item,
                                                             notification: {
                                                                 label: 'label.add.ip.range',
-                                                                poll: function(args) {
+                                                                poll: function (args) {
                                                                     args.complete();
                                                                 }
                                                             }
                                                         });
                                                     },
-                                                    error: function(XMLHttpResponse) {
+                                                    error: function (XMLHttpResponse) {
                                                         var errorMsg = parseXMLHttpResponse(XMLHttpResponse);
                                                         args.response.error(errorMsg);
                                                     }
                                                 });
                                             }
                                         },
-                                        actionPreFilter: function(args) {
-                                            var actionsToShow = ['destroy'];
+                                        actionPreFilter: function (args) {
+                                            var actionsToShow =[ 'destroy'];
                                             if (args.context.multiRule[0].domain == 'ROOT' && args.context.multiRule[0].account.account == 'system')
-                                                actionsToShow.push('addAccount');
-                                            else
-                                                actionsToShow.push('releaseFromAccount');
+                                            actionsToShow.push('addAccount'); else
+                                            actionsToShow.push('releaseFromAccount');
                                             return actionsToShow;
                                         },
                                         actions: {
                                             destroy: {
                                                 label: 'label.remove.ip.range',
-                                                action: function(args) {
+                                                action: function (args) {
                                                     $.ajax({
                                                         url: createURL('deleteVlanIpRange&id=' + args.context.multiRule[0].id),
                                                         dataType: 'json',
                                                         async: true,
-                                                        success: function(json) {
+                                                        success: function (json) {
                                                             args.response.success({
                                                                 notification: {
                                                                     label: 'label.remove.ip.range',
-                                                                    poll: function(args) {
+                                                                    poll: function (args) {
                                                                         args.complete();
                                                                     }
                                                                 }
                                                             });
                                                         },
-                                                        error: function(json) {
+                                                        error: function (json) {
                                                             args.response.error(parseXMLHttpResponse(json));
                                                         }
                                                     });
                                                 }
                                             },
-
+                                            
                                             releaseFromAccount: {
                                                 label: 'Release from Account',
-                                                action: function(args) {
+                                                action: function (args) {
                                                     $.ajax({
                                                         url: createURL('releasePublicIpRange'),
                                                         data: {
                                                             id: args.context.multiRule[0].id
                                                         },
-                                                        success: function(json) {
+                                                        success: function (json) {
                                                             args.response.success({
                                                                 notification: {
                                                                     label: 'release from account',
-                                                                    poll: function(args) {
+                                                                    poll: function (args) {
                                                                         args.complete();
                                                                     }
                                                                 }
                                                             });
                                                         },
-                                                        error: function(json) {
+                                                        error: function (json) {
                                                             args.response.error(parseXMLHttpResponse(json));
                                                         }
                                                     });
                                                 }
                                             },
-
+                                            
                                             addAccount: {
                                                 label: 'Add Account',
                                                 createForm: {
@@ -749,15 +757,15 @@
                                                         },
                                                         domainid: {
                                                             label: 'Domain',
-                                                            select: function(args) {
+                                                            select: function (args) {
                                                                 $.ajax({
                                                                     url: createURL('listDomains'),
                                                                     data: {
                                                                         listAll: true
                                                                     },
-                                                                    success: function(json) {
+                                                                    success: function (json) {
                                                                         args.response.success({
-                                                                            data: $.map(json.listdomainsresponse.domain, function(domain) {
+                                                                            data: $.map(json.listdomainsresponse.domain, function (domain) {
                                                                                 return {
                                                                                     id: domain.id,
                                                                                     description: domain.path
@@ -770,7 +778,7 @@
                                                         }
                                                     }
                                                 },
-                                                action: function(args) {
+                                                action: function (args) {
                                                     var data = {
                                                         id: args.context.multiRule[0].id,
                                                         zoneid: args.context.multiRule[0].zoneid,
@@ -780,33 +788,32 @@
                                                     $.ajax({
                                                         url: createURL('dedicatePublicIpRange'),
                                                         data: data,
-                                                        success: function(json) {
+                                                        success: function (json) {
                                                             args.response.success({
                                                                 notification: {
                                                                     label: 'Add Account',
-                                                                    poll: function(args) {
+                                                                    poll: function (args) {
                                                                         args.complete();
                                                                     }
                                                                 }
                                                             });
                                                         },
-                                                        error: function(json) {
+                                                        error: function (json) {
                                                             args.response.error(parseXMLHttpResponse(json));
                                                         }
                                                     });
                                                 }
                                             }
-
                                         },
-                                        dataProvider: function(args) {
+                                        dataProvider: function (args) {
                                             $.ajax({
                                                 url: createURL("listVlanIpRanges&zoneid=" + args.context.zones[0].id + "&networkId=" + selectedPublicNetworkObj.id),
                                                 dataType: "json",
-                                                success: function(json) {
+                                                success: function (json) {
                                                     var items = json.listvlaniprangesresponse.vlaniprange;
-
+                                                    
                                                     args.response.success({
-                                                        data: $.map(items, function(item) {
+                                                        data: $.map(items, function (item) {
                                                             return $.extend(item, {
                                                                 account: {
                                                                     _buttonLabel: item.account,
@@ -825,16 +832,16 @@
                         }
                     }
                 },
-
+                
                 'storage': {
                     detailView: {
                         actions: {
                             edit: {
                                 label: 'label.edit',
-                                action: function(args) {
+                                action: function (args) {
                                     var trafficType = getTrafficType(selectedPhysicalNetworkObj, 'Storage');
-
-                                    updateTrafficLabels(trafficType, args.data, function() {
+                                    
+                                    updateTrafficLabels(trafficType, args.data, function () {
                                         args.response.success();
                                     });
                                 }
@@ -843,14 +850,15 @@
                         tabs: {
                             details: {
                                 title: 'label.details',
-                                fields: [{
+                                fields:[ {
                                     traffictype: {
                                         label: 'label.traffic.type'
                                     },
                                     broadcastdomaintype: {
                                         label: 'label.broadcast.domain.type'
                                     }
-                                }, {
+                                },
+                                {
                                     xennetworklabel: {
                                         label: 'label.xen.traffic.label',
                                         isEditable: true
@@ -876,17 +884,17 @@
                                         isEditable: true
                                     }
                                 }],
-
-                                dataProvider: function(args) {
+                                
+                                dataProvider: function (args) {
                                     $.ajax({
                                         url: createURL("listNetworks&listAll=true&trafficType=Storage&isSystem=true&zoneId=" + selectedZoneObj.id),
                                         dataType: "json",
                                         async: false,
-                                        success: function(json) {
+                                        success: function (json) {
                                             var items = json.listnetworksresponse.network;
                                             var trafficType = getTrafficType(selectedPhysicalNetworkObj, 'Storage');
                                             selectedPublicNetworkObj = items[0];
-
+                                            
                                             selectedPublicNetworkObj.xennetworklabel = trafficType.xennetworklabel;
                                             selectedPublicNetworkObj.kvmnetworklabel = trafficType.kvmnetworklabel;
                                             selectedPublicNetworkObj.vmwarenetworklabel = trafficType.vmwarenetworklabel;
@@ -901,28 +909,29 @@
                                     });
                                 }
                             },
-
+                            
                             ipAddresses: {
                                 title: 'label.ip.ranges',
-                                custom: function(args) {
+                                custom: function (args) {
                                     return $('<div></div>').multiEdit({
                                         context: args.context,
                                         noSelect: true,
                                         fields: {
                                             'podid': {
                                                 label: 'label.pod',
-                                                select: function(args) {
+                                                select: function (args) {
                                                     $.ajax({
                                                         url: createURL("listPods&zoneid=" + selectedZoneObj.id),
                                                         dataType: "json",
-                                                        success: function(json) {
-                                                            var items = [];
+                                                        success: function (json) {
+                                                            var items =[];
                                                             var pods = json.listpodsresponse.pod;
-                                                            $(pods).each(function() {
+                                                            $(pods).each(function () {
                                                                 items.push({
                                                                     name: this.id,
                                                                     description: this.name
-                                                                }); //should be "{id: this.id, description: this.name}" (to be consistent with dropdown in createFrom and edit mode) (Brian will fix widget later)
+                                                                });
+                                                                //should be "{id: this.id, description: this.name}" (to be consistent with dropdown in createFrom and edit mode) (Brian will fix widget later)
                                                             });
                                                             args.response.success({
                                                                 data: items
@@ -959,25 +968,25 @@
                                         },
                                         add: {
                                             label: 'label.add',
-                                            action: function(args) {
-                                                var array1 = [];
+                                            action: function (args) {
+                                                var array1 =[];
                                                 array1.push("&zoneId=" + args.context.zones[0].id);
                                                 array1.push("&podid=" + args.data.podid);
-
+                                                
                                                 array1.push("&gateway=" + args.data.gateway);
-
+                                                
                                                 if (args.data.vlan != null && args.data.vlan.length > 0)
-                                                    array1.push("&vlan=" + todb(args.data.vlan));
-
+                                                array1.push("&vlan=" + todb(args.data.vlan));
+                                                
                                                 array1.push("&netmask=" + args.data.netmask);
                                                 array1.push("&startip=" + args.data.startip);
                                                 if (args.data.endip != null && args.data.endip.length > 0)
-                                                    array1.push("&endip=" + args.data.endip);
-
+                                                array1.push("&endip=" + args.data.endip);
+                                                
                                                 $.ajax({
                                                     url: createURL("createStorageNetworkIpRange" + array1.join("")),
                                                     dataType: "json",
-                                                    success: function(json) {
+                                                    success: function (json) {
                                                         args.response.success({
                                                             _custom: {
                                                                 jobId: json.createstoragenetworkiprangeresponse.jobid
@@ -988,7 +997,7 @@
                                                             }
                                                         });
                                                     },
-                                                    error: function(XMLHttpResponse) {
+                                                    error: function (XMLHttpResponse) {
                                                         var errorMsg = parseXMLHttpResponse(XMLHttpResponse);
                                                         args.response.error(errorMsg);
                                                     }
@@ -998,16 +1007,16 @@
                                         actions: {
                                             destroy: {
                                                 label: 'label.delete',
-                                                action: function(args) {
+                                                action: function (args) {
                                                     $.ajax({
                                                         url: createURL('deleteStorageNetworkIpRange&id=' + args.context.multiRule[0].id),
                                                         dataType: 'json',
                                                         async: true,
-                                                        success: function(json) {
+                                                        success: function (json) {
                                                             args.response.success({
                                                                 notification: {
                                                                     label: 'label.remove.ip.range',
-                                                                    poll: function(args) {
+                                                                    poll: function (args) {
                                                                         args.complete();
                                                                     }
                                                                 }
@@ -1017,11 +1026,11 @@
                                                 }
                                             }
                                         },
-                                        dataProvider: function(args) {
+                                        dataProvider: function (args) {
                                             $.ajax({
                                                 url: createURL("listStorageNetworkIpRange&zoneid=" + args.context.zones[0].id + "&networkId=" + selectedPublicNetworkObj.id),
                                                 dataType: "json",
-                                                success: function(json) {
+                                                success: function (json) {
                                                     var items = json.liststoragenetworkiprangeresponse.storagenetworkiprange;
                                                     args.response.success({
                                                         data: items
@@ -1035,16 +1044,16 @@
                         }
                     }
                 },
-
+                
                 'management': {
                     detailView: {
                         actions: {
                             edit: {
                                 label: 'label.edit',
-                                action: function(args) {
+                                action: function (args) {
                                     var trafficType = getTrafficType(selectedPhysicalNetworkObj, 'Management');
-
-                                    updateTrafficLabels(trafficType, args.data, function() {
+                                    
+                                    updateTrafficLabels(trafficType, args.data, function () {
                                         args.response.success();
                                     });
                                 }
@@ -1053,14 +1062,15 @@
                         tabs: {
                             details: {
                                 title: 'label.details',
-                                fields: [{
+                                fields:[ {
                                     traffictype: {
                                         label: 'label.traffic.type'
                                     },
                                     broadcastdomaintype: {
                                         label: 'label.broadcast.domain.type'
                                     }
-                                }, {
+                                },
+                                {
                                     xennetworklabel: {
                                         label: 'label.xen.traffic.label',
                                         isEditable: true
@@ -1086,15 +1096,15 @@
                                         isEditable: true
                                     }
                                 }],
-                                dataProvider: function(args) {
+                                dataProvider: function (args) {
                                     $.ajax({
                                         url: createURL("listNetworks&listAll=true&issystem=true&trafficType=Management&zoneId=" + selectedZoneObj.id),
                                         dataType: "json",
-                                        success: function(json) {
+                                        success: function (json) {
                                             selectedManagementNetworkObj = json.listnetworksresponse.network[0];
-
+                                            
                                             var trafficType = getTrafficType(selectedPhysicalNetworkObj, 'Management');
-
+                                            
                                             selectedManagementNetworkObj.xennetworklabel = trafficType.xennetworklabel;
                                             selectedManagementNetworkObj.kvmnetworklabel = trafficType.kvmnetworklabel;
                                             selectedManagementNetworkObj.vmwarenetworklabel = trafficType.vmwarenetworklabel;
@@ -1109,35 +1119,41 @@
                                     });
                                 }
                             },
-                            ipAddresses: { //read-only listView (no actions) filled with pod info (not VlanIpRange info)
+                            ipAddresses: {
+                                //read-only listView (no actions) filled with pod info (not VlanIpRange info)
                                 title: 'label.ip.ranges',
                                 listView: {
                                     fields: {
                                         name: {
                                             label: 'label.pod'
-                                        }, //pod name
+                                        },
+                                        //pod name
                                         gateway: {
                                             label: 'label.gateway'
-                                        }, //'Reserved system gateway' is too long and causes a visual format bug (2 lines overlay)
+                                        },
+                                        //'Reserved system gateway' is too long and causes a visual format bug (2 lines overlay)
                                         netmask: {
                                             label: 'label.netmask'
-                                        }, //'Reserved system netmask' is too long and causes a visual format bug (2 lines overlay)
+                                        },
+                                        //'Reserved system netmask' is too long and causes a visual format bug (2 lines overlay)
                                         startip: {
                                             label: 'label.start.IP'
-                                        }, //'Reserved system start IP' is too long and causes a visual format bug (2 lines overlay)
+                                        },
+                                        //'Reserved system start IP' is too long and causes a visual format bug (2 lines overlay)
                                         endip: {
                                             label: 'label.end.IP'
-                                        } //'Reserved system end IP' is too long and causes a visual format bug (2 lines overlay)
+                                        }
+                                        //'Reserved system end IP' is too long and causes a visual format bug (2 lines overlay)
                                     },
-                                    dataProvider: function(args) {
-                                        var array1 = [];
+                                    dataProvider: function (args) {
+                                        var array1 =[];
                                         if (args.filterBy != null) {
                                             if (args.filterBy.search != null && args.filterBy.search.by != null && args.filterBy.search.value != null) {
                                                 switch (args.filterBy.search.by) {
                                                     case "name":
-                                                        if (args.filterBy.search.value.length > 0)
-                                                            array1.push("&keyword=" + args.filterBy.search.value);
-                                                        break;
+                                                    if (args.filterBy.search.value.length > 0)
+                                                    array1.push("&keyword=" + args.filterBy.search.value);
+                                                    break;
                                                 }
                                             }
                                         }
@@ -1145,7 +1161,7 @@
                                             url: createURL("listPods&zoneid=" + selectedZoneObj.id + "&page=" + args.page + "&pagesize=" + pageSize + array1.join("")),
                                             dataType: "json",
                                             async: true,
-                                            success: function(json) {
+                                            success: function (json) {
                                                 var items = json.listpodsresponse.pod;
                                                 args.response.success({
                                                     data: items
@@ -1158,34 +1174,35 @@
                         }
                     }
                 },
-
-                'guest': { //physical network + Guest traffic type
+                
+                'guest': {
+                    //physical network + Guest traffic type
                     detailView: {
                         actions: {
                             edit: {
                                 label: 'label.edit',
-                                action: function(args) {
+                                action: function (args) {
                                     var data = {
-                                      id: selectedPhysicalNetworkObj.id
+                                        id: selectedPhysicalNetworkObj.id
                                     };
-
-                                  $.extend(data, {
-                                    vlan: args.data.vlan
-                                  });
-
-                                  $.extend(data, {
-                                    tags: args.data.tags
-                                  });
-
+                                    
+                                    $.extend(data, {
+                                        vlan: args.data.vlan
+                                    });
+                                    
+                                    $.extend(data, {
+                                        tags: args.data.tags
+                                    });
+                                    
                                     $.ajax({
                                         url: createURL('updatePhysicalNetwork'),
                                         data: data,
-                                        success: function(json) {
+                                        success: function (json) {
                                             var jobId = json.updatephysicalnetworkresponse.jobid;
-
+                                            
                                             var trafficType = getTrafficType(selectedPhysicalNetworkObj, 'Guest');
-
-                                            updateTrafficLabels(trafficType, args.data, function() {
+                                            
+                                            updateTrafficLabels(trafficType, args.data, function () {
                                                 args.response.success({
                                                     _custom: {
                                                         jobId: jobId
@@ -1200,30 +1217,32 @@
                                 }
                             }
                         },
-
-                        tabFilter: function(args) {
-                            var hiddenTabs = [];
+                        
+                        tabFilter: function (args) {
+                            var hiddenTabs =[];
                             if (selectedZoneObj.networktype == 'Basic') {
                                 hiddenTabs.push("network");
                                 hiddenTabs.push("dedicatedGuestVlanRanges");
-                            } else { //selectedZoneObj.networktype == 'Advanced'
+                            } else {
+                                //selectedZoneObj.networktype == 'Advanced'
                                 hiddenTabs.push("ipAddresses");
                             }
                             return hiddenTabs;
                         },
-
+                        
                         tabs: {
                             details: {
                                 title: 'label.details',
-                                preFilter: function(args) {
-                                    var hiddenFields = [];
+                                preFilter: function (args) {
+                                    var hiddenFields =[];
                                     if (selectedZoneObj.networktype == "Basic") {
                                         hiddenFields.push("vlan");
                                         // hiddenFields.push("endVlan");
                                     }
                                     return hiddenFields;
                                 },
-                                fields: [{ //updatePhysicalNetwork API
+                                fields:[ {
+                                    //updatePhysicalNetwork API
                                     state: {
                                         label: 'label.state'
                                     },
@@ -1238,7 +1257,9 @@
                                     broadcastdomainrange: {
                                         label: 'label.broadcast.domain.range'
                                     }
-                                }, { //updateTrafficType API
+                                },
+                                {
+                                    //updateTrafficType API
                                     xennetworklabel: {
                                         label: 'label.xen.traffic.label',
                                         isEditable: true
@@ -1264,7 +1285,8 @@
                                         isEditable: true
                                     }
                                 }],
-                                dataProvider: function(args) { //physical network + Guest traffic type
+                                dataProvider: function (args) {
+                                    //physical network + Guest traffic type
                                     //refresh physical network
                                     $.ajax({
                                         url: createURL('listPhysicalNetworks'),
@@ -1272,37 +1294,38 @@
                                             id: args.context.physicalNetworks[0].id
                                         },
                                         async: true,
-                                        success: function(json) {
+                                        success: function (json) {
                                             selectedPhysicalNetworkObj = json.listphysicalnetworksresponse.physicalnetwork[0];
-
+                                            
                                             //	var startVlan, endVlan;
                                             var vlan = selectedPhysicalNetworkObj.vlan;
                                             /*	if(vlan != null && vlan.length > 0) {
-                        if(vlan.indexOf("-") != -1) {
-                          var vlanArray = vlan.split("-");
-                          startVlan = vlanArray[0];
-                          endVlan = vlanArray[1];
-                        }
-                        else {
-                          startVlan = vlan;
-                        }
-                        selectedPhysicalNetworkObj["startVlan"] = startVlan;
-                        selectedPhysicalNetworkObj["endVlan"] = endVlan;
-                      }*/
-
+                                            if(vlan.indexOf("-") != -1) {
+                                            var vlanArray = vlan.split("-");
+                                            startVlan = vlanArray[0];
+                                            endVlan = vlanArray[1];
+                                            }
+                                            else {
+                                            startVlan = vlan;
+                                            }
+                                            selectedPhysicalNetworkObj["startVlan"] = startVlan;
+                                            selectedPhysicalNetworkObj["endVlan"] = endVlan;
+                                            }*/
+                                            
                                             //traffic type
                                             var xentrafficlabel, kvmtrafficlabel, vmwaretrafficlabel;
-                                            var trafficType = getTrafficType(selectedPhysicalNetworkObj, 'Guest'); //refresh Guest traffic type
-                                            selectedPhysicalNetworkObj["xennetworklabel"] = trafficType.xennetworklabel;
-                                            selectedPhysicalNetworkObj["kvmnetworklabel"] = trafficType.kvmnetworklabel;
-                                            selectedPhysicalNetworkObj["vmwarenetworklabel"] = trafficType.vmwarenetworklabel;
-                                            selectedPhysicalNetworkObj["ovmnetworklabel"] = trafficType.ovmnetworklabel;
-                                            selectedPhysicalNetworkObj["lxcnetworklabel"] = trafficType.lxcnetworklabel;
-                                            selectedPhysicalNetworkObj["hypervnetworklabel"] = trafficType.hypervnetworklabel;                                            
+                                            var trafficType = getTrafficType(selectedPhysicalNetworkObj, 'Guest');
+                                            //refresh Guest traffic type
+                                            selectedPhysicalNetworkObj[ "xennetworklabel"] = trafficType.xennetworklabel;
+                                            selectedPhysicalNetworkObj[ "kvmnetworklabel"] = trafficType.kvmnetworklabel;
+                                            selectedPhysicalNetworkObj[ "vmwarenetworklabel"] = trafficType.vmwarenetworklabel;
+                                            selectedPhysicalNetworkObj[ "ovmnetworklabel"] = trafficType.ovmnetworklabel;
+                                            selectedPhysicalNetworkObj[ "lxcnetworklabel"] = trafficType.lxcnetworklabel;
+                                            selectedPhysicalNetworkObj[ "hypervnetworklabel"] = trafficType.hypervnetworklabel;
                                             
                                             args.response.success({
-                                                actionFilter: function() {
-                                                    var allowedActions = ['edit', 'addVlanRange', 'removeVlanRange'];
+                                                actionFilter: function () {
+                                                    var allowedActions =[ 'edit', 'addVlanRange', 'removeVlanRange'];
                                                     return allowedActions;
                                                 },
                                                 data: selectedPhysicalNetworkObj
@@ -1311,28 +1334,29 @@
                                     });
                                 }
                             },
-
+                            
                             ipAddresses: {
                                 title: 'label.ip.ranges',
-                                custom: function(args) {
+                                custom: function (args) {
                                     return $('<div></div>').multiEdit({
                                         context: args.context,
                                         noSelect: true,
                                         fields: {
                                             'podid': {
                                                 label: 'label.pod',
-                                                select: function(args) {
+                                                select: function (args) {
                                                     $.ajax({
                                                         url: createURL("listPods&zoneid=" + selectedZoneObj.id),
                                                         dataType: "json",
-                                                        success: function(json) {
-                                                            var items = [];
+                                                        success: function (json) {
+                                                            var items =[];
                                                             var pods = json.listpodsresponse.pod;
-                                                            $(pods).each(function() {
+                                                            $(pods).each(function () {
                                                                 items.push({
                                                                     name: this.id,
                                                                     description: this.name
-                                                                }); //should be "{id: this.id, description: this.name}" (to be consistent with dropdown in createFrom and edit mode) (Brian will fix widget later)
+                                                                });
+                                                                //should be "{id: this.id, description: this.name}" (to be consistent with dropdown in createFrom and edit mode) (Brian will fix widget later)
                                                             });
                                                             args.response.success({
                                                                 data: items
@@ -1364,33 +1388,34 @@
                                         },
                                         add: {
                                             label: 'label.add',
-                                            action: function(args) {
-                                                var array1 = [];
+                                            action: function (args) {
+                                                var array1 =[];
                                                 array1.push("&podid=" + args.data.podid);
                                                 array1.push("&networkid=" + selectedGuestNetworkObj.id);
                                                 array1.push("&gateway=" + args.data.gateway);
                                                 array1.push("&netmask=" + args.data.netmask);
                                                 array1.push("&startip=" + args.data.startip);
                                                 if (args.data.endip != null && args.data.endip.length > 0)
-                                                    array1.push("&endip=" + args.data.endip);
-                                                array1.push("&forVirtualNetwork=false"); //indicates this new IP range is for guest network, not public network
-
+                                                array1.push("&endip=" + args.data.endip);
+                                                array1.push("&forVirtualNetwork=false");
+                                                //indicates this new IP range is for guest network, not public network
+                                                
                                                 $.ajax({
                                                     url: createURL("createVlanIpRange" + array1.join("")),
                                                     dataType: "json",
-                                                    success: function(json) {
+                                                    success: function (json) {
                                                         var item = json.createvlaniprangeresponse.vlan;
                                                         args.response.success({
                                                             data: item,
                                                             notification: {
                                                                 label: 'label.add.ip.range',
-                                                                poll: function(args) {
+                                                                poll: function (args) {
                                                                     args.complete();
                                                                 }
                                                             }
                                                         });
                                                     },
-                                                    error: function(XMLHttpResponse) {
+                                                    error: function (XMLHttpResponse) {
                                                         var errorMsg = parseXMLHttpResponse(XMLHttpResponse);
                                        

<TRUNCATED>

[10/11] git commit: updated refs/heads/master to 612a41e

Posted by hu...@apache.org.
Add opendaylight provider to system.js


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

Branch: refs/heads/master
Commit: e4cb9ce8bcb0ffa8b3a4f82f0e32002e19f35085
Parents: 57da2bc
Author: Hugo Trippaers <ht...@schubergphilis.com>
Authored: Wed Jan 8 16:12:32 2014 +0100
Committer: Hugo Trippaers <ht...@schubergphilis.com>
Committed: Wed Jan 8 16:12:32 2014 +0100

----------------------------------------------------------------------
 ui/scripts/system.js | 295 +++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 294 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e4cb9ce8/ui/scripts/system.js
----------------------------------------------------------------------
diff --git a/ui/scripts/system.js b/ui/scripts/system.js
index 59aab8b..b06cb57 100644
--- a/ui/scripts/system.js
+++ b/ui/scripts/system.js
@@ -6524,7 +6524,300 @@
                                 }
                             }
                         }
-                    }
+                    },
+                    Opendaylight: {
+                        type: 'detailView',
+                        id: 'openDaylightProvider',
+                        label: 'label.openDaylight',
+                        tabs: {
+                            details: {
+                                title: 'label.details',
+                                fields:[ {
+                                    name: {
+                                        label: 'label.name'
+                                    }
+                                },
+                                {
+                                    state: {
+                                        label: 'label.state'
+                                    }
+                                }],
+                                dataProvider: function (args) {
+                                    refreshNspData("Opendaylight");
+                                    var providerObj;
+                                    $(nspHardcodingArray).each(function () {
+                                        if (this.id == "Opendaylight") {
+                                            providerObj = this;
+                                            return false; //break each loop
+                                        }
+                                    });
+                                    args.response.success({
+                                        data: providerObj,
+                                        actionFilter: networkProviderActionFilter('Opendaylight')
+                                    });
+                                }
+                            },
+                            controllers: {
+                                title: 'label.opendaylight.controllers',
+                                listView: {
+                                    id: 'openDaylightControllerList',
+                                    fields: {
+                                        name: {
+                                            label: 'label.name'
+                                        },
+                                        url: {
+                                            label: 'label.url'
+                                        },
+                                        username: {
+                                            label: 'label.username'
+                                        }
+                                    },
+                                    dataProvider: function (args) {
+                                        var providerObj
+                                        $.ajax({
+                                            url: createURL("listOpenDaylightControllers"),
+                                            async: false,
+                                            success: function (json) {
+                                                providerObj = json.listOpenDaylightControllers.opendaylightcontroller
+                                            }
+                                        });
+                                        args.response.success({
+                                            data: providerObj
+                                        });
+                                    },
+                                    detailView: {
+                                        name: "OpenDaylight Controller",
+                                        tabs: {
+                                            details: {
+                                                title: 'label.opendaylight.controllerdetail',
+                                                fields:[ {
+                                                    name: {
+                                                        label: 'label.name'
+                                                    },
+                                                    url: {
+                                                        label: 'label.url', header: true
+                                                    },
+                                                    username: {
+                                                        label: 'label.username'
+                                                    }
+                                                }],
+                                                dataProvider: function (args) {
+                                                    var providerObj
+                                                    $.ajax({
+                                                        url: createURL("listOpenDaylightControllers&id=" + args.id),
+                                                        async: false,
+                                                        success: function (json) {
+                                                            providerObj = json.listOpenDaylightControllers.opendaylightcontroller
+                                                        }
+                                                    });
+                                                    args.response.success({
+                                                        data: providerObj[0],
+                                                        actionFilter: function(args) { return [ 'destroy' ] }
+                                                    });
+                                                }
+                                            }
+                                        },
+                                        actions: {
+                                            destroy: {
+                                                label: 'label.destroy.controller',
+                                                action: function (args) {
+                                                    $.ajax({
+                                                        url: createURL("deleteOpenDaylightController&id=" + args.data.id),
+                                                        dataType: "json",
+                                                        success: function (json) {
+                                                            var jid = json.deleteOpenDaylightController.jobid;
+                                                            args.response.success({
+                                                                _custom: {
+                                                                    jobId: jid,
+                                                                    getUpdatedItem: function (json) {
+                                                                        $(window).trigger('cloudStack.fullRefresh');
+                                                                    }
+                                                                }
+                                                            });
+                                                        }
+                                                    });
+                                                },
+                                                messages: {
+                                                    notification: function(args) {
+                                                        return 'label.openaylight.destroycontroller'
+                                                    }
+                                                },
+                                                notification: {
+                                                    poll: pollAsyncJobResult
+                                                }
+                                            }
+                                        }
+                                    }
+                                }
+                            }
+                        },
+                        actions: {
+                            add: {
+                                label: 'label.add.OpenDaylight.device',
+                                createForm: {
+                                    title: 'label.add.OpenDaylight.device',
+                                    preFilter: function (args) {
+                                    },
+                                    // TODO What is this?
+                                    fields: {
+                                        url: {
+                                            label: 'label.url'
+                                        },
+                                        username: {
+                                            label: 'label.username'
+                                        },
+                                        password: {
+                                            label: 'label.password',
+                                            isPassword: true
+                                        },
+                                        numretries: {
+                                            label: 'label.numretries',
+                                            defaultValue: '2'
+                                        }
+                                    }
+                                },
+                                action: function (args) {
+                                    if (nspMap[ "Opendaylight"] == null) {
+                                        $.ajax({
+                                            url: createURL("addNetworkServiceProvider&name=Opendaylight&physicalnetworkid=" + selectedPhysicalNetworkObj.id),
+                                            dataType: "json",
+                                            async: true,
+                                            success: function (json) {
+                                                var jobId = json.addnetworkserviceproviderresponse.jobid;
+                                                var addOpenDaylightProviderIntervalID = setInterval(function () {
+                                                    $.ajax({
+                                                        url: createURL("queryAsyncJobResult&jobId=" + jobId),
+                                                        dataType: "json",
+                                                        success: function (json) {
+                                                            var result = json.queryasyncjobresultresponse;
+                                                            if (result.jobstatus == 0) {
+                                                                return; //Job has not completed
+                                                            } else {
+                                                                clearInterval(addOpenDaylightProviderIntervalID);
+                                                                if (result.jobstatus == 1) {
+                                                                    nspMap[ "Opendaylight"] = json.queryasyncjobresultresponse.jobresult.networkserviceprovider;
+                                                                    addOpenDaylightController(args, selectedPhysicalNetworkObj, "addOpenDaylightController", "addopendaylightcontrollerresponse", "opendaylightcontroller")
+                                                                } else if (result.jobstatus == 2) {
+                                                                    alert("addNetworkServiceProvider&name=OpenDaylight failed. Error: " + _s(result.jobresult.errortext));
+                                                                }
+                                                            }
+                                                        },
+                                                        error: function (XMLHttpResponse) {
+                                                            var errorMsg = parseXMLHttpResponse(XMLHttpResponse);
+                                                            alert("addNetworkServiceProvider&name=OpenDaylight failed. Error: " + errorMsg);
+                                                        }
+                                                    });
+                                                },
+                                                g_queryAsyncJobResultInterval);
+                                            }
+                                        });
+                                    } else {
+                                        addOpenDaylightController(args, selectedPhysicalNetworkObj, "addOpenDaylightController", "addOpenDaylightController", "opendaylightcontroller")
+                                    }
+                                },
+                                messages: {
+                                    notification: function (args) {
+                                        return 'label.add.OpenDaylight.device';
+                                    }
+                                },
+                                notification: {
+                                    poll: pollAsyncJobResult
+                                }
+                            },
+                            enable: {
+                                label: 'label.enable.provider',
+                                action: function (args) {
+                                    $.ajax({
+                                        url: createURL("updateNetworkServiceProvider&id=" + nspMap[ "Opendaylight"].id + "&state=Enabled"),
+                                        dataType: "json",
+                                        success: function (json) {
+                                            var jid = json.updatenetworkserviceproviderresponse.jobid;
+                                            args.response.success({
+                                                _custom: {
+                                                    jobId: jid,
+                                                    getUpdatedItem: function (json) {
+                                                        $(window).trigger('cloudStack.fullRefresh');
+                                                    }
+                                                }
+                                            });
+                                        }
+                                    });
+                                },
+                                messages: {
+                                    confirm: function (args) {
+                                        return 'message.confirm.enable.provider';
+                                    },
+                                    notification: function () {
+                                        return 'label.enable.provider';
+                                    }
+                                },
+                                notification: {
+                                    poll: pollAsyncJobResult
+                                }
+                            },
+                            disable: {
+                                label: 'label.disable.provider',
+                                action: function (args) {
+                                    $.ajax({
+                                        url: createURL("updateNetworkServiceProvider&id=" + nspMap[ "Opendaylight"].id + "&state=Disabled"),
+                                        dataType: "json",
+                                        success: function (json) {
+                                            var jid = json.updatenetworkserviceproviderresponse.jobid;
+                                            args.response.success({
+                                                _custom: {
+                                                    jobId: jid,
+                                                    getUpdatedItem: function (json) {
+                                                        $(window).trigger('cloudStack.fullRefresh');
+                                                    }
+                                                }
+                                            });
+                                        }
+                                    });
+                                },
+                                messages: {
+                                    confirm: function (args) {
+                                        return 'message.confirm.disable.provider';
+                                    },
+                                    notification: function () {
+                                        return 'label.disable.provider';
+                                    }
+                                },
+                                notification: {
+                                    poll: pollAsyncJobResult
+                                }
+                            },
+                            destroy: {
+                                label: 'label.shutdown.provider',
+                                action: function (args) {
+                                    $.ajax({
+                                        url: createURL("deleteNetworkServiceProvider&id=" + nspMap[ "Opendaylight"].id),
+                                        dataType: "json",
+                                        success: function (json) {
+                                            var jid = json.deletenetworkserviceproviderresponse.jobid;
+                                            args.response.success({
+                                                _custom: {
+                                                    jobId: jid
+                                                }
+                                            });
+                                            
+                                            $(window).trigger('cloudStack.fullRefresh');
+                                        }
+                                    });
+                                },
+                                messages: {
+                                    confirm: function (args) {
+                                        return 'message.confirm.shutdown.provider';
+                                    },
+                                    notification: function (args) {
+                                        return 'label.shutdown.provider';
+                                    }
+                                },
+                                notification: {
+                                    poll: pollAsyncJobResult
+                                }
+                            }
+                        }
+                    }                    
                 }
             }
         },