Implements flow tracer in Openstack Networking UI

Change-Id: I6747de157e63b4d6ffa67274b623b29db311d2e3
diff --git a/apps/openstacknetworkingui/BUCK b/apps/openstacknetworkingui/BUCK
index ee452bd..ce5e71e 100644
--- a/apps/openstacknetworkingui/BUCK
+++ b/apps/openstacknetworkingui/BUCK
@@ -7,6 +7,13 @@
   '//lib:jersey-client',
   '//cli:onos-cli',
   '//lib:org.apache.karaf.shell.console',
+  '//lib:sshd-core',
+  '//apps/openstacknode/api:onos-apps-openstacknode-api',
+  '//apps/openstacknetworking/api:onos-apps-openstacknetworking-api',
+]
+
+EXCLUDED_BUNDLES = [
+  '//lib:sshd-core',
 ]
 
 TEST_DEPS = [
@@ -18,11 +25,6 @@
 osgi_jar_with_tests (
   deps = COMPILE_DEPS,
   test_deps = TEST_DEPS,
-  web_context = '/onos/openstacknetworkingui',
-  api_title = 'OpenStack Networking UI REST API',
-  api_version = '0.9',
-  api_description = 'OpenStack Networking UI REST API',
-  api_package = 'org.onosproject.openstacknetworkingui.web',
 )
 
 onos_app (
@@ -31,4 +33,8 @@
   category = 'GUI',
   url = 'http://onosproject.org',
   description = 'Openstack Networking UI Service',
+  excluded_bundles = EXCLUDED_BUNDLES,
+  required_apps = [
+      'org.onosproject.openstacknetworking',
+  ]
 )
diff --git a/apps/openstacknetworkingui/pom.xml b/apps/openstacknetworkingui/pom.xml
index 3e04aa4..58eed47 100644
--- a/apps/openstacknetworkingui/pom.xml
+++ b/apps/openstacknetworkingui/pom.xml
@@ -37,13 +37,6 @@
         <onos.app.category>UI</onos.app.category>
         <onos.app.url>http://onosproject.org</onos.app.url>
         <onos.app.readme>OpenStack Networking UI Application</onos.app.readme>
-        <web.context>/onos/openstacknetworkingui</web.context>
-        <api.version>1.0.0</api.version>
-        <api.title>OpenStack Networking UI REST API</api.title>
-        <api.description>
-            APIs for interacting with OpenStack Networking Monitoring server.
-        </api.description>
-        <api.package>org.onosproject.openstacknetworkingui.web</api.package>
     </properties>
 
     <dependencies>
@@ -71,6 +64,23 @@
         </dependency>
 
         <dependency>
+            <groupId>org.onosproject</groupId>
+            <artifactId>onos-apps-openstacknetworking-api</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.onosproject</groupId>
+            <artifactId>onos-apps-openstacknode-api</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.sshd</groupId>
+            <artifactId>sshd-core</artifactId>
+        </dependency>
+
+        <dependency>
             <groupId>org.apache.karaf.shell</groupId>
             <artifactId>org.apache.karaf.shell.console</artifactId>
         </dependency>
diff --git a/apps/openstacknetworkingui/src/main/java/org/onosproject/openstacknetworkingui/web/package-info.java b/apps/openstacknetworkingui/src/main/java/org/onosproject/openstacknetworkingui/FlowTraceResultParser.java
similarity index 64%
rename from apps/openstacknetworkingui/src/main/java/org/onosproject/openstacknetworkingui/web/package-info.java
rename to apps/openstacknetworkingui/src/main/java/org/onosproject/openstacknetworkingui/FlowTraceResultParser.java
index 570f9cf..e18a3e5 100644
--- a/apps/openstacknetworkingui/src/main/java/org/onosproject/openstacknetworkingui/web/package-info.java
+++ b/apps/openstacknetworkingui/src/main/java/org/onosproject/openstacknetworkingui/FlowTraceResultParser.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2017-present Open Networking Foundation
+ * Copyright 2018-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.
@@ -13,8 +13,12 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+package org.onosproject.openstacknetworkingui;
 
 /**
- *  Web implementation of OpenStack Networking UI service.
+ * Interface class for parsing flow trace string result to json with respect to OVS version.
  */
-package org.onosproject.openstacknetworkingui.web;
\ No newline at end of file
+public interface FlowTraceResultParser {
+
+    String flowTraceResultInJson(String outputStream, String hostName);
+}
diff --git a/apps/openstacknetworkingui/src/main/java/org/onosproject/openstacknetworkingui/OpenstackNetworkingUiManager.java b/apps/openstacknetworkingui/src/main/java/org/onosproject/openstacknetworkingui/OpenstackNetworkingUiManager.java
index 4a9485e..848cfc7 100644
--- a/apps/openstacknetworkingui/src/main/java/org/onosproject/openstacknetworkingui/OpenstackNetworkingUiManager.java
+++ b/apps/openstacknetworkingui/src/main/java/org/onosproject/openstacknetworkingui/OpenstackNetworkingUiManager.java
@@ -15,7 +15,6 @@
  */
 package org.onosproject.openstacknetworkingui;
 
-import com.fasterxml.jackson.databind.node.ObjectNode;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Streams;
 import org.apache.felix.scr.annotations.Activate;
@@ -117,32 +116,6 @@
         log.info("Stopped");
     }
 
-    @Override
-    public void sendMessage(String type, ObjectNode payload) {
-        messageHandler.sendMessagetoUi(type, payload);
-    }
-
-    @Override
-    public void setRestServerIp(String ipAddress) {
-        messageHandler.setRestUrl(ipAddress);
-    }
-
-    @Override
-    public String restServerUrl() {
-        return messageHandler.restUrl();
-    }
-
-    @Override
-    public void setRestServerAuthInfo(String id, String password) {
-        messageHandler.setRestAuthInfo(id, password);
-    }
-
-    @Override
-    public String restServerAuthInfo() {
-        return messageHandler.restAuthInfo();
-    }
-
-
     private Optional<Port> vxlanPort(DeviceId deviceId) {
         return deviceService.getPorts(deviceId)
                 .stream()
@@ -178,5 +151,4 @@
     private LinkDescription createLinkDescription(ConnectPoint srcConnectPoint, ConnectPoint dstConnectPoint) {
         return new DefaultLinkDescription(srcConnectPoint, dstConnectPoint, Type.DIRECT, true);
     }
-
 }
