1 var express = require('express');
2 var router = express.Router();
3 var exec = require('child_process').exec;
4 var util = require('util');
5 var fs = require('fs.extra');
6 var dbRoutes = require('./dbRoutes');
7 var csp = require('./csp');
8 var multer = require('multer');
9 var cookieParser = require('cookie-parser');
10 var bodyParser = require('body-parser');
11 var sax = require('sax'),strict=true,parser = sax.parser(strict);
12 var async = require('async');
13 var l_ = require('lodash');
14 var dateFormat = require('dateformat');
15 var properties = require(process.env.SDNC_CONFIG_DIR + '/admportal.json');
16 var crypto = require('crypto');
17 var csrf = require('csurf');
19 var csrfProtection = csrf({cookie: true});
20 router.use(cookieParser())
22 // pass host, username and password to ODL
23 // target host for ODL request
24 var username = properties.odlUser;
25 var password = properties.odlPasswd;
26 var auth = 'Basic ' + new Buffer(username + ':' + password).toString('base64');
27 var host = properties.odlHost;
28 var port = properties.odlPort;
30 var header = {'Host': host, 'Authorization': auth, 'Content-Type': 'application/json'};
35 rejectUnauthorized:false,
39 // Connection to OpenDaylight
40 OdlInterface = require('./OdlInterface');
42 // used for file upload button, retain original file name
43 //router.use(bodyParser());
44 //router.use(bodyParser.urlencoded({
48 //var upload = multer({ dest: process.cwd() + '/uploads/', rename: function(fieldname,filename){ return filename; } });
51 var storage = multer.diskStorage({
52 destination: function (req, file, cb) {
53 cb(null, process.cwd() + '/uploads/')
55 filename: function (req, file, cb) {
56 cb(null, file.originalname )
66 router.get('/getVnfData', csp.checkAuth, csrfProtection, function(req,res) {
67 dbRoutes.getVnfData(req,res, {code:'', msg:''}, req.session.loggedInAdmin);
69 router.get('/getVnfNetworkData', csp.checkAuth, csrfProtection, function(req,res) {
70 dbRoutes.getVnfNetworkData(req,res, {code:'', msg:''}, req.session.loggedInAdmin);
72 router.get('/getVnfProfile', csp.checkAuth, csrfProtection, function(req,res) {
73 dbRoutes.getVnfProfile(req,res, {code:'', msg:''}, req.session.loggedInAdmin);
75 //router.get('/getVmNetworks', csp.checkAuth, function(req,res) {
76 // dbRoutes.getVmNetworks(req,res, {code:'', msg:''}, req.session.loggedInAdmin);
78 //router.get('/getVnfNetworks', csp.checkAuth, function(req,res) {
79 // dbRoutes.getVnfNetworks(req,res, {code:'', msg:''}, req.session.loggedInAdmin);
81 //router.get('/getVmProfile', csp.checkAuth, function(req,res) {
82 // dbRoutes.getVmProfile(req,res, {code:'', msg:''}, req.session.loggedInAdmin);
86 router.get('/viewVnfNetworkData', csp.checkAuth, csrfProtection, function(req,res)
88 var privilegeObj = req.session.loggedInAdmin;
90 var network_name = req.query.network_name;
91 var network_type = req.query.network_type;
94 tasks.push(function(callback){
95 OdlInterface.GetPreloadVnfData('/restconf/config/VNF-API:preload-vnfs/vnf-preload-list/'
96 + encodeURIComponent(network_name) + '/' + encodeURIComponent(network_type) + '/', options,res,callback);
99 async.series(tasks, function(err,result)
101 var msgArray = new Array();
104 res.render('mobility/displayVnfNetworkData', {result:{code:'failure', msg:resp_msg}, header:process.env.MAIN_MENU});
108 resp_msg = JSON.stringify(JSON.parse(result[0],null,4));
109 res.render('mobility/displayVnfNetworkData', {result:{code:'success', msg:JSON.parse(result[0])}, header:process.env.MAIN_MENU});
116 router.get('/viewVnfData', csp.checkAuth, csrfProtection, function(req,res)
118 var privilegeObj = req.session.loggedInAdmin;
120 var vnf_name = req.query.vnf_name;
121 var vnf_type = req.query.vnf_type;
124 tasks.push(function(callback){
125 OdlInterface.GetPreloadVnfData('/restconf/config/VNF-API:preload-vnfs/vnf-preload-list/'
126 + encodeURIComponent(vnf_name) + '/' + encodeURIComponent(vnf_type) + '/', options,res,callback);
129 async.series(tasks, function(err,result)
131 var msgArray = new Array();
134 res.render('mobility/displayVnfData', {result:{code:'failure', msg:resp_msg}, header:process.env.MAIN_MENU});
138 resp_msg = JSON.stringify(JSON.parse(result[0],null,4));
139 res.render('mobility/displayVnfData', {result:{code:'success', msg:JSON.parse(result[0])}, header:process.env.MAIN_MENU});
146 router.get('/loadVnfNetworkData', csp.checkAuth, csp.checkPriv, function(req,res)
148 var privilegeObj = req.session.loggedInAdmin;
149 var msgArray = new Array();
151 if ( req.query.status != 'pending' )
153 msgArray.push("Upload Status must be in 'pending' state.");
154 dbRoutes.getVnfNetworkData(req,res, {code:'failure', msg:msgArray}, privilegeObj);
159 var now = new Date();
160 var df = dateFormat(now,"isoDateTime");
161 const rnum = crypto.randomBytes(4);
162 var svc_req_id = req.query.id + "-" + df + "-" + rnum.toString('hex');;
165 // first get the contents of the file from the db
166 tasks.push(function(callback){
167 dbRoutes.getVnfPreloadData(req,res,"PRE_LOAD_VNF_NETWORK_DATA",callback);
170 // then format the request and send it using the arg1 parameter
171 // which is the contents of the file returned from the previous function
172 // call in the tasks array
173 tasks.push(function(arg1,callback){
175 var s_file = JSON.stringify(arg1);
177 // remove the last two braces, going to add the headers there
178 // will add them back later.
179 s_file = s_file.substring(0, (s_file.length-2));
181 // add the request-information header
182 s_file = s_file.concat(',"request-information": {"request-action": "PreloadNetworkRequest"}');
184 // add the sdnc-request-header
185 s_file = s_file.concat(',"sdnc-request-header": {"svc-request-id":"');
186 s_file = s_file.concat(svc_req_id);
187 s_file = s_file.concat('","svc-action": "reserve"}');
189 // add the two curly braces at the end that we stripped off
190 s_file = s_file.concat('}}');
192 OdlInterface.Post('/restconf/operations/VNF-API:preload-network-topology-operation',
193 options,s_file,res,callback);
196 // if successful then update the status
197 tasks.push(function(arg1,callback){
198 dbRoutes.updatePreloadStatus("UPDATE PRE_LOAD_VNF_NETWORK_DATA SET status='uploaded',svc_request_id='" + svc_req_id + "',svc_action='reserve'",req,res,callback);
201 // use the waterfall method of making calls
202 async.waterfall(tasks, function(err,result)
204 var msgArray = new Array();
206 msgArray.push("Error posting pre-load data to ODL: "+err);
207 dbRoutes.getVnfNetworkData(req,res, {code:'failure', msg:msgArray}, privilegeObj);
211 msgArray.push('Successfully loaded VNF pre-loaded data.');
212 dbRoutes.getVnfNetworkData(req,res,{code:'success', msg:msgArray},privilegeObj);
219 router.get('/loadVnfData', csp.checkAuth, csp.checkPriv, function(req,res)
221 var privilegeObj = req.session.loggedInAdmin;
222 var full_path_file_name = process.cwd() + "/uploads/" + req.sanitize(req.query.filename)
223 var msgArray = new Array();
225 if ( req.query.status != 'pending' )
227 msgArray.push("Upload Status must be in 'pending' state.");
228 dbRoutes.getVnfData(req,res, {code:'failure', msg:msgArray}, privilegeObj);
233 var now = new Date();
234 var df = dateFormat(now,"isoDateTime");
235 const rnum = crypto.randomBytes(4);
236 var svc_req_id = req.sanitize(req.query.id) + "-" + df + "-" + rnum.toString('hex');
239 // first get the contents of the file from the db
240 tasks.push(function(callback){
241 dbRoutes.getVnfPreloadData(req,res,"PRE_LOAD_VNF_DATA",callback);
244 // then format the request and send it using the arg1 parameter
245 // which is the contents of the file returned from the previous function
246 // call in the tasks array
247 tasks.push(function(arg1,callback){
249 var s1_file = JSON.stringify(arg1);
250 var s_file = decodeURI(s1_file);
253 // remove the last two braces, going to add the headers there
254 // will add them back later.
255 s_file = s_file.substring(0, (s_file.length-2));
257 // add the request-information header
258 s_file = s_file.concat(',"request-information": {"request-action": "PreloadVNFRequest"}');
260 // add the sdnc-request-header
261 s_file = s_file.concat(',"sdnc-request-header": {"svc-request-id":"');
262 s_file = s_file.concat(svc_req_id);
263 s_file = s_file.concat('","svc-action": "reserve"}');
265 // add the two curly braces at the end that we stripped off
266 s_file = s_file.concat('}}');
268 OdlInterface.Post('/restconf/operations/VNF-API:preload-vnf-topology-operation',
269 options,s_file,res,callback);
272 // if successful then update the status
273 tasks.push(function(arg1,callback){
274 dbRoutes.executeSQL("UPDATE PRE_LOAD_VNF_DATA SET status='uploaded',svc_request_id='" + svc_req_id + "',svc_action='reserve'",req,res,callback);
277 // use the waterfall method of making calls
278 async.waterfall(tasks, function(err,result)
280 var msgArray = new Array();
282 msgArray.push("Error posting pre-load data to ODL: "+err);
283 dbRoutes.getVnfData(req,res, {code:'failure', msg:msgArray}, privilegeObj);
287 msgArray.push('Successfully loaded VNF pre-loaded data.');
288 dbRoutes.getVnfData(req,res,{code:'success', msg:msgArray},privilegeObj);
295 router.get('/deleteVnfNetworkData', csp.checkAuth, csp.checkPriv, csrfProtection, function(req,res) {
297 var privilegeObj = req.session.loggedInAdmin;
300 // if status is pending, then we do not have to call
301 // ODL, just remove from db
302 if (req.query.status == 'pending'){
303 tasks.push(function(callback) {
304 dbRoutes.deleteVnfNetworkData(req,res,callback);
307 // format the request to ODL
308 var inputString = '{"input":{"network-topology-information":{"network-topology-identifier":{"service-type":"SDN-MOBILITY","network-name": "';
309 inputString = inputString.concat(req.query.network_name);
310 inputString = inputString.concat('","network-type":"');
311 inputString = inputString.concat(req.query.network_type);
312 inputString = inputString.concat('"}},');
314 // add the request-information header
315 inputString = inputString.concat('"request-information": {"request-action": "DeletePreloadNetworkRequest"},');
317 // add the sdnc-request-header
318 inputString = inputString.concat('"sdnc-request-header": {"svc-request-id":"');
319 inputString = inputString.concat(req.query.svc_request_id);
320 inputString = inputString.concat('","svc-action": "delete"}}}');
322 tasks.push(function(callback) {
323 OdlInterface.Post('/restconf/operations/VNF-API:preload-network-topology-operation',
324 options,inputString,res,callback);
326 tasks.push(function(callback) {
327 dbRoutes.executeSQL(sql,req,res,callback);
330 async.series(tasks, function(err,result){
332 var msgArray = new Array();
335 dbRoutes.getVnfNetworkData(req,res,{code:'failure', msg:msgArray},privilegeObj);
339 msgArray.push('Row successfully deleted from PRE_LOAD_VNF_NETWORK_DATA table and ODL.');
340 dbRoutes.getVnfNetworkData(req,res,{code:'success', msg:msgArray},privilegeObj);
347 router.get('/deleteVnfData', csp.checkAuth, csp.checkPriv, csrfProtection, function(req,res) {
349 var privilegeObj = req.session.loggedInAdmin;
352 // if status is pending, then we do not have to call
353 // ODL, just remove from db
354 if (req.query.status == 'pending'){
355 tasks.push(function(callback) {
356 dbRoutes.deleteVnfData(req,res,callback);
359 var inputString = '{"input":{"vnf-topology-information":{"vnf-topology-identifier":{"service-type":"SDN-MOBILITY","vnf-name": "';
360 inputString = inputString.concat(req.query.vnf_name);
361 inputString = inputString.concat('","vnf-type":"');
362 inputString = inputString.concat(req.query.vnf_type);
363 inputString = inputString.concat('"}},');
365 // add the request-information header
366 inputString = inputString.concat('"request-information": {"request-action": "DeletePreloadVNFRequest"},');
368 // add the request-information header
369 //inputString = inputString.concat('"request-information": {"request-id": "259c0f93-23cf-46ad-84dc-162ea234fff1",');
370 //inputString = inputString.concat('"source": "ADMINPORTAL",');
371 //inputString = inputString.concat('"order-version": "1",');
372 //inputString = inputString.concat('"notification-url": "notused-this would be infrastructure portal",');
373 //inputString = inputString.concat('"order-number": "1",');
374 //inputString = inputString.concat('"request-action": "DeletePreloadVNFRequest"},');
376 // add the sdnc-request-header
377 inputString = inputString.concat('"sdnc-request-header": {"svc-request-id":"');
378 inputString = inputString.concat(req.query.svc_request_id);
379 inputString = inputString.concat('","svc-action": "delete"}}}');
381 //inputString = inputString.concat('"sdnc-request-header":{');
382 //inputString = inputString.concat('"svc-request-id": "2015-01-15T14:34:54.st1101a",');
383 //inputString = inputString.concat('"svc-notification-url": "not used",');
384 //inputString = inputString.concat('"svc-action": "delete"}}}');
386 tasks.push(function(callback) {
387 OdlInterface.Post('/restconf/operations/VNF-API:preload-vnf-topology-operation',
388 options,inputString,res,callback);
390 tasks.push(function(callback) {
391 dbRoutes.executeSQL(sql,req,res,callback);
394 async.series(tasks, function(err,result){
396 var msgArray = new Array();
399 dbRoutes.getVnfData(req,res,{code:'failure', msg:msgArray},privilegeObj);
403 msgArray.push('Row successfully deleted from PRE_LOAD_VNF_DATA table and ODL.');
404 dbRoutes.getVnfData(req,res,{code:'success', msg:msgArray},privilegeObj);
411 router.get('/deleteVnfNetwork', csp.checkAuth, csp.checkPriv, csrfProtection, function(req,res) {
413 var privilegeObj = req.session.loggedInAdmin;
417 sql = "DELETE FROM VNF_NETWORKS WHERE vnf_type='" + req.query.vnf_type + "'"
418 + " AND network_role='" + req.query.network_role + "'";
420 tasks.push(function(callback) {
421 dbRoutes.executeSQL(sql,req,res,callback);
423 async.series(tasks, function(err,result)
425 var msgArray = new Array();
428 dbRoutes.getVnfNetwork(req,res,{code:'failure', msg:msgArray},privilegeObj);
432 msgArray.push('Row successfully deleted from VNF_NETWORKS table.');
433 dbRoutes.getVnfNetworks(req,res,{code:'success', msg:msgArray},privilegeObj);
439 router.get('/deleteVnfProfile', csp.checkAuth, csp.checkPriv, csrfProtection, function(req,res) {
441 var privilegeObj = req.session.loggedInAdmin;
446 tasks.push(function(callback) {
447 dbRoutes.deleteVnfProfile(req,res,callback);
449 async.series(tasks, function(err,result)
451 var msgArray = new Array();
454 dbRoutes.getVnfProfile(req,res,{code:'failure', msg:msgArray},privilegeObj);
458 msgArray.push('Row successfully deleted from VNF_PROFILE table.');
459 dbRoutes.getVnfProfile(req,res,{code:'success', msg:msgArray},privilegeObj);
466 router.post('/addVnfProfile', csp.checkAuth, csp.checkPriv, csrfProtection, function(req,res){
468 var privilegeObj = req.session.loggedInAdmin;
469 var vnf_type = req.sanitize(req.body.nf_vnf_type);
470 var availability_zone_count = req.sanitize(req.body.nf_availability_zone_count);
471 var equipment_role = req.sanitize(req.body.nf_equipment_role);
475 sql = "INSERT INTO VNF_PROFILE (vnf_type,availability_zone_count,equipment_role) VALUES ("
476 + "'" + vnf_type + "'," + availability_zone_count + ",'" + equipment_role + "')";
480 tasks.push( function(callback) { dbRoutes.executeSQL(sql,req,res,callback); } );
481 async.series(tasks, function(err,result){
482 var msgArray = new Array();
485 dbRoutes.getVnfProfile(req,res,{code:'failure', msg:msgArray},privilegeObj);
489 msgArray.push('Successfully added VNF Profile');
490 dbRoutes.getVnfProfile(req,res,{code:'success', msg:msgArray},privilegeObj);
497 router.post('/uploadVnfData', csp.checkAuth, csp.checkPriv, upload.single('filename'), function(req, res)
499 console.log('filename:'+ JSON.stringify(req.file.originalname));
500 var msgArray = new Array();
501 var privilegeObj = req.session.loggedInAdmin;
503 if(req.file.originalname)
505 if (req.file.originalname.size == 0) {
506 msgArray.push('There was an error uploading the file.');
507 dbRoutes.getVnfData(req,res,{code:'failure', msg:msgArray},privilegeObj);
510 fs.exists(req.file.path, function(exists)
514 var str = req.file.originalname;
519 content = fs.readFileSync(req.file.path);
520 enc_content = encodeURI(content);
523 var sql = "INSERT INTO PRE_LOAD_VNF_DATA "
524 + "(filename,preload_data) VALUES ("
525 + "'"+ str + "'," + "'" + enc_content + "')";
527 var privilegeObj = req.session.loggedInAdmin;
529 tasks.push( function(callback) { dbRoutes.addRow(sql,req,res,callback); } );
530 async.series(tasks, function(err,result)
534 dbRoutes.getVnfData(req,res,{code:'failure', msg:msgArray},privilegeObj);
538 msgArray.push('Successfully uploaded ' + str);
539 dbRoutes.getVnfData(req,res,{code:'success', msg:msgArray},privilegeObj);
545 fs.removeSync(req.file.path); // remove bad file that was uploaded
546 console.error("There was an error reading the file '"+str+"'. Error: " + error);
547 msgArray.push("There was an error reading the file '"+str+"'. Error: " + error);
548 dbRoutes.getVnfData(req,res,{code:'failure', msg:msgArray},privilegeObj);
553 msgArray.push('There was an error uploading the file.');
554 dbRoutes.getVnfData(req,res,{code:'danger', msg:msgArray},privilegeObj);
562 msgArray.push('There was an error uploading the file.');
563 dbRoutes.getVnfData(req,res,{code:'danger', msg:msgArray},privilegeObj);
569 router.post('/uploadVnfNetworkData', csp.checkAuth, csp.checkPriv, upload.single('filename'), function(req, res)
571 var msgArray = new Array();
572 var privilegeObj = req.session.loggedInAdmin;
574 if(req.file.originalname)
576 if (req.file.originalname.size == 0) {
577 msgArray.push('There was an error uploading the file.');
578 dbRoutes.getVnfData(req,res,{code:'failure', msg:msgArray},privilegeObj);
581 fs.exists(req.file.path, function(exists)
585 var str = req.file.originalname;
590 content = fs.readFileSync(req.file.path);
591 enc_content = encodeURI(content);
593 var sql = "INSERT INTO PRE_LOAD_VNF_NETWORK_DATA "
594 + "(filename,preload_data) VALUES ("
595 + "'"+ str + "'," + "'" + enc_content + "')";
597 var privilegeObj = req.session.loggedInAdmin;
599 tasks.push( function(callback) { dbRoutes.addRow(sql,req,res,callback); } );
600 async.series(tasks, function(err,result)
604 dbRoutes.getVnfNetworkData(req,res,{code:'failure', msg:msgArray},privilegeObj);
608 msgArray.push('Successfully uploaded ' + str);
609 dbRoutes.getVnfNetworkData(req,res,{code:'success', msg:msgArray},privilegeObj);
615 fs.removeSync(req.file.path); // remove bad file that was uploaded
616 msgArray.push("There was an error reading the file '"+str+"'. Error: " + error);
617 dbRoutes.getVnfNetworkData(req,res,{code:'failure', msg:msgArray},privilegeObj);
622 msgArray.push('There was an error uploading the file.');
623 dbRoutes.getVnfNetworkData(req,res,{code:'danger', msg:msgArray},privilegeObj);
631 msgArray.push('There was an error uploading the file.');
632 dbRoutes.getVnfNetworkData(req,res,{code:'danger', msg:msgArray},privilegeObj);
639 router.post('/uploadVnfProfile', csp.checkAuth, csp.checkPriv, upload.single('filename'), function(req, res){
641 var msgArray = new Array();
642 var privilegeObj = req.session.loggedInAdmin;
644 if(req.file.originalname)
646 if (req.file.originalname.size == 0) {
647 dbRoutes.getVnfProfile(req,res,{code:'failure', msg:'There was an error uploading the file, please try again.'},privilegeObj);
650 fs.exists(req.file.path, function(exists) {
654 var str = req.file.originalname;
657 var csv = require('csv');
659 // the job of the parser is to convert a CSV file
660 // to a list of rows (array of rows)
661 var parser = csv.parse({
662 columns: function(line) {
663 // By defining this callback, we get handed the
664 // first line of the spreadsheet. Which we'll
665 // ignore and effectively skip this line from processing
667 skip_empty_lines: true
672 var transformer = csv.transform(function(data){
673 // this will get row by row data, so for example,
674 //logger.debug(data[0]+','+data[1]+','+data[2]);
676 // build an array of rows
677 f[row] = new Array();
678 for ( col=0; col<data.length; col++ )
680 f[row][col] = data[col];
685 // called when done with processing the CSV
686 transformer.on("finish", function() {
688 var funcArray = new Array();
690 function createFunction(lrow,res)
692 return function(callback) { dbRoutes.addVnfProfile(lrow,res,callback); }
694 // loop for each row and create an array of callbacks for async.parallelLimit
695 // had to create a function above 'createFunction' to get
696 for (var x=0; x<f.length; x++)
698 funcArray.push( createFunction(f[x],res) );
701 // make db calls in parrallel
702 async.series(funcArray, function(err,result){
705 dbRoutes.getVnfProfile(req,res,result,privilegeObj);
709 // result array has an entry in it, success entries are blank, figure out
710 // how many are not blank, aka errors.
712 for(var i=0;i<result.length;i++){
713 if ( result[i].length > 0 )
718 console.log('rowError='+rowError);
719 var rowsProcessed = f.length - rowError;
720 console.log('rowsProcessed='+rowsProcessed);
721 result.push(rowsProcessed + ' of ' + f.length + ' rows processed.');
724 result = {code:'failure', msg:result};
728 result = {code:'success', msg:result};
730 console.log('result='+JSON.stringify(result));
731 dbRoutes.getVnfProfile(req,res,result,privilegeObj);
737 var stream = fs.createReadStream(req.file.path, "utf8");
738 stream.pipe(parser).pipe(transformer);
742 msgArray.push('There was an error uploading the file. '+ex);
743 console.error('There was an error uploading the file. '+ex);
744 dbRoutes.getVnfProfile(req,res,{code:'danger', msg:msgArray},privilegeObj);
749 msgArray.push('There was an error uploading the file.');
750 dbRoutes.getVnfProfile(req,res,{code:'danger', msg:msgArray},privilegeObj);
757 msgArray.push('There was an error uploading the file.');
758 dbRoutes.getVnfProfile(req,res,{code:'danger', msg:msgArray},privilegeObj);
763 module.exports = router;