Adding Gluon App code to support EVPN

Change-Id: I24aee104482a166e412e5e7b42ea1dbf518d51c6
diff --git a/apps/gluon/BUCK b/apps/gluon/BUCK
new file mode 100755
index 0000000..a2ddcd9
--- /dev/null
+++ b/apps/gluon/BUCK
@@ -0,0 +1,36 @@
+COMPILE_DEPS = [
+    '//lib:CORE_DEPS',
+    '//cli:onos-cli',
+    '//lib:httpclient-osgi',
+    '//lib:httpcore-osgi',
+    '//lib:org.apache.httpcomponents.httpasyncclient-osgi',
+    '//lib:org.apache.httpcomponents.httpcore-nio',
+    '//lib:org.apache.karaf.shell.console',
+    '//lib:org.apache.karaf.jaas',
+
+]
+TEST_DEPS = [
+  '//lib:TEST',
+]
+
+BUNDLES = [
+  ':onos-apps-gluon',
+  '//lib:httpclient-osgi',
+  '//lib:httpcore-osgi',
+  '//lib:org.apache.httpcomponents.httpasyncclient-osgi',
+  '//lib:org.apache.httpcomponents.httpcore-nio',
+]
+
+osgi_jar_with_tests (
+    deps = COMPILE_DEPS,
+    test_deps = TEST_DEPS,
+)
+
+onos_app (
+    app_name = 'org.onosproject.gluon',
+    title = 'Gluon Shim Application',
+    category = 'Monitoring',
+    url = 'http://onosproject.org',
+    included_bundles = BUNDLES,
+    description = 'To fetch data from Gluon Server over Http session.',
+)
\ No newline at end of file
diff --git a/apps/gluon/features.xml b/apps/gluon/features.xml
new file mode 100755
index 0000000..ae6bf2b
--- /dev/null
+++ b/apps/gluon/features.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!--
+  ~ Copyright 2017-present Open Networking Foundation
+  ~
+  ~ Licensed 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.
+  -->
+<features xmlns="http://karaf.apache.org/xmlns/features/v1.2.0" name="${project.artifactId}-${project.version}">
+    <feature name="${project.artifactId}" version="${project.version}"
+             description="${project.description}">
+        <feature>onos-api</feature>
+    </feature>
+</features>
diff --git a/apps/gluon/pom.xml b/apps/gluon/pom.xml
new file mode 100755
index 0000000..cd39c33
--- /dev/null
+++ b/apps/gluon/pom.xml
@@ -0,0 +1,102 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Copyright 2017-present Open Networking Foundation
+  ~
+  ~ Licensed 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>
+    <parent>
+        <groupId>org.onosproject</groupId>
+        <artifactId>onos-apps</artifactId>
+        <version>1.11.0-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>onos-app-gluon</artifactId>
+    <packaging>bundle</packaging>
+
+    <description>ONOS GLUON application</description>
+    <url>http://onosproject.org</url>
+
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <onos.version>1.11.0-SNAPSHOT</onos.version>
+        <onos.app.name>onos-app-gluon</onos.app.name>
+        <onos.app.origin>Huawei Technology India Pvt Ltd</onos.app.origin>
+        <onos.app.title>Gluon App</onos.app.title>
+        <onos.app.url>http://onosproject.org</onos.app.url>
+    </properties>
+    <dependencies>
+        <dependency>
+            <groupId>org.onosproject</groupId>
+            <artifactId>onos-api</artifactId>
+            <version>${onos.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.onosproject</groupId>
+            <artifactId>onlab-osgi</artifactId>
+            <version>${onos.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <version>4.12</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.onosproject</groupId>
+            <artifactId>onos-api</artifactId>
+            <version>${onos.version}</version>
+            <scope>test</scope>
+            <classifier>tests</classifier>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>org.apache.felix.scr.annotations</artifactId>
+            <version>1.9.12</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.karaf.shell</groupId>
+            <artifactId>org.apache.karaf.shell.console</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.onosproject</groupId>
+            <artifactId>onos-cli</artifactId>
+            <version>1.11.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpasyncclient</artifactId>
+            <version>4.1.1</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpcore</artifactId>
+            <version>4.4.4</version>
+        </dependency>
+        <dependency>
+            <groupId>org.onosproject</groupId>
+            <artifactId>onlab-junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.onosproject</groupId>
+            <artifactId>onos-core-net</artifactId>
+            <version>1.11.0-SNAPSHOT</version>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+</project>
diff --git a/apps/gluon/src/main/java/org/onosproject/gluon/manager/GluonManager.java b/apps/gluon/src/main/java/org/onosproject/gluon/manager/GluonManager.java
new file mode 100755
index 0000000..11f3738
--- /dev/null
+++ b/apps/gluon/src/main/java/org/onosproject/gluon/manager/GluonManager.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed 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.onosproject.gluon.manager;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.onosproject.core.CoreService;
+import org.onosproject.gluon.rsc.GluonConfig;
+import org.onosproject.gluon.rsc.GluonServer;
+import org.onosproject.net.config.ConfigFactory;
+import org.onosproject.net.config.NetworkConfigRegistry;
+import org.onosproject.net.config.basics.SubjectFactories;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * Gluon Shim Application.
+ */
+@Component(immediate = true)
+public class GluonManager {
+
+    private final Logger log = LoggerFactory.getLogger(getClass());
+    private static final String APP_ID = "org.onosproject.gluon";
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected CoreService coreService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected NetworkConfigRegistry configRegistry;
+
+
+    private final ConfigFactory configFactory =
+            new ConfigFactory(SubjectFactories.APP_SUBJECT_FACTORY,
+                              GluonConfig.class, "gluon") {
+                @Override
+                public GluonConfig createConfig() {
+                    return new GluonConfig();
+                }
+            };
+
+    public static Map<String, GluonServer> serverMap = new LinkedHashMap<>();
+
+    @Activate
+    public void activate() {
+        coreService.registerApplication(APP_ID);
+        configRegistry.registerConfigFactory(configFactory);
+        log.info("Gluon app Started");
+    }
+
+    @Deactivate
+    public void deactivate() {
+        configRegistry.unregisterConfigFactory(configFactory);
+        log.info("Gluon app Stopped");
+    }
+
+    /**
+     * Creating gluon server object.
+     *
+     * @param etcduri         server url
+     * @param targetProtonKey server key type, default net-l3vpn
+     * @param mode            server mode start or stop
+     * @param version         running server version
+     */
+    public static void createServer(String etcduri, String targetProtonKey,
+                                    String mode, String version) {
+        new GluonServer(etcduri, targetProtonKey, mode, version);
+    }
+
+    /**
+     * Deleting gluon server from server list.
+     *
+     * @param etcduri server url
+     */
+    public static void deleteServer(String etcduri) {
+        for (Map.Entry<String, GluonServer> server : serverMap.entrySet()) {
+            if (etcduri.equals(server.getKey())) {
+                serverMap.remove(etcduri);
+                return;
+            }
+        }
+    }
+
+    /**
+     * Add server into map.
+     *
+     * @param etcduri     server url
+     * @param gluonObject store server object
+     */
+    public static void addServer(String etcduri, GluonServer gluonObject) {
+        serverMap.put(etcduri, gluonObject);
+    }
+
+    /**
+     * Returns serverMap size.
+     *
+     * @return total number of servers
+     */
+    public static int getTotalServers() {
+        return serverMap.size();
+    }
+
+    /**
+     * Returns all server IPs.
+     *
+     * @return serverMap
+     */
+    public static Map<String, GluonServer> getAllServersIP() {
+        return serverMap;
+    }
+
+
+}
\ No newline at end of file
diff --git a/apps/gluon/src/main/java/org/onosproject/gluon/manager/package-info.java b/apps/gluon/src/main/java/org/onosproject/gluon/manager/package-info.java
new file mode 100755
index 0000000..d20ea1a
--- /dev/null
+++ b/apps/gluon/src/main/java/org/onosproject/gluon/manager/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed 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.
+ */
+
+/**
+ * Gluon Shim Application manager class.
+ */
+package org.onosproject.gluon.manager;
\ No newline at end of file
diff --git a/apps/gluon/src/main/java/org/onosproject/gluon/rsc/GluonConfig.java b/apps/gluon/src/main/java/org/onosproject/gluon/rsc/GluonConfig.java
new file mode 100755
index 0000000..70f944a
--- /dev/null
+++ b/apps/gluon/src/main/java/org/onosproject/gluon/rsc/GluonConfig.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed 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.onosproject.gluon.rsc;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import org.onosproject.net.config.Config;
+
+/**
+ * Representation of a Etcd response.
+ */
+public class GluonConfig extends Config<String> {
+    public String action;
+    public String key;
+    public JsonNode value;
+    long modifiedIndex;
+    long createdIndex;
+
+    public GluonConfig() {
+    }
+
+    /**
+     * Gluon configuration data model.
+     *
+     * @param action operation type
+     * @param key    proton key
+     * @param value  proton value
+     * @param mIndex modified time
+     * @param cIndex created time
+     */
+    public GluonConfig(String action, String key, JsonNode value, long mIndex,
+                       long cIndex) {
+        this.action = action;
+        this.key = key;
+        this.value = value;
+        this.modifiedIndex = mIndex;
+        this.createdIndex = cIndex;
+    }
+
+    /**
+     * Sets the etcdresponse used by network config.
+     *
+     * @param gluonConfig Etcdresponse data after parsing
+     */
+    public void setEtcdResponse(GluonConfig gluonConfig) {
+        object.put(gluonConfig.key, gluonConfig.value);
+    }
+
+    @Override
+    public String toString() {
+        return "GluonConfig{" +
+                "action='" + action + '\'' +
+                ", key='" + key + '\'' +
+                ", value=" + value +
+                ", modifiedIndex=" + modifiedIndex +
+                ", createdIndex=" + createdIndex +
+                '}';
+    }
+}
diff --git a/apps/gluon/src/main/java/org/onosproject/gluon/rsc/GluonConstants.java b/apps/gluon/src/main/java/org/onosproject/gluon/rsc/GluonConstants.java
new file mode 100755
index 0000000..3b41030
--- /dev/null
+++ b/apps/gluon/src/main/java/org/onosproject/gluon/rsc/GluonConstants.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed 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.onosproject.gluon.rsc;
+
+/**
+ * Gluon application related constants.
+ */
+
+public final class GluonConstants {
+
+    protected GluonConstants() {
+    }
+
+    /**
+     * String constants.
+     */
+    public static final String KEYS = "/keys";
+    public static final String PROTON = "/proton/";
+    public static final String MODE_STOP = "stop";
+    public static final String MODE_START = "start";
+    public static final String ACTION_SET = "set";
+    public static final String ACTION_GET = "get";
+    public static final String ACTION_DEL = "delete";
+    public static final String GLUON_HTTP = "http://";
+    public static final String KEY_TYPE = "net-l3vpn";
+    public static final String GLUON_ACTION = "action";
+    public static final String GLUON_KEY = "key";
+    public static final String GLUON_NODE = "node";
+    public static final String GLUON_NODES = "nodes";
+    public static final String GLUON_VALUE = "value";
+    public static final String GLUON_MOD_INDEX = "modifiedIndex";
+    public static final String GLUON_CREATE_INDEX = "createdIndex";
+    public static final String GLUON_DEFAULT_PORT = "2379";
+
+    /**
+     * INFO Constants.
+     */
+    public static final String BATCH_SERVICE_STATUS =
+            "executorBatchService shutdown status: {}";
+    public static final String REAL_TIME_SERVICE_STATUS =
+            "executorRealTimeService shutdown status: {}";
+    public static final String SERVER_RUNNING =
+            "Server is already running";
+    public static final String ACTIVE_SERVER =
+            "Number of active servers: {}";
+    public static final String NO_SUBKEYS_AVAIL =
+            "No subKeys available. Nothing to smooth";
+    public static final String SERVER_STOPPED =
+            "Server has stopped successfully";
+    public static final String NO_SERVER_AVAIL =
+            "Server is unavailable";
+    public static final String NO_SERVER_AVAIL_ON_PORT =
+            "Server is unavailable on specified port";
+    public static final String REAL_TIME_PROCESSING =
+            "Started Real time etcd monitoring for {}";
+    public static final String BATCH_PROCESSING =
+            "Started Batch time etcd monitoring for {}";
+    public static final String BATCH_QUERING =
+            "Sending Batch time etcd request for {}";
+    public static final String BATCH_STOPPED =
+            "Stopped Batch time etcd monitoring for {}";
+    public static final String REAL_TIME_RECEIVED =
+            "Received RealTime etcd monitor data {}";
+    public static final String BATCH_RECEIVED =
+            "Received batch etcd monitor data {}";
+    public static final String SUBKEYS_RECEIVED =
+            "Recieved subkeys {}";
+    public static final String INVALID_ACTION =
+            "Invalid action has been received";
+    public static final String DATA_UPDATED =
+            "Gluon data updated to network config datastore";
+    public static final String DATA_REMOVED =
+            "Gluon data removed from network config datastore";
+    public static final String SERVER_POOL =
+            "Server IP is not available in server pool";
+    public static final String PROTON_KEY_SUPPORT =
+            "Currently only net-l3vpn type supported";
+    public static final String WRONG_INPUT = "Either server is not available " +
+            "or wrong input";
+    public static final String WRONG_INPUT_TYPE = "Wrong format type";
+    public static final String INVALID_MODE = "Invalid mode";
+    public static final String WRONG_IP_FORMAT = "Wrong IP address format";
+    public static final String INVALID_RANGE = "Wrong port range <1-65535>";
+    public static final String PROCESSING_FAILED = "Error occurred while " +
+            "processing";
+
+    /**
+     * ERROR Constants.
+     */
+    public static final String E_BATCH_PROCESSING =
+            "Batch mode etcd monitor failed with error {}";
+    public static final String E_BATCH_PROCESSING_URL =
+            "Batch mode etcd monitor failed for {}";
+    public static final String E_SUBKEYS_PROCESSING =
+            "Error observed while fetching subkeys for {}";
+    public static final String E_REAL_TIME_PROCESSING =
+            "Real time etcd monitor failed with error {}";
+    public static final String E_CLIENT_STOP =
+            "http client unable to stop with error {}";
+
+    /**
+     * Integer Constants.
+     */
+    public static final int STATUS_CODE = 200;
+
+}
diff --git a/apps/gluon/src/main/java/org/onosproject/gluon/rsc/GluonServer.java b/apps/gluon/src/main/java/org/onosproject/gluon/rsc/GluonServer.java
new file mode 100755
index 0000000..f4f400e
--- /dev/null
+++ b/apps/gluon/src/main/java/org/onosproject/gluon/rsc/GluonServer.java
@@ -0,0 +1,537 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed 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.onosproject.gluon.rsc;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.http.HttpResponse;
+import org.apache.http.StatusLine;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.config.RequestConfig;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.concurrent.FutureCallback;
+import org.apache.http.impl.client.HttpClientBuilder;
+import org.apache.http.impl.nio.client.CloseableHttpAsyncClient;
+import org.apache.http.impl.nio.client.HttpAsyncClients;
+import org.apache.http.util.EntityUtils;
+import org.onlab.osgi.DefaultServiceDirectory;
+import org.onosproject.net.config.NetworkConfigService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.net.URI;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+import static org.onlab.util.Tools.groupedThreads;
+import static org.onosproject.gluon.manager.GluonManager.addServer;
+import static org.onosproject.gluon.manager.GluonManager.deleteServer;
+import static org.onosproject.gluon.manager.GluonManager.getAllServersIP;
+import static org.onosproject.gluon.rsc.GluonConstants.ACTION_DEL;
+import static org.onosproject.gluon.rsc.GluonConstants.ACTION_GET;
+import static org.onosproject.gluon.rsc.GluonConstants.ACTION_SET;
+import static org.onosproject.gluon.rsc.GluonConstants.ACTIVE_SERVER;
+import static org.onosproject.gluon.rsc.GluonConstants.BATCH_PROCESSING;
+import static org.onosproject.gluon.rsc.GluonConstants.BATCH_QUERING;
+import static org.onosproject.gluon.rsc.GluonConstants.BATCH_RECEIVED;
+import static org.onosproject.gluon.rsc.GluonConstants.BATCH_SERVICE_STATUS;
+import static org.onosproject.gluon.rsc.GluonConstants.BATCH_STOPPED;
+import static org.onosproject.gluon.rsc.GluonConstants.DATA_REMOVED;
+import static org.onosproject.gluon.rsc.GluonConstants.DATA_UPDATED;
+import static org.onosproject.gluon.rsc.GluonConstants.E_BATCH_PROCESSING;
+import static org.onosproject.gluon.rsc.GluonConstants.E_BATCH_PROCESSING_URL;
+import static org.onosproject.gluon.rsc.GluonConstants.E_CLIENT_STOP;
+import static org.onosproject.gluon.rsc.GluonConstants.E_REAL_TIME_PROCESSING;
+import static org.onosproject.gluon.rsc.GluonConstants.E_SUBKEYS_PROCESSING;
+import static org.onosproject.gluon.rsc.GluonConstants.GLUON_ACTION;
+import static org.onosproject.gluon.rsc.GluonConstants.GLUON_CREATE_INDEX;
+import static org.onosproject.gluon.rsc.GluonConstants.GLUON_KEY;
+import static org.onosproject.gluon.rsc.GluonConstants.GLUON_MOD_INDEX;
+import static org.onosproject.gluon.rsc.GluonConstants.GLUON_NODE;
+import static org.onosproject.gluon.rsc.GluonConstants.GLUON_NODES;
+import static org.onosproject.gluon.rsc.GluonConstants.GLUON_VALUE;
+import static org.onosproject.gluon.rsc.GluonConstants.INVALID_ACTION;
+import static org.onosproject.gluon.rsc.GluonConstants.KEYS;
+import static org.onosproject.gluon.rsc.GluonConstants.MODE_START;
+import static org.onosproject.gluon.rsc.GluonConstants.MODE_STOP;
+import static org.onosproject.gluon.rsc.GluonConstants.NO_SERVER_AVAIL;
+import static org.onosproject.gluon.rsc.GluonConstants.NO_SUBKEYS_AVAIL;
+import static org.onosproject.gluon.rsc.GluonConstants.PROCESSING_FAILED;
+import static org.onosproject.gluon.rsc.GluonConstants.PROTON;
+import static org.onosproject.gluon.rsc.GluonConstants.REAL_TIME_PROCESSING;
+import static org.onosproject.gluon.rsc.GluonConstants.REAL_TIME_RECEIVED;
+import static org.onosproject.gluon.rsc.GluonConstants.REAL_TIME_SERVICE_STATUS;
+import static org.onosproject.gluon.rsc.GluonConstants.SERVER_RUNNING;
+import static org.onosproject.gluon.rsc.GluonConstants.SERVER_STOPPED;
+import static org.onosproject.gluon.rsc.GluonConstants.STATUS_CODE;
+import static org.onosproject.gluon.rsc.GluonConstants.SUBKEYS_RECEIVED;
+
+
+public class GluonServer {
+
+    private static String protonKeyUri;
+    private static String serverUri;
+
+    private static CloseableHttpAsyncClient httpClient;
+
+    //store gluon server supported subkeys
+    private List<String> subKeys = new LinkedList<>();
+
+    // Lists of gluon servers
+    public Map<String, GluonServer> serverMap = getAllServersIP();
+
+    private final Logger log = LoggerFactory.getLogger(getClass());
+
+    // Real time executor thread
+    private final ExecutorService executorRealTimeService = Executors
+            .newSingleThreadExecutor(groupedThreads("EtcdRealTimeMonitor",
+                                                    "executor-%d", log));
+    // Batch executor thread
+    private final ExecutorService executorBatchService = Executors
+            .newSingleThreadExecutor(groupedThreads("EtcdBatchMonitor",
+                                                    "executor-%d", log));
+
+    // Statistics counter
+    private int setCount = 0;
+    private int delCount = 0;
+    private int getCount = 0;
+    // Server etcd version
+    public String version;
+
+    /**
+     * To get Gluon server running version, needs to create at-least one object.
+     */
+    public GluonServer() {
+    }
+
+    /**
+     * Realising server functionality.
+     *
+     * @param etcduri         server url
+     * @param targetProtonKey server key type, default net-l3vpn
+     * @param mode            server mode start or stop
+     * @param version         running server version
+     */
+    public GluonServer(String etcduri, String targetProtonKey,
+                       String mode, String version) {
+        this.version = version;
+
+        switch (mode) {
+            // Handling stop mode
+            case MODE_STOP:
+                // return if server is not available into the server list
+                if (!serverMap.containsKey(etcduri)) {
+                    log.debug(NO_SERVER_AVAIL);
+                    return;
+                }
+                try {
+                    // stop batch service executor thread
+                    log.debug(BATCH_SERVICE_STATUS,
+                              executorBatchService.isShutdown());
+                    executorBatchService.shutdown();
+                    // stop real time service executor thread
+                    log.debug(REAL_TIME_SERVICE_STATUS,
+                              executorRealTimeService.isShutdown());
+                    executorRealTimeService.shutdown();
+                    // closing http client
+                    httpClient.close();
+                } catch (IOException io) {
+                    log.error(E_CLIENT_STOP, io.getMessage());
+                }
+                // deletes server from gluon server list
+                deleteServer(etcduri);
+                log.debug(SERVER_STOPPED);
+                return;
+            // Handling start mode
+            case MODE_START:
+                if (serverMap.containsKey(etcduri)) {
+                    //Returns user CLI if server is already running
+                    // and logs all server info into log files
+                    log.info(SERVER_RUNNING);
+                    log.debug(ACTIVE_SERVER, serverMap.size());
+                    return;
+                }
+                // Store gluon manager object and gluon server url
+                addServer(etcduri, this);
+                // Preparing server uri
+                serverUri = etcduri + "/v2" + KEYS;
+                // Preparing server subkeys uri
+                protonKeyUri = PROTON + targetProtonKey;
+                // Starts http client
+                RequestConfig requestConfig = RequestConfig.custom().build();
+                httpClient = HttpAsyncClients.custom()
+                        .setDefaultRequestConfig(requestConfig).build();
+                httpClient.start();
+
+                // Start thread to handle and process RealTime data
+                handleRealTimeData(null);
+
+                // Start thread to handle and process batch data,
+                // iff subkeys are available
+                getAllProtonSubkeys(serverUri + protonKeyUri);
+                if (getProtonSubkeys().isEmpty()) {
+                    log.debug(NO_SUBKEYS_AVAIL);
+                    return;
+                }
+                // handle RealTime data
+                handleBatchData(0);
+                return;
+            default:
+                log.debug(INVALID_ACTION);
+
+        }
+    }
+
+    /**
+     * Handles real time data which is received from Gluon server.
+     *
+     * @param index, It will be used in recursive call of
+     *               real time monitoring method.
+     *               modified index receive from GluonConfig config file
+     */
+    private void handleRealTimeData(Long index) {
+        String realTimeUri = serverUri + protonKeyUri +
+                "/?wait=true&recursive=true";
+        if (index != null) {
+            realTimeUri += "&waitIndex=" + index;
+        }
+        HttpGet request = new HttpGet(URI.create(realTimeUri));
+        log.info(REAL_TIME_PROCESSING, realTimeUri);
+        // Starts real time executor thread
+        executorRealTimeService.execute(new Runnable() {
+            public void run() {
+                try {
+                    httpClient.execute(
+                            request, new FutureCallback<HttpResponse>() {
+
+                                @Override
+                                public void completed(HttpResponse result) {
+                                    StatusLine statusLine =
+                                            result.getStatusLine();
+                                    int statusCode = statusLine.getStatusCode();
+                                    if (statusCode ==
+                                            STATUS_CODE &&
+                                            result.getEntity() != null) {
+                                        try {
+                                            String json = EntityUtils
+                                                    .toString(result.getEntity());
+                                            GluonConfig response =
+                                                    processRealTimeResponse(json);
+                                            // Recursive call to handle
+                                            // real time data
+                                            handleRealTimeData(
+                                                    response.modifiedIndex + 1);
+                                        } catch (IOException e) {
+                                            failed(e);
+                                        }
+                                    } else {
+                                        log.error(E_REAL_TIME_PROCESSING);
+                                    }
+                                }
+
+                                @Override
+                                public void cancelled() {
+                                    log.debug("Nothing to do with " +
+                                                      "this overridden method");
+                                }
+
+                                @Override
+                                public void failed(Exception e) {
+                                    log.error(E_REAL_TIME_PROCESSING,
+                                              e.getMessage());
+                                }
+                            });
+                } catch (Exception e) {
+                    log.error(E_REAL_TIME_PROCESSING, e.getMessage());
+                }
+            }
+        });
+    }
+
+
+    /**
+     * Handles batch data which is received from Gluon server.
+     *
+     * @param subKeyIndex gets all proton subkey value
+     */
+    private void handleBatchData(int subKeyIndex) {
+        String currBatchUri = serverUri + getProtonSubkeys().get(subKeyIndex);
+        HttpGet request = new HttpGet(URI.create(currBatchUri));
+
+        if (0 == subKeyIndex) {
+            log.debug(BATCH_PROCESSING, protonKeyUri);
+        }
+        log.info(BATCH_QUERING, currBatchUri);
+        // Starts batch executor thread
+        executorBatchService.execute(new Runnable() {
+            public void run() {
+                try {
+                    httpClient.execute(request, new FutureCallback<HttpResponse>() {
+                        @Override
+                        public void completed(HttpResponse result) {
+                            StatusLine statusLine = result.getStatusLine();
+                            int statusCode = statusLine.getStatusCode();
+                            if (statusCode == STATUS_CODE &&
+                                    result.getEntity() != null) {
+                                try {
+                                    String json = EntityUtils
+                                            .toString(result.getEntity());
+                                    processBatchResponse(json);
+                                    // Stop batch executor thread
+                                    // once all gluon server subkeys processed
+                                    if (subKeyIndex ==
+                                            ((getProtonSubkeys().size()) - 1)) {
+                                        cancelled();
+                                        return;
+                                    }
+
+                                    handleBatchData(subKeyIndex + 1);
+                                } catch (IOException e) {
+                                    failed(e);
+                                }
+                            } else {
+                                log.error(E_BATCH_PROCESSING_URL, currBatchUri);
+                            }
+                        }
+
+                        @Override
+                        public void cancelled() {
+                            executorBatchService.shutdown();
+                            log.debug(BATCH_STOPPED, protonKeyUri);
+                        }
+
+                        @Override
+                        public void failed(Exception e) {
+                            log.error(E_BATCH_PROCESSING, e.getMessage());
+                        }
+                    });
+                } catch (Exception e) {
+                    log.error(E_BATCH_PROCESSING, e.getMessage());
+                }
+            }
+        });
+    }
+
+    /**
+     * Parse and process real time json data which is received from Gluon server.
+     *
+     * @param result real time json data
+     * @return GluonConfig response
+     */
+    public GluonConfig processRealTimeResponse(String result) {
+        ObjectMapper mapper = new ObjectMapper();
+        GluonConfig response = null;
+        try {
+            log.info(REAL_TIME_RECEIVED, result);
+            JsonNode jsonNode = mapper.readTree(result);
+            String action = jsonNode.get(GLUON_ACTION).asText();
+            String key = jsonNode.get(GLUON_NODE).get(GLUON_KEY).asText();
+            long mIndex = jsonNode.get(GLUON_NODE)
+                    .get(GLUON_MOD_INDEX).asLong();
+            long cIndex = jsonNode.get(GLUON_NODE)
+                    .get(GLUON_CREATE_INDEX).asLong();
+            if (action.equals(ACTION_SET)) {
+                String value = jsonNode.get(GLUON_NODE)
+                        .get(GLUON_VALUE).asText();
+                JsonNode modifyValue = mapper.readTree(value.replace("\\", ""));
+                response = new GluonConfig(action, key, modifyValue, mIndex,
+                                           cIndex);
+                setCount++;
+            } else if (action.equals(ACTION_DEL)) {
+                response = new GluonConfig(action, key, null, mIndex, cIndex);
+                delCount++;
+            } else {
+                log.debug(INVALID_ACTION);
+            }
+        } catch (IOException e) {
+            log.error(E_REAL_TIME_PROCESSING, e.getMessage());
+        }
+        processEtcdResponse(response);
+        return response;
+    }
+
+    /**
+     * Parse and process batch json data which is received from Gluon server.
+     *
+     * @param result batch json data
+     * @return GluonConfig response
+     */
+    public GluonConfig processBatchResponse(String result) {
+        ObjectMapper mapper = new ObjectMapper();
+        GluonConfig response = null;
+        try {
+            log.debug(BATCH_RECEIVED, result);
+            JsonNode jsonNode = mapper.readTree(result);
+            log.info("JSON NODE VALUE ARE: {}", jsonNode);
+            String action = jsonNode.get(GLUON_ACTION).asText();
+            JsonNode nodes = jsonNode.get(GLUON_NODE).get(GLUON_NODES);
+            if (null != nodes) {
+                for (JsonNode confNode : nodes) {
+                    String key = confNode.get(GLUON_KEY).asText();
+                    long mIndex = confNode.get(GLUON_MOD_INDEX).asLong();
+                    long cIndex = confNode.get(GLUON_CREATE_INDEX).asLong();
+                    String value = confNode.get(GLUON_VALUE).asText();
+                    log.info("JSON NODE VALUE ARE 2: {}", value);
+                    JsonNode modifyValue = mapper.readTree(value.replace("\\", ""));
+                    log.info("JSON NODE MODIFY VALUE ARE 2: {}", modifyValue);
+                    response = new GluonConfig(action, key,
+                                               modifyValue, mIndex, cIndex);
+                    getCount++;
+                    processEtcdResponse(response);
+
+                }
+            }
+        } catch (IOException e) {
+            log.error(E_BATCH_PROCESSING, e.getMessage());
+        }
+        return response;
+    }
+
+    /**
+     * Gets all the proton subkeys from Gluon server.
+     *
+     * @param subKeyUrl get every proton subkey Url
+     */
+    public void getAllProtonSubkeys(String subKeyUrl) {
+        HttpClient client = HttpClientBuilder.create().build();
+        HttpGet request = new HttpGet(subKeyUrl);
+        ObjectMapper mapper = new ObjectMapper();
+        try {
+            HttpResponse result = client.execute(request);
+            StatusLine statusLine = result.getStatusLine();
+            int statusCode = statusLine.getStatusCode();
+            if (statusCode == STATUS_CODE && result.getEntity() != null) {
+                String json = EntityUtils
+                        .toString(result.getEntity());
+                log.debug(SUBKEYS_RECEIVED, json);
+                JsonNode jsonNode = mapper.readTree(json);
+                JsonNode nodes = jsonNode.get(GLUON_NODE).get(GLUON_NODES);
+
+                for (JsonNode confNode : nodes) {
+                    String key = confNode.get(GLUON_KEY).asText();
+                    storeProtonSubkey(key);
+                }
+            }
+        } catch (IOException e) {
+            log.error(E_SUBKEYS_PROCESSING, subKeyUrl);
+        }
+        return;
+    }
+
+    /**
+     * Gets all the proton subkeys from Gluon server.
+     *
+     * @param uri get every proton subkey Url
+     * @return version server version
+     */
+    public String getGluonServerVersion(String uri) {
+        HttpClient client = HttpClientBuilder.create().build();
+        HttpGet request = new HttpGet(uri);
+        ObjectMapper mapper = new ObjectMapper();
+        String version = null;
+        try {
+            HttpResponse result = client.execute(request);
+            StatusLine statusLine = result.getStatusLine();
+            int statusCode = statusLine.getStatusCode();
+            if (statusCode == STATUS_CODE && result.getEntity() != null) {
+                String json = EntityUtils
+                        .toString(result.getEntity());
+                JsonNode jsonNode = mapper.readTree(json);
+                version = jsonNode.get("etcdserver").asText();
+            }
+        } catch (IOException e) {
+            log.error(PROCESSING_FAILED);
+        }
+        return version;
+    }
+
+    /**
+     * Gluon data updating and deleting into/from NetworkConfig datastore.
+     * config.apply will raise GluonConfig.class event for add,
+     * get and delete operations.
+     *
+     * @param gluonConfigMessage Etcdresponse data after parsing
+     */
+    public void processEtcdResponse(GluonConfig gluonConfigMessage) {
+
+        NetworkConfigService configService =
+                DefaultServiceDirectory.getService(NetworkConfigService.class);
+        if (gluonConfigMessage.action.equals(ACTION_SET) ||
+                gluonConfigMessage.action.equals(ACTION_GET)) {
+            GluonConfig config = configService
+                    .addConfig(gluonConfigMessage.key, GluonConfig.class);
+            config.setEtcdResponse(gluonConfigMessage);
+            config.apply();
+            log.info(DATA_UPDATED);
+        } else if (gluonConfigMessage.action.equals(ACTION_DEL)) {
+            configService.removeConfig(gluonConfigMessage.key,
+                                       GluonConfig.class);
+            log.info(DATA_REMOVED);
+        } else {
+            log.info(INVALID_ACTION);
+        }
+    }
+
+    /**
+     * Returns set statistics.
+     *
+     * @return setCount
+     */
+    public int getSetCount() {
+        return setCount;
+    }
+
+    /**
+     * Returns get statistics.
+     *
+     * @return getCount
+     */
+    public int getGetCount() {
+        return getCount;
+    }
+
+    /**
+     * Returns delete statistics.
+     *
+     * @return delCount
+     */
+    public int getDelCount() {
+        return delCount;
+    }
+
+    /**
+     * Returns proton subkeys.
+     *
+     * @return subkeys
+     */
+    public List<String> getProtonSubkeys() {
+        return subKeys;
+    }
+
+    /**
+     * store proton subkeys.
+     *
+     * @param keys proton subkey
+     */
+    public void storeProtonSubkey(String keys) {
+        subKeys.add(keys);
+    }
+}
+
diff --git a/apps/gluon/src/main/java/org/onosproject/gluon/rsc/cli/GluonServerCommand.java b/apps/gluon/src/main/java/org/onosproject/gluon/rsc/cli/GluonServerCommand.java
new file mode 100755
index 0000000..6dec71f
--- /dev/null
+++ b/apps/gluon/src/main/java/org/onosproject/gluon/rsc/cli/GluonServerCommand.java
@@ -0,0 +1,231 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed 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.onosproject.gluon.rsc.cli;
+
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.commands.Option;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.gluon.rsc.GluonServer;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import static org.onosproject.gluon.manager.GluonManager.createServer;
+import static org.onosproject.gluon.rsc.GluonConstants.GLUON_DEFAULT_PORT;
+import static org.onosproject.gluon.rsc.GluonConstants.GLUON_HTTP;
+import static org.onosproject.gluon.rsc.GluonConstants.INVALID_MODE;
+import static org.onosproject.gluon.rsc.GluonConstants.INVALID_RANGE;
+import static org.onosproject.gluon.rsc.GluonConstants.KEY_TYPE;
+import static org.onosproject.gluon.rsc.GluonConstants.MODE_START;
+import static org.onosproject.gluon.rsc.GluonConstants.MODE_STOP;
+import static org.onosproject.gluon.rsc.GluonConstants.NO_SERVER_AVAIL;
+import static org.onosproject.gluon.rsc.GluonConstants.NO_SERVER_AVAIL_ON_PORT;
+import static org.onosproject.gluon.rsc.GluonConstants.PROTON_KEY_SUPPORT;
+import static org.onosproject.gluon.rsc.GluonConstants.WRONG_INPUT;
+import static org.onosproject.gluon.rsc.GluonConstants.WRONG_INPUT_TYPE;
+import static org.onosproject.gluon.rsc.GluonConstants.WRONG_IP_FORMAT;
+
+
+/**
+ * To monitor Gluon etcd server.
+ */
+@Command(scope = "onos", name = "gluon",
+        description = "Support for reading Gluon data via etcd client")
+public class GluonServerCommand extends AbstractShellCommand {
+
+    @Option(name = "-m", aliases = "--mode",
+            description = "Gluon server monitoring mode: start; stop",
+            required = false, multiValued = false)
+    String mode = MODE_START;
+
+    @Option(name = "-i", aliases = "--server-ip",
+            description = "Gluon server ip address",
+            required = true, multiValued = false)
+    String ipAddress = null;
+
+    @Option(name = "-p", aliases = "--port", description = "Gluon server port",
+            required = false, multiValued = false)
+    String port = GLUON_DEFAULT_PORT;
+
+    @Option(name = "-k", aliases = "--key",
+            description = "Proton key : net-l3vpn",
+            required = false, multiValued = false)
+    String protonKey = KEY_TYPE;
+
+    public String version = null;
+
+    @Override
+    public void execute() {
+        try {
+            if (ipAddress != null && isValidIP(ipAddress) && isValidPort(port)
+                    && isValidMode(mode) && isValidProtonKey(protonKey)
+                    && isSeverReachable()) {
+                String url = GLUON_HTTP + ipAddress + ":" + port;
+                if (isEtcdSeverAvailable()) {
+                    //Gets gluon server running version
+                    version = gluonServerVersion();
+                    createServer(url, protonKey, mode, version);
+                } else {
+                    log.info(NO_SERVER_AVAIL_ON_PORT);
+                    return;
+                }
+            } else {
+                log.info(WRONG_INPUT);
+            }
+        } catch (Exception e) {
+            print(null, e.getMessage());
+        }
+    }
+
+    /**
+     * Returns boolean if given IP format is valid.
+     *
+     * @param ipAddr Ip Address
+     * @return boolean
+     */
+    public boolean isValidIP(String ipAddr) {
+        boolean isIPaddrValid;
+        Pattern pattern = Pattern.compile("^(\\d{1,3})\\" +
+                                                  ".(\\d{1,3})\\" +
+                                                  ".(\\d{1,3})\\.(\\d{1,3})$");
+        Matcher matcher = pattern.matcher(ipAddr);
+        if (matcher.find()) {
+            isIPaddrValid = true;
+        } else {
+            print(WRONG_IP_FORMAT);
+            isIPaddrValid = false;
+        }
+        return isIPaddrValid;
+    }
+
+    /**
+     * Returns boolean if given port value is valid.
+     *
+     * @param portValue port number
+     * @return boolean
+     */
+    public boolean isValidPort(String portValue) {
+        boolean isPortValid = false;
+        try {
+            Integer portNum = Integer.parseInt(portValue);
+            if (portNum >= 0 && portNum <= 65535) {
+                isPortValid = true;
+            } else {
+                print(INVALID_RANGE);
+                isPortValid = false;
+            }
+        } catch (NumberFormatException nfe) {
+            print(WRONG_INPUT_TYPE);
+        }
+        return isPortValid;
+    }
+
+    /**
+     * Returns boolean if given mode is valid.
+     *
+     * @param mode server mode
+     * @return boolean
+     */
+    public boolean isValidMode(String mode) {
+        boolean isValidMode;
+        if (mode.equalsIgnoreCase(MODE_START) ||
+                mode.equalsIgnoreCase(MODE_STOP)) {
+            isValidMode = true;
+        } else {
+            print(INVALID_MODE);
+            isValidMode = false;
+        }
+        return isValidMode;
+    }
+
+    /**
+     * Returns boolean if given mode is valid.
+     *
+     * @param key key
+     * @return boolean
+     */
+    public boolean isValidProtonKey(String key) {
+        boolean isValidProtonKey = true;
+        if (!KEY_TYPE.equalsIgnoreCase(key)) {
+            print(PROTON_KEY_SUPPORT);
+            isValidProtonKey = false;
+        }
+        return isValidProtonKey;
+    }
+
+    /**
+     * Returns version of gluon server.
+     *
+     * @return String
+     */
+
+    public String gluonServerVersion() {
+        String serverUrl = GLUON_HTTP + this.ipAddress + ":" +
+                this.port + "/version";
+        GluonServer gluonServer = new GluonServer();
+        String gluonversion = gluonServer.getGluonServerVersion(serverUrl);
+        String[] versionArray = gluonversion.split("\\.");
+        version = versionArray[0];
+        return version;
+    }
+
+    /**
+     * Returns reachability of Gluon server.
+     *
+     * @return isSeverReachable
+     */
+    public boolean isSeverReachable() {
+        boolean isSeverReachable = false;
+        try {
+            InetAddress inet = InetAddress.getByName(ipAddress);
+            if (inet.isReachable(5000)) {
+                isSeverReachable = true;
+            } else {
+                isSeverReachable = false;
+                print(NO_SERVER_AVAIL);
+            }
+        } catch (IOException e) {
+            isSeverReachable = false;
+            log.error("Check server process is failed with {} ",
+                      e.getMessage());
+        }
+        return isSeverReachable;
+    }
+
+    /**
+     * Returns availability of Gluon server.
+     *
+     * @return isServerAvailable
+     */
+    public boolean isEtcdSeverAvailable() {
+        String serverUrl = GLUON_HTTP + ipAddress + ":" + port;
+        boolean isServerAvailable;
+        try {
+            URL url = new URL(serverUrl);
+            URLConnection connection = url.openConnection();
+            connection.connect();
+            isServerAvailable = true;
+        } catch (IOException e) {
+            print(NO_SERVER_AVAIL_ON_PORT);
+            isServerAvailable = false;
+        }
+        return isServerAvailable;
+    }
+}
diff --git a/apps/gluon/src/main/java/org/onosproject/gluon/rsc/cli/GluonServerListCommand.java b/apps/gluon/src/main/java/org/onosproject/gluon/rsc/cli/GluonServerListCommand.java
new file mode 100755
index 0000000..3ef4a43
--- /dev/null
+++ b/apps/gluon/src/main/java/org/onosproject/gluon/rsc/cli/GluonServerListCommand.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed 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.onosproject.gluon.rsc.cli;
+
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.commands.Option;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.gluon.manager.GluonManager;
+import org.onosproject.gluon.rsc.GluonServer;
+
+import java.util.Map;
+
+import static org.onosproject.gluon.manager.GluonManager.getAllServersIP;
+import static org.onosproject.gluon.rsc.GluonConstants.ACTIVE_SERVER;
+import static org.onosproject.gluon.rsc.GluonConstants.GLUON_DEFAULT_PORT;
+import static org.onosproject.gluon.rsc.GluonConstants.GLUON_HTTP;
+import static org.onosproject.gluon.rsc.GluonConstants.SERVER_POOL;
+
+/**
+ * Supports for querying Gluon Servers list and statistics.
+ */
+@Command(scope = "onos", name = "gluon-server-list",
+        description = "Gluon server list")
+public class GluonServerListCommand extends AbstractShellCommand {
+
+    @Option(name = "-i", aliases = "--server-ip",
+            description = "Supports for querying Gluon server statistics",
+            required = false, multiValued = false)
+    String ipAddress = null;
+
+    @Option(name = "-p", aliases = "--port", description = "Gluon server port",
+            required = false, multiValued = false)
+    String port = GLUON_DEFAULT_PORT;
+
+    protected Map<String, GluonServer> serverMap = getAllServersIP();
+
+    private static final String SERVER_STATISTICS =
+            "Server %s details:\nVersion: %s\nPort: %s\nReal time data:\n" +
+                    "\tSet Statistics   : %s\n\tDelete Statistics: %s\n" +
+                    "Batch data:\n\tGet Statistics   : %s";
+
+
+    @Override
+    public void execute() {
+        try {
+            String serverUrl = GLUON_HTTP + ipAddress + ":" + port;
+            if (ipAddress != null && checkServerPool(serverUrl)) {
+                for (Map.Entry<String,
+                        GluonServer> server : serverMap.entrySet()) {
+
+                    if (serverUrl.equals(server.getKey())) {
+                        //Gets Etcd object reference
+                        GluonServer gluonServer = server.getValue();
+                        //Gets Etcd version from server list
+                        print(SERVER_STATISTICS, ipAddress, gluonServer.version,
+                              port, gluonServer.getSetCount(),
+                              gluonServer.getDelCount(),
+                              gluonServer.getGetCount());
+                    }
+                }
+            } else {
+                int totalServers = GluonManager.getTotalServers();
+                log.info(ACTIVE_SERVER, totalServers);
+                print("Number of active servers: " + totalServers);
+                printServersIP();
+            }
+        } catch (Exception e) {
+            print(null, e.getMessage());
+        }
+    }
+
+    /**
+     * Prints all servers IPs in table format.
+     */
+    protected void printServersIP() {
+        int countServer = 1;
+        for (Map.Entry<String, GluonServer> server : serverMap.entrySet()) {
+            String serverUrl = server.getKey();
+            String[] serverIP = serverUrl.split("//");
+            print("Server %d: %s", countServer, serverIP[1]);
+            countServer++;
+        }
+    }
+
+    /**
+     * Returns boolean if given IP available in server pool.
+     *
+     * @param ipAddr Ip Address
+     * @return boolean
+     */
+    protected boolean checkServerPool(String ipAddr) {
+        boolean isServerAvailable;
+        if (serverMap.containsKey(ipAddr)) {
+            isServerAvailable = true;
+        } else {
+            print(SERVER_POOL);
+            isServerAvailable = false;
+        }
+        return isServerAvailable;
+    }
+}
diff --git a/apps/gluon/src/main/java/org/onosproject/gluon/rsc/cli/package-info.java b/apps/gluon/src/main/java/org/onosproject/gluon/rsc/cli/package-info.java
new file mode 100755
index 0000000..274ff4d
--- /dev/null
+++ b/apps/gluon/src/main/java/org/onosproject/gluon/rsc/cli/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed 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.
+ */
+
+/**
+ * Gluon Shim Application Command line interface package.
+ */
+package org.onosproject.gluon.rsc.cli;
\ No newline at end of file
diff --git a/apps/gluon/src/main/java/org/onosproject/gluon/rsc/package-info.java b/apps/gluon/src/main/java/org/onosproject/gluon/rsc/package-info.java
new file mode 100755
index 0000000..f2506ea
--- /dev/null
+++ b/apps/gluon/src/main/java/org/onosproject/gluon/rsc/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed 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.
+ */
+
+/**
+ * Gluon Shim Application resource package.
+ */
+package org.onosproject.gluon.rsc;
\ No newline at end of file
diff --git a/apps/gluon/src/main/resources/OSGI-INF/blueprint/shell-config.xml b/apps/gluon/src/main/resources/OSGI-INF/blueprint/shell-config.xml
new file mode 100755
index 0000000..82809d2
--- /dev/null
+++ b/apps/gluon/src/main/resources/OSGI-INF/blueprint/shell-config.xml
@@ -0,0 +1,27 @@
+<!--
+  ~ Copyright 2017-present Open Networking Foundation
+  ~
+  ~ Licensed 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.
+  -->
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
+
+  <command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.1.0">
+    <command>
+      <action class="org.onosproject.gluon.rsc.cli.GluonServerCommand"/>
+    </command>
+
+    <command>
+      <action class="org.onosproject.gluon.rsc.cli.GluonServerListCommand"/>
+    </command>
+  </command-bundle>
+</blueprint>
diff --git a/apps/pom.xml b/apps/pom.xml
index 7978976..3351e39 100644
--- a/apps/pom.xml
+++ b/apps/pom.xml
@@ -89,6 +89,7 @@
         <module>yang</module>
         <module>openroadm</module>
         <module>netconf/client</module>
+	<module>gluon</module>
     </modules>
 
     <properties>
diff --git a/lib/BUCK b/lib/BUCK
index 1013dcf..e3b6a78 100644
--- a/lib/BUCK
+++ b/lib/BUCK
@@ -933,6 +933,33 @@
 )
 
 remote_jar (
+  name = 'org.apache.httpcomponents.httpasyncclient-osgi',
+  out = 'httpasyncclient-osgi-4.1.2.jar',
+  url = 'mvn:org.apache.httpcomponents:httpasyncclient-osgi:jar:4.1.2',
+  sha1 = '17eccd8d9f2803ee95e80ee8283155432600e17b',
+  maven_coords = 'org.apache.httpcomponents:httpasyncclient-osgi:4.1.2',
+  visibility = [ 'PUBLIC' ],
+)
+
+remote_jar (
+  name = 'org.apache.httpcomponents.httpcore-nio',
+  out = 'httpcore-nio-4.4.4.jar',
+  url = 'mvn:org.apache.httpcomponents:httpcore-nio:jar:4.4.4',
+  sha1 = '16badfc2d99db264c486ba8c57ae577301a58bd9',
+  maven_coords = 'org.apache.httpcomponents:httpcore-nio:jar:NON-OSGI:4.4.4',
+  visibility = [ 'PUBLIC' ],
+)
+
+remote_jar (
+  name = 'org.apache.karaf.jaas',
+  out = 'org.apache.karaf.jaas.modules-3.0.5.jar',
+  url = 'mvn:org.apache.karaf.jaas:org.apache.karaf.jaas.modules:jar:3.0.5',
+  sha1 = '008ff2ef5fa49f346789dfa8919c0537b6261864',
+  maven_coords = 'org.apache.karaf.jaas:org.apache.karaf.jaas.modules:3.0.5',
+  visibility = [ 'PUBLIC' ],
+)
+
+remote_jar (
   name = 'org.apache.karaf.system.core',
   out = 'org.apache.karaf.system.core-3.0.8.jar',
   url = 'mvn:org.apache.karaf.system:org.apache.karaf.system.core:jar:3.0.8',
diff --git a/lib/deps.json b/lib/deps.json
index 5dd2f70..b5675dd 100644
--- a/lib/deps.json
+++ b/lib/deps.json
@@ -196,6 +196,9 @@
     "org.apache.felix.scr.annotations": "mvn:org.apache.felix:org.apache.felix.scr.annotations:1.9.12",
     "org.apache.karaf.features.core": "mvn:org.apache.karaf.features:org.apache.karaf.features.core:3.0.8",
     "org.apache.karaf.shell.console": "mvn:org.apache.karaf.shell:org.apache.karaf.shell.console:3.0.8",
+    "org.apache.httpcomponents.httpasyncclient-osgi": "mvn:org.apache.httpcomponents:httpasyncclient-osgi:4.1.2",
+    "org.apache.httpcomponents.httpcore-nio": "mvn:org.apache.httpcomponents:httpcore-nio:4.4.4",
+    "org.apache.karaf.jaas": "mvn:org.apache.karaf.jaas:org.apache.karaf.jaas.modules:3.0.5",
     "org.apache.karaf.system.core": "mvn:org.apache.karaf.system:org.apache.karaf.system.core:3.0.8",
     "org.apache.servicemix.bundles.snmp4j": "mvn:org.apache.servicemix.bundles:org.apache.servicemix.bundles.snmp4j:2.3.4_1",
     "org.osgi.compendium": "mvn:org.osgi:org.osgi.compendium:5.0.0",
diff --git a/modules.defs b/modules.defs
index b18fcbe..350fc38 100644
--- a/modules.defs
+++ b/modules.defs
@@ -208,6 +208,7 @@
     '//apps/l3vpn:onos-apps-l3vpn-oar',
     '//apps/openroadm:onos-apps-openroadm-oar',
     '//apps/artemis:onos-apps-artemis-oar',
+    '//apps/gluon:onos-apps-gluon-oar',
 ]
 
 PROTOCOL_APPS = [