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.executeSQL("UPDATE PRE_LOAD_VNF_NETWORK_DATA SET status='uploaded',svc_request_id='"
199 + svc_req_id + "',svc_action='reserve' WHERE id="+req.query.id,req,res,callback);
202 // use the waterfall method of making calls
203 async.waterfall(tasks, function(err,result)
205 var msgArray = new Array();
207 msgArray.push("Error posting pre-load data to ODL: "+err);
208 dbRoutes.getVnfNetworkData(req,res, {code:'failure', msg:msgArray}, privilegeObj);
212 msgArray.push('Successfully loaded VNF pre-loaded data.');
213 dbRoutes.getVnfNetworkData(req,res,{code:'success', msg:msgArray},privilegeObj);
220 router.get('/loadVnfData', csp.checkAuth, csp.checkPriv, function(req,res)
222 var privilegeObj = req.session.loggedInAdmin;
223 var full_path_file_name = process.cwd() + "/uploads/" + req.query.filename
224 var msgArray = new Array();
226 if ( req.query.status != 'pending' )
228 msgArray.push("Upload Status must be in 'pending' state.");
229 dbRoutes.getVnfData(req,res, {code:'failure', msg:msgArray}, privilegeObj);
234 var now = new Date();
235 var df = dateFormat(now,"isoDateTime");
236 const rnum = crypto.randomBytes(4);
237 var svc_req_id = req.query.id + "-" + df + "-" + rnum.toString('hex');
240 // first get the contents of the file from the db
241 tasks.push(function(callback){
242 dbRoutes.getVnfPreloadData(req,res,"PRE_LOAD_VNF_DATA",callback);
245 // then format the request and send it using the arg1 parameter
246 // which is the contents of the file returned from the previous function
247 // call in the tasks array
248 tasks.push(function(arg1,callback){
250 var s1_file = JSON.stringify(arg1);
251 var s_file = decodeURI(s1_file);
254 // remove the last two braces, going to add the headers there
255 // will add them back later.
256 s_file = s_file.substring(0, (s_file.length-2));
258 // add the request-information header
259 s_file = s_file.concat(',"request-information": {"request-action": "PreloadVNFRequest"}');
261 // add the sdnc-request-header
262 s_file = s_file.concat(',"sdnc-request-header": {"svc-request-id":"');
263 s_file = s_file.concat(svc_req_id);
264 s_file = s_file.concat('","svc-action": "reserve"}');
266 // add the two curly braces at the end that we stripped off
267 s_file = s_file.concat('}}');
269 OdlInterface.Post('/restconf/operations/VNF-API:preload-vnf-topology-operation',
270 options,s_file,res,callback);
273 // if successful then update the status
274 tasks.push(function(arg1,callback){
275 dbRoutes.executeSQL("UPDATE PRE_LOAD_VNF_DATA SET status='uploaded',svc_request_id='"
276 + svc_req_id + "',svc_action='reserve' WHERE id="+req.query.id,req,res,callback);
279 // use the waterfall method of making calls
280 async.waterfall(tasks, function(err,result)
282 var msgArray = new Array();
284 msgArray.push("Error posting pre-load data to ODL: "+err);
285 dbRoutes.getVnfData(req,res, {code:'failure', msg:msgArray}, privilegeObj);
289 msgArray.push('Successfully loaded VNF pre-loaded data.');
290 dbRoutes.getVnfData(req,res,{code:'success', msg:msgArray},privilegeObj);
297 router.get('/deleteVnfNetworkData', csp.checkAuth, csp.checkPriv, csrfProtection, function(req,res) {
299 var privilegeObj = req.session.loggedInAdmin;
301 var sql = 'DELETE FROM PRE_LOAD_VNF_NETWORK_DATA WHERE id=' + req.query.id;
303 // if status is pending, then we do not have to call
304 // ODL, just remove from db
305 if (req.query.status == 'pending'){
306 tasks.push(function(callback) {
307 dbRoutes.executeSQL(sql,req,res,callback);
310 // format the request to ODL
311 var inputString = '{"input":{"network-topology-information":{"network-topology-identifier":{"service-type":"SDN-MOBILITY","network-name": "';
312 inputString = inputString.concat(req.query.network_name);
313 inputString = inputString.concat('","network-type":"');
314 inputString = inputString.concat(req.query.network_type);
315 inputString = inputString.concat('"}},');
317 // add the request-information header
318 inputString = inputString.concat('"request-information": {"request-action": "DeletePreloadNetworkRequest"},');
320 // add the sdnc-request-header
321 inputString = inputString.concat('"sdnc-request-header": {"svc-request-id":"');
322 inputString = inputString.concat(req.query.svc_request_id);
323 inputString = inputString.concat('","svc-action": "delete"}}}');
325 tasks.push(function(callback) {
326 OdlInterface.Post('/restconf/operations/VNF-API:preload-network-topology-operation',
327 options,inputString,res,callback);
329 tasks.push(function(callback) {
330 dbRoutes.executeSQL(sql,req,res,callback);
333 async.series(tasks, function(err,result){
335 var msgArray = new Array();
338 dbRoutes.getVnfNetworkData(req,res,{code:'failure', msg:msgArray},privilegeObj);
342 msgArray.push('Row successfully deleted from PRE_LOAD_VNF_NETWORK_DATA table and ODL.');
343 dbRoutes.getVnfNetworkData(req,res,{code:'success', msg:msgArray},privilegeObj);
350 router.get('/deleteVnfData', csp.checkAuth, csp.checkPriv, csrfProtection, function(req,res) {
352 console.log('deleteVnfData');
354 var privilegeObj = req.session.loggedInAdmin;
356 var sql = 'DELETE FROM PRE_LOAD_VNF_DATA WHERE id=' + req.query.id;
358 // if status is pending, then we do not have to call
359 // ODL, just remove from db
360 if (req.query.status == 'pending'){
361 tasks.push(function(callback) {
362 dbRoutes.executeSQL(sql,req,res,callback);
365 var inputString = '{"input":{"vnf-topology-information":{"vnf-topology-identifier":{"service-type":"SDN-MOBILITY","vnf-name": "';
366 inputString = inputString.concat(req.query.vnf_name);
367 inputString = inputString.concat('","vnf-type":"');
368 inputString = inputString.concat(req.query.vnf_type);
369 inputString = inputString.concat('"}},');
371 // add the request-information header
372 inputString = inputString.concat('"request-information": {"request-action": "DeletePreloadVNFRequest"},');
374 // add the request-information header
375 //inputString = inputString.concat('"request-information": {"request-id": "259c0f93-23cf-46ad-84dc-162ea234fff1",');
376 //inputString = inputString.concat('"source": "ADMINPORTAL",');
377 //inputString = inputString.concat('"order-version": "1",');
378 //inputString = inputString.concat('"notification-url": "notused-this would be infrastructure portal",');
379 //inputString = inputString.concat('"order-number": "1",');
380 //inputString = inputString.concat('"request-action": "DeletePreloadVNFRequest"},');
382 // add the sdnc-request-header
383 inputString = inputString.concat('"sdnc-request-header": {"svc-request-id":"');
384 inputString = inputString.concat(req.query.svc_request_id);
385 inputString = inputString.concat('","svc-action": "delete"}}}');
387 //inputString = inputString.concat('"sdnc-request-header":{');
388 //inputString = inputString.concat('"svc-request-id": "2015-01-15T14:34:54.st1101a",');
389 //inputString = inputString.concat('"svc-notification-url": "not used",');
390 //inputString = inputString.concat('"svc-action": "delete"}}}');
392 tasks.push(function(callback) {
393 OdlInterface.Post('/restconf/operations/VNF-API:preload-vnf-topology-operation',
394 options,inputString,res,callback);
396 tasks.push(function(callback) {
397 dbRoutes.executeSQL(sql,req,res,callback);
400 async.series(tasks, function(err,result){
402 var msgArray = new Array();
405 dbRoutes.getVnfData(req,res,{code:'failure', msg:msgArray},privilegeObj);
409 msgArray.push('Row successfully deleted from PRE_LOAD_VNF_DATA table and ODL.');
410 dbRoutes.getVnfData(req,res,{code:'success', msg:msgArray},privilegeObj);
417 router.get('/deleteVnfNetwork', csp.checkAuth, csp.checkPriv, csrfProtection, function(req,res) {
419 var privilegeObj = req.session.loggedInAdmin;
423 sql = "DELETE FROM VNF_NETWORKS WHERE vnf_type='" + req.query.vnf_type + "'"
424 + " AND network_role='" + req.query.network_role + "'";
426 tasks.push(function(callback) {
427 dbRoutes.executeSQL(sql,req,res,callback);
429 async.series(tasks, function(err,result)
431 var msgArray = new Array();
434 dbRoutes.getVnfNetwork(req,res,{code:'failure', msg:msgArray},privilegeObj);
438 msgArray.push('Row successfully deleted from VNF_NETWORKS table.');
439 dbRoutes.getVnfNetworks(req,res,{code:'success', msg:msgArray},privilegeObj);
445 router.get('/deleteVnfProfile', csp.checkAuth, csp.checkPriv, csrfProtection, function(req,res) {
447 var privilegeObj = req.session.loggedInAdmin;
451 sql = "DELETE FROM VNF_PROFILE WHERE vnf_type='" + req.query.vnf_type + "'";
453 tasks.push(function(callback) {
454 dbRoutes.executeSQL(sql,req,res,callback);
456 async.series(tasks, function(err,result)
458 var msgArray = new Array();
461 dbRoutes.getVnfProfile(req,res,{code:'failure', msg:msgArray},privilegeObj);
465 msgArray.push('Row successfully deleted from VNF_PROFILE table.');
466 dbRoutes.getVnfProfile(req,res,{code:'success', msg:msgArray},privilegeObj);
473 router.post('/addVnfProfile', csp.checkAuth, csp.checkPriv, csrfProtection, function(req,res){
475 var privilegeObj = req.session.loggedInAdmin;
476 var vnf_type = req.sanitize(req.body.nf_vnf_type);
477 var availability_zone_count = req.sanitize(req.body.nf_availability_zone_count);
478 var equipment_role = req.sanitize(req.body.nf_equipment_role);
482 sql = "INSERT INTO VNF_PROFILE (vnf_type,availability_zone_count,equipment_role) VALUES ("
483 + "'" + vnf_type + "'," + availability_zone_count + ",'" + equipment_role + "')";
487 tasks.push( function(callback) { dbRoutes.executeSQL(sql,req,res,callback); } );
488 async.series(tasks, function(err,result){
489 var msgArray = new Array();
492 dbRoutes.getVnfProfile(req,res,{code:'failure', msg:msgArray},privilegeObj);
496 msgArray.push('Successfully added VNF Profile');
497 dbRoutes.getVnfProfile(req,res,{code:'success', msg:msgArray},privilegeObj);
504 router.post('/uploadVnfData', csp.checkAuth, csp.checkPriv, upload.single('filename'), function(req, res)
506 console.log('filename:'+ JSON.stringify(req.file.originalname));
507 var msgArray = new Array();
508 var privilegeObj = req.session.loggedInAdmin;
510 if(req.file.originalname)
512 if (req.file.originalname.size == 0) {
513 msgArray.push('There was an error uploading the file.');
514 dbRoutes.getVnfData(req,res,{code:'failure', msg:msgArray},privilegeObj);
517 fs.exists(req.file.path, function(exists)
521 var str = req.file.originalname;
526 content = fs.readFileSync(req.file.path);
527 enc_content = encodeURI(content);
530 var sql = "INSERT INTO PRE_LOAD_VNF_DATA "
531 + "(filename,preload_data) VALUES ("
532 + "'"+ str + "'," + "'" + enc_content + "')";
534 var privilegeObj = req.session.loggedInAdmin;
536 tasks.push( function(callback) { dbRoutes.addRow(sql,req,res,callback); } );
537 async.series(tasks, function(err,result)
541 dbRoutes.getVnfData(req,res,{code:'failure', msg:msgArray},privilegeObj);
545 msgArray.push('Successfully uploaded ' + str);
546 dbRoutes.getVnfData(req,res,{code:'success', msg:msgArray},privilegeObj);
552 fs.removeSync(req.file.path); // remove bad file that was uploaded
553 console.error("There was an error reading the file '"+str+"'. Error: " + error);
554 msgArray.push("There was an error reading the file '"+str+"'. Error: " + error);
555 dbRoutes.getVnfData(req,res,{code:'failure', msg:msgArray},privilegeObj);
560 msgArray.push('There was an error uploading the file.');
561 dbRoutes.getVnfData(req,res,{code:'danger', msg:msgArray},privilegeObj);
569 msgArray.push('There was an error uploading the file.');
570 dbRoutes.getVnfData(req,res,{code:'danger', msg:msgArray},privilegeObj);
576 router.post('/uploadVnfNetworkData', csp.checkAuth, csp.checkPriv, upload.single('filename'), function(req, res)
578 var msgArray = new Array();
579 var privilegeObj = req.session.loggedInAdmin;
581 if(req.file.originalname)
583 if (req.file.originalname.size == 0) {
584 msgArray.push('There was an error uploading the file.');
585 dbRoutes.getVnfData(req,res,{code:'failure', msg:msgArray},privilegeObj);
588 fs.exists(req.file.path, function(exists)
592 var str = req.file.originalname;
597 content = fs.readFileSync(req.file.path);
598 enc_content = encodeURI(content);
600 var sql = "INSERT INTO PRE_LOAD_VNF_NETWORK_DATA "
601 + "(filename,preload_data) VALUES ("
602 + "'"+ str + "'," + "'" + enc_content + "')";
604 var privilegeObj = req.session.loggedInAdmin;
606 tasks.push( function(callback) { dbRoutes.addRow(sql,req,res,callback); } );
607 async.series(tasks, function(err,result)
611 dbRoutes.getVnfNetworkData(req,res,{code:'failure', msg:msgArray},privilegeObj);
615 msgArray.push('Successfully uploaded ' + str);
616 dbRoutes.getVnfNetworkData(req,res,{code:'success', msg:msgArray},privilegeObj);
622 fs.removeSync(req.file.path); // remove bad file that was uploaded
623 msgArray.push("There was an error reading the file '"+str+"'. Error: " + error);
624 dbRoutes.getVnfNetworkData(req,res,{code:'failure', msg:msgArray},privilegeObj);
629 msgArray.push('There was an error uploading the file.');
630 dbRoutes.getVnfNetworkData(req,res,{code:'danger', msg:msgArray},privilegeObj);
638 msgArray.push('There was an error uploading the file.');
639 dbRoutes.getVnfNetworkData(req,res,{code:'danger', msg:msgArray},privilegeObj);
646 router.post('/uploadVnfProfile', csp.checkAuth, csp.checkPriv, upload.single('filename'), function(req, res){
648 var msgArray = new Array();
649 var privilegeObj = req.session.loggedInAdmin;
651 if(req.file.originalname)
653 if (req.file.originalname.size == 0) {
654 dbRoutes.getVnfProfile(req,res,{code:'failure', msg:'There was an error uploading the file, please try again.'},privilegeObj);
657 fs.exists(req.file.path, function(exists) {
661 var str = req.file.originalname;
664 var csv = require('csv');
666 // the job of the parser is to convert a CSV file
667 // to a list of rows (array of rows)
668 var parser = csv.parse({
669 columns: function(line) {
670 // By defining this callback, we get handed the
671 // first line of the spreadsheet. Which we'll
672 // ignore and effectively skip this line from processing
674 skip_empty_lines: true
679 var transformer = csv.transform(function(data){
680 // this will get row by row data, so for example,
681 //logger.debug(data[0]+','+data[1]+','+data[2]);
683 // build an array of rows
684 f[row] = new Array();
685 for ( col=0; col<data.length; col++ )
687 f[row][col] = data[col];
692 // called when done with processing the CSV
693 transformer.on("finish", function() {
695 var funcArray = new Array();
697 function createFunction(lrow,res)
699 return function(callback) { dbRoutes.addVnfProfile(lrow,res,callback); }
701 // loop for each row and create an array of callbacks for async.parallelLimit
702 // had to create a function above 'createFunction' to get
703 for (var x=0; x<f.length; x++)
705 funcArray.push( createFunction(f[x],res) );
708 // make db calls in parrallel
709 async.series(funcArray, function(err,result){
712 dbRoutes.getVnfProfile(req,res,result,privilegeObj);
716 // result array has an entry in it, success entries are blank, figure out
717 // how many are not blank, aka errors.
719 for(var i=0;i<result.length;i++){
720 if ( result[i].length > 0 )
725 console.log('rowError='+rowError);
726 var rowsProcessed = f.length - rowError;
727 console.log('rowsProcessed='+rowsProcessed);
728 result.push(rowsProcessed + ' of ' + f.length + ' rows processed.');
731 result = {code:'failure', msg:result};
735 result = {code:'success', msg:result};
737 console.log('result='+JSON.stringify(result));
738 dbRoutes.getVnfProfile(req,res,result,privilegeObj);
744 var stream = fs.createReadStream(req.file.path, "utf8");
745 stream.pipe(parser).pipe(transformer);
749 msgArray.push('There was an error uploading the file. '+ex);
750 console.error('There was an error uploading the file. '+ex);
751 dbRoutes.getVnfProfile(req,res,{code:'danger', msg:msgArray},privilegeObj);
756 msgArray.push('There was an error uploading the file.');
757 dbRoutes.getVnfProfile(req,res,{code:'danger', msg:msgArray},privilegeObj);
764 msgArray.push('There was an error uploading the file.');
765 dbRoutes.getVnfProfile(req,res,{code:'danger', msg:msgArray},privilegeObj);
770 module.exports = router;