mirror of
https://github.com/opennetworkinglab/onos.git
synced 2026-01-06 17:11:40 +01:00
Implements flow tracer in Openstack Networking UI
Change-Id: I6747de157e63b4d6ffa67274b623b29db311d2e3
This commit is contained in:
parent
50ac0983c8
commit
577b69c945
@ -139,4 +139,29 @@ public interface OpenstackNetworkService
|
||||
*/
|
||||
Set<ExternalPeerRouter> 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);
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -567,6 +567,64 @@ public class OpenstackNetworkManager
|
||||
public Set<ExternalPeerRouter> 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();
|
||||
}
|
||||
|
||||
@ -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) {
|
||||
|
||||
|
||||
@ -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',
|
||||
]
|
||||
)
|
||||
|
||||
@ -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>
|
||||
@ -70,6 +63,23 @@
|
||||
<version>${project.version}</version>
|
||||
</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>
|
||||
|
||||
@ -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;
|
||||
public interface FlowTraceResultParser {
|
||||
|
||||
String flowTraceResultInJson(String outputStream, String hostName);
|
||||
}
|
||||
@ -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<Port> 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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -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<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 @@ 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<RequestHandler> 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<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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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();
|
||||
|
||||
}
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -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());
|
||||
}
|
||||
}
|
||||
@ -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());
|
||||
}
|
||||
}
|
||||
@ -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());
|
||||
}
|
||||
}
|
||||
@ -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());
|
||||
}
|
||||
}
|
||||
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
@ -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;
|
||||
@ -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>
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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");
|
||||
}
|
||||
|
||||
@ -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>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user