diff --git a/apps/openstacknetworkingui/src/main/java/org/onosproject/openstacknetworkingui/OpenstackNetworkingUiMessageHandler.java b/apps/openstacknetworkingui/src/main/java/org/onosproject/openstacknetworkingui/OpenstackNetworkingUiMessageHandler.java
index ec01cec..8668096 100644
--- a/apps/openstacknetworkingui/src/main/java/org/onosproject/openstacknetworkingui/OpenstackNetworkingUiMessageHandler.java
+++ b/apps/openstacknetworkingui/src/main/java/org/onosproject/openstacknetworkingui/OpenstackNetworkingUiMessageHandler.java
@@ -15,38 +15,38 @@
  */
 package org.onosproject.openstacknetworkingui;
 
-import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.node.ArrayNode;
 import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.google.common.base.Charsets;
 import com.google.common.base.Strings;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Sets;
 import com.google.common.collect.Streams;
-import org.apache.commons.io.IOUtils;
+import org.apache.sshd.client.SshClient;
+import org.apache.sshd.client.channel.ClientChannel;
+import org.apache.sshd.client.channel.ClientChannelEvent;
+import org.apache.sshd.client.future.OpenFuture;
+import org.apache.sshd.client.session.ClientSession;
+import org.apache.sshd.common.util.io.NoCloseInputStream;
 import org.onlab.osgi.ServiceDirectory;
-import org.onlab.util.DefaultHashMap;
-import org.onosproject.cluster.ClusterService;
-import org.onosproject.cluster.NodeId;
-import org.onosproject.mastership.MastershipService;
-import org.onosproject.net.AnnotationKeys;
-import org.onosproject.net.Annotations;
+import org.onlab.packet.IpAddress;
 import org.onosproject.net.Device;
 import org.onosproject.net.DeviceId;
 import org.onosproject.net.Element;
 import org.onosproject.net.Host;
 import org.onosproject.net.HostId;
 import org.onosproject.net.Path;
-import org.onosproject.net.config.NetworkConfigService;
-import org.onosproject.net.config.basics.BasicDeviceConfig;
-import org.onosproject.net.config.basics.BasicElementConfig;
-import org.onosproject.net.device.DeviceEvent;
 import org.onosproject.net.device.DeviceService;
-import org.onosproject.net.driver.Driver;
-import org.onosproject.net.driver.DriverService;
 import org.onosproject.net.host.HostService;
 import org.onosproject.net.topology.PathService;
+import org.onosproject.openstacknetworking.api.InstancePort;
+import org.onosproject.openstacknetworking.api.InstancePortService;
+import org.onosproject.openstacknetworking.api.OpenstackNetworkService;
+import org.onosproject.openstacknode.api.OpenstackNode;
+import org.onosproject.openstacknode.api.OpenstackNodeService;
+import org.onosproject.openstacknode.api.OpenstackSshAuth;
 import org.onosproject.ui.JsonUtils;
 import org.onosproject.ui.RequestHandler;
 import org.onosproject.ui.UiConnection;
@@ -59,32 +59,21 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import javax.ws.rs.client.Client;
-import javax.ws.rs.client.ClientBuilder;
-import javax.ws.rs.client.Entity;
-import javax.ws.rs.client.Invocation;
-import javax.ws.rs.client.WebTarget;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
 import java.io.ByteArrayInputStream;
-import java.io.IOException;
+import java.io.ByteArrayOutputStream;
 import java.io.InputStream;
-import java.nio.charset.StandardCharsets;
-import java.util.Base64;
+import java.io.OutputStream;
 import java.util.Collection;
 import java.util.List;
-import java.util.Map;
-import java.util.Objects;
+import java.util.Optional;
 import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.TimeUnit;
 
-import static com.google.common.base.Strings.isNullOrEmpty;
-import static org.onosproject.net.AnnotationKeys.DRIVER;
+import static java.util.concurrent.Executors.newSingleThreadExecutor;
+import static org.onlab.util.Tools.groupedThreads;
 import static org.onosproject.net.DefaultEdgeLink.createEdgeLink;
