diff options
Diffstat (limited to 'framework/src/onos/apps/pathpainter/src/main/java')
6 files changed, 631 insertions, 0 deletions
diff --git a/framework/src/onos/apps/pathpainter/src/main/java/org/onosproject/pathpainter/PathLink.java b/framework/src/onos/apps/pathpainter/src/main/java/org/onosproject/pathpainter/PathLink.java new file mode 100644 index 00000000..57241705 --- /dev/null +++ b/framework/src/onos/apps/pathpainter/src/main/java/org/onosproject/pathpainter/PathLink.java @@ -0,0 +1,51 @@ +/* + * Copyright 2014,2015 Open Networking Laboratory + * + * 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.pathpainter; + +import org.onosproject.net.Link; +import org.onosproject.net.LinkKey; +import org.onosproject.ui.topo.BiLink; +import org.onosproject.ui.topo.LinkHighlight; +import org.onosproject.ui.topo.LinkHighlight.Flavor; + +import java.util.Set; + +/** + * Bi-directional link capable of different hilights. + */ +public class PathLink extends BiLink { + + private boolean primary = false; + private boolean secondary = false; + + public PathLink(LinkKey key, Link link) { + super(key, link); + } + + public void computeHilight(Set<Link> selectedLinks, Set<Link> allLinks) { + primary = selectedLinks.contains(this.one()) || + (two() != null && selectedLinks.contains(two())); + secondary = allLinks.contains(this.one()) || + (two() != null && allLinks.contains(two())); + } + + @Override + public LinkHighlight highlight(Enum<?> anEnum) { + Flavor flavor = primary ? Flavor.PRIMARY_HIGHLIGHT : + (secondary ? Flavor.SECONDARY_HIGHLIGHT : Flavor.NO_HIGHLIGHT); + return new LinkHighlight(this.linkId(), flavor); + } +} diff --git a/framework/src/onos/apps/pathpainter/src/main/java/org/onosproject/pathpainter/PathLinkMap.java b/framework/src/onos/apps/pathpainter/src/main/java/org/onosproject/pathpainter/PathLinkMap.java new file mode 100644 index 00000000..9f2ea216 --- /dev/null +++ b/framework/src/onos/apps/pathpainter/src/main/java/org/onosproject/pathpainter/PathLinkMap.java @@ -0,0 +1,30 @@ +/* + * Copyright 2014,2015 Open Networking Laboratory + * + * 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.pathpainter; + +import org.onosproject.net.Link; +import org.onosproject.net.LinkKey; +import org.onosproject.ui.topo.BiLinkMap; + +/** + * Our concrete link map. + */ +public class PathLinkMap extends BiLinkMap<PathLink> { + @Override + protected PathLink create(LinkKey linkKey, Link link) { + return new PathLink(linkKey, link); + } +} diff --git a/framework/src/onos/apps/pathpainter/src/main/java/org/onosproject/pathpainter/PathPainter.java b/framework/src/onos/apps/pathpainter/src/main/java/org/onosproject/pathpainter/PathPainter.java new file mode 100644 index 00000000..07ce3fe8 --- /dev/null +++ b/framework/src/onos/apps/pathpainter/src/main/java/org/onosproject/pathpainter/PathPainter.java @@ -0,0 +1,86 @@ +/* + * Copyright 2014,2015 Open Networking Laboratory + * + * 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.pathpainter; + +import com.google.common.collect.ImmutableList; +import org.apache.felix.scr.annotations.Activate; +import org.apache.felix.scr.annotations.Component; +import org.apache.felix.scr.annotations.Deactivate; +import org.apache.felix.scr.annotations.Reference; +import org.apache.felix.scr.annotations.ReferenceCardinality; +import org.onosproject.ui.UiExtension; +import org.onosproject.ui.UiExtensionService; +import org.onosproject.ui.UiMessageHandlerFactory; +import org.onosproject.ui.UiTopoOverlayFactory; +import org.onosproject.ui.UiView; +import org.onosproject.ui.UiViewHidden; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; + +/** + * Skeletal ONOS UI Topology-Overlay application component. + */ +@Component(immediate = true) +public class PathPainter { + + private static final ClassLoader CL = PathPainter.class.getClassLoader(); + private static final String VIEW_ID = "ppTopov"; + + private final Logger log = LoggerFactory.getLogger(getClass()); + + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected UiExtensionService uiExtensionService; + + // List of application views + private final List<UiView> uiViews = ImmutableList.of( + new UiViewHidden(VIEW_ID) + ); + + // Factory for UI message handlers + private final UiMessageHandlerFactory messageHandlerFactory = + () -> ImmutableList.of( + new PathPainterTopovMessageHandler() + ); + + // Factory for UI topology overlays + private final UiTopoOverlayFactory topoOverlayFactory = + () -> ImmutableList.of( + new PathPainterTopovOverlay() + ); + + // Application UI extension + protected UiExtension extension = + new UiExtension.Builder(CL, uiViews) + .resourcePath(VIEW_ID) + .messageHandlerFactory(messageHandlerFactory) + .topoOverlayFactory(topoOverlayFactory) + .build(); + + @Activate + protected void activate() { + uiExtensionService.register(extension); + log.info("Started"); + } + + @Deactivate + protected void deactivate() { + uiExtensionService.unregister(extension); + log.info("Stopped"); + } + +} diff --git a/framework/src/onos/apps/pathpainter/src/main/java/org/onosproject/pathpainter/PathPainterTopovMessageHandler.java b/framework/src/onos/apps/pathpainter/src/main/java/org/onosproject/pathpainter/PathPainterTopovMessageHandler.java new file mode 100644 index 00000000..cf395e49 --- /dev/null +++ b/framework/src/onos/apps/pathpainter/src/main/java/org/onosproject/pathpainter/PathPainterTopovMessageHandler.java @@ -0,0 +1,388 @@ +/* + * Copyright 2014,2015 Open Networking Laboratory + * + * 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.pathpainter; + +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Sets; +import org.onlab.osgi.ServiceDirectory; +import org.onosproject.net.DeviceId; +import org.onosproject.net.DisjointPath; +import org.onosproject.net.ElementId; +import org.onosproject.net.HostId; +import org.onosproject.net.Link; +import org.onosproject.net.Path; +import org.onosproject.net.device.DeviceService; +import org.onosproject.net.topology.GeoDistanceLinkWeight; +import org.onosproject.net.topology.LinkWeight; +import org.onosproject.net.topology.PathService; +import org.onosproject.net.topology.TopologyEvent; +import org.onosproject.net.topology.TopologyListener; +import org.onosproject.net.topology.TopologyService; +import org.onosproject.ui.RequestHandler; +import org.onosproject.ui.UiConnection; +import org.onosproject.ui.UiMessageHandler; +import org.onosproject.ui.topo.DeviceHighlight; +import org.onosproject.ui.topo.Highlights; +import org.onosproject.ui.topo.HostHighlight; +import org.onosproject.ui.topo.NodeBadge; +import org.onosproject.ui.topo.TopoJson; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Collection; +import java.util.List; +import java.util.Set; + +/** + * Skeletal ONOS UI Topology-Overlay message handler. + */ +public class PathPainterTopovMessageHandler extends UiMessageHandler { + + private static final String PAINTER_CLEAR = "ppTopovClear"; + private static final String PAINTER_SET_SRC = "ppTopovSetSrc"; + private static final String PAINTER_SET_DST = "ppTopovSetDst"; + private static final String PAINTER_SWAP_SRC_DST = "ppTopovSwapSrcDst"; + private static final String PAINTER_SET_MODE = "ppTopovSetMode"; + + private static final String PAINTER_NEXT_PATH = "ppTopovNextPath"; + private static final String PAINTER_PREV_PATH = "ppTopovPrevPath"; + + private static final String ID = "id"; + private static final String MODE = "mode"; + private static final String TYPE = "type"; + private static final String SWITCH = "switch"; + private static final String ENDSTATION = "endstation"; + public static final String DST = "Dst"; + public static final String SRC = "Src"; + private static LinkWeight linkData; + + private final TopologyListener topologyListener = new InternalTopologyListener(); + + private Set<Link> allPathLinks; + private boolean listenersRemoved; + + private enum Mode { + SHORTEST, DISJOINT, GEODATA, SRLG, INVALID + } + + private final Logger log = LoggerFactory.getLogger(getClass()); + + private PathService pathService; + + private ElementId src, dst; + private String srcType, dstType; + private Mode currentMode = Mode.SHORTEST; + private List<Path> paths; + private int pathIndex; + + protected TopologyService topologyService; + + + // ===============-=-=-=-=-=-======================-=-=-=-=-=-=-================================ + + + @Override + public void init(UiConnection connection, ServiceDirectory directory) { + super.init(connection, directory); + pathService = directory.get(PathService.class); + topologyService = directory.get(TopologyService.class); + linkData = new GeoDistanceLinkWeight(directory.get(DeviceService.class)); + addListeners(); + } + + + @Override + public void destroy() { + removeListeners(); + super.destroy(); + } + + @Override + protected Collection<RequestHandler> createRequestHandlers() { + return ImmutableSet.of( + new ClearHandler(), + new SetSrcHandler(), + new SetDstHandler(), + new SwapSrcDstHandler(), + new NextPathHandler(), + new PrevPathHandler(), + new SetModeHandler() + ); + } + + // === ------------------------- + // === Handler classes + + private final class ClearHandler extends RequestHandler { + + public ClearHandler() { + super(PAINTER_CLEAR); + } + + @Override + public void process(long sid, ObjectNode payload) { + src = null; + dst = null; + sendMessage(TopoJson.highlightsMessage(new Highlights())); + } + } + + private final class SetSrcHandler extends RequestHandler { + + public SetSrcHandler() { + super(PAINTER_SET_SRC); + } + + @Override + public void process(long sid, ObjectNode payload) { + String id = string(payload, ID); + src = elementId(id); + srcType = string(payload, TYPE); + if (src.equals(dst)) { + dst = null; + } + sendMessage(TopoJson.highlightsMessage(addBadge(new Highlights(), + srcType, + src.toString(), + SRC))); + findAndSendPaths(currentMode); + } + } + + private final class SetDstHandler extends RequestHandler { + public SetDstHandler() { + super(PAINTER_SET_DST); + } + + @Override + public void process(long sid, ObjectNode payload) { + String id = string(payload, ID); + dst = elementId(id); + dstType = string(payload, TYPE); + if (src.equals(dst)) { + src = null; + } + + sendMessage(TopoJson.highlightsMessage(addBadge(new Highlights(), + dstType, + dst.toString(), + DST))); + findAndSendPaths(currentMode); + } + } + + private final class SwapSrcDstHandler extends RequestHandler { + public SwapSrcDstHandler() { + super(PAINTER_SWAP_SRC_DST); + } + + @Override + public void process(long sid, ObjectNode payload) { + ElementId temp = src; + src = dst; + dst = temp; + String s = srcType; + srcType = dstType; + dstType = s; + findAndSendPaths(currentMode); + } + } + + + + private final class NextPathHandler extends RequestHandler { + public NextPathHandler() { + super(PAINTER_NEXT_PATH); + } + + @Override + public void process(long sid, ObjectNode payload) { + pathIndex = (pathIndex >= paths.size() - 1 ? 0 : pathIndex + 1); + hilightAndSendPaths(); + } + } + + private final class PrevPathHandler extends RequestHandler { + public PrevPathHandler() { + super(PAINTER_PREV_PATH); + } + + @Override + public void process(long sid, ObjectNode payload) { + pathIndex = (pathIndex <= 0 ? paths.size() - 1 : pathIndex - 1); + hilightAndSendPaths(); + } + } + + private final class SetModeHandler extends RequestHandler { + public SetModeHandler() { + super(PAINTER_SET_MODE); + } + + @Override + public void process(long sid, ObjectNode payload) { + String mode = string(payload, MODE); + switch (mode) { + case "shortest": + currentMode = Mode.SHORTEST; + break; + case "disjoint": + currentMode = Mode.DISJOINT; + break; + case "geodata": + currentMode = Mode.GEODATA; + break; + case "srlg": + currentMode = Mode.SRLG; + break; + default: + currentMode = Mode.INVALID; + break; + } + //TODO: add support for SRLG + findAndSendPaths(currentMode); + } + } + + // === ------------ + + private ElementId elementId(String id) { + try { + return DeviceId.deviceId(id); + } catch (IllegalArgumentException e) { + return HostId.hostId(id); + } + } + + private void findAndSendPaths(Mode mode) { + log.info("src={}; dst={}; mode={}", src, dst, currentMode); + if (src != null && dst != null) { + pathIndex = 0; + ImmutableSet.Builder<Link> builder = ImmutableSet.builder(); + if (mode.equals(Mode.SHORTEST)) { + paths = ImmutableList.copyOf(pathService.getPaths(src, dst)); + allPathLinks = buildPaths(builder).build(); + } else if (mode.equals(Mode.DISJOINT)) { + paths = ImmutableList.copyOf(pathService.getDisjointPaths(src, dst)); + allPathLinks = buildDisjointPaths(builder).build(); + } else if (mode.equals(Mode.GEODATA)) { + paths = ImmutableList.copyOf(pathService.getPaths(src, dst, linkData)); + allPathLinks = buildPaths(builder).build(); + } else { + log.info("Unsupported MODE"); + } + } else { + paths = ImmutableList.of(); + allPathLinks = ImmutableSet.of(); + } + hilightAndSendPaths(); + + } + + private ImmutableSet.Builder<Link> buildPaths(ImmutableSet.Builder<Link> pathBuilder) { + paths.forEach(path -> path.links().forEach(pathBuilder::add)); + return pathBuilder; + } + + private ImmutableSet.Builder<Link> buildDisjointPaths(ImmutableSet.Builder<Link> pathBuilder) { + paths.forEach(path -> { + DisjointPath dp = (DisjointPath) path; + pathBuilder.addAll(dp.primary().links()); + pathBuilder.addAll(dp.backup().links()); + }); + return pathBuilder; + } + + private void hilightAndSendPaths() { + PathLinkMap linkMap = new PathLinkMap(); + allPathLinks.forEach(linkMap::add); + + Set<Link> selectedPathLinks; + + // Prepare two working sets; one containing selected path links and + // the other containing all paths links. + if (currentMode.equals(Mode.DISJOINT)) { + DisjointPath dp = (DisjointPath) paths.get(pathIndex); + selectedPathLinks = paths.isEmpty() ? + ImmutableSet.of() : Sets.newHashSet(dp.primary().links()); + selectedPathLinks.addAll(dp.backup().links()); + } else { + selectedPathLinks = paths.isEmpty() ? + ImmutableSet.of() : ImmutableSet.copyOf(paths.get(pathIndex).links()); + } + Highlights highlights = new Highlights(); + for (PathLink plink : linkMap.biLinks()) { + plink.computeHilight(selectedPathLinks, allPathLinks); + highlights.add(plink.highlight(null)); + } + if (src != null) { + highlights = addBadge(highlights, srcType, src.toString(), SRC); + } + if (dst != null) { + highlights = addBadge(highlights, dstType, dst.toString(), DST); + } + sendMessage(TopoJson.highlightsMessage(highlights)); + } + + private Highlights addBadge(Highlights highlights, String type, String elemId, String src) { + if (SWITCH.equals(type)) { + highlights = addDeviceBadge(highlights, elemId, src); + } else if (ENDSTATION.equals(type)) { + highlights = addHostBadge(highlights, elemId, src); + } + return highlights; + } + + private Highlights addDeviceBadge(Highlights h, String elemId, String type) { + DeviceHighlight dh = new DeviceHighlight(elemId); + dh.setBadge(createBadge(type)); + h.add(dh); + return h; + } + + private Highlights addHostBadge(Highlights h, String elemId, String type) { + HostHighlight hh = new HostHighlight(elemId); + hh.setBadge(createBadge(type)); + h.add(hh); + return h; + } + + private NodeBadge createBadge(String type) { + return NodeBadge.text(type); + } + + private synchronized void addListeners() { + listenersRemoved = false; + topologyService.addListener(topologyListener); + } + private synchronized void removeListeners() { + if (!listenersRemoved) { + listenersRemoved = true; + topologyService.removeListener(topologyListener); + } + } + + // Link event listener. + private class InternalTopologyListener implements TopologyListener { + @Override + public void event(TopologyEvent event) { + findAndSendPaths(currentMode); + } + } + +}
\ No newline at end of file diff --git a/framework/src/onos/apps/pathpainter/src/main/java/org/onosproject/pathpainter/PathPainterTopovOverlay.java b/framework/src/onos/apps/pathpainter/src/main/java/org/onosproject/pathpainter/PathPainterTopovOverlay.java new file mode 100644 index 00000000..78f5f905 --- /dev/null +++ b/framework/src/onos/apps/pathpainter/src/main/java/org/onosproject/pathpainter/PathPainterTopovOverlay.java @@ -0,0 +1,56 @@ +/* + * Copyright 2014,2015 Open Networking Laboratory + * + * 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.pathpainter; + +import org.onosproject.net.DeviceId; +import org.onosproject.net.HostId; +import org.onosproject.ui.UiTopoOverlay; +import org.onosproject.ui.topo.ButtonId; +import org.onosproject.ui.topo.PropertyPanel; + +/** + * Our topology overlay. + */ +public class PathPainterTopovOverlay extends UiTopoOverlay { + + // NOTE: this must match the ID defined in ppTopovOverlay.js + private static final String OVERLAY_ID = "pp-overlay"; + + private static final ButtonId SRC_BUTTON = new ButtonId("src"); + private static final ButtonId DST_BUTTON = new ButtonId("dst"); + + public PathPainterTopovOverlay() { + super(OVERLAY_ID); + } + + @Override + public void deactivate() { + super.deactivate(); + log.debug("PathPainterOverlay Deactivated"); + } + + @Override + public void modifyDeviceDetails(PropertyPanel pp, DeviceId deviceId) { + pp.addButton(SRC_BUTTON).addButton(DST_BUTTON); + } + + @Override + public void modifyHostDetails(PropertyPanel pp, HostId hostId) { + pp.addButton(SRC_BUTTON).addButton(DST_BUTTON); + } + + +} diff --git a/framework/src/onos/apps/pathpainter/src/main/java/org/onosproject/pathpainter/package-info.java b/framework/src/onos/apps/pathpainter/src/main/java/org/onosproject/pathpainter/package-info.java new file mode 100644 index 00000000..e625933b --- /dev/null +++ b/framework/src/onos/apps/pathpainter/src/main/java/org/onosproject/pathpainter/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2014-2015 Open Networking Laboratory + * + * 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. + */ + +/** + * Path visualization GUI topology view overlay. + */ +package org.onosproject.pathpainter;
\ No newline at end of file |