Committed by
Gerrit Code Review
Enabling UI live-reload for apps not in the ONOS source code
Change-Id: Ib88929a8825b7adf136d2b6b90d66db10549c165
Showing
9 changed files
with
308 additions
and
24 deletions
| 1 | +namespace java org.p4.bmv2.thrift | ||
| 2 | +namespace cpp cpservice | ||
| 3 | + | ||
| 4 | +service ControlPlaneService { | ||
| 5 | + | ||
| 6 | + bool ping(), | ||
| 7 | + | ||
| 8 | + oneway void packetIn(1: i32 port, 2: i64 reason, 3: i32 tableId, 4: i32 contextId, 5: binary packet), | ||
| 9 | + | ||
| 10 | + oneway void hello(1: i32 thriftServerPort, 2: i32 deviceId) | ||
| 11 | + | ||
| 12 | +} | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| 1 | +namespace java org.p4.bmv2.thrift | ||
| 2 | +/* Copyright 2013-present Barefoot Networks, Inc. | ||
| 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 | + * Antonin Bas (antonin@barefootnetworks.com) | ||
| 19 | + * | ||
| 20 | + */ | ||
| 21 | + | ||
| 22 | +namespace cpp bm_runtime.simple_pre | ||
| 23 | +namespace py bm_runtime.simple_pre | ||
| 24 | + | ||
| 25 | +typedef i32 BmMcMgrp | ||
| 26 | +typedef i32 BmMcRid | ||
| 27 | +typedef i32 BmMcMgrpHandle | ||
| 28 | +typedef i32 BmMcL1Handle | ||
| 29 | +typedef string BmMcPortMap // string of 0s and 1s | ||
| 30 | + | ||
| 31 | +enum McOperationErrorCode { | ||
| 32 | + TABLE_FULL = 1, | ||
| 33 | + INVALID_HANDLE = 2, | ||
| 34 | + INVALID_MGID = 3, | ||
| 35 | + INVALID_L1_HANDLE = 4, | ||
| 36 | + INVALID_L2_HANLDE = 5, | ||
| 37 | + ERROR = 6 | ||
| 38 | +} | ||
| 39 | + | ||
| 40 | +exception InvalidMcOperation { | ||
| 41 | + 1:McOperationErrorCode code | ||
| 42 | +} | ||
| 43 | + | ||
| 44 | +service SimplePre { | ||
| 45 | + | ||
| 46 | + BmMcMgrpHandle bm_mc_mgrp_create( | ||
| 47 | + 1:i32 cxt_id, | ||
| 48 | + 2:BmMcMgrp mgrp | ||
| 49 | + ) throws (1:InvalidMcOperation ouch), | ||
| 50 | + | ||
| 51 | + void bm_mc_mgrp_destroy( | ||
| 52 | + 1:i32 cxt_id, | ||
| 53 | + 2:BmMcMgrpHandle mgrp_handle | ||
| 54 | + ) throws (1:InvalidMcOperation ouch), | ||
| 55 | + | ||
| 56 | + BmMcL1Handle bm_mc_node_create( | ||
| 57 | + 1:i32 cxt_id, | ||
| 58 | + 2:BmMcRid rid | ||
| 59 | + 3:BmMcPortMap port_map | ||
| 60 | + ) throws (1:InvalidMcOperation ouch), | ||
| 61 | + | ||
| 62 | + void bm_mc_node_associate( | ||
| 63 | + 1:i32 cxt_id, | ||
| 64 | + 2:BmMcMgrpHandle mgrp_handle, | ||
| 65 | + 3:BmMcL1Handle l1_handle | ||
| 66 | + ) throws (1:InvalidMcOperation ouch), | ||
| 67 | + | ||
| 68 | + void bm_mc_node_dissociate( | ||
| 69 | + 1:i32 cxt_id, | ||
| 70 | + 2:BmMcMgrpHandle mgrp_handle, | ||
| 71 | + 3:BmMcL1Handle l1_handle | ||
| 72 | + ) throws (1:InvalidMcOperation ouch), | ||
| 73 | + | ||
| 74 | + void bm_mc_node_destroy( | ||
| 75 | + 1:i32 cxt_id, | ||
| 76 | + 2:BmMcL1Handle l1_handle | ||
| 77 | + ) throws (1:InvalidMcOperation ouch), | ||
| 78 | + | ||
| 79 | + void bm_mc_node_update( | ||
| 80 | + 1:i32 cxt_id, | ||
| 81 | + 2:BmMcL1Handle l1_handle, | ||
| 82 | + 3:BmMcPortMap port_map | ||
| 83 | + ) throws (1:InvalidMcOperation ouch), | ||
| 84 | +} |
| 1 | +namespace java org.p4.bmv2.thrift | ||
| 2 | +/* Copyright 2013-present Barefoot Networks, Inc. | ||
| 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 | + * Srikrishna Gopu (krishna@barefootnetworks.com) | ||
| 19 | + * Antonin Bas (antonin@barefootnetworks.com) | ||
| 20 | + * | ||
| 21 | + */ | ||
| 22 | + | ||
| 23 | +namespace cpp bm_runtime.simple_pre_lag | ||
| 24 | +namespace py bm_runtime.simple_pre_lag | ||
| 25 | + | ||
| 26 | +typedef i32 BmMcMgrp | ||
| 27 | +typedef i32 BmMcRid | ||
| 28 | +typedef i32 BmMcMgrpHandle | ||
| 29 | +typedef i32 BmMcL1Handle | ||
| 30 | +typedef i16 BmMcLagIndex | ||
| 31 | +typedef string BmMcPortMap // string of 0s and 1s | ||
| 32 | +typedef string BmMcLagMap // string of 0s and 1s | ||
| 33 | + | ||
| 34 | +enum McOperationErrorCode { | ||
| 35 | + TABLE_FULL = 1, | ||
| 36 | + INVALID_HANDLE = 2, | ||
| 37 | + INVALID_MGID = 3, | ||
| 38 | + INVALID_L1_HANDLE = 4, | ||
| 39 | + INVALID_L2_HANLDE = 5, | ||
| 40 | + ERROR = 6 | ||
| 41 | +} | ||
| 42 | + | ||
| 43 | +exception InvalidMcOperation { | ||
| 44 | + 1:McOperationErrorCode code | ||
| 45 | +} | ||
| 46 | + | ||
| 47 | +service SimplePreLAG { | ||
| 48 | + | ||
| 49 | + BmMcMgrpHandle bm_mc_mgrp_create( | ||
| 50 | + 1:i32 cxt_id, | ||
| 51 | + 2:BmMcMgrp mgrp | ||
| 52 | + ) throws (1:InvalidMcOperation ouch), | ||
| 53 | + | ||
| 54 | + void bm_mc_mgrp_destroy( | ||
| 55 | + 1:i32 cxt_id, | ||
| 56 | + 2:BmMcMgrpHandle mgrp_handle | ||
| 57 | + ) throws (1:InvalidMcOperation ouch), | ||
| 58 | + | ||
| 59 | + BmMcL1Handle bm_mc_node_create( | ||
| 60 | + 1:i32 cxt_id, | ||
| 61 | + 2:BmMcRid rid, | ||
| 62 | + 3:BmMcPortMap port_map, | ||
| 63 | + 4:BmMcLagMap lag_map | ||
| 64 | + ) throws (1:InvalidMcOperation ouch), | ||
| 65 | + | ||
| 66 | + void bm_mc_node_associate( | ||
| 67 | + 1:i32 cxt_id, | ||
| 68 | + 2:BmMcMgrpHandle mgrp_handle, | ||
| 69 | + 3:BmMcL1Handle l1_handle | ||
| 70 | + ) throws (1:InvalidMcOperation ouch), | ||
| 71 | + | ||
| 72 | + void bm_mc_node_dissociate( | ||
| 73 | + 1:i32 cxt_id, | ||
| 74 | + 2:BmMcMgrpHandle mgrp_handle, | ||
| 75 | + 3:BmMcL1Handle l1_handle | ||
| 76 | + ) throws (1:InvalidMcOperation ouch), | ||
| 77 | + | ||
| 78 | + void bm_mc_node_destroy( | ||
| 79 | + 1:i32 cxt_id, | ||
| 80 | + 2:BmMcL1Handle l1_handle | ||
| 81 | + ) throws (1:InvalidMcOperation ouch), | ||
| 82 | + | ||
| 83 | + void bm_mc_node_update( | ||
| 84 | + 1:i32 cxt_id, | ||
| 85 | + 2:BmMcL1Handle l1_handle, | ||
| 86 | + 3:BmMcPortMap port_map, | ||
| 87 | + 4:BmMcLagMap lag_map | ||
| 88 | + ) throws (1:InvalidMcOperation ouch), | ||
| 89 | + | ||
| 90 | + void bm_mc_set_lag_membership( | ||
| 91 | + 1:i32 cxt_id, | ||
| 92 | + 2:BmMcLagIndex lag_index, | ||
| 93 | + 3:BmMcPortMap port_map | ||
| 94 | + ) throws (1:InvalidMcOperation ouch), | ||
| 95 | +} |
| 1 | +namespace java org.p4.bmv2.thrift | ||
| 2 | +/* Copyright 2013-present Barefoot Networks, Inc. | ||
| 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 | + * Antonin Bas (antonin@barefootnetworks.com) | ||
| 19 | + * | ||
| 20 | + */ | ||
| 21 | + | ||
| 22 | +namespace cpp sswitch_runtime | ||
| 23 | +namespace py sswitch_runtime | ||
| 24 | + | ||
| 25 | +service SimpleSwitch { | ||
| 26 | + | ||
| 27 | + i32 mirroring_mapping_add(1:i32 mirror_id, 2:i32 egress_port); | ||
| 28 | + i32 mirroring_mapping_delete(1:i32 mirror_id); | ||
| 29 | + i32 mirroring_mapping_get_egress_port(1:i32 mirror_id); | ||
| 30 | + | ||
| 31 | + i32 set_egress_queue_depth(1:i32 depth_pkts); | ||
| 32 | + i32 set_egress_queue_rate(1:i64 rate_pps); | ||
| 33 | + | ||
| 34 | + oneway void push_packet(1:i32 port, 2:binary packet); | ||
| 35 | + | ||
| 36 | + bool ping(); | ||
| 37 | + | ||
| 38 | +} |
This diff is collapsed. Click to expand it.
| ... | @@ -26,4 +26,17 @@ Dev server is up and listening on http://localhost: 8182 | ... | @@ -26,4 +26,17 @@ Dev server is up and listening on http://localhost: 8182 |
| 26 | [BS] Watching files... | 26 | [BS] Watching files... |
| 27 | ``` | 27 | ``` |
| 28 | 28 | ||
| 29 | -To open ONOS visit the local URL (eg: `http://localhost:3000`) plus `/onos/ui` (eg: `http://localhost:3000/onos/ui`) | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| 29 | +To open ONOS visit the local URL (eg: `http://localhost:3000`) plus `/onos/ui` | ||
| 30 | +(eg: `http://localhost:3000/onos/ui`) | ||
| 31 | + | ||
| 32 | +## Loading files from external applications | ||
| 33 | + | ||
| 34 | +The UI development environment provide the ability to serve UI files | ||
| 35 | +from an external forlder that can be specified with: | ||
| 36 | +`ONOS_EXTERNAL_APP_DIRS="appName:path-to-the-first-folder" npm start` | ||
| 37 | + | ||
| 38 | +Eg: | ||
| 39 | +`ONOS_EXTERNAL_APP_DIRS="sampleCustom:../../meow/sample/meowster-sample/" npm start` | ||
| 40 | + | ||
| 41 | +_Note that `ONOS_EXTERNAL_APP_DIRS` is an environment variable,so it can be set with_ | ||
| 42 | +_`export ONOS_EXTERNAL_APP_DIRS="sampleCustom:../../meow/sample/meowster-sample/"`_ | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
| ... | @@ -19,15 +19,38 @@ var proxy = httpProxy.createProxyServer({ | ... | @@ -19,15 +19,38 @@ var proxy = httpProxy.createProxyServer({ |
| 19 | target: 'http://localhost:8182', | 19 | target: 'http://localhost:8182', |
| 20 | }); | 20 | }); |
| 21 | 21 | ||
| 22 | +if (process.env.ONOS_EXTERNAL_APP_DIRS) { | ||
| 23 | + var external_apps = process.env.ONOS_EXTERNAL_APP_DIRS.replace(/\s/,'').split(','); | ||
| 24 | + external_apps = external_apps.reduce(function(dict, app){ | ||
| 25 | + var pieces = app.split(':'); | ||
| 26 | + var appName = pieces[0]; | ||
| 27 | + var appPath = pieces[1]; | ||
| 28 | + dict[appName] = appPath; | ||
| 29 | + return dict; | ||
| 30 | + }, {}); | ||
| 31 | +} | ||
| 32 | + | ||
| 22 | var defaultViews = fs.readdirSync('./app/view/'); | 33 | var defaultViews = fs.readdirSync('./app/view/'); |
| 23 | var viewNameMatcher = new RegExp(/\/onos\/ui\/app\/view\/(.+)\/.+\.(?:js|css|html)/); | 34 | var viewNameMatcher = new RegExp(/\/onos\/ui\/app\/view\/(.+)\/.+\.(?:js|css|html)/); |
| 24 | 35 | ||
| 36 | +var checkExternalApp = function (url) { | ||
| 37 | + if(external_apps){ | ||
| 38 | + for(var i = 0; i < Object.keys(external_apps).length; i++){ | ||
| 39 | + var key = Object.keys(external_apps)[i]; | ||
| 40 | + if(url.indexOf(key) !== -1){ | ||
| 41 | + return key; | ||
| 42 | + }; | ||
| 43 | + } | ||
| 44 | + } | ||
| 45 | + return false; | ||
| 46 | +}; | ||
| 47 | + | ||
| 25 | proxy.on('upgrade', function (req, socket, head) { | 48 | proxy.on('upgrade', function (req, socket, head) { |
| 26 | console.log('[WS]: ', head); | 49 | console.log('[WS]: ', head); |
| 27 | proxy.ws(req, socket, head); | 50 | proxy.ws(req, socket, head); |
| 28 | }); | 51 | }); |
| 29 | 52 | ||
| 30 | -proxy.on('error', function(error, req, res) { | 53 | +proxy.on('error', function (error, req, res) { |
| 31 | res.writeHead(500, { | 54 | res.writeHead(500, { |
| 32 | 'Content-Type': 'text/plain' | 55 | 'Content-Type': 'text/plain' |
| 33 | }); | 56 | }); |
| ... | @@ -50,21 +73,29 @@ module.exports = { | ... | @@ -50,21 +73,29 @@ module.exports = { |
| 50 | proxy: { | 73 | proxy: { |
| 51 | target: "http://localhost:8181", | 74 | target: "http://localhost:8181", |
| 52 | ws: true, | 75 | ws: true, |
| 53 | - middleware: function(req, res, next){ | 76 | + middleware: function (req, res, next) { |
| 54 | - | ||
| 55 | 77 | ||
| 56 | var viewName = viewNameMatcher.exec(req.url); | 78 | var viewName = viewNameMatcher.exec(req.url); |
| 57 | - if(!!viewName && defaultViews.indexOf(viewName[1]) === -1){ | 79 | + var isExternalApp = checkExternalApp(req.url); |
| 58 | - // in this case it is an external application that extend the view | 80 | + |
| 81 | + if (!!viewName && !isExternalApp && defaultViews.indexOf(viewName[1]) === -1) { | ||
| 82 | + // in this case it is an application that extend the view | ||
| 59 | // so we redirect the request to the app folder in case of .js, .css, .html | 83 | // so we redirect the request to the app folder in case of .js, .css, .html |
| 60 | req.url = req.url.replace('/onos/ui/', '/apps/' + viewName[1] + '/app/src/main/resources/'); | 84 | req.url = req.url.replace('/onos/ui/', '/apps/' + viewName[1] + '/app/src/main/resources/'); |
| 61 | proxy.web(req, res); | 85 | proxy.web(req, res); |
| 62 | } | 86 | } |
| 87 | + else if (isExternalApp) { | ||
| 88 | + // in this case it is an external application (not in ONOS source code) that extend the view | ||
| 89 | + // so we redirect the request to the app folder in case of .js, .css, .html | ||
| 90 | + req.url = req.url.replace('/onos/ui/', '/src/main/resources/'); | ||
| 91 | + proxy.web(req, res); | ||
| 92 | + } | ||
| 63 | // NOTE onos.js and index.html should not be proxied (require server side injection) | 93 | // NOTE onos.js and index.html should not be proxied (require server side injection) |
| 64 | - else if(req.url.match(/(?:js|css|html)/) && req.url !== '/onos/ui/onos.js' && req.url !== '/onos/ui/index.html' && req.url !== '/onos/ui/nav.html'){ | 94 | + else if (req.url.match(/(?:js|css|html)/) && req.url !== '/onos/ui/onos.js' && |
| 95 | + req.url !== '/onos/ui/index.html' && req.url !== '/onos/ui/nav.html') { | ||
| 65 | // redirect onos base js files to the source folder | 96 | // redirect onos base js files to the source folder |
| 66 | req.url = req.url.replace('/onos/ui/', '/web/gui/src/main/webapp/'); | 97 | req.url = req.url.replace('/onos/ui/', '/web/gui/src/main/webapp/'); |
| 67 | - proxy.web(req, res); | 98 | + proxy.web(req, res); |
| 68 | } | 99 | } |
| 69 | else { | 100 | else { |
| 70 | return next(); | 101 | return next(); | ... | ... |
| 1 | 'use strict'; | 1 | 'use strict'; |
| 2 | 2 | ||
| 3 | -var http = require('http'); | ||
| 4 | -// var httpProxy = require('http-proxy'); | ||
| 5 | -var connect = require('connect'); | ||
| 6 | -var serveStatic = require('serve-static'); | ||
| 7 | var path = require('path'); | 3 | var path = require('path'); |
| 4 | +var express = require('express'); | ||
| 5 | +var app = express(); | ||
| 8 | 6 | ||
| 9 | var conf = { | 7 | var conf = { |
| 10 | paths: { | 8 | paths: { |
| ... | @@ -13,17 +11,31 @@ var conf = { | ... | @@ -13,17 +11,31 @@ var conf = { |
| 13 | port: '8182' | 11 | port: '8182' |
| 14 | } | 12 | } |
| 15 | 13 | ||
| 16 | -var httpProxyInit = function (baseDir) { | 14 | +if (process.env.ONOS_EXTERNAL_APP_DIRS) { |
| 15 | + var external_apps = process.env.ONOS_EXTERNAL_APP_DIRS.replace(/\s/,'').split(','); | ||
| 16 | + external_apps.forEach(function(a, i){ | ||
| 17 | + let [appName, appPath] = a.split(':'); | ||
| 18 | + conf.paths[appName] = appPath; | ||
| 19 | + }); | ||
| 20 | +} | ||
| 17 | 21 | ||
| 18 | - var app = connect(); | 22 | +var httpProxyInit = function (baseDirs) { |
| 19 | 23 | ||
| 20 | - app.use(serveStatic(path.join(__dirname, baseDir))); | 24 | + Object.keys(baseDirs).forEach(dir => { |
| 25 | + var d = path.isAbsolute(baseDirs[dir]) ? baseDirs[dir] : path.join(__dirname, baseDirs[dir]); | ||
| 26 | + app.use(express.static(d)); | ||
| 27 | + }); | ||
| 21 | 28 | ||
| 22 | - var server = http.createServer(app); | 29 | + app.get('/', function (req, res) { |
| 30 | + res.send('Hello World!'); | ||
| 31 | + }); | ||
| 23 | 32 | ||
| 24 | - server.listen(conf.port, function(){ | 33 | + app.listen(conf.port, function () { |
| 25 | - console.log('Dev server is up and listening on http://localhost:', conf.port); | 34 | + console.log(`Dev server is up and listening on http://localhost:${conf.port}!`); |
| 26 | }); | 35 | }); |
| 27 | }; | 36 | }; |
| 28 | 37 | ||
| 29 | -httpProxyInit(conf.paths.root); | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| 38 | +httpProxyInit(conf.paths); | ||
| 39 | + | ||
| 40 | + | ||
| 41 | + | ... | ... |
| ... | @@ -7,17 +7,16 @@ | ... | @@ -7,17 +7,16 @@ |
| 7 | "test": "tests" | 7 | "test": "tests" |
| 8 | }, | 8 | }, |
| 9 | "scripts": { | 9 | "scripts": { |
| 10 | - "bs": "browser-sync start --config bs-config.js", | 10 | + "bs": "browser-sync start --config bs-config.js", |
| 11 | - "dev-server": "node dev_server.js", | 11 | + "dev-server": "node --harmony_destructuring dev_server.js", |
| 12 | "start": "parallelshell \"npm run dev-server\" \"npm run bs\"" | 12 | "start": "parallelshell \"npm run dev-server\" \"npm run bs\"" |
| 13 | }, | 13 | }, |
| 14 | "author": "ON.Lab", | 14 | "author": "ON.Lab", |
| 15 | "license": "Apache 2.0", | 15 | "license": "Apache 2.0", |
| 16 | "devDependencies": { | 16 | "devDependencies": { |
| 17 | "browser-sync": "^2.12.8", | 17 | "browser-sync": "^2.12.8", |
| 18 | - "connect": "^3.4.1", | ||
| 19 | - "http-proxy": "^1.13.2", | ||
| 20 | "parallelshell": "^2.0.0", | 18 | "parallelshell": "^2.0.0", |
| 21 | - "serve-static": "^1.10.2" | 19 | + "serve-static": "^1.10.2", |
| 20 | + "express": "^4.14.0" | ||
| 22 | } | 21 | } |
| 23 | } | 22 | } | ... | ... |
-
Please register or login to post a comment