-import static org.onosproject.net.Device.Type.SWITCH;
-import static org.onosproject.net.config.basics.BasicElementConfig.LOC_TYPE_GEO;
-import static org.onosproject.net.config.basics.BasicElementConfig.LOC_TYPE_GRID;
-import static org.onosproject.net.device.DeviceEvent.Type.DEVICE_REMOVED;
+import static org.onosproject.openstacknetworking.api.Constants.DEFAULT_GATEWAY_MAC_STR;
 
 /**
  * OpenStack Networking UI message handler.
@@ -99,24 +88,32 @@
     private static final String SRC_IP = "srcIp";
     private static final String DST_IP = "dstIp";
     private static final String ANNOTATION_SEGMENT_ID = "segId";
-    private static final String AUTHORIZATION = "Authorization";
-    private static final String COMMAND = "command";
-    private static final String FLOW_TRACE = "flowtrace";
-    private static final String REVERSE = "reverse";
-    private static final String TRANSACTION_ID = "transaction_id";
-    private static final String TRANSACTION_VALUE = "sona";
-    private static final String APP_REST_URL = "app_rest_url";
-    private static final String MATCHING_FIELDS = "matchingfields";
-    private static final String SOURCE_IP = "source_ip";
-    private static final String DESTINATION_IP = "destination_ip";
-    private static final String TO_GATEWAY = "to_gateway";
-    private static final String IP_PROTOCOL = "ip_protocol";
-    private static final String HTTP = "http://";
-    private static final String OPENSTACK_NETWORKING_UI_RESULT = ":8181/onos/openstacknetworkingui/result";
 
     private static final String ID = "id";
     private static final String MODE = "mode";
     private static final String MOUSE = "mouse";
+    private static final String TRACE_RESULT = "traceResult";
+    private static final String IS_SUCCESS = "isSuccess";
+    private static final String TRACE_SUCCESS = "traceSuccess";
+    private static final String FLOW_TRACE_RESULT = "flowTraceResult";
+    private static final String SRC_DEVICE_ID = "srcDeviceId";
+    private static final String DST_DEVICE_ID = "dstDeviceId";
+    private static final String SW_VERSION = "sw";
+    private static final String OVS_VERSION_2_8 = "2.8";
+    private static final String OVS_VERSION_2_6 = "2.6";
+    private static final String FLAT = "FLAT";
+    private static final String VXLAN = "VXLAN";
+    private static final String VLAN = "VLAN";
+    private static final String DL_DST = "dl_dst=";
+    private static final String NW_DST = "nw_dst=";
+    private static final String DEFAULT_REQUEST_STRING = "sudo ovs-appctl ofproto/trace br-int ip,in_port=";
+    private static final String NW_SRC = "nw_src=";
+    private static final String COMMA = ",";
+
+
+    private static final long TIMEOUT_MS = 5000;
+    private static final long WAIT_OUTPUT_STREAM_SECOND = 2;
+    private static final int SSH_PORT = 22;
 
     private enum Mode { IDLE, MOUSE }
 
@@ -125,21 +122,16 @@
     private DeviceService deviceService;
     private HostService hostService;
     private PathService pathService;
-    private ClusterService clusterService;
-    private DriverService driverService;
-    private MastershipService mastershipService;
+    private OpenstackNodeService osNodeService;
+    private InstancePortService instancePortService;
+    private OpenstackNetworkService osNetService;
     private String restUrl;
     private String restAuthInfo;
     private Mode currentMode = Mode.IDLE;
     private Element elementOfNote;
-    private final Client client = ClientBuilder.newClient();
-    private static Map<String, ObjectNode> metaUi = new ConcurrentHashMap<>();
-    private static final DefaultHashMap<DeviceEvent.Type, String> DEVICE_EVENT =
-            new DefaultHashMap<>("updateDevice");
 
-    static {
-        DEVICE_EVENT.put(DEVICE_REMOVED, "removeDevice");
-    }
+    private final ExecutorService eventExecutor = newSingleThreadExecutor(
+            groupedThreads(this.getClass().getSimpleName(), "event-handler", log));
 
     @Override
     public void init(UiConnection connection, ServiceDirectory directory) {
@@ -147,107 +139,11 @@
         deviceService = directory.get(DeviceService.class);
         hostService = directory.get(HostService.class);
         pathService = directory.get(PathService.class);
-        clusterService = directory.get(ClusterService.class);
-        driverService = directory.get((DriverService.class));
-        mastershipService = directory.get(MastershipService.class);
-
-        // Removes non switch devices such as an ovsdb device
-        removeNonSwitchDevices();
+        osNodeService = directory.get(OpenstackNodeService.class);
+        instancePortService = directory.get(InstancePortService.class);
+        osNetService = directory.get(OpenstackNetworkService.class);
     }
 
-    private void removeNonSwitchDevices() {
-        Streams.stream(deviceService.getAvailableDevices())
-                .filter(device -> device.type() != SWITCH)
-                .forEach(device -> sendMessage(deviceMessage(new DeviceEvent(DEVICE_REMOVED, device))));
-    }
-
-    // Produces a device event message to the client.
-    protected ObjectNode deviceMessage(DeviceEvent event) {
-        Device device = event.subject();
-        String uiType = device.annotations().value(AnnotationKeys.UI_TYPE);
-        String driverName = device.annotations().value(DRIVER);
-        Driver driver = driverName == null ? null : driverService.getDriver(driverName);
-        String devType = uiType != null ? uiType :
-                (driver != null ? driver.getProperty(AnnotationKeys.UI_TYPE) : null);
-        if (devType == null) {
-            devType = device.type().toString().toLowerCase();
-        }
-        String name = device.annotations().value(AnnotationKeys.NAME);
-        name = isNullOrEmpty(name) ? device.id().toString() : name;
-
-        ObjectNode payload = objectNode()
-                .put("id", device.id().toString())
-                .put("type", devType)
-                .put("online", deviceService.isAvailable(device.id()))
-                .put("master", master(device.id()));
-
-        payload.set("labels", labels("", name, device.id().toString()));
-        payload.set("props", props(device.annotations()));
-
-        BasicDeviceConfig cfg = get(NetworkConfigService.class)
-                .getConfig(device.id(), BasicDeviceConfig.class);
-        if (!addLocation(cfg, payload)) {
-            addMetaUi(device.id().toString(), payload);
-        }
-
-        String type = DEVICE_EVENT.get(event.type());
-        return JsonUtils.envelope(type, payload);
-    }
-
-    // Returns the name of the master node for the specified device id.
-    private String master(DeviceId deviceId) {
-        NodeId master = mastershipService.getMasterFor(deviceId);
-        return master != null ? master.toString() : "";
-    }
-
-    // Encodes the specified list of labels a JSON array.
-    private ArrayNode labels(String... labels) {
-        ArrayNode json = arrayNode();
-        for (String label : labels) {
-            json.add(label);
-        }
-        return json;
-    }
-
-    private boolean addLocation(BasicElementConfig cfg, ObjectNode payload) {
-        if (cfg != null) {
-            String locType = cfg.locType();
-            boolean isGeo = Objects.equals(locType, LOC_TYPE_GEO);
-            boolean isGrid = Objects.equals(locType, LOC_TYPE_GRID);
-            if (isGeo || isGrid) {
-                try {
-                    ObjectNode loc = objectNode()
-                            .put("locType", locType)
-                            .put("latOrY", isGeo ? cfg.latitude() : cfg.gridY())
-                            .put("longOrX", isGeo ? cfg.longitude() : cfg.gridX());
-                    payload.set("location", loc);
-                    return true;
-                } catch (NumberFormatException e) {
-                    log.warn("Invalid location data: {}", cfg);
-                }
-            }
-        }
-        return false;
-    }
-
-    // Adds meta UI information for the specified object.
-    private void addMetaUi(String id, ObjectNode payload) {
-        ObjectNode meta = metaUi.get(id);
-        if (meta != null) {
-            payload.set("metaUi", meta);
-        }
-    }
-
-    // Produces JSON structure from annotations.
-    private JsonNode props(Annotations annotations) {
-        ObjectNode props = objectNode();
-        if (annotations != null) {
-            for (String key : annotations.keys()) {
-                props.put(key, annotations.value(key));
-            }
-        }
-        return props;
-    }
     @Override
     protected Collection<RequestHandler> createRequestHandlers() {
         return ImmutableSet.of(
@@ -258,22 +154,6 @@
         );
     }
 
-    public void setRestUrl(String ipAddress) {
-        restUrl = "http://" + ipAddress + ":8000/trace_request";
-    }
-
-    public String restUrl() {
-        return restUrl;
-    }
-
-    public void setRestAuthInfo(String id, String password) {
-        restAuthInfo = Base64.getEncoder().encodeToString(id.concat(":").concat(password).getBytes());
-    }
-
-    public String restAuthInfo() {
-        return restAuthInfo;
-    }
-
     private final class DisplayStartHandler extends RequestHandler {
 
         public DisplayStartHandler() {
@@ -310,75 +190,18 @@
         public void process(ObjectNode payload) {
             String srcIp = string(payload, SRC_IP);
             String dstIp = string(payload, DST_IP);
-            log.debug("SendEvent called with src IP: {}, dst IP: {}", srcIp, dstIp);
+            String srcDeviceId = string(payload, SRC_DEVICE_ID);
+            String dstDeviceId = string(payload, DST_DEVICE_ID);
+            log.info("Flow trace request called with src IP: {}, dst IP: {}, src device ID: {}, dst device Id: {}",
+                    srcIp,
+                    dstIp,
+                    srcDeviceId,
+                    dstDeviceId);
 
-            ObjectNode objectNode = getFlowTraceRequestAsJson(srcIp, dstIp);
-            InputStream byteArrayInputStream
-                    = new ByteArrayInputStream(objectNode.toString().getBytes());
-
-            Invocation.Builder builder = getClientBuilder(restUrl);
-
-            if (builder == null) {
-                log.error("Fail to get the client builder for the trace from {} to {}", srcIp, dstIp);
-                return;
-            }
-
-            try {
-                Response response = builder.header(AUTHORIZATION, restAuthInfo.toString())
-                        .post(Entity.entity(IOUtils.toString(byteArrayInputStream, StandardCharsets.UTF_8),
-                                MediaType.APPLICATION_JSON_TYPE));
-
-                log.debug("Response from server: {}", response);
-
-                if (response.getStatus() != 200) {
-                    log.error("FlowTraceRequest failed because of {}", response);
-                }
-
-            } catch (IOException e) {
-                log.error("Exception occured because of {}", e.toString());
-            }
-
+            processFlowTraceRequest(srcIp, dstIp, srcDeviceId, dstDeviceId);
         }
     }
 
-    private ObjectNode getFlowTraceRequestAsJson(String srcIp, String dstIp) {
-        ObjectMapper mapper = new ObjectMapper();
-        String controllerUrl = HTTP + clusterService.getLocalNode().ip()
-                + OPENSTACK_NETWORKING_UI_RESULT;
-
-        ObjectNode objectNode = mapper.createObjectNode();
-
-        objectNode.put(COMMAND, FLOW_TRACE)
-                .put(REVERSE, false)
-                .put(TRANSACTION_ID, TRANSACTION_VALUE)
-                .put(APP_REST_URL, controllerUrl);
-
-        if (srcIp.equals(dstIp)) {
-            objectNode.putObject(MATCHING_FIELDS)
-                    .put(SOURCE_IP, srcIp)
-                    .put(DESTINATION_IP, dstIp)
-                    .put(TO_GATEWAY, true)
-                    .put(IP_PROTOCOL, 1);
-
-        } else {
-            objectNode.putObject(MATCHING_FIELDS)
-                    .put(SOURCE_IP, srcIp)
-                    .put(DESTINATION_IP, dstIp);
-        }
-        return  objectNode;
-    }
-
-    private Invocation.Builder getClientBuilder(String url) {
-        if (Strings.isNullOrEmpty(url)) {
-            log.warn("URL in not set");
-            return null;
-        }
-
-        WebTarget wt = client.target(url);
-
-        return wt.request(MediaType.APPLICATION_JSON_TYPE);
-    }
-
     private final class DisplayUpdateHandler extends RequestHandler {
         public DisplayUpdateHandler() {
             super(OPENSTACK_NETWORKING_UI_UPDATE);
@@ -572,4 +395,166 @@
     private NodeBadge createBadge(int n) {
         return NodeBadge.number(Status.INFO, n, "Openstack Node");
     }
+
+    private void processFlowTraceRequest(String srcIp, String dstIp, String srcDeviceId, String dstDeviceId) {
+        boolean traceSuccess = true;
+
+        ObjectMapper mapper = new ObjectMapper();
+
+        ObjectNode traceResult = mapper.createObjectNode();
+
+        ArrayNode traceResultArray = traceResult.putArray(TRACE_RESULT);
+
+        OpenstackNode srcOpenstackNode = osNodeService.node(DeviceId.deviceId(srcDeviceId));
+        if (srcOpenstackNode == null) {
+            return;
+        }
+
+        if (srcOpenstackNode.sshAuthInfo() == null) {
+            log.error("Openstack node {} has no SSH authentication information..",
+                    srcOpenstackNode.hostname());
+            return;
+        }
+
+        String traceResultForward = sendTraceRequestToNode(srcIp, dstIp, srcOpenstackNode);
+        if (traceResultForward == null) {
+            return;
+        }
+
+        log.debug("traceResultForward raw data: {}", traceResultForward);
+
+        ObjectNode traceResultForwardJson = null;
+
+        Device srcDevice = deviceService.getDevice(srcOpenstackNode.intgBridge());
+        if (srcDevice.annotations().value(SW_VERSION).startsWith(OVS_VERSION_2_8)) {
+            traceResultForwardJson = Ovs28FlowTraceResultParser.flowTraceResultInJson(
+                    traceResultForward, srcOpenstackNode.hostname());
+        } else {
+            log.error("Currently OVS version {} is not supported",
+                    deviceService.getDevice(srcOpenstackNode.intgBridge()));
+        }
+
+        if (traceResultForwardJson == null) {
+            return;
+        }
+
+        traceResultArray.add(traceResultForwardJson);
+
+        log.debug("traceResultForward Json: {}", traceResultForwardJson);
+
+        if (!traceResultForwardJson.get(IS_SUCCESS).asBoolean()) {
+            traceSuccess = false;
+        }
+
+        //TODO implements trace result in backward
+
+        traceResult.put(TRACE_SUCCESS, traceSuccess);
+        log.debug("traceResult Json: {}", traceResult);
+
+        sendMessagetoUi(FLOW_TRACE_RESULT, traceResult);
+
+    }
+
+    private String sendTraceRequestToNode(String srcIp, String dstIp, OpenstackNode openstackNode) {
+        String traceResult = null;
+        OpenstackSshAuth sshAuth = openstackNode.sshAuthInfo();
+
+        try (SshClient client = SshClient.setUpDefaultClient()) {
+            client.start();
+
+            try (ClientSession session = client
+                    .connect(sshAuth.id(), openstackNode.managementIp().getIp4Address().toString(), SSH_PORT)
+                    .verify(TIMEOUT_MS, TimeUnit.SECONDS).getSession()) {
+                session.addPasswordIdentity(sshAuth.password());
+                session.auth().verify(TIMEOUT_MS, TimeUnit.SECONDS);
+
+
+                try (ClientChannel channel = session.createChannel(ClientChannel.CHANNEL_SHELL)) {
+
+                    String requestString = traceRequestString(srcIp, dstIp, openstackNode);
+                    if (requestString == null) {
+                        return null;
+                    }
+
+                    log.debug("requestString: {}", requestString);
+                    final InputStream inputStream =
+                            new ByteArrayInputStream(requestString.getBytes());
+
+                    OutputStream outputStream = new ByteArrayOutputStream();
+                    OutputStream errStream = new ByteArrayOutputStream();
+
+                    channel.setIn(new NoCloseInputStream(inputStream));
+                    channel.setErr(errStream);
+                    channel.setOut(outputStream);
+
+                    Collection<ClientChannelEvent> eventList = Lists.newArrayList();
+                    eventList.add(ClientChannelEvent.OPENED);
+
+                    OpenFuture channelFuture = channel.open();
+
+                    if (channelFuture.await(TIMEOUT_MS, TimeUnit.SECONDS)) {
+
+                        long timeoutExpiredMs = System.currentTimeMillis() + TIMEOUT_MS;
+
+                        while (!channelFuture.isOpened()) {
+                            if ((timeoutExpiredMs - System.currentTimeMillis()) <= 0) {
+                                log.error("Failed to open channel");
+                                return null;
+                            }
+                        }
+                        TimeUnit.SECONDS.sleep(WAIT_OUTPUT_STREAM_SECOND);
+
+                        traceResult = ((ByteArrayOutputStream) outputStream).toString(Charsets.UTF_8.name());
+
+                        channel.close();
+                    }
+                } finally {
+                    session.close();
+                }
+            } finally {
+                client.stop();
+            }
+
+        } catch (Exception e) {
+            log.error("Exception occurred because of {}", e.toString());
+        }
+
+        return traceResult.trim();
+    }
+
+    private String traceRequestString(String srcIp, String dstIp, OpenstackNode openstackNode) {
+
+        Optional<InstancePort> instancePort = instancePortService.instancePorts().stream()
+                .filter(port -> port.ipAddress().getIp4Address().toString().equals(srcIp)
+                        && port.deviceId().equals(openstackNode.intgBridge()))
+                .findAny();
+
+        if (!instancePort.isPresent()) {
+            return null;
+        }
+
+        String requestString = DEFAULT_REQUEST_STRING
+                + instancePort.get().portNumber().toString()
+                + COMMA
+                + NW_SRC
+                + srcIp
+                + COMMA;
+
+        if (osNetService.networkType(instancePort.get().networkId()).equals(VXLAN)) {
+            if (srcIp.equals(dstIp)) {
+                dstIp = osNetService.gatewayIp(instancePort.get().portId());
+                requestString = requestString + DL_DST + DEFAULT_GATEWAY_MAC_STR + COMMA;
+            } else if (!osNetService.ipPrefix(instancePort.get().portId()).contains(IpAddress.valueOf(dstIp))) {
+                requestString = requestString + DL_DST + DEFAULT_GATEWAY_MAC_STR + COMMA;
+            }
+        } else if (osNetService.networkType(instancePort.get().networkId()).equals(FLAT)) {
+            if (srcIp.equals(dstIp)) {
+                dstIp = osNetService.gatewayIp(instancePort.get().portId());
+            }
+        }
+
+        requestString = requestString + NW_DST + dstIp + "\n";
+
+        return requestString;
+    }
 }
diff --git a/apps/openstacknetworkingui/src/main/java/org/onosproject/openstacknetworkingui/OpenstackNetworkingUiOverlay.java b/apps/openstacknetworkingui/src/main/java/org/onosproject/openstacknetworkingui/OpenstackNetworkingUiOverlay.java
index 8ad477c..ec71db7 100644
--- a/apps/openstacknetworkingui/src/main/java/org/onosproject/openstacknetworkingui/OpenstackNetworkingUiOverlay.java
+++ b/apps/openstacknetworkingui/src/main/java/org/onosproject/openstacknetworkingui/OpenstackNetworkingUiOverlay.java
@@ -16,6 +16,7 @@
 package org.onosproject.openstacknetworkingui;
 
 import org.onlab.osgi.DefaultServiceDirectory;
+import org.onosproject.net.DeviceId;
 import org.onosproject.net.HostId;
 import org.onosproject.net.host.HostService;
 import org.onosproject.ui.UiTopoOverlay;
@@ -38,6 +39,7 @@
     private static final String SUMMARY_VERSION = "0.9";
     private static final String VNI = "VNI";
     private static final String ANNOTATION_SEGMENT_ID = "segId";
+    private static final String DEVICE_ID = "DeviceId";
 
     private static final String NOT_AVAILABLE = "N/A";
 
@@ -68,9 +70,11 @@
     @Override
     public void modifyHostDetails(PropertyPanel pp, HostId hostId) {
         String vni = hostService.getHost(hostId).annotations().value(ANNOTATION_SEGMENT_ID);
+        DeviceId deviceId = hostService.getHost(hostId).location().deviceId();
 
         pp.removeProps(VLAN);
-        pp.addProp(SONA, VNI, vni == null ? NOT_AVAILABLE : vni)
+        pp.addProp(VNI, VNI, vni == null ? NOT_AVAILABLE : vni)
+                .addProp(DEVICE_ID, DEVICE_ID, deviceId.toString())
                 .addButton(FLOW_TRACE_BUTTON)
                 .addButton(RESET_BUTTON)
                 .addButton(TO_GATEWAY_BUTTON)
diff --git a/apps/openstacknetworkingui/src/main/java/org/onosproject/openstacknetworkingui/OpenstackNetworkingUiService.java b/apps/openstacknetworkingui/src/main/java/org/onosproject/openstacknetworkingui/OpenstackNetworkingUiService.java
index aea9763..3d9f51c 100644
--- a/apps/openstacknetworkingui/src/main/java/org/onosproject/openstacknetworkingui/OpenstackNetworkingUiService.java
+++ b/apps/openstacknetworkingui/src/main/java/org/onosproject/openstacknetworkingui/OpenstackNetworkingUiService.java
@@ -15,48 +15,8 @@
  */
 package org.onosproject.openstacknetworkingui;
 
