From 577b69c94589ef8a489397b97e2fb63778e07273 Mon Sep 17 00:00:00 2001 From: Daniel Park Date: Mon, 16 Jul 2018 17:29:34 +0900 Subject: [PATCH] Implements flow tracer in Openstack Networking UI Change-Id: I6747de157e63b4d6ffa67274b623b29db311d2e3 --- .../api/OpenstackNetworkService.java | 25 + .../impl/OpenstackNetworkManager.java | 58 +++ .../impl/OpenstackNetworkServiceAdapter.java | 15 + apps/openstacknetworkingui/BUCK | 16 +- apps/openstacknetworkingui/pom.xml | 24 +- ...e-info.java => FlowTraceResultParser.java} | 10 +- .../OpenstackNetworkingUiManager.java | 28 -- .../OpenstackNetworkingUiMessageHandler.java | 459 +++++++++--------- .../OpenstackNetworkingUiOverlay.java | 6 +- .../OpenstackNetworkingUiService.java | 40 -- .../Ovs28FlowTraceResultParser.java | 133 +++++ .../cli/GetRestServerAuthInfoCommand.java | 34 -- .../cli/GetRestServerCommand.java | 35 -- .../cli/SetRestServerAuthInfoCommand.java | 45 -- .../cli/SetRestServerCommand.java | 40 -- .../web/FlowTraceWebResource.java | 76 --- .../web/package-info.java | 20 - .../OSGI-INF/blueprint/shell-config.xml | 12 - .../app/view/sonaTopov/sonaTopovOverlay.js | 24 +- .../app/view/sonaTopov/sonaTopovService.js | 18 +- .../src/main/webapp/WEB-INF/web.xml | 1 - 21 files changed, 523 insertions(+), 596 deletions(-) rename apps/openstacknetworkingui/src/main/java/org/onosproject/openstacknetworkingui/{cli/package-info.java => FlowTraceResultParser.java} (65%) create mode 100644 apps/openstacknetworkingui/src/main/java/org/onosproject/openstacknetworkingui/Ovs28FlowTraceResultParser.java delete mode 100644 apps/openstacknetworkingui/src/main/java/org/onosproject/openstacknetworkingui/cli/GetRestServerAuthInfoCommand.java delete mode 100644 apps/openstacknetworkingui/src/main/java/org/onosproject/openstacknetworkingui/cli/GetRestServerCommand.java delete mode 100644 apps/openstacknetworkingui/src/main/java/org/onosproject/openstacknetworkingui/cli/SetRestServerAuthInfoCommand.java delete mode 100644 apps/openstacknetworkingui/src/main/java/org/onosproject/openstacknetworkingui/cli/SetRestServerCommand.java delete mode 100644 apps/openstacknetworkingui/src/main/java/org/onosproject/openstacknetworkingui/web/FlowTraceWebResource.java delete mode 100644 apps/openstacknetworkingui/src/main/java/org/onosproject/openstacknetworkingui/web/package-info.java diff --git a/apps/openstacknetworking/api/src/main/java/org/onosproject/openstacknetworking/api/OpenstackNetworkService.java b/apps/openstacknetworking/api/src/main/java/org/onosproject/openstacknetworking/api/OpenstackNetworkService.java index d0bab0fae1..864b4a4851 100644 --- a/apps/openstacknetworking/api/src/main/java/org/onosproject/openstacknetworking/api/OpenstackNetworkService.java +++ b/apps/openstacknetworking/api/src/main/java/org/onosproject/openstacknetworking/api/OpenstackNetworkService.java @@ -139,4 +139,29 @@ public interface OpenstackNetworkService */ Set externalPeerRouters(); + /** + * Returns ip prefix with supplied port ID. + * + * @param portId openstack port id + * @return ip prefix + */ + IpPrefix ipPrefix(String portId); + + /** + * Returns network type with supplied network ID. + * + * @param netId openstack network id + * @return network type + */ + String networkType(String netId); + + /** + * Returns gateway ip address upplied port ID. + * + * @param portId openstack port id + * @return gateway ip address + */ + String gatewayIp(String portId); + + } diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackNetworkManager.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackNetworkManager.java index e8747ccf26..bceb9ea818 100644 --- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackNetworkManager.java +++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackNetworkManager.java @@ -567,6 +567,64 @@ public class OpenstackNetworkManager public Set externalPeerRouters() { return ImmutableSet.copyOf(externalPeerRouterMap.asJavaMap().values()); } + + @Override + public IpPrefix ipPrefix(String portId) { + checkNotNull(portId); + + Port port = port(portId); + + checkNotNull(port); + + IpAddress ipAddress = port.getFixedIps().stream() + .map(ip -> IpAddress.valueOf(ip.getIpAddress())) + .findAny().orElse(null); + + checkNotNull(ipAddress); + + Network network = network(port.getNetworkId()); + + checkNotNull(network); + + return subnets(network.getId()).stream() + .map(s -> IpPrefix.valueOf(s.getCidr())) + .filter(prefix -> prefix.contains(ipAddress)) + .findAny().orElse(null); + } + + @Override + public String networkType(String netId) { + Network network = network(netId); + + checkNotNull(network); + + return network.getNetworkType().toString(); + } + + @Override + public String gatewayIp(String portId) { + checkNotNull(portId); + + Port port = port(portId); + + checkNotNull(port); + + IpAddress ipAddress = port.getFixedIps().stream() + .map(ip -> IpAddress.valueOf(ip.getIpAddress())) + .findAny().orElse(null); + + checkNotNull(ipAddress); + + Network network = network(port.getNetworkId()); + + checkNotNull(network); + + return subnets(network.getId()).stream() + .filter(s -> IpPrefix.valueOf(s.getCidr()).contains(ipAddress)) + .map(s -> s.getGateway()) + .findAny().orElse(null); + } + private boolean isNetworkInUse(String netId) { return !subnets(netId).isEmpty() && !ports(netId).isEmpty(); } diff --git a/apps/openstacknetworking/app/src/test/java/org/onosproject/openstacknetworking/impl/OpenstackNetworkServiceAdapter.java b/apps/openstacknetworking/app/src/test/java/org/onosproject/openstacknetworking/impl/OpenstackNetworkServiceAdapter.java index 07290adb0c..59f8f5bafc 100644 --- a/apps/openstacknetworking/app/src/test/java/org/onosproject/openstacknetworking/impl/OpenstackNetworkServiceAdapter.java +++ b/apps/openstacknetworking/app/src/test/java/org/onosproject/openstacknetworking/impl/OpenstackNetworkServiceAdapter.java @@ -103,6 +103,21 @@ public class OpenstackNetworkServiceAdapter implements OpenstackNetworkService { return ImmutableSet.of(); } + @Override + public IpPrefix ipPrefix(String portId) { + return null; + } + + @Override + public String networkType(String netId) { + return null; + } + + @Override + public String gatewayIp(String portId) { + return null; + } + @Override public void addListener(OpenstackNetworkListener listener) { diff --git a/apps/openstacknetworkingui/BUCK b/apps/openstacknetworkingui/BUCK index ee452bdef5..ce5e71ede7 100644 --- a/apps/openstacknetworkingui/BUCK +++ b/apps/openstacknetworkingui/BUCK @@ -7,6 +7,13 @@ COMPILE_DEPS = [ '//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 @@ TEST_DEPS = [ 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 @@ onos_app ( 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 3e04aa41c9..58eed47861 100644 --- a/apps/openstacknetworkingui/pom.xml +++ b/apps/openstacknetworkingui/pom.xml @@ -37,13 +37,6 @@ UI http://onosproject.org OpenStack Networking UI Application - /onos/openstacknetworkingui - 1.0.0 - OpenStack Networking UI REST API - - APIs for interacting with OpenStack Networking Monitoring server. - - org.onosproject.openstacknetworkingui.web @@ -70,6 +63,23 @@ ${project.version} + + org.onosproject + onos-apps-openstacknetworking-api + ${project.version} + + + + org.onosproject + onos-apps-openstacknode-api + ${project.version} + + + + org.apache.sshd + sshd-core + + org.apache.karaf.shell org.apache.karaf.shell.console diff --git a/apps/openstacknetworkingui/src/main/java/org/onosproject/openstacknetworkingui/cli/package-info.java b/apps/openstacknetworkingui/src/main/java/org/onosproject/openstacknetworkingui/FlowTraceResultParser.java similarity index 65% rename from apps/openstacknetworkingui/src/main/java/org/onosproject/openstacknetworkingui/cli/package-info.java rename to apps/openstacknetworkingui/src/main/java/org/onosproject/openstacknetworkingui/FlowTraceResultParser.java index 2a69dda791..e18a3e5527 100644 --- a/apps/openstacknetworkingui/src/main/java/org/onosproject/openstacknetworkingui/cli/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; /** - * CLI handlers of OpenStack Networking UI service. + * Interface class for parsing flow trace string result to json with respect to OVS version. */ -package org.onosproject.openstacknetworkingui.cli; \ 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 4a9485e68a..848cfc73f5 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 @@ public class OpenstackNetworkingUiManager implements OpenstackNetworkingUiServic 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 vxlanPort(DeviceId deviceId) { return deviceService.getPorts(deviceId) .stream() @@ -178,5 +151,4 @@ public class OpenstackNetworkingUiManager implements OpenstackNetworkingUiServic 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 ec01cececa..8668096636 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.onosproject.ui.topo.TopoJson; 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 @@ public class OpenstackNetworkingUiMessageHandler extends UiMessageHandler { 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 @@ public class OpenstackNetworkingUiMessageHandler extends UiMessageHandler { 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 metaUi = new ConcurrentHashMap<>(); - private static final DefaultHashMap 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 @@ public class OpenstackNetworkingUiMessageHandler extends UiMessageHandler { 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 createRequestHandlers() { return ImmutableSet.of( @@ -258,22 +154,6 @@ public class OpenstackNetworkingUiMessageHandler extends UiMessageHandler { ); } - 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 class OpenstackNetworkingUiMessageHandler extends UiMessageHandler { 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); - - 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()); - } + 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); + 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 @@ public class OpenstackNetworkingUiMessageHandler extends UiMessageHandler { 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 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 = 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 8ad477ce1d..ec71db701f 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 @@ public class OpenstackNetworkingUiOverlay extends UiTopoOverlay { 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 @@ public class OpenstackNetworkingUiOverlay extends UiTopoOverlay { @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 aea97639a7..3d9f51c449 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 0000000000..9468984a6a --- /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 fdaf23dc5e..0000000000 --- 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 6cccfa1d0a..0000000000 --- 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 148818cd75..0000000000 --- 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 f9cef4d38c..0000000000 --- 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/web/FlowTraceWebResource.java b/apps/openstacknetworkingui/src/main/java/org/onosproject/openstacknetworkingui/web/FlowTraceWebResource.java deleted file mode 100644 index 36b5bd3631..0000000000 --- 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/java/org/onosproject/openstacknetworkingui/web/package-info.java b/apps/openstacknetworkingui/src/main/java/org/onosproject/openstacknetworkingui/web/package-info.java deleted file mode 100644 index 570f9cf632..0000000000 --- a/apps/openstacknetworkingui/src/main/java/org/onosproject/openstacknetworkingui/web/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. - */ - -/** - * Web implementation of OpenStack Networking UI service. - */ -package org.onosproject.openstacknetworkingui.web; \ No newline at end of file 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 9e78f63fcb..cebe47191d 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 @@ --> - - - - - - - - - - - - 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 39517b6848..c9d6262f22 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 a9bbf69dca..719703af41 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 d5d4006848..00d82dfa41 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 @@ jersey.config.server.provider.classnames - org.onosproject.openstacknetworkingui.web.FlowTraceWebResource 1