blob: 61c80fee5e663188c748bad5499b04c79185ea51 [file] [log] [blame]
daniel park128c52c2017-09-04 13:15:51 +09001/*
2 * Copyright 2017-present Open Networking Laboratory
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17/*
18 OpenStack Networking UI Service
19
20 Provides a mechanism to highlight hosts, devices and links according to
21 a virtual network. Also provides trace functionality to prove that
22 flow rules for the specific vm are installed appropriately.
23 */
24
25(function () {
26 'use strict';
27
28 // injected refs
29 var $log, fs, flash, wss, ds;
30
Daniel Park4e037f52018-09-20 18:04:18 +090031 var traceSrc = null;
32 var traceDst = null;
33 var srcDeviceId = null;
34 var dstDeviceId = null;
35 var uplink = null;
36
daniel park128c52c2017-09-04 13:15:51 +090037 // constants
38 var displayStart = 'openstackNetworkingUiStart',
39 displayUpdate = 'openstackNetworkingUiUpdate',
40 displayStop = 'openstackNetworkingUiStop',
41 flowTraceRequest = 'flowTraceRequest';
42
43 // internal state
44 var currentMode = null;
45
46 // === ---------------------------
47 // === Helper functions
48
49 function sendDisplayStart(mode) {
50 wss.sendEvent(displayStart, {
51 mode: mode
52 });
53 }
54
55 function sendDisplayUpdate(what) {
56 wss.sendEvent(displayUpdate, {
57 id: what ? what.id : ''
58 });
59 }
60
61 function sendDisplayStop() {
62 wss.sendEvent(displayStop);
63 }
64
Daniel Park4e037f52018-09-20 18:04:18 +090065 function sendFlowTraceRequest(src, dst, srcDeviceId, dstDeviceId, uplink) {
daniel park128c52c2017-09-04 13:15:51 +090066 wss.sendEvent(flowTraceRequest, {
67 srcIp: src,
Daniel Park577b69c2018-07-16 17:29:34 +090068 dstIp: dst,
69 srcDeviceId: srcDeviceId,
70 dstDeviceId: dstDeviceId,
Daniel Park4e037f52018-09-20 18:04:18 +090071 uplink: uplink,
daniel park128c52c2017-09-04 13:15:51 +090072 });
73 flash.flash('sendFlowTraceRequest called');
74 }
75
76 // === ---------------------------
77 // === Main API functions
78
79 function startDisplay(mode) {
80 if (currentMode === mode) {
81 $log.debug('(in mode', mode, 'already)');
82 } else {
83 currentMode = mode;
84 sendDisplayStart(mode);
85
86 flash.flash('Starting Openstack Networking UI mode');
87 }
88 }
89
90 function updateDisplay(m) {
91 if (currentMode) {
92 sendDisplayUpdate(m);
93 }
94 }
95
96 function stopDisplay() {
97 if (currentMode) {
98 currentMode = null;
99 sendDisplayStop();
100 flash.flash('Canceling Openstack Networking UI Overlay mode');
101 return true;
102 }
103 return false;
104 }
105
daniel park128c52c2017-09-04 13:15:51 +0900106 function dOk() {
107 ds.closeDialog();
108 }
boyoung27b444122018-09-01 17:28:13 +0900109
daniel park128c52c2017-09-04 13:15:51 +0900110 function openFlowTraceResultDialog(data) {
111 var flowTraceResultDialogId = 'flowTraceResultDialogId',
112 flowTraceResultDialogOpt = {
113 width: 650,
114 edge: 'left',
115 margin: 20,
116 hideMargin: -20
117 }
Daniel Park577b69c2018-07-16 17:29:34 +0900118 var traceSuccess = data.traceSuccess == true ? "SUCCESS" : "FALSE";
Daniel Park4e037f52018-09-20 18:04:18 +0900119 traceSrc = data.srcIp;
120 traceDst = data.dstIp;
121 srcDeviceId = data.srcDeviceId;
122 dstDeviceId = data.dstDeviceId;
123 uplink = data.uplink;
124
125 if (data.uplink == true) {
126 ds.openDialog(flowTraceResultDialogId, flowTraceResultDialogOpt)
127 .setTitle('Flow Trace Result: ' + traceSuccess)
128 .addContent(createTraceResultInfoDiv(data))
129 .addOk(downlinkTraceRequestBtn, 'Downlink Trace')
130 .bindKeys();
131 } else {
132 ds.openDialog(flowTraceResultDialogId, flowTraceResultDialogOpt)
133 .setTitle('Flow Trace Result: ' + traceSuccess)
134 .addContent(createTraceResultInfoDiv(data))
135 .addOk(dOk, 'Close')
136 .bindKeys();
137 }
138
139 }
140
141 function downlinkTraceRequestBtn() {
142 sendFlowTraceRequest(traceSrc, traceDst, srcDeviceId, dstDeviceId, false);
143 ds.closeDialog();
144 flash.flash('Send Downlink Flow Trace Request')
daniel park128c52c2017-09-04 13:15:51 +0900145 }
146
147 function createTraceResultInfoDiv(data) {
148 var texts = ds.createDiv('flowTraceResult');
149
150 texts.append('div').attr("class", "table-header");
151 texts.append('div').attr("class", "table-body");
152
153 texts.select('.table-header').append('table').append('tbody').append('tr');
154 texts.select('.table-body').append('table').append('tbody');
155
156
157 var theaderSelection = texts.select('.table-header')
158 .select('table').select('tbody').select('tr');
159
160 theaderSelection.append('td').text('Node');
161 theaderSelection.append('td').text('Table Id');
162 theaderSelection.append('td').text('Priority');
163 theaderSelection.append('td').text('Selector');
164 theaderSelection.append('td').text('Action');
165
166 var tbodySelection = texts.select('.table-body').select('table').select('tbody');
167 var rowNum = 1;
168
Daniel Park577b69c2018-07-16 17:29:34 +0900169 data.traceResult.forEach(function(result) {
170 result.flowRules.forEach(function(flowRule) {
daniel park128c52c2017-09-04 13:15:51 +0900171 tbodySelection.append('tr');
172 var tbodyTrSelection = tbodySelection.select('tr:nth-child(' + rowNum + ')');
Daniel Park577b69c2018-07-16 17:29:34 +0900173 tbodyTrSelection.append('td').text(result.traceNodeName);
daniel park128c52c2017-09-04 13:15:51 +0900174 tbodyTrSelection.append('td').text(flowRule.table);
175 tbodyTrSelection.append('td').text(flowRule.priority);
Daniel Park577b69c2018-07-16 17:29:34 +0900176 tbodyTrSelection.append('td').text(flowRule.selector);
177 tbodyTrSelection.append('td').text(flowRule.actions);
daniel park128c52c2017-09-04 13:15:51 +0900178 if (jsonToSring(flowRule.actions).includes("drop")) {
179 tbodyTrSelection.attr("class", "drop");
180 }
181 rowNum++;
182 });
183
184 });
185
186 return texts;
187 }
188
189 function jsonToSring(jsonData) {
190 var result = [];
191 for (var key in jsonData) {
192 result.push(key + ':' + jsonData[key]);
193 }
194
195 return result.join('/');
196
197 }
198
199 function flowTraceResult(data) {
200 flash.flash('flowTraceResult called');
201 $log.debug(data);
202
203 openFlowTraceResultDialog(data)
204 }
205
206 // === ---------------------------
207 // === Module Factory Definition
208
209 angular.module('ovSonaTopov', [])
210 .factory('SonaTopovService',
211 ['$log', 'FnService', 'FlashService', 'WebSocketService', 'DialogService',
212
213 function (_$log_, _fs_, _flash_, _wss_, _ds_) {
214 $log = _$log_;
215 fs = _fs_;
216 flash = _flash_;
217 wss = _wss_;
218 ds = _ds_;
219
220 return {
221 startDisplay: startDisplay,
222 updateDisplay: updateDisplay,
223 stopDisplay: stopDisplay,
daniel park128c52c2017-09-04 13:15:51 +0900224 flowTraceResult: flowTraceResult,
225 sendFlowTraceRequest: sendFlowTraceRequest,
226 };
227 }]);
228}());