-import com.fasterxml.jackson.databind.node.ObjectNode;
-
 /**
  * Service for OpenStack Networking UI.
  */
 public interface OpenstackNetworkingUiService {
-
-    /**
-     * Sends message to OpenStack Networking UI.
-     *
-     * @param type event type
-     * @param payload payload
-     */
-    void sendMessage(String type, ObjectNode payload);
-
-    /**
-     * Sets the REST server ip address.
-     *
-     * @param ipAddress rest server ip address
-     */
-    void setRestServerIp(String ipAddress);
-
-    /**
-     * Gets the REST server url.
-     *
-     * @return REST server url
-     */
-    String restServerUrl();
-
-    /**
-     * Sets the REST server authorization information.
-     *
-     * @param id id
-     * @param password password
-     */
-    void setRestServerAuthInfo(String id, String password);
-
-    /**
-     * Gets the REST server authorization information.
-     *
-     * @return REST server authorization information as String
-     */
-    String restServerAuthInfo();
-
 }
diff --git a/apps/openstacknetworkingui/src/main/java/org/onosproject/openstacknetworkingui/Ovs28FlowTraceResultParser.java b/apps/openstacknetworkingui/src/main/java/org/onosproject/openstacknetworkingui/Ovs28FlowTraceResultParser.java
new file mode 100644
index 0000000..9468984
--- /dev/null
+++ b/apps/openstacknetworkingui/src/main/java/org/onosproject/openstacknetworkingui/Ovs28FlowTraceResultParser.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright 2018-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.openstacknetworkingui;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+/**
+ * Parser class for flow trace result string from OVS28.
+ */
+public final class Ovs28FlowTraceResultParser {
+    private static final String TRACE_NODE_NAME = "traceNodeName";
+    private static final String IS_SUCCESS = "isSuccess";
+    private static final String FLOW_RULES = "flowRules";
+    private static final String TABLE = "table";
+    private static final String PRIORITY = "priority";
+    private static final String SELECTOR = "selector";
+    private static final String ACTIONS = "actions";
+    private static final String BRIDGE = "bridge";
+    private static final String DATAPATH = "Datapath";
+    private static final String DROP = "drop";
+    private static final String COMMA = ",";
+    private static final String DOT = "\\.";
+    private static final String NEW_LINE = "\n";
+
+    private Ovs28FlowTraceResultParser() {
+    }
+
+    public static ObjectNode flowTraceResultInJson(String outputStream, String hostName) {
+        if (outputStream == null || hostName == null) {
+            return null;
+        }
+
+        ObjectMapper mapper = new ObjectMapper();
+        ObjectNode jsonNode = mapper.createObjectNode();
+
+        int flowRuleStartLineNum = 0;
+        int flowRuleEndLineNum = 0;
+
+        jsonNode.put(TRACE_NODE_NAME, hostName);
+
+        String[] lines = outputStream.split(NEW_LINE);
+
+        for (int i = 0; i < lines.length; i++) {
+            if (lines[i].startsWith(BRIDGE)) {
+                flowRuleStartLineNum = i + 2;
+            }
+
+            if (lines[i].startsWith(DATAPATH)) {
+                flowRuleEndLineNum = i;
+                break;
+            }
+        }
+
+        ArrayNode arrayNode = jsonNode.putArray(FLOW_RULES);
+
+        for (int i = flowRuleStartLineNum; i < flowRuleEndLineNum; i = i + 2) {
+            if (!isNewFlowTable(lines[i])) {
+                break;
+            }
+
+            ObjectNode flowRule = arrayNode.addObject();
+
+            flowRule.put(TABLE, tableNum(lines[i]));
+            flowRule.put(PRIORITY, priority(lines[i]));
+            flowRule.put(SELECTOR, selector(lines[i]));
+
+            String actions = action(lines[i + 1]);
+
+            if (!isNewFlowTable(lines[i + 2])) {
+                actions = actions + "\n" + action(lines[i + 2]);
+                i = i + 1;
+            }
+
+            flowRule.put(ACTIONS, actions);
+        }
+
+        if (lines[flowRuleEndLineNum].contains(DROP)) {
+            jsonNode.put(IS_SUCCESS, false);
+        } else {
+            jsonNode.put(IS_SUCCESS, true);
+        }
+
+        return jsonNode;
+    }
+
+    private static boolean isNewFlowTable(String line) {
+        return line.contains(PRIORITY);
+    }
+
+    private static String tableNum(String line) {
+        return line.split(DOT)[0];
+    }
+
+    private static String priority(String line) {
+        return line.split(PRIORITY)[1].trim().split(COMMA)[0];
+    }
+
+    private static String selector(String line) {
+        if (!hasSelector(line)) {
+            return "";
+        }
+
+        String selectorString = line.trim().split(PRIORITY)[0].split(" ")[1];
+
+        return selectorString.replaceAll(COMMA, NEW_LINE);
+    }
+
+    private static boolean hasSelector(String line) {
+        String tableNum = tableNum(line);
+        return !line.replaceFirst(tableNum + DOT + " ", "").startsWith(PRIORITY);
+    }
+
+    private static String action(String line) {
+        return line.trim();
+    }
+
+
+}
diff --git a/apps/openstacknetworkingui/src/main/java/org/onosproject/openstacknetworkingui/cli/GetRestServerAuthInfoCommand.java b/apps/openstacknetworkingui/src/main/java/org/onosproject/openstacknetworkingui/cli/GetRestServerAuthInfoCommand.java
deleted file mode 100644
index fdaf23d..0000000
--- a/apps/openstacknetworkingui/src/main/java/org/onosproject/openstacknetworkingui/cli/GetRestServerAuthInfoCommand.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * 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.openstacknetworkingui.cli;
-
-import org.apache.karaf.shell.commands.Command;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.openstacknetworkingui.OpenstackNetworkingUiService;
-
-/**
- * Gets the REST server authorization information.
- */
-@Command(scope = "onos", name = "openstacknetworking-ui-get-restserver-auth",
-        description = "Gets the REST server authorization information")
-public class GetRestServerAuthInfoCommand extends AbstractShellCommand {
-
-    @Override
-    protected void execute() {
-        OpenstackNetworkingUiService service = AbstractShellCommand.get(OpenstackNetworkingUiService.class);
-        print("Encoded information for the REST server authorization: %s", service.restServerAuthInfo());
-    }
-}
diff --git a/apps/openstacknetworkingui/src/main/java/org/onosproject/openstacknetworkingui/cli/GetRestServerCommand.java b/apps/openstacknetworkingui/src/main/java/org/onosproject/openstacknetworkingui/cli/GetRestServerCommand.java
deleted file mode 100644
index 6cccfa1..0000000
--- a/apps/openstacknetworkingui/src/main/java/org/onosproject/openstacknetworkingui/cli/GetRestServerCommand.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * 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.openstacknetworkingui.cli;
-
-import org.apache.karaf.shell.commands.Command;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.openstacknetworkingui.OpenstackNetworkingUiService;
-
-/**
- * Gets the REST server url.
- */
-
-@Command(scope = "onos", name = "openstacknetworking-ui-get-restserver-url",
-        description = "Gets the REST server url")
-public class GetRestServerCommand extends AbstractShellCommand {
-
-    @Override
-    protected void execute() {
-        OpenstackNetworkingUiService service = AbstractShellCommand.get(OpenstackNetworkingUiService.class);
-        print("REST server url : %s", service.restServerUrl());
-    }
-}
diff --git a/apps/openstacknetworkingui/src/main/java/org/onosproject/openstacknetworkingui/cli/SetRestServerAuthInfoCommand.java b/apps/openstacknetworkingui/src/main/java/org/onosproject/openstacknetworkingui/cli/SetRestServerAuthInfoCommand.java
deleted file mode 100644
index 148818c..0000000
--- a/apps/openstacknetworkingui/src/main/java/org/onosproject/openstacknetworkingui/cli/SetRestServerAuthInfoCommand.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * 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.openstacknetworkingui.cli;
-
-import org.apache.karaf.shell.commands.Argument;
-import org.apache.karaf.shell.commands.Command;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.openstacknetworkingui.OpenstackNetworkingUiService;
-
-/**
- * Sets the REST server authorization information.
- */
-@Command(scope = "onos", name = "openstacknetworking-ui-set-restserver-auth",
-        description = "Sets the REST server authorization information")
-public class SetRestServerAuthInfoCommand extends AbstractShellCommand {
-
-    @Argument(index = 0, name = "restServerAuthId", description = "REST server authorization id",
-            required = true, multiValued = false)
-    private String restServerAuthId = null;
-
-    @Argument(index = 1, name = "restServerAuthPass", description = "REST server authorization password",
-            required = true, multiValued = false)
-    private String restServerAuthPass = null;
-
-    @Override
-    protected void execute() {
-        OpenstackNetworkingUiService service = AbstractShellCommand.get(OpenstackNetworkingUiService.class);
-        service.setRestServerAuthInfo(restServerAuthId, restServerAuthPass);
-        print("Id and password for the REST server authorization are %s and %s.", restServerAuthId, restServerAuthPass);
-        print("Encoded result as based 64 format: %s", service.restServerAuthInfo());
-    }
-}
diff --git a/apps/openstacknetworkingui/src/main/java/org/onosproject/openstacknetworkingui/cli/SetRestServerCommand.java b/apps/openstacknetworkingui/src/main/java/org/onosproject/openstacknetworkingui/cli/SetRestServerCommand.java
deleted file mode 100644
index f9cef4d..0000000
--- a/apps/openstacknetworkingui/src/main/java/org/onosproject/openstacknetworkingui/cli/SetRestServerCommand.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * 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.openstacknetworkingui.cli;
-
-import org.apache.karaf.shell.commands.Argument;
-import org.apache.karaf.shell.commands.Command;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.openstacknetworkingui.OpenstackNetworkingUiService;
-
-/**
- * Sets the REST server ip address.
- */
-@Command(scope = "onos", name = "openstacknetworking-ui-set-restserver-ip",
-        description = "Sets the REST server ip address")
-public class SetRestServerCommand extends AbstractShellCommand {
-
-    @Argument(index = 0, name = "restServerIp", description = "REST server ip address",
-            required = true, multiValued = false)
-    private String restServerIp = null;
-
-    @Override
-    protected void execute() {
-        OpenstackNetworkingUiService service = AbstractShellCommand.get(OpenstackNetworkingUiService.class);
-        service.setRestServerIp(restServerIp);
-        print("The REST server url is set to %s", service.restServerUrl());
-    }
-}
diff --git a/apps/openstacknetworkingui/src/main/java/org/onosproject/openstacknetworkingui/cli/package-info.java b/apps/openstacknetworkingui/src/main/java/org/onosproject/openstacknetworkingui/cli/package-info.java
deleted file mode 100644
index 2a69dda..0000000
--- a/apps/openstacknetworkingui/src/main/java/org/onosproject/openstacknetworkingui/cli/package-info.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * 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.
- */
-
-/**
- *  CLI handlers of OpenStack Networking UI service.
- */
-package org.onosproject.openstacknetworkingui.cli;
\ No newline at end of file
diff --git a/apps/openstacknetworkingui/src/main/java/org/onosproject/openstacknetworkingui/web/FlowTraceWebResource.java b/apps/openstacknetworkingui/src/main/java/org/onosproject/openstacknetworkingui/web/FlowTraceWebResource.java
deleted file mode 100644
index 36b5bd3..0000000
--- a/apps/openstacknetworkingui/src/main/java/org/onosproject/openstacknetworkingui/web/FlowTraceWebResource.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * 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.openstacknetworkingui.web;
-
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.SerializationFeature;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-import org.onlab.osgi.DefaultServiceDirectory;
-import org.onosproject.openstacknetworkingui.OpenstackNetworkingUiService;
-import org.onosproject.rest.AbstractWebResource;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import javax.ws.rs.Consumes;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.UriInfo;
-import java.io.IOException;
-import java.io.InputStream;
-
-import static javax.ws.rs.core.Response.status;
-import static org.onlab.util.Tools.readTreeFromStream;
-
-/**
- * Handles REST API from monitoring server.
- */
-
-@Path("result")
-public class FlowTraceWebResource extends AbstractWebResource {
-    protected final Logger log = LoggerFactory.getLogger(getClass());
-    private final OpenstackNetworkingUiService uiService =
-            DefaultServiceDirectory.getService(OpenstackNetworkingUiService.class);
-
-    private static final String FLOW_TRACE_RESULT = "flowTraceResult";
-
-    @Context
-    private UriInfo uriInfo;
-
-    @POST
-    @Consumes(MediaType.APPLICATION_JSON)
-    @Produces(MediaType.APPLICATION_JSON)
-    public Response flowTraceResponse(InputStream inputStream) throws IOException {
-        try {
-            JsonNode jsonNode = readTreeFromStream(mapper().enable(SerializationFeature.INDENT_OUTPUT), inputStream);
-            ObjectNode objectNode = jsonNode.deepCopy();
-
-            log.debug("FlowTraceResponse: {}", jsonNode.toString());
-
-            uiService.sendMessage(FLOW_TRACE_RESULT, objectNode);
-
-        } catch (IOException e) {
-            log.error("Exception occured because of {}", e.toString());
-        }
-
-        return status(Response.Status.OK).build();
-    }
-
-}
diff --git a/apps/openstacknetworkingui/src/main/resources/OSGI-INF/blueprint/shell-config.xml b/apps/openstacknetworkingui/src/main/resources/OSGI-INF/blueprint/shell-config.xml
index 9e78f63..cebe471 100644
--- a/apps/openstacknetworkingui/src/main/resources/OSGI-INF/blueprint/shell-config.xml
+++ b/apps/openstacknetworkingui/src/main/resources/OSGI-INF/blueprint/shell-config.xml
@@ -15,17 +15,5 @@
 -->
 <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.openstacknetworkingui.cli.SetRestServerCommand"/>
