blob: cac0b8ddfb583c5b851dbb402b7b2d024d1da9f9 [file] [log] [blame]
/*
* Copyright 2016-present 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.ui.impl.topo;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.collect.ImmutableSet;
import org.onlab.osgi.ServiceDirectory;
import org.onosproject.ui.RequestHandler;
import org.onosproject.ui.UiConnection;
import org.onosproject.ui.UiMessageHandler;
import org.onosproject.ui.impl.UiWebSocket;
import org.onosproject.ui.model.topo.UiClusterMember;
import org.onosproject.ui.model.topo.UiNode;
import org.onosproject.ui.model.topo.UiRegion;
import org.onosproject.ui.model.topo.UiSynthLink;
import org.onosproject.ui.model.topo.UiTopoLayout;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Collection;
import java.util.List;
import java.util.Set;
/*
NOTES:
The original topology view message handler was broken into two classes
TopologyViewMessageHandler, and TopologyViewMessageHandlerBase.
We do not need to follow that model necessarily. Instead, we have this
class and Topo2Jsonifier, which takes UiModel objects and renders them
as JSON objects.
*/
/**
* Server-side component for interacting with the new "Region aware" topology
* view in the Web UI.
*/
public class Topo2ViewMessageHandler extends UiMessageHandler {
private final Logger log = LoggerFactory.getLogger(getClass());
// === Inbound event identifiers
private static final String START = "topo2Start";
private static final String NAV_REGION = "topo2navRegion";
private static final String STOP = "topo2Stop";
private static final String UPDATE_META2 = "updateMeta2";
// === Outbound event identifiers
private static final String ALL_INSTANCES = "topo2AllInstances";
private static final String CURRENT_LAYOUT = "topo2CurrentLayout";
private static final String CURRENT_REGION = "topo2CurrentRegion";
private static final String PEER_REGIONS = "topo2PeerRegions";
private static final String OVERLAYS = "topo2Overlays";
private UiTopoSession topoSession;
private Topo2Jsonifier t2json;
private Topo2OverlayCache overlay2Cache;
private Topo2TrafficMessageHandler trafficHandler;
@Override
public void init(UiConnection connection, ServiceDirectory directory) {
super.init(connection, directory);
// get the topo session from the UiWebSocket
topoSession = ((UiWebSocket) connection).topoSession();
t2json = new Topo2Jsonifier(directory, connection.userName());
}
/**
* Sets a reference to the overlay cache for interacting with registered
* overlays.
*
* @param overlay2Cache the overlay cache
*/
public void setOverlayCache(Topo2OverlayCache overlay2Cache) {
this.overlay2Cache = overlay2Cache;
}
/**
* Sets a reference to the traffic message handler.
*
* @param traffic the traffic message handler instance
*/
public void setTrafficHandler(Topo2TrafficMessageHandler traffic) {
trafficHandler = traffic;
}
@Override
protected Collection<RequestHandler> createRequestHandlers() {
return ImmutableSet.of(
new Topo2Start(),
new Topo2NavRegion(),
new Topo2Stop(),
new Topo2UpdateMeta()
);
}
// ==================================================================
private ObjectNode mkLayoutMessage(UiTopoLayout currentLayout) {
List<UiTopoLayout> crumbs = topoSession.breadCrumbs();
return t2json.layout(currentLayout, crumbs);
}
private ObjectNode mkRegionMessage(UiTopoLayout currentLayout) {
UiRegion region = topoSession.getRegion(currentLayout);
Set<UiRegion> kids = topoSession.getSubRegions(currentLayout);
List<UiSynthLink> links = topoSession.getLinks(currentLayout);
return t2json.region(region, kids, links);
}
private ObjectNode mkPeersMessage(UiTopoLayout currentLayout) {
Set<UiNode> peers = topoSession.getPeerNodes(currentLayout);
ObjectNode peersPayload = objectNode();
String rid = currentLayout.regionId().toString();
peersPayload.set("peers", t2json.closedNodes(rid, peers));
return peersPayload;
}
// ==================================================================
private final class Topo2Start extends RequestHandler {
private Topo2Start() {
super(START);
}
@Override
public void process(ObjectNode payload) {
// client view is ready to receive data to display; so start up
// server-side processing, and send over initial state
log.debug("topo2Start: {}", payload);
// this may be a little heavyweight, but it might be safer to do
// this than make assumptions about the order in which devices
// and regions are added... and thus internal linkages set up
// correctly
topoSession.refreshModel();
// start with the list of ONOS cluster members
List<UiClusterMember> instances = topoSession.getAllInstances();
sendMessage(ALL_INSTANCES, t2json.instances(instances));
// Send layout, region, peers data...
// this is the layout that the user has chosen to display
UiTopoLayout currentLayout = topoSession.currentLayout();
sendMessage(CURRENT_LAYOUT, mkLayoutMessage(currentLayout));
// this is the region that is associated with the current layout
// this message includes details of the sub-regions, devices,
// hosts, and links within the region
// (as well as layer-order hints)
sendMessage(CURRENT_REGION, mkRegionMessage(currentLayout));
// these are the regions/devices that are siblings to this region
sendMessage(PEER_REGIONS, mkPeersMessage(currentLayout));
}
}
private final class Topo2NavRegion extends RequestHandler {
private Topo2NavRegion() {
super(NAV_REGION);
}
@Override
public void process(ObjectNode payload) {
String rid = string(payload, "rid");
log.debug("topo2navRegion: rid={}", rid);
// NOTE: we are NOT re-issuing information about the cluster nodes
// switch to the selected region...
topoSession.navToRegion(rid);
// re-send layout, region, peers data...
UiTopoLayout currentLayout = topoSession.currentLayout();
sendMessage(CURRENT_LAYOUT, mkLayoutMessage(currentLayout));
sendMessage(CURRENT_REGION, mkRegionMessage(currentLayout));
sendMessage(PEER_REGIONS, mkPeersMessage(currentLayout));
}
}
private final class Topo2Stop extends RequestHandler {
private Topo2Stop() {
super(STOP);
}
@Override
public void process(ObjectNode payload) {
// client view has gone away; so shut down server-side processing
log.debug("topo2Stop: {}", payload);
trafficHandler.ceaseAndDesist();
// OLD CODE DID THE FOLLOWING...
// stopSummaryMonitoring();
}
}
private final class Topo2UpdateMeta extends RequestHandler {
private Topo2UpdateMeta() {
super(UPDATE_META2);
}
@Override
public void process(ObjectNode payload) {
// NOTE: metadata for a node is stored within the context of the
// current region.
String rid = topoSession.currentLayout().regionId().toString();
t2json.updateMeta(rid, payload);
}
}
}