mirror of
https://github.com/opennetworkinglab/onos.git
synced 2026-05-05 04:06:49 +02:00
Adding topology overlay support for the server-side topo layout app.
Also: - parametrized access network layout in preparation for multiple variants - removed WS authentication code temporarily until proper forced-logout is implemented - updated STC warden environment (test only) Change-Id: I0adbe60737828db79350e7eb2fc72cf313b78a28
This commit is contained in:
parent
4a9c094d1d
commit
5b48d6ca84
@ -1,5 +1,6 @@
|
||||
COMPILE_DEPS = [
|
||||
'//lib:CORE_DEPS',
|
||||
'//lib:JACKSON',
|
||||
'//lib:org.apache.karaf.shell.console',
|
||||
'//core/common:onos-core-common',
|
||||
'//cli:onos-cli',
|
||||
|
||||
@ -27,6 +27,7 @@ import org.onosproject.net.HostId;
|
||||
import org.onosproject.utils.Comparators;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@ -35,31 +36,62 @@ import java.util.stream.Collectors;
|
||||
*/
|
||||
public class AccessNetworkLayout extends LayoutAlgorithm {
|
||||
|
||||
private static final double COMPUTE_Y = -400.0;
|
||||
private static final double SERVICE_Y = -200.0;
|
||||
private static final double SPINE_Y = 0.0;
|
||||
private static final double AGGREGATION_Y = +200.0;
|
||||
private static final double ACCESS_Y = +400.0;
|
||||
private static final double HOSTS_Y = +700.0;
|
||||
private static final double GATEWAY_X = 900.0;
|
||||
private double computeY = -350.0;
|
||||
private double serviceY = -200.0;
|
||||
private double spineY = 0.0;
|
||||
private double aggregationY = +200.0;
|
||||
private double accessY = +400.0;
|
||||
private double hostsY = +550.0;
|
||||
|
||||
private static final double ROW_GAP = 70;
|
||||
private static final double COMPUTE_ROW_GAP = -120;
|
||||
private static final double COL_GAP = 54;
|
||||
private static final double COMPUTE_OFFSET = 800.0;
|
||||
private static final double GATEWAY_GAP = 200.0;
|
||||
private static final double GATEWAY_OFFSET = -200.0;
|
||||
|
||||
private static final double SERVICE_GAP = 800;
|
||||
private static final int COMPUTE_PER_ROW = 25;
|
||||
|
||||
private static final double SPINES_GAP = 800;
|
||||
private static final double AGGREGATION_GAP = 400;
|
||||
private static final double ACCESS_GAP = 400;
|
||||
private static final int HOSTS_PER_ROW = 6;
|
||||
private double gatewayX = 900.0;
|
||||
private double rowGap = 70;
|
||||
private double computeRowGap = -120;
|
||||
private double colGap = 54;
|
||||
private double computeOffset = 800.0;
|
||||
private double gatewayGap = 200.0;
|
||||
private double gatewayOffset = -200.0;
|
||||
private double serviceGap = 800;
|
||||
private int computePerRow = 25;
|
||||
private double spinesGap = 800;
|
||||
private double aggregationGap = 400;
|
||||
private double accessGap = 400;
|
||||
private int hostsPerRow = 6;
|
||||
|
||||
private int spine, aggregation, accessLeaf, serviceLeaf, gateway;
|
||||
|
||||
/**
|
||||
* Creates the network layout using default layout options.
|
||||
*/
|
||||
public AccessNetworkLayout() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the network layout using the specified layout property overrides.
|
||||
*
|
||||
* @param custom overrides of the default layout properties
|
||||
*/
|
||||
public AccessNetworkLayout(Map<String, Object> custom) {
|
||||
computeY = (double) custom.getOrDefault("computeY", computeY);
|
||||
serviceY = (double) custom.getOrDefault("serviceY", serviceY);
|
||||
spineY = (double) custom.getOrDefault("spineY", spineY);
|
||||
aggregationY = (double) custom.getOrDefault("aggregationY", aggregationY);
|
||||
accessY = (double) custom.getOrDefault("accessY", accessY);
|
||||
hostsY = (double) custom.getOrDefault("hostsY", hostsY);
|
||||
gatewayX = (double) custom.getOrDefault("gatewayX", gatewayX);
|
||||
rowGap = (double) custom.getOrDefault("rowGap", rowGap);
|
||||
computeRowGap = (double) custom.getOrDefault("computeRowGap", computeRowGap);
|
||||
colGap = (double) custom.getOrDefault("colGap", colGap);
|
||||
computeOffset = (double) custom.getOrDefault("computeOffset", computeOffset);
|
||||
gatewayGap = (double) custom.getOrDefault("gatewayGap", gatewayGap);
|
||||
gatewayOffset = (double) custom.getOrDefault("gatewayOffset", gatewayOffset);
|
||||
serviceGap = (double) custom.getOrDefault("serviceGap", serviceGap);
|
||||
computePerRow = (int) custom.getOrDefault("computePerRow", computePerRow);
|
||||
spinesGap = (double) custom.getOrDefault("spinesGap", spinesGap);
|
||||
aggregationGap = (double) custom.getOrDefault("aggregationGap", aggregationGap);
|
||||
accessGap = (double) custom.getOrDefault("accessGap", accessGap);
|
||||
hostsPerRow = (int) custom.getOrDefault("hostsPerRow", hostsPerRow);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean classify(Device device) {
|
||||
if (!super.classify(device)) {
|
||||
@ -112,7 +144,7 @@ public class AccessNetworkLayout extends LayoutAlgorithm {
|
||||
spine = 1;
|
||||
List<DeviceId> spines = deviceCategories.get(SPINE);
|
||||
spines.stream().sorted(Comparators.ELEMENT_ID_COMPARATOR)
|
||||
.forEach(d -> place(d, c(spine++, spines.size(), SPINES_GAP), SPINE_Y));
|
||||
.forEach(d -> place(d, c(spine++, spines.size(), spinesGap), spineY));
|
||||
}
|
||||
|
||||
private void placeServiceLeavesAndHosts() {
|
||||
@ -124,7 +156,7 @@ public class AccessNetworkLayout extends LayoutAlgorithm {
|
||||
serviceLeaf = 1;
|
||||
leaves.stream().sorted(Comparators.ELEMENT_ID_COMPARATOR).forEach(id -> {
|
||||
gateway = 1;
|
||||
place(id, c(serviceLeaf++, leaves.size(), SERVICE_GAP), SERVICE_Y);
|
||||
place(id, c(serviceLeaf++, leaves.size(), serviceGap), serviceY);
|
||||
|
||||
List<HostId> gwHosts = hostService.getConnectedHosts(id).stream()
|
||||
.map(Host::id)
|
||||
@ -134,8 +166,8 @@ public class AccessNetworkLayout extends LayoutAlgorithm {
|
||||
.collect(Collectors.toList());
|
||||
|
||||
gwHosts.forEach(hid -> {
|
||||
place(hid, serviceLeaf <= 2 ? -GATEWAY_X : GATEWAY_X,
|
||||
c(gateway++, gwHosts.size(), GATEWAY_GAP, GATEWAY_OFFSET));
|
||||
place(hid, serviceLeaf <= 2 ? -gatewayX : gatewayX,
|
||||
c(gateway++, gwHosts.size(), gatewayGap, gatewayOffset));
|
||||
placed.add(hid);
|
||||
});
|
||||
|
||||
@ -146,9 +178,9 @@ public class AccessNetworkLayout extends LayoutAlgorithm {
|
||||
.sorted(Comparators.ELEMENT_ID_COMPARATOR)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
placeHostBlock(hosts, serviceLeaf <= 2 ? -COMPUTE_OFFSET : COMPUTE_OFFSET,
|
||||
COMPUTE_Y, COMPUTE_PER_ROW, COMPUTE_ROW_GAP,
|
||||
serviceLeaf <= 2 ? -COL_GAP : COL_GAP);
|
||||
placeHostBlock(hosts, serviceLeaf <= 2 ? -computeOffset : computeOffset,
|
||||
computeY, computePerRow, computeRowGap,
|
||||
serviceLeaf <= 2 ? -colGap : colGap);
|
||||
placed.addAll(hosts);
|
||||
});
|
||||
}
|
||||
@ -165,7 +197,7 @@ public class AccessNetworkLayout extends LayoutAlgorithm {
|
||||
.forEach(lid -> placeAccessLeafAndHosts(lid, leaves.size(), placed));
|
||||
} else {
|
||||
spines.stream().sorted(Comparators.ELEMENT_ID_COMPARATOR).forEach(id -> {
|
||||
place(id, c(aggregation++, spines.size(), AGGREGATION_GAP), AGGREGATION_Y);
|
||||
place(id, c(aggregation++, spines.size(), aggregationGap), aggregationY);
|
||||
linkService.getDeviceEgressLinks(id).stream()
|
||||
.map(l -> l.dst().deviceId())
|
||||
.filter(leaves::contains)
|
||||
@ -177,14 +209,14 @@ public class AccessNetworkLayout extends LayoutAlgorithm {
|
||||
}
|
||||
|
||||
private void placeAccessLeafAndHosts(DeviceId leafId, int leafCount, Set<DeviceId> placed) {
|
||||
double x = c(accessLeaf++, leafCount, ACCESS_GAP);
|
||||
place(leafId, x, ACCESS_Y);
|
||||
double x = c(accessLeaf++, leafCount, accessGap);
|
||||
place(leafId, x, accessY);
|
||||
placed.add(leafId);
|
||||
placeHostBlock(hostService.getConnectedHosts(leafId).stream()
|
||||
.map(Host::id)
|
||||
.sorted(Comparators.ELEMENT_ID_COMPARATOR)
|
||||
.collect(Collectors.toList()), x, HOSTS_Y,
|
||||
HOSTS_PER_ROW, ROW_GAP, COL_GAP);
|
||||
.collect(Collectors.toList()), x, hostsY,
|
||||
hostsPerRow, rowGap, colGap);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,74 @@
|
||||
/*
|
||||
* 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.layout;
|
||||
|
||||
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.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* ONOS UI Layout Topology-Overlay message handler.
|
||||
*/
|
||||
public class LayoutOverlayMessageHandler extends UiMessageHandler {
|
||||
|
||||
private final Logger log = LoggerFactory.getLogger(getClass());
|
||||
|
||||
private static final String DO_LAYOUT = "doLayout";
|
||||
private static final String TYPE = "type";
|
||||
|
||||
RoleBasedLayoutManager layoutManager;
|
||||
|
||||
@Override
|
||||
public void init(UiConnection connection, ServiceDirectory directory) {
|
||||
super.init(connection, directory);
|
||||
layoutManager = directory.get(RoleBasedLayoutManager.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Collection<RequestHandler> createRequestHandlers() {
|
||||
return ImmutableSet.of(
|
||||
new LayoutHandler()
|
||||
);
|
||||
}
|
||||
|
||||
private final class LayoutHandler extends RequestHandler {
|
||||
|
||||
public LayoutHandler() {
|
||||
super(DO_LAYOUT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void process(ObjectNode payload) {
|
||||
String algorithm = string(payload, TYPE);
|
||||
switch (algorithm) {
|
||||
case "access":
|
||||
layoutManager.layout(new AccessNetworkLayout());
|
||||
break;
|
||||
default:
|
||||
layoutManager.layout(new DefaultForceLayout());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -16,6 +16,7 @@
|
||||
|
||||
package org.onosproject.layout;
|
||||
|
||||
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;
|
||||
@ -26,9 +27,18 @@ import org.onosproject.net.config.NetworkConfigService;
|
||||
import org.onosproject.net.device.DeviceService;
|
||||
import org.onosproject.net.host.HostService;
|
||||
import org.onosproject.net.link.LinkService;
|
||||
import org.onosproject.ui.UiExtension;
|
||||
import org.onosproject.ui.UiExtensionService;
|
||||
import org.onosproject.ui.UiMessageHandlerFactory;
|
||||
import org.onosproject.ui.UiTopoOverlay;
|
||||
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;
|
||||
|
||||
/**
|
||||
* Manages automatic layout of the current network elements into one of several
|
||||
* supported layout variants using roles assigned to network elements using
|
||||
@ -40,6 +50,30 @@ public class RoleBasedLayoutManager {
|
||||
|
||||
private Logger log = LoggerFactory.getLogger(getClass());
|
||||
|
||||
private static final String VIEW_ID = "tlTopov";
|
||||
private static final String OVERLAY_ID = "tl-overlay";
|
||||
|
||||
// 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 LayoutOverlayMessageHandler());
|
||||
|
||||
// Factory for UI topology overlays
|
||||
private final UiTopoOverlayFactory topoOverlayFactory =
|
||||
() -> ImmutableList.of(new UiTopoOverlay(OVERLAY_ID));
|
||||
|
||||
// Application UI extension
|
||||
protected UiExtension extension =
|
||||
new UiExtension.Builder(getClass().getClassLoader(), uiViews)
|
||||
.resourcePath(VIEW_ID)
|
||||
.messageHandlerFactory(messageHandlerFactory)
|
||||
.topoOverlayFactory(topoOverlayFactory)
|
||||
.build();
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
|
||||
protected NetworkConfigService networkConfigService;
|
||||
|
||||
@ -52,17 +86,21 @@ public class RoleBasedLayoutManager {
|
||||
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
|
||||
protected LinkService linkService;
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
|
||||
protected UiExtensionService uiExtensionService;
|
||||
|
||||
@Activate
|
||||
protected void activate() {
|
||||
uiExtensionService.register(extension);
|
||||
log.info("Started");
|
||||
}
|
||||
|
||||
@Deactivate
|
||||
protected void deactivate() {
|
||||
uiExtensionService.unregister(extension);
|
||||
log.info("Stopped");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Executes the specified layout algorithm.
|
||||
*
|
||||
|
||||
@ -0,0 +1,2 @@
|
||||
/* css for layout topology overlay */
|
||||
|
||||
@ -0,0 +1,4 @@
|
||||
<!-- partial HTML -->
|
||||
<div id="ov-tl-topov">
|
||||
<p>This is a hidden view .. just a placeholder to house the javascript</p>
|
||||
</div>
|
||||
47
apps/layout/src/main/resources/app/view/tlTopov/tlTopov.js
Normal file
47
apps/layout/src/main/resources/app/view/tlTopov/tlTopov.js
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2015-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.
|
||||
*/
|
||||
|
||||
/*
|
||||
Module containing the "business logic" for the layout topology overlay.
|
||||
*/
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
// injected refs
|
||||
var $log, flash, wss;
|
||||
|
||||
function doLayout(type, description) {
|
||||
flash.flash(description);
|
||||
wss.sendEvent('doLayout', {
|
||||
type: type
|
||||
});
|
||||
}
|
||||
|
||||
angular.module('ovTlTopov', [])
|
||||
.factory('LayoutTopovService',
|
||||
['$log', 'FlashService', 'WebSocketService',
|
||||
|
||||
function (_$log_, _flash_, _wss_) {
|
||||
$log = _$log_;
|
||||
flash = _flash_;
|
||||
wss = _wss_;
|
||||
|
||||
return {
|
||||
doLayout: doLayout
|
||||
};
|
||||
}]);
|
||||
}());
|
||||
@ -0,0 +1,58 @@
|
||||
// path painter topology overlay - client side
|
||||
//
|
||||
// This is the glue that binds our business logic (in ppTopov.js)
|
||||
// to the overlay framework.
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
// injected refs
|
||||
var $log, tov, lts;
|
||||
|
||||
// our overlay definition
|
||||
var overlay = {
|
||||
overlayId: 'tl-overlay',
|
||||
glyphId: 'm_disjointPaths',
|
||||
tooltip: 'Algorithmic Layout Overlay',
|
||||
|
||||
activate: function () {
|
||||
$log.debug("Layout topology overlay ACTIVATED");
|
||||
},
|
||||
deactivate: function () {
|
||||
lts.clear();
|
||||
$log.debug("Layout topology overlay DEACTIVATED");
|
||||
},
|
||||
|
||||
keyBindings: {
|
||||
0: {
|
||||
cb: function () {
|
||||
lts.doLayout('default', 'Default (force-based) Layout');
|
||||
},
|
||||
tt: 'Default (force-based) layout',
|
||||
gid: 'm_fiberSwitch'
|
||||
},
|
||||
1: {
|
||||
cb: function () {
|
||||
lts.doLayout('access', 'Access Network Layout - separate service leafs');
|
||||
},
|
||||
tt: 'Access layout - separate service leafs',
|
||||
gid: 'm_disjointPaths'
|
||||
},
|
||||
|
||||
_keyOrder: [
|
||||
'0', '1'
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
// invoke code to register with the overlay service
|
||||
angular.module('ovTlTopov')
|
||||
.run(['$log', 'TopoOverlayService', 'LayoutTopovService',
|
||||
|
||||
function (_$log_, _tov_, _lts_) {
|
||||
$log = _$log_;
|
||||
tov = _tov_;
|
||||
lts = _lts_;
|
||||
tov.register(overlay);
|
||||
}]);
|
||||
}());
|
||||
1
apps/layout/src/main/resources/tlTopov/css.html
Normal file
1
apps/layout/src/main/resources/tlTopov/css.html
Normal file
@ -0,0 +1 @@
|
||||
<link rel="stylesheet" href="app/view/tlTopov/tlTopov.css">
|
||||
2
apps/layout/src/main/resources/tlTopov/js.html
Normal file
2
apps/layout/src/main/resources/tlTopov/js.html
Normal file
@ -0,0 +1,2 @@
|
||||
<script src="app/view/tlTopov/tlTopov.js"></script>
|
||||
<script src="app/view/tlTopov/tlTopovOverlay.js"></script>
|
||||
@ -251,18 +251,18 @@ public class UiWebSocket
|
||||
ObjectNode message = (ObjectNode) mapper.reader().readTree(data);
|
||||
String type = message.path(EVENT).asText(UNKNOWN);
|
||||
|
||||
if (sessionToken == null) {
|
||||
authenticate(type, message);
|
||||
|
||||
// if (sessionToken == null) {
|
||||
// authenticate(type, message);
|
||||
//
|
||||
// } else {
|
||||
UiMessageHandler handler = handlers.get(type);
|
||||
if (handler != null) {
|
||||
log.debug("RX message: {}", message);
|
||||
handler.process(message);
|
||||
} else {
|
||||
UiMessageHandler handler = handlers.get(type);
|
||||
if (handler != null) {
|
||||
log.debug("RX message: {}", message);
|
||||
handler.process(message);
|
||||
} else {
|
||||
log.warn("No GUI message handler for type {}", type);
|
||||
}
|
||||
log.warn("No GUI message handler for type {}", type);
|
||||
}
|
||||
// }
|
||||
|
||||
} catch (Exception e) {
|
||||
log.warn("Unable to parse GUI message {} due to {}", data, e);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user