-        </command>
-        <command>
-            <action class="org.onosproject.openstacknetworkingui.cli.GetRestServerCommand"/>
-        </command>
-        <command>
-            <action class="org.onosproject.openstacknetworkingui.cli.GetRestServerAuthInfoCommand"/>
-        </command>
-        <command>
-            <action class="org.onosproject.openstacknetworkingui.cli.SetRestServerAuthInfoCommand"/>
-        </command>
     </command-bundle>
 </blueprint>
diff --git a/apps/openstacknetworkingui/src/main/resources/app/view/sonaTopov/sonaTopovOverlay.js b/apps/openstacknetworkingui/src/main/resources/app/view/sonaTopov/sonaTopovOverlay.js
index 39517b6..c9d6262 100644
--- a/apps/openstacknetworkingui/src/main/resources/app/view/sonaTopov/sonaTopovOverlay.js
+++ b/apps/openstacknetworkingui/src/main/resources/app/view/sonaTopov/sonaTopovOverlay.js
@@ -22,10 +22,12 @@
     var $log, tov, sts, flash, ds, wss;
     var traceSrc = null;
     var traceDst = null;
+    var srcDeviceId = null;
+    var dstDeviceId = null;
 
     var traceInfoDialogId = 'traceInfoDialogId',
         traceInfoDialogOpt = {
-            width: 200,
+            width: 300,
             edge: 'left',
             margin: 20,
             hideMargin: -20
@@ -64,11 +66,13 @@
                 cb: function (data) {
 
                     if (traceSrc == null && data.navPath == 'host') {
-                        traceSrc = data.title;
+                        traceSrc = data.propValues.ip;
+                        srcDeviceId = data.propValues.DeviceId
 
                         flash.flash('Src ' + traceSrc + ' selected. Please select the dst');
                     } else if (traceDst == null && data.title != traceSrc && data.navPath == 'host') {
-                        traceDst = data.title;
+                        traceDst = data.propValues.ip;
+                        dstDeviceId = data.propValues.DeviceId;
                         openTraceInfoDialog();
                         flash.flash('Dst ' + traceDst + ' selected. Press Request button');
                     }
@@ -95,6 +99,7 @@
                     if (traceSrc != null && data.title == traceSrc && data.navPath == 'host') {
                         //Set traceSrc to traceDst in case trace to gateway
                         traceDst = traceSrc;
+                        dstDeviceId = 'toGateway';
                         openTraceInfoDialog();
                         flash.flash('Trace to Gateway');
                     }
@@ -107,6 +112,7 @@
                     if (traceSrc != null && data.title == traceSrc && data.navPath == 'host') {
                         //Set traceDst to 8.8.8.8 to check external connection
                         traceDst = '8.8.8.8';
+                        dstDeviceId = 'toExternal';
                         openTraceInfoDialog();
                         flash.flash('Trace to External')
                     }
@@ -184,6 +190,16 @@
             tBodySelection.append('td').text(dst).attr("class", "value");
         }
 
+        texts.select('table').select('tbody').append('tr');
+        tBodySelection = texts.select('table').select('tbody').select('tr:nth-child(3)');
+        tBodySelection.append('td').text('SrcDeviceId').attr("class", "label");
+        tBodySelection.append('td').text(srcDeviceId).attr("class", "value");
+
+        texts.select('table').select('tbody').append('tr');
+        tBodySelection = texts.select('table').select('tbody').select('tr:nth-child(4)');
+        tBodySelection.append('td').text('DstDeviceId').attr("class", "label");
+        tBodySelection.append('td').text(dstDeviceId).attr("class", "value");
+
         texts.append('hr');
 
         return texts;
@@ -191,7 +207,7 @@
     }
 
     function flowTraceResultBtn() {
-        sts.sendFlowTraceRequest(traceSrc, traceDst);
+        sts.sendFlowTraceRequest(traceSrc, traceDst, srcDeviceId, dstDeviceId);
         ds.closeDialog();
         traceSrc = null;
         traceDst = null;
diff --git a/apps/openstacknetworkingui/src/main/resources/app/view/sonaTopov/sonaTopovService.js b/apps/openstacknetworkingui/src/main/resources/app/view/sonaTopov/sonaTopovService.js
index a9bbf69..719703a 100644
--- a/apps/openstacknetworkingui/src/main/resources/app/view/sonaTopov/sonaTopovService.js
+++ b/apps/openstacknetworkingui/src/main/resources/app/view/sonaTopov/sonaTopovService.js
@@ -56,10 +56,12 @@
         wss.sendEvent(displayStop);
     }
 
