edit descriptor model for composer rbac fix
[osm/UI.git] / skyquake / skyquake.js
1 /*
2 *
3 * Copyright 2016 RIFT.IO Inc
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
18
19 /**
20 * Main skyquake module.
21 * @module skyquake
22 * @author Kiran Kashalkar <kiran.kashalkar@riftio.com>
23 */
24
25 // Standard library imports for forking
26 var cluster = require("cluster");
27 var cpu = require('os').cpus().length;
28 var clusteredLaunch = process.env.CLUSTER_SUPPORT || false;
29 var constants = require('./framework/core/api_utils/constants');
30 // Uncomment for Replay support
31 // const Replay = require('replay');
32 var freePorts = [];
33 for (var i = 0; i < constants.SOCKET_POOL_LENGTH; i++) {
34 freePorts[i] = constants.SOCKET_BASE_PORT + i;
35 };
36
37
38 if (cluster.isMaster && clusteredLaunch) {
39 console.log(cpu, 'CPUs found');
40 for (var i = 0; i < cpu; i ++) {
41 var worker = cluster.fork();
42 worker.on('message', function(msg) {
43 if (msg && msg.getPort) {
44 worker.send({
45 port: freePorts.shift()
46 });
47 console.log('freePorts after shift for worker', this.process.pid, ':', freePorts);
48 } else if (msg && msg.freePort) {
49 freePorts.unshift(msg.port);
50 console.log('freePorts after unshift of', msg.port, 'for worker', this.process.pid, ':', freePorts);
51 }
52 });
53 }
54
55 cluster.on('online', function(worker) {
56 console.log("Worker Started pid : " + worker.process.pid);
57 });
58 cluster.on('exit', function(worker, code, signal) {
59 console.log('worker ' + worker.process.pid + ' stopped');
60 });
61 } else {
62 // Standard library imports
63 var argv = require('minimist')(process.argv.slice(2));
64 var pid = process.pid;
65 var fs = require('fs');
66 var https = require('https');
67 var http = require('http');
68 var express = require('express');
69 var session = require('express-session');
70 var cors = require('cors');
71 var bodyParser = require('body-parser');
72 var _ = require('lodash');
73 var reload = require('require-reload')(require);
74 var Sockets = require('./framework/core/api_utils/sockets.js');
75
76 require('require-json');
77
78 // SSL related configuration bootstrap
79 var httpServer = null;
80 var secureHttpServer = null;
81
82 var httpsConfigured = false;
83
84 var sslOptions = null;
85
86 var apiServer = argv['api-server'] ? argv['api-server'] : 'localhost';
87 var uploadServer = argv['upload-server'] ? argv['upload-server'] : null;
88
89 try {
90 if (argv['enable-https']) {
91 var keyFilePath = argv['keyfile-path'];
92 var certFilePath = argv['certfile-path'];
93
94 sslOptions = {
95 key: fs.readFileSync(keyFilePath),
96 cert: fs.readFileSync(certFilePath)
97 };
98
99 httpsConfigured = true;
100 }
101 } catch (e) {
102 console.log('HTTPS enabled but file paths missing/incorrect');
103 process.exit(code = -1);
104 }
105
106 var app = express();
107
108 app.set('views', __dirname + '/framework/core/views');
109 app.engine('html', require('ejs').renderFile);
110
111 app.use(session({
112 secret: 'ritio rocks',
113 resave: false,
114 saveUninitialized: true
115 }));
116 app.use(bodyParser.json());
117 app.use(cors());
118 app.use(bodyParser.urlencoded({
119 extended: true
120 }));
121
122 var socketManager = new Sockets();
123 var socketConfig = {
124 httpsConfigured: httpsConfigured
125 };
126
127 if (httpsConfigured) {
128 socketConfig.sslOptions = sslOptions;
129 }
130
131 // Rift framework imports
132 var constants = require('./framework/core/api_utils/constants');
133 var skyquakeEmitter = require('./framework/core/modules/skyquakeEmitter');
134 var navigation_routes = require('./framework/core/modules/routes/navigation');
135 var socket_routes = require('./framework/core/modules/routes/sockets');
136 var restconf_routes = require('./framework/core/modules/routes/restconf');
137 var inactivity_routes = require('./framework/core/modules/routes/inactivity');
138 var descriptor_routes = require('./framework/core/modules/routes/descriptorModel');
139 var configuration_routes = require('./framework/core/modules/routes/configuration');
140 var configurationAPI = require('./framework/core/modules/api/configuration');
141 var userManagement_routes = require('./framework/core/modules/routes/userManagement');
142 var projectManagement_routes = require('./framework/core/modules/routes/projectManagement');
143 var session_routes = require('./framework/core/modules/routes/sessions');
144 /**
145 * Processing when a plugin is added or modified
146 * @param {string} plugin_name - Name of the plugin
147 */
148 function onPluginAdded(plugin_name) {
149 // Load plugin config
150 var plugin_config = reload('./plugins/' + plugin_name + '/config.json');
151
152 // Load all app's views
153 app.use('/' + plugin_name, express.static('./plugins/' + plugin_name + '/' + plugin_config.root));
154
155 // Load all app's routes
156 app.use('/' + plugin_name, require('./plugins/' + plugin_name + '/routes'));
157
158 // Publish navigation links
159 if (plugin_config.routes && _.isArray(plugin_config.routes)) {
160 skyquakeEmitter.emit('config_discoverer.navigation_discovered', plugin_name, plugin_config);
161 }
162
163 }
164
165 /**
166 * Serve jquery
167 */
168 app.use('/jquery', express.static('./node_modules/jquery/dist/jquery.min.js'));
169 /**
170 * Serve images
171 */
172 app.use('/img', express.static('./framework/style/img'));
173
174 /**
175 * Start listening on a port
176 * @param {string} port - Port to listen on
177 * @param {object} httpServer - httpServer created with http(s).createServer
178 */
179 function startListening(port, httpServer) {
180 var server = httpServer.listen(port, function () {
181 var host = server.address().address;
182
183 var port = server.address().port;
184
185 console.log('Express server listening on port', port);
186 });
187 return server;
188 }
189
190 /**
191 * Initialize skyquake
192 */
193 function init() {
194 skyquakeEmitter.on('plugin_discoverer.plugin_discovered', onPluginAdded);
195 skyquakeEmitter.on('plugin_discoverer.plugin_updated', onPluginAdded);
196 }
197
198 /**
199 * Configure skyquake
200 */
201 function config() {
202 // Conigure any globals
203 process.env.NODE_TLS_REJECT_UNAUTHORIZED=0;
204
205 // Configure navigation router
206 app.use(navigation_routes);
207
208 // Configure restconf router
209 app.use(restconf_routes);
210
211 //Configure inactivity route(s)
212 app.use(inactivity_routes);
213
214 // Configure global config with ssl enabled/disabled
215 var globalConfig = {
216 ssl_enabled: httpsConfigured,
217 api_server: apiServer
218 };
219
220 if (uploadServer) {
221 globalConfig.upload_server = uploadServer;
222 }
223
224 configurationAPI.globalConfiguration.update(globalConfig);
225
226 // Configure configuration route(s)
227 app.use(configuration_routes);
228
229 //Configure descriptor route(s)
230 app.use(descriptor_routes);
231
232 //Configure user management route(s)
233 app.use(userManagement_routes);
234
235 //Configure project management route(s)
236 app.use(projectManagement_routes);
237
238 //Configure session route(s)
239 app.use(session_routes);
240
241 // app.get('/testme', function(req, res) {
242 // res.sendFile(__dirname + '/index.html');
243 // });
244
245 // Configure HTTP/HTTPS server and populate socketConfig.
246 if (httpsConfigured) {
247 console.log('HTTPS configured. Will create 2 servers');
248 secureHttpServer = https.createServer(sslOptions, app);
249 // Add redirection on SERVER_PORT
250 httpServer = http.createServer(function(req, res) {
251 var host = req.headers['host'];
252 host = host.replace(/:\d+$/, ":" + constants.SECURE_SERVER_PORT);
253
254 res.writeHead(301, { "Location": "https://" + host + req.url });
255 res.end();
256 });
257
258 socketConfig.httpServer = secureHttpServer;
259 } else {
260 httpServer = http.createServer(app);
261 socketConfig.httpServer = httpServer;
262 }
263
264 // Configure socket manager
265 socketManager.configure(socketConfig);
266
267 // Configure socket router
268 socket_routes.routes(socketManager);
269 app.use(socket_routes.router);
270
271 // Serve multiplex-client
272 app.get('/multiplex-client', function(req, res) {
273 res.sendFile(__dirname + '/node_modules/websocket-multiplex/multiplex_client.js');
274 });
275 }
276
277 /**
278 * Run skyquake functionality
279 */
280 function run() {
281
282 // Start plugin_discoverer
283 var navigation_manager = require('./framework/core/modules/navigation_manager');
284 var plugin_discoverer = require('./framework/core/modules/plugin_discoverer');
285
286 // Initialize asynchronous modules
287 navigation_manager.init();
288 plugin_discoverer.init();
289
290 // Configure asynchronous modules
291 navigation_manager.config()
292 plugin_discoverer.config({
293 plugins_path: './plugins'
294 });
295
296 // Run asynchronous modules
297 navigation_manager.run();
298 plugin_discoverer.run();
299
300
301 // Server start
302 if (httpsConfigured) {
303 console.log('HTTPS configured. Will start 2 servers');
304 // Start listening on SECURE_SERVER_PORT (8443)
305 var secureServer = startListening(constants.SECURE_SERVER_PORT, secureHttpServer);
306 }
307 // Start listening on SERVER_PORT (8000)
308 var server = startListening(constants.SERVER_PORT, httpServer);
309
310 }
311
312 init();
313
314 config();
315
316 run();
317 }