Java tutorial
/* * 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; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; 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.onlab.osgi.ServiceDirectory; import org.onosproject.cluster.ClusterService; 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.device.DeviceService; import org.onosproject.net.host.HostService; import org.onosproject.net.topology.PathService; import org.onosproject.ui.JsonUtils; import org.onosproject.ui.RequestHandler; import org.onosproject.ui.UiConnection; import org.onosproject.ui.UiMessageHandler; import org.apache.commons.io.IOUtils; import org.onosproject.ui.topo.Highlights; import org.onosproject.ui.topo.HostHighlight; import org.onosproject.ui.topo.NodeBadge; import org.onosproject.ui.topo.NodeBadge.Status; 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.InputStream; import java.nio.charset.StandardCharsets; import java.util.Base64; import java.util.Collection; import java.util.List; import java.util.Set; import static org.onosproject.net.DefaultEdgeLink.createEdgeLink; /** * OpenStack Networking UI message handler. */ public class OpenstackNetworkingUiMessageHandler extends UiMessageHandler { private static final String OPENSTACK_NETWORKING_UI_START = "openstackNetworkingUiStart"; private static final String OPENSTACK_NETWORKING_UI_UPDATE = "openstackNetworkingUiUpdate"; private static final String OPENSTACK_NETWORKING_UI_STOP = "openstackNetworkingUiStop"; private static final String ANNOTATION_NETWORK_ID = "networkId"; private static final String FLOW_TRACE_REQUEST = "flowTraceRequest"; 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 enum Mode { IDLE, MOUSE } private final Logger log = LoggerFactory.getLogger(getClass()); private DeviceService deviceService; private HostService hostService; private PathService pathService; private ClusterService clusterService; private String restUrl; private String restAuthInfo; private Mode currentMode = Mode.IDLE; private Element elementOfNote; private final Client client = ClientBuilder.newClient(); // ===============-=-=-=-=-=-======================-=-=-=-=-=-=-================================ @Override public void init(UiConnection connection, ServiceDirectory directory) { super.init(connection, directory); deviceService = directory.get(DeviceService.class); hostService = directory.get(HostService.class); pathService = directory.get(PathService.class); clusterService = directory.get(ClusterService.class); } @Override protected Collection<RequestHandler> createRequestHandlers() { return ImmutableSet.of(new DisplayStartHandler(), new DisplayUpdateHandler(), new DisplayStopHandler(), new FlowTraceRequestHandler()); } 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() { super(OPENSTACK_NETWORKING_UI_START); } @Override public void process(ObjectNode payload) { String mode = string(payload, MODE); log.debug("Start Display: mode [{}]", mode); clearState(); clearForMode(); switch (mode) { case MOUSE: currentMode = Mode.MOUSE; sendMouseData(); break; default: currentMode = Mode.IDLE; break; } } } private final class FlowTraceRequestHandler extends RequestHandler { public FlowTraceRequestHandler() { super(FLOW_TRACE_REQUEST); } @Override 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()); } } } 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); } @Override public void process(ObjectNode payload) { String id = string(payload, ID); log.debug("Update Display: id [{}]", id); if (!Strings.isNullOrEmpty(id)) { updateForMode(id); } else { clearForMode(); } } } private final class DisplayStopHandler extends RequestHandler { public DisplayStopHandler() { super(OPENSTACK_NETWORKING_UI_STOP); } @Override public void process(ObjectNode payload) { log.debug("Stop Display"); clearState(); clearForMode(); } } // === ------------ private void clearState() { currentMode = Mode.IDLE; elementOfNote = null; } private void updateForMode(String id) { try { HostId hid = HostId.hostId(id); elementOfNote = hostService.getHost(hid); } catch (Exception e) { try { DeviceId did = DeviceId.deviceId(id); elementOfNote = deviceService.getDevice(did); } catch (Exception e2) { log.debug("Unable to process ID [{}]", id); elementOfNote = null; } } switch (currentMode) { case MOUSE: sendMouseData(); break; default: break; } } private void clearForMode() { sendHighlights(new Highlights()); } private void sendHighlights(Highlights highlights) { sendMessage(TopoJson.highlightsMessage(highlights)); } public void sendMessagetoUi(String type, ObjectNode payload) { sendMessage(JsonUtils.envelope(type, payload)); } private int getVni(Host host) { String vni = host.annotations().value(ANNOTATION_SEGMENT_ID); return vni == null ? 0 : Integer.valueOf(vni).intValue(); } private void sendMouseData() { Highlights highlights = new Highlights(); if (elementOfNote != null && elementOfNote instanceof Device) { DeviceId deviceId = (DeviceId) elementOfNote.id(); List<OpenstackLink> edgeLinks = edgeLinks(deviceId); edgeLinks.forEach(edgeLink -> { highlights.add(edgeLink.highlight(OpenstackLink.RequestType.DEVICE_SELECTED)); }); hostService.getConnectedHosts(deviceId).forEach(host -> { HostHighlight hostHighlight = new HostHighlight(host.id().toString()); hostHighlight.setBadge(createBadge(getVni(host))); highlights.add(hostHighlight); }); sendHighlights(highlights); } else if (elementOfNote != null && elementOfNote instanceof Host) { HostId hostId = HostId.hostId(elementOfNote.id().toString()); if (!hostMadeFromOpenstack(hostId)) { return; } List<OpenstackLink> openstackLinks = linksInSameNetwork(hostId); openstackLinks.forEach(openstackLink -> { highlights.add(openstackLink.highlight(OpenstackLink.RequestType.HOST_SELECTED)); }); hostHighlightsInSameNetwork(hostId).forEach(highlights::add); sendHighlights(highlights); } } private boolean hostMadeFromOpenstack(HostId hostId) { return hostService.getHost(hostId).annotations().value(ANNOTATION_NETWORK_ID) == null ? false : true; } private String networkId(HostId hostId) { return hostService.getHost(hostId).annotations().value(ANNOTATION_NETWORK_ID); } private Set<HostHighlight> hostHighlightsInSameNetwork(HostId hostId) { Set<HostHighlight> hostHighlights = Sets.newHashSet(); Streams.stream(hostService.getHosts()).filter(host -> isHostInSameNetwork(host, networkId(hostId))) .forEach(host -> { HostHighlight hostHighlight = new HostHighlight(host.id().toString()); hostHighlight.setBadge(createBadge(getVni(host))); hostHighlights.add(hostHighlight); }); return hostHighlights; } private List<OpenstackLink> edgeLinks(DeviceId deviceId) { OpenstackLinkMap openstackLinkMap = new OpenstackLinkMap(); hostService.getConnectedHosts(deviceId).forEach(host -> { openstackLinkMap.add(createEdgeLink(host, true)); openstackLinkMap.add(createEdgeLink(host, false)); }); List<OpenstackLink> edgeLinks = Lists.newArrayList(); openstackLinkMap.biLinks().forEach(edgeLinks::add); return edgeLinks; } private List<OpenstackLink> linksInSameNetwork(HostId hostId) { OpenstackLinkMap linkMap = new OpenstackLinkMap(); Streams.stream(hostService.getHosts()).filter(host -> isHostInSameNetwork(host, networkId(hostId))) .forEach(host -> { linkMap.add(createEdgeLink(host, true)); linkMap.add(createEdgeLink(host, false)); Set<Path> paths = pathService.getPaths(hostId, host.id()); if (!paths.isEmpty()) { paths.forEach(path -> path.links().forEach(linkMap::add)); } }); List<OpenstackLink> openstackLinks = Lists.newArrayList(); linkMap.biLinks().forEach(openstackLinks::add); return openstackLinks; } private boolean isHostInSameNetwork(Host host, String networkId) { return hostService.getHost(host.id()).annotations().value(ANNOTATION_NETWORK_ID).equals(networkId); } private NodeBadge createBadge(int n) { return NodeBadge.number(Status.INFO, n, "Openstack Node"); } }