-    function sendFlowTraceRequest(src, dst) {
+    function sendFlowTraceRequest(src, dst, srcDeviceId, dstDeviceId) {
         wss.sendEvent(flowTraceRequest, {
             srcIp: src,
-            dstIp: dst
+            dstIp: dst,
+            srcDeviceId: srcDeviceId,
+            dstDeviceId: dstDeviceId,
         });
         flash.flash('sendFlowTraceRequest called');
     }
@@ -106,7 +108,7 @@
                 margin: 20,
                 hideMargin: -20
             }
-        var traceSuccess = data.trace_success == true ? "SUCCESS" : "FALSE";
+        var traceSuccess = data.traceSuccess == true ? "SUCCESS" : "FALSE";
         ds.openDialog(flowTraceResultDialogId, flowTraceResultDialogOpt)
                     .setTitle('Flow Trace Result: ' + traceSuccess)
                     .addContent(createTraceResultInfoDiv(data))
@@ -136,15 +138,15 @@
         var tbodySelection = texts.select('.table-body').select('table').select('tbody');
         var rowNum = 1;
 
-        data.trace_result.forEach(function(result) {
-            result.flow_rules.forEach(function(flowRule) {
+        data.traceResult.forEach(function(result) {
+            result.flowRules.forEach(function(flowRule) {
                 tbodySelection.append('tr');
                 var tbodyTrSelection = tbodySelection.select('tr:nth-child(' + rowNum + ')');
-                tbodyTrSelection.append('td').text(result.trace_node_name);
+                tbodyTrSelection.append('td').text(result.traceNodeName);
                 tbodyTrSelection.append('td').text(flowRule.table);
                 tbodyTrSelection.append('td').text(flowRule.priority);
-                tbodyTrSelection.append('td').text(jsonToSring(flowRule.selector));
-                tbodyTrSelection.append('td').text(jsonToSring(flowRule.actions));
+                tbodyTrSelection.append('td').text(flowRule.selector);
+                tbodyTrSelection.append('td').text(flowRule.actions);
                 if (jsonToSring(flowRule.actions).includes("drop")) {
                     tbodyTrSelection.attr("class", "drop");
                 }
diff --git a/apps/openstacknetworkingui/src/main/webapp/WEB-INF/web.xml b/apps/openstacknetworkingui/src/main/webapp/WEB-INF/web.xml
index d5d4006..00d82df 100644
--- a/apps/openstacknetworkingui/src/main/webapp/WEB-INF/web.xml
+++ b/apps/openstacknetworkingui/src/main/webapp/WEB-INF/web.xml
@@ -47,7 +47,6 @@
         <init-param>
             <param-name>jersey.config.server.provider.classnames</param-name>
             <param-value>
-                org.onosproject.openstacknetworkingui.web.FlowTraceWebResource
             </param-value>
         </init-param>
         <load-on-startup>1</load-on-startup>