Merge "Change RANGE_RULE table to support multiple ranges"
[ccsdk/distribution.git] / dgbuilder / red / server.js
1 /**
2  * Copyright 2013 IBM Corp.
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 var express = require('express');
18 var util = require('util');
19 var multer = require('multer');
20 var when = require('when');
21 var exec = require('child_process').exec;
22
23 var createUI = require("./ui");
24 var redNodes = require("./nodes");
25 var comms = require("./comms");
26 var storage = require("./storage");
27 var fs=require('fs');
28 var path = require("path");
29 var app = null;
30 var nodeApp = null;
31 var server = null;
32 var settings = null;
33
34 var flowShareUsers = require("../flowShareUsers");
35         
36 //console.dir(flowShareUsers);
37
38 function createServer(_server,_settings) {
39     server = _server;
40     settings = _settings;
41
42     comms.init(_server,_settings);
43     
44     nodeApp = express();
45     app = express();
46         
47     if (settings.httpAdminRoot !== false) {
48         
49         
50         if (!settings.disableEditor) {
51             createUI(settings,app);
52         }
53         
54         var slaActions = require("./sla");
55
56         app.get("/flows",function(req,res) {
57             res.json(redNodes.getFlows());
58         });
59
60         app.get("/loadJSFiles",function(req,res) {
61                 var appDir = path.dirname(require.main.filename);
62                 var generatedJSDir=appDir + "/generatedJS";
63                 var glob = require("glob")
64                 glob(generatedJSDir + "/**/*.js", null, function (er, files) {
65                           // files is an array of filenames.
66                          // If the `nonull` option is set, and nothing
67                         // was found, then files is ["**/*.js"]
68                         // er is an error object or null.
69                         //console.dir(files);
70                         var sliValuesObj =[];
71                         for(var i=0;files!= null && i<files.length;i++){
72                                 var f = files[i].replace( new RegExp(generatedJSDir + "/", "g" ), "" );
73                                 console.log("loading file " + f);
74                                 try{
75                                         sliValuesObj.push(require(files[i]));
76                                         //console.dir(sliValuesObj);
77                                 }catch(err){
78                                         console.log("Error:Could not load file " + files[i]);
79                                 }
80                         }
81                         res.json({"sliValuesObj" : sliValuesObj});
82                 });
83         });
84
85         app.get("/loadSelectedModules",function(req,res) {
86                 var appDir = path.dirname(require.main.filename);
87                 var userDir = appDir + "/" + settings.userDir;
88                 var generatedJSDir=appDir + "/generatedJS";
89                 //console.dir(req);
90                 var selectedModulesStr = req.query.selectedModules;
91                 var selectedModules = [];
92                 if(selectedModulesStr != undefined && selectedModulesStr != null){ 
93                         selectedModules = selectedModulesStr.split(",");                
94                 }
95                 console.log(selectedModules);
96                 var loaded_modules = {"selected_modules" :selectedModules};
97                 var file = userDir + "/selected_modules";
98                 var content = "module.exports=\n" + JSON.stringify(loaded_modules);
99                 try{
100                         fs.writeFileSync(file, content, 'utf8');
101                 }catch(err){
102                         console.log("could not write to file " + file);
103                 }
104                 var sliValuesObj =[];
105                 for(var i=0;selectedModules!= null && i<selectedModules.length;i++){
106                         var f = generatedJSDir + "/" + selectedModules[i] + "_inputs.js";
107                         try{
108                                 delete require.cache[require.resolve(f)]
109                                 require.resolve();
110                         }catch(err){
111                                 console.log("error deleting loaded module " + f + " from cache");
112                         }
113                         //console.log("loading file " + f);
114                         try{
115                                 sliValuesObj.push(require(f));
116                         }catch(err){
117                                 console.log("Error:Could not load file " + f);
118                         }
119                 }
120                 //console.dir(sliValuesObj);
121                 res.json({"sliValuesObj" : sliValuesObj});
122         });
123
124         app.get("/initialLoadSelectedModules",function(req,res) {
125                 var appDir = path.dirname(require.main.filename);
126                 var userDir = appDir + "/" + settings.userDir;
127                 var generatedJSDir=appDir + "/generatedJS";
128                 var file = userDir + "/selected_modules";
129                 var sliValuesObj =[];
130                 var selected_modules = [];
131                 var selectedModules;
132                 try{
133                         selectedModules = require(file);        
134                         selected_modules=selectedModules["selected_modules"];
135                         //console.log("selected_modules are ");
136                         //console.dir(selected_modules);
137                 }catch(err){
138                         console.log("Could not load the file " + file);
139                 }
140                 for(var i=0;selected_modules!= null && i<selected_modules.length;i++){
141                         var f = generatedJSDir + "/" + selected_modules[i] + "_inputs.js";
142                         console.log("loading file " + f);
143                         try{
144                                 sliValuesObj.push(require(f));
145                         }catch(err){
146                                 console.log("Error:Could not load file " + f);
147                         }
148                 }
149                 res.json({"sliValuesObj" : sliValuesObj});
150         });
151
152         app.get("/listAvailableModules",function(req,res) {
153                 var appDir = path.dirname(require.main.filename);
154                 var userDir = appDir + "/" + settings.userDir;
155                 var generatedJSDir=appDir + "/generatedJS";
156                 var glob = require("glob")
157                 var file = userDir + "/selected_modules";
158                 var selected_modules = [];
159                 var selectedModules;
160                 try{
161                         delete require.cache[require.resolve(file)]
162                         require.resolve();
163                 }catch(err){
164                         console.log("error deleting loaded module " + file + " from cache");
165                 }
166                 try{
167                         selectedModules = require(file);        
168                         selected_modules=selectedModules["selected_modules"];
169                         console.log("selected_modules are ");
170                         //console.dir(selected_modules);
171                 }catch(err){
172                         console.log("Could not load the file " + file);
173                 }
174                 glob(generatedJSDir + "/**/*.js", null, function (er, files) {
175                         var filesList =[];
176                         for(var i=0;files!= null && i<files.length;i++){
177                                 var f = files[i].replace( new RegExp(generatedJSDir + "/", "g" ), "" );
178                                 f = f.replace("_inputs.js","");
179                                 if(selected_modules != undefined && selected_modules != null && selected_modules.indexOf(f) != -1){
180                                         filesList.push(f + ":checked");
181                                 }else{
182                                         filesList.push(f + ":unchecked");
183                                 }
184                         }
185                         res.json({"files" : filesList});
186                 });
187         });
188
189         app.get("/listSLA",function(req,res) {
190                 var appDir = path.dirname(require.main.filename);
191                 var userDir = appDir + "/" + settings.userDir;
192                 var settingsFile = userDir + "/customSettings.js"; 
193                 var jsonObj = require(settingsFile);
194                 slaActions.listSLA(jsonObj,req,res);
195         });
196
197         app.get("/listCurrentDGs",function(req,res) {
198                 var appDir = path.dirname(require.main.filename);
199                 var userDir = appDir + "/" + settings.userDir;
200                 var settingsFile = userDir + "/customSettings.js"; 
201                 var jsonObj = require(settingsFile);
202                 slaActions.listCurrentDGs(jsonObj,req,res);
203         });
204
205         app.get("/activateDG",function(req,res) {
206                 var appDir = path.dirname(require.main.filename);
207                 var userDir = appDir + "/" + settings.userDir;
208                 var settingsFile = userDir + "/customSettings.js"; 
209                 var jsonObj = require(settingsFile);
210             slaActions.activateDG(jsonObj,req,res);
211         });
212
213         app.get("/deActivateDG",function(req,res) {
214                 var appDir = path.dirname(require.main.filename);
215                 var userDir = appDir + "/" + settings.userDir;
216                 var settingsFile = userDir + "/customSettings.js"; 
217                 var jsonObj = require(settingsFile);
218             slaActions.deActivateDG(jsonObj,req,res);
219         });
220
221         app.get("/deleteDG",function(req,res) {
222                 var appDir = path.dirname(require.main.filename);
223                 var userDir = appDir + "/" + settings.userDir;
224                 var settingsFile = userDir + "/customSettings.js"; 
225                 var jsonObj = require(settingsFile);
226             slaActions.deleteDG(jsonObj,req,res);
227         });
228
229         app.get("/getCurrentSettings",function(req,res) {
230                 var appDir = path.dirname(require.main.filename);
231                 var userDir = appDir + "/" + settings.userDir;
232                 //console.log("userDir:" + userDir);
233                 var settingsFile = userDir + "/customSettings.js"; 
234                 var jsonObj = require(settingsFile);
235                 res.json(jsonObj);
236         });
237
238         app.get("/getCommitsInfo", function(req,res) {
239                 var appDir = path.dirname(require.main.filename);
240                 var userDir = appDir + "/" + settings.userDir;
241                 //console.dir(req);
242                 var filePath = req.query.filePath;
243                 var fullFilePath = userDir + "/codecloud/" + filePath ;
244                 //console.log("fullFilePath:" + fullFilePath);  
245                 var exec = require('child_process').exec;
246                 var commandToExec = appDir + "/git_scripts/gitlog " + fullFilePath ;
247                 console.log("commandToExec:" + commandToExec);
248                 var child = exec(commandToExec ,function (error,stdout,stderr){
249                 if(error){
250                         console.log("Error occured:" + error);
251                         if(stderr){
252                                 //console.log("stderr:" + stderr);
253                                 res.send(500,{'error':error,'stderr':stderr});
254                         }else{
255                                 res.send(500,{'error':error});
256                         }
257                         //console.log("stdout :" + stdout);
258                 }else{
259                         if(stderr){
260                                 console.log("stderr:" + stderr);
261                         }
262                         if(stdout){
263                                 //console.log("output:" + stdout);
264                                 res.send(200,{'stdout':stdout,'stderr':stderr});
265                         }
266                 }
267                 });
268         });
269
270         app.get("/importCodeCloudFlow",
271                  function(req,res) {
272                 var appDir = path.dirname(require.main.filename);
273                 var userDir = appDir + "/" + settings.userDir;
274                 //console.dir(req);
275                 var commitId = req.query.commitId;
276                 var filePath = req.query.filePath;
277                 var fullFilePath = userDir + "/codecloud/" + filePath ;
278                 //console.log("fullFilePath:" + fullFilePath);  
279                 var exec = require('child_process').exec;
280                 var commandToExec = appDir + "/git_scripts/gitckout " + commitId + " " + fullFilePath ;
281                 console.log("commandToExec:" + commandToExec);
282                 var child = exec(commandToExec ,{maxBuffer: 1024 * 1024 * 16}, function (error,stdout,stderr){
283                 if(error){
284                         console.log("Error occured:" + error);
285                         if(stderr){
286                                 //console.log("stderr:" + stderr);
287                                 res.send(500,{'error':error,'stderr':stderr});
288                         }else{
289                                 res.send(500,{'error':error});
290                         }
291                 }else{
292                         if(stderr){
293                                 console.log("stderr:" + stderr);
294                         }
295                         if(stdout){
296                                 //console.log("output:" + stdout);
297                                 res.send(200,{'stdout':stdout,'stderr':stderr});
298                         }
299                 }
300                 });
301         });
302
303         app.get("/importGitLocalFlow",
304                 function(req,res) {
305                 var appDir = path.dirname(require.main.filename);
306                 var gitLocalRepository =  settings.gitLocalRepository;
307                 //console.dir(req);
308                 var filePath = req.query.filePath;
309                 var fullFilePath = gitLocalRepository +"/" + filePath ;
310                 //console.log("fullFilePath:" + fullFilePath);  
311                 var exec = require('child_process').exec;
312                 var commandToExec =  "cat " + fullFilePath ;
313                 console.log("commandToExec:" + commandToExec);
314                 var child = exec(commandToExec ,{maxBuffer: 1024 * 1024 * 16}, function (error,stdout,stderr){
315                 if(error){
316                         console.log("Error occured:" + error);
317                         if(stderr){
318                                 //console.log("stderr:" + stderr);
319                                 res.send(500,{'error':error,'stderr':stderr});
320                         }else{
321                                 res.send(500,{'error':error});
322                         }
323                 }else{
324                         if(stderr){
325                                 console.log("stderr:" + stderr);
326                         }
327                         if(stdout){
328                                 //console.log("output:" + stdout);
329                                 res.send(200,{'stdout':stdout,'stderr':stderr});
330                         }
331                 }
332                 });
333         });
334
335
336         app.get("/gitcheckout", function(req,res) {
337                 var appDir = path.dirname(require.main.filename);
338                 var gitLocalRepository =  settings.gitLocalRepository;
339                 //console.dir(req);
340                 var branch = req.query.branch;
341                 //console.log("fullFilePath:" + fullFilePath);  
342                 var exec = require('child_process').exec;
343                 var commandToExec = appDir + "/git_scripts/gitcheckout " + gitLocalRepository + " " + branch ;
344                 console.log("commandToExec:" + commandToExec);
345                 var child = exec(commandToExec ,function (error,stdout,stderr){
346                                 if(error){
347                                         console.log("Error occured:" + error);
348                                         if(stderr){
349                                                 console.log("stderr:" + stderr);
350                                                 res.json({"output":stderr});
351                                         }else{
352                                                 res.json({"output":error});
353                                         }
354                                 }else{
355                                         if(stderr){
356                                                 console.log("stderr:" + stderr);
357                                         }
358                                         if(stdout){
359                                                 res.json({"output": stderr + " " + stdout});
360                                         }
361                                 }
362                         });
363         });
364
365         app.get("/gitpull", function(req,res) {
366                 var appDir = path.dirname(require.main.filename);
367                 var gitLocalRepository =  settings.gitLocalRepository;
368                 //console.dir(req);
369                 var branch = req.query.branch;
370                 //console.log("fullFilePath:" + fullFilePath);  
371                 var exec = require('child_process').exec;
372                 var commandToExec = appDir + "/git_scripts/gitpull " + gitLocalRepository ;
373                 console.log("commandToExec:" + commandToExec);
374                 var child = exec(commandToExec ,function (error,stdout,stderr){
375                                 if(error){
376                                         console.log("Error occured:" + error);
377                                         if(stderr){
378                                                 console.log("stderr:" + stderr);
379                                                 res.json({"output":stderr});
380                                         }else{
381                                                 res.json({"output":error});
382                                         }
383                                 }else{
384                                         if(stderr){
385                                                 console.log("stderr:" + stderr);
386                                         }
387                                         if(stdout){
388                                                 res.json({"output": stderr + " " + stdout});
389                                         }
390                                 }
391                         });
392         });
393
394         app.get("/gitstatus", function(req,res) {
395                 var appDir = path.dirname(require.main.filename);
396                 var gitLocalRepository =  settings.gitLocalRepository;
397                 //console.dir(req);
398                 var branch = req.query.branch;
399                 //console.log("fullFilePath:" + fullFilePath);  
400                 var exec = require('child_process').exec;
401                 var commandToExec = appDir + "/git_scripts/gitstatus " + gitLocalRepository ;
402                 console.log("commandToExec:" + commandToExec);
403                 var child = exec(commandToExec ,function (error,stdout,stderr){
404                                 if(error){
405                                         console.log("Error occured:" + error);
406                                         if(stderr){
407                                                 console.log("stderr:" + stderr);
408                                                 res.json({"output":stderr});
409                                         }else{
410                                                 res.json({"output":error});
411                                         }
412                                 }else{
413                                         if(stderr){
414                                                 console.log("stderr:" + stderr);
415                                         }
416                                         if(stdout){
417                                                 res.json({"output": stderr + " " + stdout});
418                                         }
419                                 }
420                         });
421         });
422         
423         app.post("/getSharedFlow",
424             express.json(),
425             function(req,res) {
426                 var qs = require('querystring');
427                 var body = '';
428                 req.on('data', function (data) {
429                         body += data;
430                 });
431                 req.on('end', function () {
432                         var post = qs.parse(body);
433                         //console.log("body:" + body);
434                         fs.readFile(post.filePath, 'utf8', function (err,data) {
435                                 if (err) {
436                                         return console.log(err);
437                                 }
438                                 res.json(data);
439                                 //console.log(data);
440                         });
441                 //res.sendFile(body.filePath);
442                 });
443         });
444         
445         app.post("/downloadYang",
446             express.json(),
447             function(req,res) {
448                 var qs = require('querystring');
449                 var body = '';
450                 req.on('data', function (data) {
451                         body += data;
452                 });
453                 req.on('end', function () {
454                         var post = qs.parse(body);
455                         var fileName = post.fileName;
456                         var appDir = path.dirname(require.main.filename);
457                         var yangDir = appDir + "/yangFiles" ;
458                         var fullPathToFile = yangDir + "/" + fileName;
459                         res.setHeader('Content-disposition', 'attachment; filename=' + fileName);
460                         res.setHeader('Content-type', 'application/yang');
461                         res.download(fullPathToFile);
462                 });
463         });
464
465         function writeToFile(fullPathToFileName,str){
466                 try{
467                         fs.writeFileSync(fullPathToFileName,str);
468                 }catch(e){
469                         console.log("Error:" + e);
470                 }
471         }
472         function getCurrentDate(){
473                 var d = new Date();
474                 var mm = d.getMonth() + 1;
475                 var dd =   d.getDate();
476                 var yyyy = d.getYear() + 1900;
477                 var hr = d.getHours();
478                 var min = d.getMinutes();
479                 var sec = d.getSeconds();
480                 if(mm<10) mm = "0" + mm;
481                 if(dd<10) dd = "0" + dd;
482                 if(hr<10) hr = "0" + hr;
483                 if(min<10) min = "0" + min;
484                 if(sec<10) sec = "0" + sec;
485                 var formatedValue = mm + "-" + dd + "-" + yyyy + "_" + hr + "" + min + "" + sec;
486                 return formatedValue;
487         }
488
489
490         app.post("/downloadXml",
491             express.json({'limit':'16mb'}),
492             function(req,res) {
493                 //console.log("Received request and processing:" + new Date());
494                 var qs = require('querystring');
495                 var body = '';
496                 //var msecs1= Date.now();
497                 req.on('data', function (data) {
498                         body += data;
499                 });
500                 req.on('end', function () {
501                         var appDir = path.dirname(require.main.filename);
502                         var xmlDir = appDir + "/" + settings.xmlPath;
503                         //var msecs2= Date.now();
504                         //console.log("Time taken to get request body:" + (msecs2 - msecs1));
505                         var msecs3= Date.now();
506                         var post = qs.parse(body);
507                         var msecs4= Date.now();
508                         //console.log("Time taken to parse body:" + (msecs4 - msecs3));
509                         var xml = post['flowXml'];
510                         //var pd = require('pretty-data').pd;
511                         //var formatted_xml = pd.xml(xml);
512                         var moduleName = post['moduleName'];
513                         var methodName = post['methodName'];
514                         if(moduleName == "" || methodName == ""){
515                                 res.send({"ERROR":"ServiceLogic Module Name and method name are required."});
516                         }else{
517                                 //var formatted_date = getCurrentDate();
518                                 //var fileNameForServer=moduleName + "_" +methodName+ "_" +  formatted_date + ".xml";
519                                 //var fileName=moduleName + "_method_" +methodName+ ".xml";
520                                 var fileName=moduleName + "_" +methodName+ ".xml";
521                                 var file = xmlDir + "/" + fileName;
522
523                                 //var msecs2= Date.now();
524                                 writeToFile(file,xml);
525                                 //var msecs3= Date.now();
526                                 //console.log("Time taken to write File:" + (msecs3 - msecs2));
527                                 res.setHeader('Content-disposition', 'attachment; filename=' + fileName);
528                                 res.setHeader('Content-type', 'text/xml');
529                                 res.end(xml);
530                                 //console.log("Response sent:" + new Date());
531                         }
532                 });
533         });
534
535         app.post("/downloadJson",
536             express.json({'limit':'16mb'}),
537             function(req,res) {
538                         var appDir = path.dirname(require.main.filename);
539                         var sharedDir = appDir + "/" + settings.sharedDir;
540                         var qs = require('querystring');
541                         var body = '';
542                         req.on('data', function (data) {
543                                 body += data;
544                         });
545                         req.on('end', function () {
546                                 var post = qs.parse(body);
547                                 var jsonStr = post['flowJson'];
548                                 var moduleName = post['moduleName'];
549                                 var methodName = post['methodName'];
550                                 //console.log("jsonStr:" + jsonStr);
551                                 if(moduleName == "" || methodName == ""){
552                                         res.send({"ERROR":"ServiceLogic Module Name and method name are required."});
553                                 }else{
554                                         var formatted_date = getCurrentDate();
555                                         //console.log("moduleName:" + moduleName);
556                                         //console.log("methodName:" + methodName);
557
558                                         //var fileName=moduleName + "_method_" +methodName + ".json";
559                                         //var renameOldfileTo=moduleName + "_method_" +methodName+ "_" +  formatted_date + ".json";
560                                         var fileName=moduleName + "_" +methodName + ".json";
561                                         var renameOldfileTo=moduleName + "_" +methodName+ "_" +  formatted_date + ".json";
562                                         var file = sharedDir + "/" + fileName;
563                                         //console.log("fileName:" + fileName);
564                                         var renameFilePath = sharedDir + "/backups/" + renameOldfileTo;
565                                         //console.log("localfile:" + localfile);
566                                         if (fs.existsSync(file)) {
567                                                 fs.rename(file,renameFilePath, function (err) {
568                                                         if(err){
569                                                                 console.log('Error :' + err);
570                                                         }
571                                                         //write the newer version
572                                                         writeToFile(file,jsonStr);
573                                                         res.setHeader('Content-disposition', 'attachment; filename=' + fileName);
574                                                         res.setHeader('Content-type', 'application/json');
575                                                         //res.download(file);
576                                                         res.end(jsonStr);
577                                                 });
578                                         }else{
579                                                 //write the newer version
580                                                 writeToFile(file,jsonStr);
581                                                 res.setHeader('Content-disposition', 'attachment; filename=' + fileName);
582                                                 res.setHeader('Content-type', 'application/json');
583                                                 //res.download(file);
584                                                 res.end(jsonStr);
585                                         }
586                                 }
587                         });
588         });
589
590         app.post("/flows",
591             express.json({'limit':'16mb'}),
592             function(req,res) {
593                 //console.log("Processing Request");
594                 var flows = req.body;
595                 redNodes.setFlows(flows).then(function() {
596                     res.send(204);
597                 }).otherwise(function(err) {
598                     util.log("[red] Error saving flows : "+err);
599                     res.send(500,err.message);
600                 });
601             },
602             function(error,req,res,next) {
603                 res.send(400,"Invalid Flow.  Error " + error);
604             }
605         );
606             
607         app.get("/nodes",function(req,res) {
608             if (req.get("accept") == "application/json") {
609                 res.json(redNodes.getNodeList());
610             } else {
611                 res.send(redNodes.getNodeConfigs());
612             }
613         });
614         
615         app.post("/nodes",
616             express.json(),
617             function(req,res) {
618                 if (!settings.available()) {
619                     res.send(400,new Error("Settings unavailable").toString());
620                     return;
621                 }
622                 var node = req.body;
623                 var promise;
624                 if (node.file) {
625                     promise = redNodes.addNode(node.file).then(reportAddedModules);
626                 } else if (node.module) {
627                     var module = redNodes.getNodeModuleInfo(node.module);
628                     if (module) {
629                         res.send(400,"Module already loaded");
630                         return;
631                     }
632                     promise = installModule(node.module);
633                 } else {
634                     res.send(400,"Invalid request");
635                     return;
636                 }
637                 promise.then(function(info) {
638                     res.json(info);
639                 }).otherwise(function(err) {
640                     if (err.code === 404) {
641                         res.send(404);
642                     } else {
643                         res.send(400,err.toString());
644                     }
645                 });
646             },
647             function(err,req,res,next) {
648                 console.log(err.toString());
649                 res.send(400,err);
650             }
651         );
652         
653         app.delete("/nodes/:id",
654             function(req,res) {
655                 if (!settings.available()) {
656                     res.send(400,new Error("Settings unavailable").toString());
657                     return;
658                 }
659                 var id = req.params.id;
660                 var removedNodes = [];
661                 try {
662                     var node = redNodes.getNodeInfo(id);
663                     var promise = null;
664                     if (!node) {
665                         var module = redNodes.getNodeModuleInfo(id);
666                         if (!module) {
667                             res.send(404);
668                             return;
669                         } else {
670                             promise = uninstallModule(id);
671                         }
672                     } else {
673                         promise = when.resolve([redNodes.removeNode(id)]).then(reportRemovedModules);
674                     }
675                     
676                     promise.then(function(removedNodes) {
677                         res.json(removedNodes);
678                     }).otherwise(function(err) {
679                         console.log(err.stack);
680                         res.send(400,err.toString());
681                     });
682                 } catch(err) {
683                     res.send(400,err.toString());
684                 }
685             },
686             function(err,req,res,next) {
687                 res.send(400,err);
688             }
689         );
690         
691         app.get("/nodes/:id", function(req,res) {
692             var id = req.params.id;
693             var result = null;
694             if (req.get("accept") == "application/json") {
695                 result = redNodes.getNodeInfo(id);
696             } else {
697                 result = redNodes.getNodeConfig(id);
698             }
699             if (result) {
700                 res.send(result);
701             } else {
702                 res.send(404);
703             }
704         });
705         
706         app.put("/nodes/:id", 
707             express.json(),
708             function(req,res) {
709                 if (!settings.available()) {
710                     res.send(400,new Error("Settings unavailable").toString());
711                     return;
712                 }
713                 var body = req.body;
714                 if (!body.hasOwnProperty("enabled")) {
715                     res.send(400,"Invalid request");
716                     return;
717                 }
718                 try {
719                     var info;
720                     var id = req.params.id;
721                     var node = redNodes.getNodeInfo(id);
722                     if (!node) {
723                         res.send(404);
724                     } else if (!node.err && node.enabled === body.enabled) {
725                         res.json(node);
726                     } else {
727                         if (body.enabled) {
728                             info = redNodes.enableNode(id);
729                         } else {
730                             info = redNodes.disableNode(id);
731                         }
732                         if (info.enabled == body.enabled && !info.err) {
733                             comms.publish("node/"+(body.enabled?"enabled":"disabled"),info,false);
734                             util.log("[red] "+(body.enabled?"Enabled":"Disabled")+" node types:");
735                             for (var i=0;i<info.types.length;i++) {
736                                 util.log("[red] - "+info.types[i]);
737                             }
738                         } else if (body.enabled && info.err) {
739                             util.log("[red] Failed to enable node:");
740                             util.log("[red] - "+info.name+" : "+info.err);
741                         }
742                         res.json(info);
743                     }
744                 } catch(err) {
745                     res.send(400,err.toString());
746                 }            
747             }
748         );
749         app.get("/getCodeCloudFlows",function(req,res) {
750                 var userDir=settings.userDir;
751                 var codeCloudDir=userDir + "/codecloud";
752                 var glob = require("glob")
753                 glob(codeCloudDir + "/**/*.json", null, function (er, files) {
754                           // files is an array of filenames.
755                          // If the `nonull` option is set, and nothing
756                         // was found, then files is ["**/*.js"]
757                         // er is an error object or null.
758                         //console.dir(files);
759                         var filesList =[];
760                         for(var i=0;files!= null && i<files.length;i++){
761                                 var f = files[i].replace( new RegExp(codeCloudDir + "/", "g" ), "" );
762                                 filesList.push(f);
763
764                         }
765                         res.json({"files" : filesList});
766                 });
767         });
768
769         app.get("/getCurrentGitBranch",function(req,res) {
770                 var appDir = path.dirname(require.main.filename);
771                 var userDir=settings.userDir;
772                 var settingsFile = appDir + "/" +  userDir + "/customSettings.js"; 
773                 //console.log("settingsFile:" + settingsFile);
774                 var jsonObj = require(settingsFile);
775                 var gitLocalRepository=jsonObj.gitLocalRepository;
776                 if(gitLocalRepository == undefined || gitLocalRepository == null || gitLocalRepository == ''){
777                         res.json({"output" : "GIT_LOCAL_REPOSITORY_NOT_SET"});
778                         return;
779                 }
780                 var exec = require('child_process').exec;
781                 var commandToExec = appDir + "/git_scripts/gitcurbranch " + gitLocalRepository ;
782                         console.log("commandToExec:" + commandToExec);
783                         var child = exec(commandToExec ,function (error,stdout,stderr){
784                                 if(error){
785                                         console.log("Error occured:" + error);
786                                         if(stderr){
787                                                 console.log("stderr:" + stderr);
788                                                 res.json({"output":stderr});
789                                         }else{
790                                                 res.json({"output":error});
791                                         }
792                                 }else{
793                                         if(stderr){
794                                                 console.log("stderr:" + stderr);
795                                         }
796                                         if(stdout){
797                                                 res.json({"output":stdout});
798                                         }
799                                 }
800                         });
801                                 
802         });
803
804         app.get("/getGitLocalFlows",function(req,res) {
805                 var appDir = path.dirname(require.main.filename);
806                 var userDir=settings.userDir;
807                 var settingsFile = appDir + "/" +  userDir + "/customSettings.js"; 
808                 //console.log("settingsFile:" + settingsFile);
809                 var jsonObj = require(settingsFile);
810                 var performGitPull = jsonObj.performGitPull;
811                 if(performGitPull == undefined || performGitPull == null) {
812                         performGitPull="N";
813                 }
814                 var gitLocalRepository=jsonObj.gitLocalRepository;
815                 if(gitLocalRepository == undefined || gitLocalRepository == null || gitLocalRepository == ''){
816                         res.json({"files" : ["GIT_LOCAL_REPOSITORY_NOT_SET"]});
817                         return;
818                                 
819                    }
820
821                 if(performGitPull == "Y"){      
822                         var exec = require('child_process').exec;
823                         var commandToExec = appDir + "/git_scripts/gitpull " + gitLocalRepository ;
824                         console.log("commandToExec:" + commandToExec);
825                         var child = exec(commandToExec ,function (error,stdout,stderr){
826                                 if(error){
827                                         console.log("Error occured:" + error);
828                                         if(stderr){
829                                                 console.log("stderr:" + stderr);
830                                                 res.json({"files":[]});
831                                         }else{
832                                                 res.json({"files":[]});
833                                         }
834                                 }else{
835                                         if(stderr){
836                                                 console.log("stderr:" + stderr);
837                                         }
838                                         if(stdout){
839                                                 var glob = require("glob")
840                                                 glob(gitLocalRepository + "/**/*.json", null, function (er, files) {
841                                                 // files is an array of filenames.
842                                                 // If the `nonull` option is set, and nothing
843                                                 // was found, then files is ["**/*.js"]
844                                                 // er is an error object or null.
845                                                 //console.dir(files);
846                                                 var filesList =[];
847                                                 for(var i=0;files!= null && i<files.length;i++){
848                                                         var f = files[i].replace( new RegExp(gitLocalRepository + "/", "g" ), "" );
849                                                         filesList.push(f);
850
851                                                 }
852                                                 res.json({"files" : filesList});
853                                                 });
854                                         }
855                                 }
856                         });
857                 }else{//git pull not requested
858                         var glob = require("glob")
859                         glob(gitLocalRepository + "/**/*.json", null, function (er, files) {
860                         // files is an array of filenames.
861                         // If the `nonull` option is set, and nothing
862                         // was found, then files is ["**/*.js"]
863                         // er is an error object or null.
864                         //console.dir(files);
865                         var filesList =[];
866                         for(var i=0;files!= null && i<files.length;i++){
867                                 var f = files[i].replace( new RegExp(gitLocalRepository + "/", "g" ), "" );
868                                 filesList.push(f);
869
870                         }
871                         res.json({"files" : filesList});
872                         });
873                 }
874         
875         });
876
877         app.get("/flowShareUsers",function(req,res) {
878             res.json(flowShareUsers);
879         });
880         app.get("/getRelease",function(req,res) {
881                 var userDir = settings.userDir;
882                 //var release = userDir.replace(/releases/g,"release");
883                 res.json({"release" : userDir});
884         });
885         app.post("/getFiles/:id",function(req,res) {
886             var id = req.params.id;
887                 //console.log("id:" + id);
888                 var userDir=settings.userDir;
889                 var flowDir= userDir + "/../" + id + "/flows/shared"; 
890                 //console.log("flowDir:" + flowDir);
891                 fs.readdir(flowDir,function(err, files){
892                         if(err){
893                                 res.json({"files": []});
894                         }else{
895                                 var onlyFilesArr =[];
896                                 if(files != null && files.length>0){
897                                         files.sort(function(a,b){
898                                                 //console.log("file1:" + a);    
899                                                 //console.log("file2:" + b);    
900                                                 var fileStat1=fs.statSync(flowDir+ "/" + a);    
901                                                 var fileStat2=fs.statSync(flowDir+ "/" + b);    
902                                                 if(fileStat1.mtime > fileStat2.mtime){
903                                                         return 1;
904                                                 }else if(fileStat1.mtime < fileStat2.mtime){
905                                                         return -1;
906                                                 }else{
907                                                         return 0;
908                                                 }
909                                         });
910                                         for(var i=0;i<files.length;i++){
911                                                 var fileStat=fs.statSync(flowDir+ "/" + files[i]);
912                                                 if(fileStat.isFile()){
913                                                     onlyFilesArr.push({"filePath":flowDir+ "/" + files[i],"name":files[i]});
914                                                 }
915                                         }
916                                         res.json(onlyFilesArr);
917                                 }else{
918                                         res.json({"files": []});
919                                 }
920                         }
921                 });
922         });
923
924         app.post("/updateConfiguration",
925             express.json(),
926             function(req,res) {
927                 var qs = require('querystring');
928                 //console.log("Received the request:");
929                 var body ="";
930                  req.on('data', function (data) {
931                         body += data;
932                 });
933                 req.on('end',function(){
934                         var post = qs.parse(body);
935                         var dbHost = post["dbHost"];
936                         var dbPort = post["dbPort"];
937                         var dbName = post["dbName"];
938                         var dbUser = post["dbUser"];
939                         var dbPassword = post["dbPassword"];
940                         var gitLocalRepository = post["gitLocalRepository"];
941                         var performGitPull = post["performGitPull"];
942                         var restConfUrl = post["restConfUrl"];
943                         var restConfUser = post["restConfUser"];
944                         var restConfPassword = post["restConfPassword"];
945                         var emailAddress = post["emailAddress"];
946                         var formatXML = post["formatXML"];
947                         var formatJSON = post["formatJSON"];
948                         var appDir = path.dirname(require.main.filename);
949                         var userDir = appDir + "/" + settings.userDir;
950                         console.log("userDir:" + userDir);
951                         try{
952                                 var settingsFile = userDir + "/customSettings.js"; 
953                                 var jsonObj = require(settingsFile);
954                                 jsonObj.emailAddress = emailAddress;
955                                 jsonObj.flowFile = jsonObj.flowFile.replace(appDir + "/",'');
956                                 jsonObj.dbHost = dbHost;
957                                 jsonObj.dbPort = dbPort;
958                                 jsonObj.dbName = dbName;
959                                 jsonObj.dbUser = dbUser;
960                                 jsonObj.dbPassword = dbPassword;
961                                 jsonObj.gitLocalRepository = gitLocalRepository;
962                                 jsonObj.performGitPull = performGitPull;
963                                 jsonObj.restConfUrl = restConfUrl;
964                                 jsonObj.restConfUser = restConfUser;
965                                 jsonObj.restConfPassword = restConfPassword;
966                                 jsonObj.formatXML = formatXML;
967                                 jsonObj.formatJSON = formatJSON;
968                                 var updatedSettings = jsonObj;
969
970                                 var settingsStr= "module.exports=" + JSON.stringify(updatedSettings,null,4);
971                                 //console.log("settingsStr:" + settingsStr);
972                                 fs.writeFileSync(settingsFile,settingsStr);
973                                 var svcLogicPropStr = "" ;
974                                         svcLogicPropStr += "org.onap.ccsdk.sli.dbtype=jdbc" + "\n";
975                                         svcLogicPropStr += "org.onap.ccsdk.sli.jdbc.url=jdbc:mysql://" + dbHost + ":" + dbPort + "/" + dbName + "\n";
976                                         svcLogicPropStr += "org.onap.ccsdk.sli.jdbc.database=" + dbName + "\n";
977                                         svcLogicPropStr += "org.onap.ccsdk.sli.jdbc.user=" + dbUser  + "\n";
978                                         svcLogicPropStr += "org.onap.ccsdk.sli.jdbc.password=" + dbPassword;
979                                 
980                                 //create svclogic.properties file in the conf dir
981                                 var svcPropFile = userDir + "/conf/svclogic.properties";
982                                 fs.writeFileSync(svcPropFile,svcLogicPropStr);
983
984                                 res.send({"status": "success"});
985                         }catch(e){
986                                 console.log("Error:" + e);
987                                 res.send({"status": "error"});
988                         }
989                 });
990             }
991         );
992
993         app.post("/deleteYangFile",
994             express.json(),
995             function(req,res) {
996                 var qs = require('querystring');
997                 //console.log("Received the request:");
998                 var body ="";
999                  req.on('data', function (data) {
1000                         body += data;
1001                 });
1002                 req.on('end',function(){
1003                         var post = qs.parse(body);
1004                         //console.dir(body);
1005                         var fileName = post["fileName"];
1006                         var appDir = path.dirname(require.main.filename);
1007                         var yangFilePath = appDir + "/yangFiles/" + fileName;
1008                         try{
1009                                 fs.unlinkSync(yangFilePath);
1010                                 res.send({"status" :"SUCCESS"});
1011                         }catch(err){
1012                                 console.log("error" + err);
1013                                 res.send({"status" :"ERROR"});
1014                         }
1015                         //console.log("prevPassword:" + settings.httpAuth.pass );
1016                 });
1017             }
1018         );
1019
1020         app.post("/updatePassword",
1021             express.json(),
1022             function(req,res) {
1023                 var qs = require('querystring');
1024                 //console.log("Received the request:");
1025                 var body ="";
1026                  req.on('data', function (data) {
1027                         body += data;
1028                 });
1029                 req.on('end',function(){
1030                         var post = qs.parse(body);
1031                         //console.dir(body);
1032                         var password = post["password"];
1033                         //console.log("prevPassword:" + settings.httpAuth.pass );
1034                         //console.log("New password:" + password);
1035                         var crypto = require("crypto");
1036                         var cryptPasswd = crypto.createHash('md5').update(password,'utf8').digest('hex')
1037                         var appDir = path.dirname(require.main.filename);
1038                         var userDir = appDir + "/" + settings.userDir;
1039                         //console.log("userDir:" + userDir);
1040                         /*var newSettings = settings;
1041                         newSettings.httpAuth.pass = cryptPasswd;
1042                         var updatedSettings = JSON.stringify(settings,null,4);
1043                         var settingsStr = "module.exports=" + updatedSettings;
1044                         console.log(updatedSettings);
1045                         */
1046                         try{
1047                                 var settingsFile = userDir + "/customSettings.js"; 
1048                                 //console.log("settingsFile:" + settingsFile);
1049                                 //var buf = fs.readFileSync(settingsFile, "utf8");
1050                                 var jsonObj = require(settingsFile);
1051                                 //console.log("jsonObj:" + JSON.stringify(jsonObj));
1052                                 jsonObj.httpAuth.pass = cryptPasswd;
1053                                 jsonObj.httpAdminAuth.pass = cryptPasswd;
1054                                 jsonObj.httpNodeAuth.pass = cryptPasswd;
1055                                 jsonObj.flowFile = jsonObj.flowFile.replace(appDir + "/",'');
1056                                 var updatedSettings = jsonObj;
1057                                 /*
1058                                 delete updatedSettings.httpRoot;
1059                                 delete updatedSettings.disableEditor;
1060                                 delete updatedSettings.httpAdminRoot;
1061                                 delete updatedSettings.httpAdminAuth;
1062                                 delete updatedSettings.httpNodeRoot;
1063                                 delete updatedSettings.httpNodeAuth;
1064                                 delete updatedSettings.uiHost;
1065                                 delete updatedSettings.version;
1066                                 */
1067                                 var settingsStr= "module.exports=" + JSON.stringify(updatedSettings,null,4);
1068                                 //console.log("settingsStr:" + settingsStr);
1069                                 fs.writeFileSync(settingsFile,settingsStr);
1070                                 settings.httpAuth.pass = cryptPasswd;
1071                                 res.send({"status": "success"});
1072                         }catch(e){
1073                                 console.log("Error:" + e);
1074                                 res.send({"status": "error"});
1075                         }
1076                 });
1077             }
1078         );
1079
1080         var appDir = path.dirname(require.main.filename);
1081         var yangDir = appDir + "/yangFiles" ;
1082         var diskStorage =   multer.diskStorage({
1083                         destination: function (req, file, callback) {
1084                                                 callback(null, yangDir);
1085                         },
1086                         filename: function (req, file, callback) {
1087                                 //callback(null, file.fieldname + '-' + Date.now());
1088                                 callback(null, file.originalname);
1089                         }
1090         });
1091         var upload = multer({ storage : diskStorage}).single('yangFile');
1092
1093         app.post('/api/uploadyang',function(req,res){
1094                 upload(req,res,function(err) {
1095                         if(err) {
1096                                 console.log(err);
1097                                 return res.end("Error uploading file." + err);
1098                         }
1099                         //console.dir(req);     
1100                         var fileName = req.file.originalname;
1101                         var yangFileFullPath =  appDir + "/yangFiles/" + fileName;
1102                         console.log("yangFileFullPath:" + yangFileFullPath);
1103                         var commandToExec =""; 
1104                         if(fileName != null){
1105                                 var matchedArr = fileName.match(/.zip$/);
1106                                 if(matchedArr != null && matchedArr.length >0){
1107                                         console.log("uploaded zip file" + fileName);
1108                                         //commandToExec = appDir + "/tools/generate_props_from_yangs_zip.sh " + yangFileFullPath ;
1109                                         commandToExec = appDir + "/tools/generate_props_from_yang.sh " + yangFileFullPath ;
1110                                 }else{
1111                                         commandToExec = appDir + "/tools/generate_props_from_yang.sh " + yangFileFullPath ;
1112                                         console.log("uploaded file" + fileName);
1113                                 }
1114                         }
1115                         var exec = require('child_process').exec;
1116                         console.log("commandToExec:" + commandToExec);
1117                         var child = exec(commandToExec ,function (error,stdout,stderr){
1118                                 if(error){
1119                                         console.log("Error occured:" + error);
1120                                         var msg = "File " + fileName + " could not be processed successfully.";
1121                                         if(stderr){
1122                                                 console.log("stderr:" + stderr);
1123                                                 res.json({"sliValuesObj" : [],"message":msg});
1124                                         }else{
1125                                                 res.json({"sliValuesObj" : [],"message":msg});
1126                                         }
1127                                 }else{
1128                                         if(stderr){
1129                                                 console.log("stderr:" + stderr);
1130                                         }
1131                                         if(stdout){
1132                                                 console.log("stdout:" + stdout);
1133                                         }
1134                                         var msg = "File " + fileName + " processed successfully.";
1135                                         var generatedJSDir=appDir + "/generatedJS";
1136                                         var sliValuesObj =[];
1137                                         //var glob = require("glob");
1138                                         //glob(generatedJSDir + "/**/*.js", null, function (er, files) {
1139                                         /*
1140                                                 var sliValuesObj =[];
1141                                                 for(var i=0;files!= null && i<files.length;i++){
1142                                                         var f = files[i].replace( new RegExp(generatedJSDir + "/", "g" ), "" );
1143                                                         console.log("loading file " + f);
1144                                                         try{
1145                                                                 sliValuesObj.push(require(files[i]));
1146                                                                 //console.dir(sliValuesObj);
1147                                                         }catch(err){
1148                                                                 console.log("Error:Could not load file " + files[i]);
1149                                                         }
1150                                                 } 
1151                                                 res.json({"sliValuesObj" : sliValuesObj,"message":msg});
1152                                         });
1153                                         */
1154                                         res.json({"sliValuesObj" : sliValuesObj,"message":msg});
1155                                 }
1156                         });
1157                 });
1158         });
1159
1160         function getFormattedDate(){
1161                 var d = new Date();
1162                 var mm = d.getMonth() + 1;
1163                 var dd =   d.getDate();
1164                 var yyyy = d.getYear() + 1900;
1165                 var hr = d.getHours();
1166                 var min = d.getMinutes();
1167                 var sec = d.getSeconds();
1168                 if(mm<10) mm = "0" + mm;
1169                 if(dd<10) dd = "0" + dd;
1170                 if(hr<10) hr = "0" + hr;
1171                 if(min<10) min = "0" + min;
1172                 if(sec<10) sec = "0" + sec;
1173                 var formatedValue = yyyy + "-" + mm + "-" + dd +  "_" + hr + ":" + min + ":" + sec;
1174                 return formatedValue;
1175         }
1176
1177
1178         app.post("/saveTestDGInput",
1179             express.json({'limit':'16mb'}),
1180             function(req,res) {
1181                 var qs = require('querystring');
1182                 var body = '';
1183                 req.on('data', function (data) {
1184                         body += data;
1185                 });
1186                 req.on('end', function () {
1187                         var appDir = path.dirname(require.main.filename);
1188                         var inputFilesDir = appDir + "/" + "inputFiles";
1189                         if (!fs.existsSync(inputFilesDir)){
1190                                 fs.mkdirSync(inputFilesDir);
1191                         }
1192                         var post = qs.parse(body);
1193                         var moduleName = post['moduleName'];
1194                         var rpcName = post['rpcName'];
1195                         var fullFileName = inputFilesDir + "/" +moduleName + "_" + rpcName + "_" + getFormattedDate();
1196                         var inputStr = post['inputStr'];
1197                         writeToFile(fullFileName,inputStr);
1198                         res.end();
1199                 });
1200         });
1201
1202         app.post("/getInputFiles",function(req,res) {
1203                         var qs = require('querystring');
1204                         var body = '';
1205                         req.on('data', function (data) {
1206                                 body += data;
1207                         });
1208                         req.on('end', function () {
1209                                 var appDir = path.dirname(require.main.filename);
1210                                 var inputFilesDir = appDir + "/" + "inputFiles";
1211                                 if (!fs.existsSync(inputFilesDir)){
1212                                         fs.mkdirSync(inputFilesDir);
1213                                 }
1214                                 var post = qs.parse(body);
1215                                 var moduleName = post['moduleName'];
1216                                 var rpcName = post['rpcName'];
1217                                 var glob = require("glob");
1218                                 var filePatt = "/**/" + moduleName + "_" + rpcName + "*";
1219                                 glob(inputFilesDir + filePatt, null, function (er, files) {
1220                                         var filesList =[];
1221                                         for(var i=0;files!= null && i<files.length;i++){
1222                                                 var f = files[i].replace( new RegExp(inputFilesDir + "/", "g" ), "" );
1223                                                 filesList.push(f); 
1224                                         }
1225                                         res.json({"files" : filesList});
1226                                 });
1227                         });
1228         });
1229
1230         app.post("/deleteInputFile",
1231             express.json(),
1232             function(req,res) {
1233                 var qs = require('querystring');
1234                 var body ="";
1235                  req.on('data', function (data) {
1236                         body += data;
1237                 });
1238                 req.on('end',function(){
1239                         var post = qs.parse(body);
1240                         var fileName = post["fileName"];
1241                         var appDir = path.dirname(require.main.filename);
1242                         var filePath = appDir + "/inputFiles/" + fileName;
1243                         try{
1244                                 fs.unlinkSync(filePath);
1245                                 res.send({"status" :"SUCCESS"});
1246                         }catch(err){
1247                                 console.log("error" + err);
1248                                 res.send({"status" :"ERROR"});
1249                         }
1250                         //console.log("prevPassword:" + settings.httpAuth.pass );
1251                 });
1252             });
1253
1254         app.post("/loadInputFile",
1255             express.json(),
1256             function(req,res) {
1257                 var qs = require('querystring');
1258                 var body ="";
1259                  req.on('data', function (data) {
1260                         body += data;
1261                 });
1262                 req.on('end',function(){
1263                         var post = qs.parse(body);
1264                         var fileName = post["fileName"];
1265                         //console.log("fileName" + fileName);
1266                         var appDir = path.dirname(require.main.filename);
1267                         var filePath = appDir + "/inputFiles/" + fileName;
1268                         //console.log("filePath:" + filePath);
1269                         try{
1270                                 fs.readFile(filePath, 'utf8', function (err,data) {
1271                                         if (err) {
1272                                                 return console.log(err);
1273                                         }
1274                                         res.json({'input':data});
1275                                 });     
1276                         }catch(err){
1277                                 console.log("error" + err);
1278                                 res.json({"status" :"ERROR"});
1279                         }
1280                 });
1281             });
1282
1283         app.get("/getYangFiles",function(req,res) {
1284                 var appDir = path.dirname(require.main.filename);
1285                 var yangFilesDir=appDir + "/yangFiles";
1286                 var glob = require("glob")
1287                 glob(yangFilesDir + "/**/*.yang", null, function (er, files) {
1288                         var filesList =[];
1289                         for(var i=0;files!= null && i<files.length;i++){
1290                                 var f = files[i].replace( new RegExp(yangFilesDir + "/", "g" ), "" );
1291                                 filesList.push(f);
1292
1293                         }
1294                         res.json({"files" : filesList});
1295                 });
1296         });
1297         }
1298 }
1299
1300 function reportAddedModules(info) {
1301     comms.publish("node/added",info,false);
1302     if (info.length > 0) {
1303         util.log("[red] Added node types:");
1304         for (var i=0;i<info.length;i++) {
1305             for (var j=0;j<info[i].types.length;j++) {
1306                 util.log("[red] - "+
1307                     (info[i].module?info[i].module+":":"")+
1308                     info[i].types[j]+
1309                     (info[i].err?" : "+info[i].err:"")
1310                     );
1311             }
1312         }
1313     }
1314     return info;
1315 }
1316
1317 function reportRemovedModules(removedNodes) {
1318     comms.publish("node/removed",removedNodes,false);
1319     util.log("[red] Removed node types:");
1320     for (var j=0;j<removedNodes.length;j++) {
1321         for (var i=0;i<removedNodes[j].types.length;i++) {
1322             util.log("[red] - "+(removedNodes[i].module?removedNodes[i].module+":":"")+removedNodes[j].types[i]);
1323         }
1324     }
1325     return removedNodes;
1326 }
1327
1328 function installModule(module) { 
1329     //TODO: ensure module is 'safe'
1330     return when.promise(function(resolve,reject) {
1331         if (/[\s;]/.test(module)) {
1332             reject(new Error("Invalid module name"));
1333             return;
1334         }
1335         util.log("[red] Installing module: "+module);
1336         var child = exec('npm install --production '+module, function(err, stdin, stdout) {
1337             if (err) {
1338                 var lookFor404 = new RegExp(" 404 .*"+module+"$","m");
1339                 if (lookFor404.test(stdout)) {
1340                     util.log("[red] Installation of module "+module+" failed: module not found");
1341                     var e = new Error();
1342                     e.code = 404;
1343                     reject(e);
1344                 } else {
1345                     util.log("[red] Installation of module "+module+" failed:");
1346                     util.log("------------------------------------------");
1347                     console.log(err.toString());
1348                     util.log("------------------------------------------");
1349                     reject(new Error("Install failed"));
1350                 }
1351             } else {
1352                 util.log("[red] Installed module: "+module);
1353                 resolve(redNodes.addModule(module).then(reportAddedModules));
1354             }
1355         });
1356     });
1357 }
1358
1359 function uninstallModule(module) {
1360     var list = redNodes.removeModule(module);
1361     return when.promise(function(resolve,reject) {
1362         if (/[\s;]/.test(module)) {
1363             reject(new Error("Invalid module name"));
1364             return;
1365         }
1366         util.log("[red] Removing module: "+module);
1367         var child = exec('npm remove '+module, function(err, stdin, stdout) {
1368             if (err) {
1369                 util.log("[red] Removal of module "+module+" failed:");
1370                 util.log("------------------------------------------");
1371                 console.log(err.toString());
1372                 util.log("------------------------------------------");
1373                 reject(new Error("Removal failed"));
1374             } else {
1375                 util.log("[red] Removed module: "+module);
1376                 reportRemovedModules(list);
1377                 resolve(list);
1378             }
1379         });
1380     });
1381 }
1382
1383 function start() {
1384     var defer = when.defer();
1385     
1386     storage.init(settings).then(function() {
1387         settings.load(storage).then(function() {
1388             console.log("\nWelcome to Node-RED\n===================\n");
1389             if (settings.version) {
1390                 util.log("[red] Version: "+settings.version);
1391             }
1392             util.log("[red] Loading palette nodes");
1393             redNodes.init(settings,storage);
1394             redNodes.load().then(function() {
1395                 var i;
1396                 var nodes = redNodes.getNodeList();
1397                 var nodeErrors = nodes.filter(function(n) { return n.err!=null;});
1398                 var nodeMissing = nodes.filter(function(n) { return n.module && n.enabled && !n.loaded && !n.err;});
1399                 if (nodeErrors.length > 0) {
1400                     util.log("------------------------------------------");
1401                     if (settings.verbose) {
1402                         for (i=0;i<nodeErrors.length;i+=1) {
1403                             util.log("["+nodeErrors[i].name+"] "+nodeErrors[i].err);
1404                         }
1405                     } else {
1406                         util.log("[red] Failed to register "+nodeErrors.length+" node type"+(nodeErrors.length==1?"":"s"));
1407                         util.log("[red] Run with -v for details");
1408                     }
1409                     util.log("------------------------------------------");
1410                 }
1411                 if (nodeMissing.length > 0) {
1412                     util.log("[red] Missing node modules:");
1413                     var missingModules = {};
1414                     for (i=0;i<nodeMissing.length;i++) {
1415                         var missing = nodeMissing[i];
1416                         missingModules[missing.module] = (missingModules[missing.module]||[]).concat(missing.types);
1417                     }
1418                     var promises = [];
1419                     for (i in missingModules) {
1420                         if (missingModules.hasOwnProperty(i)) {
1421                             util.log("[red] - "+i+": "+missingModules[i].join(", "));
1422                             if (settings.autoInstallModules) {
1423                                 installModule(i).otherwise(function(err) {
1424                                     // Error already reported. Need the otherwise handler
1425                                     // to stop the error propagating any further
1426                                 });
1427                             }
1428                         }
1429                     }
1430                     if (!settings.autoInstallModules) {
1431                         util.log("[red] Removing modules from config");
1432                         redNodes.cleanNodeList();
1433                     }
1434                 }
1435                 defer.resolve();
1436                 
1437                 redNodes.loadFlows();
1438             }).otherwise(function(err) {
1439                 console.log(err);
1440             });
1441             comms.start();
1442         });
1443     }).otherwise(function(err) {
1444         defer.reject(err);
1445     });
1446     
1447     return defer.promise;
1448 }
1449
1450 function stop() {
1451     redNodes.stopFlows();
1452     comms.stop();
1453 }
1454
1455 module.exports = { 
1456     init: createServer,
1457     start: start,
1458     stop: stop
1459 }
1460
1461 module.exports.__defineGetter__("app", function() { return app });
1462 module.exports.__defineGetter__("nodeApp", function() { return nodeApp });
1463 module.exports.__defineGetter__("server", function() { return server });