| /* |
| * Copyright 2019-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. |
| */ |
| import {Injectable, SimpleChange} from '@angular/core'; |
| import { |
| LogService, WebSocketService, |
| } from '../../gui2-fw-lib/public_api'; |
| import {Instance, InstanceComponent} from './panel/instance/instance.component'; |
| import { BackgroundSvgComponent } from './layer/backgroundsvg/backgroundsvg.component'; |
| import { ForceSvgComponent } from './layer/forcesvg/forcesvg.component'; |
| import { |
| ModelEventMemo, |
| ModelEventType, |
| Region |
| } from './layer/forcesvg/models'; |
| |
| /** |
| * Model of the Intent to be displayed |
| */ |
| export interface Intent { |
| appId: string; |
| appName: string; |
| key: string; |
| type: string; |
| } |
| |
| export interface RelatedIntent { |
| ids: string[]; |
| hover: string; |
| } |
| |
| /** |
| * ONOS GUI -- Topology Service Module. |
| */ |
| @Injectable() |
| export class TopologyService { |
| |
| private handlers: string[] = []; |
| private openListener: any; |
| public instancesIndex: Map<string, number>; |
| |
| constructor( |
| protected log: LogService, |
| protected wss: WebSocketService |
| ) { |
| this.instancesIndex = new Map(); |
| this.log.debug('TopologyService constructed'); |
| } |
| |
| /** |
| * bind our event handlers to the web socket service, so that our |
| * callbacks get invoked for incoming events |
| */ |
| init(instance: InstanceComponent, background: BackgroundSvgComponent, force: ForceSvgComponent) { |
| this.wss.bindHandlers(new Map<string, (data) => void>([ |
| ['topo2AllInstances', (data) => { |
| this.log.debug('Instances updated through WSS as topo2AllInstances', data); |
| instance.ngOnChanges( |
| {'onosInstances': new SimpleChange({}, data.members, true)}); |
| |
| // Also generate an index locally of the instances |
| // needed so that devices can be coloured by instance |
| this.instancesIndex.clear(); |
| (<Instance[]>data.members).forEach((inst, idx) => this.instancesIndex.set(inst.id, idx)); |
| this.log.debug('Created local index of instances', this.instancesIndex); |
| } |
| ], |
| ['topo2CurrentLayout', (data) => { |
| this.log.debug('Background Data updated from WSS as topo2CurrentLayout', data); |
| if (background) { |
| background.layoutData = data; |
| } |
| } |
| ], |
| ['topo2CurrentRegion', (data) => { |
| force.regionData = data; |
| force.ngOnChanges({ |
| 'regionData' : new SimpleChange(<Region>{}, data, true) |
| }); |
| this.log.debug('Region Data replaced from WSS as topo2CurrentRegion', force.regionData); |
| } |
| ], |
| ['topo2PeerRegions', (data) => { this.log.warn('Add fn for topo2PeerRegions callback', data); } ], |
| ['topo2UiModelEvent', (event) => { |
| // this.log.debug('Handling', event); |
| force.handleModelEvent( |
| <ModelEventType><unknown>(ModelEventType[event.type]), // Number based enum |
| <ModelEventMemo>(event.memo), // String based enum |
| event.subject, event.data); |
| } |
| ], |
| ['showHighlights', (event) => { |
| this.log.debug('Handling showHighlights', event); |
| force.handleHighlights(event.devices, event.hosts, event.links, 5000); |
| }] |
| // topo2Highlights is handled by TrafficService |
| ])); |
| this.handlers.push('topo2AllInstances'); |
| this.handlers.push('topo2CurrentLayout'); |
| this.handlers.push('topo2CurrentRegion'); |
| this.handlers.push('topo2PeerRegions'); |
| this.handlers.push('topo2UiModelEvent'); |
| this.handlers.push('showHighlights'); |
| // this.handlers.push('topo2Highlights'); |
| |
| // in case we fail over to a new server, |
| // listen for wsock-open events |
| this.openListener = this.wss.addOpenListener(() => this.wsOpen); |
| |
| // tell the server we are ready to receive topology events |
| this.wss.sendEvent('topo2Start', {}); |
| this.log.debug('TopologyService initialized'); |
| } |
| |
| /** |
| * tell the server we no longer wish to receive topology events |
| */ |
| destroy() { |
| this.wss.sendEvent('topo2Stop', {}); |
| this.wss.unbindHandlers(this.handlers); |
| this.wss.removeOpenListener(this.openListener); |
| this.openListener = null; |
| this.log.debug('TopologyService destroyed'); |
| } |
| |
| |
| wsOpen(host: string, url: string) { |
| this.log.debug('topo2Event: WSopen - cluster node:', host, 'URL:', url); |
| // tell the server we are ready to receive topo events |
| this.wss.sendEvent('topo2Start', {}); |
| } |
| |
| /* |
| * Result will be handled by showHighlights handler (set up in topology service) |
| * which will call handleHighlights() in Force Component |
| */ |
| setSelectedIntent(selectedIntent: Intent): void { |
| this.log.debug('Selected intent changed to', selectedIntent); |
| this.wss.sendEvent('selectIntent', selectedIntent); |
| } |
| |
| selectRelatedIntent(ids: string[]): void { |
| this.log.debug('Select next intent'); |
| this.wss.sendEvent('requestNextRelatedIntent', <RelatedIntent>{ |
| ids: ids, |
| hover: undefined, |
| }); |
| } |
| |
| /* |
| * Tell the backend to stop sending highlights - any present will fade after 5 seconds |
| * There is also a cancel traffic for Topo 2 in Traffic Service |
| */ |
| cancelHighlights(): void { |
| this.wss.sendEvent('cancelTraffic', {}); |
| this.log.debug('Highlights canceled'); |
| } |
| } |