Merge "Add Graph/Node to org.ops4j.pax.logging.cfg"
[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                                         fs.rename(file,renameFilePath, function (err) {
567                                                 if(err){
568                                                         console.log('Error :' + err);
569                                                 }
570                                                 //write the newer version
571                                                 writeToFile(file,jsonStr);
572                                                 res.setHeader('Content-disposition', 'attachment; filename=' + fileName);
573                                                 res.setHeader('Content-type', 'application/json');
574                                                 //res.download(file);
575                                                 res.end(jsonStr);
576                                         });
577                                 }
578                         });
579         });
580
581         app.post("/flows",
582             express.json({'limit':'16mb'}),
583             function(req,res) {
584                 //console.log("Processing Request");
585                 var flows = req.body;
586                 redNodes.setFlows(flows).then(function() {
587                     res.send(204);
588                 }).otherwise(function(err) {
589                     util.log("[red] Error saving flows : "+err);
590                     res.send(500,err.message);
591                 });
592             },
593             function(error,req,res,next) {
594                 res.send(400,"Invalid Flow.  Error " + error);
595             }
596         );
597             
598         app.get("/nodes",function(req,res) {
599             if (req.get("accept") == "application/json") {
600                 res.json(redNodes.getNodeList());
601             } else {
602                 res.send(redNodes.getNodeConfigs());
603             }
604         });
605         
606         app.post("/nodes",
607             express.json(),
608             function(req,res) {
609                 if (!settings.available()) {
610                     res.send(400,new Error("Settings unavailable").toString());
611                     return;
612                 }
613                 var node = req.body;
614                 var promise;
615                 if (node.file) {
616                     promise = redNodes.addNode(node.file).then(reportAddedModules);
617                 } else if (node.module) {
618                     var module = redNodes.getNodeModuleInfo(node.module);
619                     if (module) {
620                         res.send(400,"Module already loaded");
621                         return;
622                     }
623                     promise = installModule(node.module);
624                 } else {
625                     res.send(400,"Invalid request");
626                     return;
627                 }
628                 promise.then(function(info) {
629                     res.json(info);
630                 }).otherwise(function(err) {
631                     if (err.code === 404) {
632                         res.send(404);
633                     } else {
634                         res.send(400,err.toString());
635                     }
636                 });
637             },
638             function(err,req,res,next) {
639                 console.log(err.toString());
640                 res.send(400,err);
641             }
642         );
643         
644         app.delete("/nodes/:id",
645             function(req,res) {
646                 if (!settings.available()) {
647                     res.send(400,new Error("Settings unavailable").toString());
648                     return;
649                 }
650                 var id = req.params.id;
651                 var removedNodes = [];
652                 try {
653                     var node = redNodes.getNodeInfo(id);
654                     var promise = null;
655                     if (!node) {
656                         var module = redNodes.getNodeModuleInfo(id);
657                         if (!module) {
658                             res.send(404);
659                             return;
660                         } else {
661                             promise = uninstallModule(id);
662                         }
663                     } else {
664                         promise = when.resolve([redNodes.removeNode(id)]).then(reportRemovedModules);
665                     }
666                     
667                     promise.then(function(removedNodes) {
668                         res.json(removedNodes);
669                     }).otherwise(function(err) {
670                         console.log(err.stack);
671                         res.send(400,err.toString());
672                     });
673                 } catch(err) {
674                     res.send(400,err.toString());
675                 }
676             },
677             function(err,req,res,next) {
678                 res.send(400,err);
679             }
680         );
681         
682         app.get("/nodes/:id", function(req,res) {
683             var id = req.params.id;
684             var result = null;
685             if (req.get("accept") == "application/json") {
686                 result = redNodes.getNodeInfo(id);
687             } else {
688                 result = redNodes.getNodeConfig(id);
689             }
690             if (result) {
691                 res.send(result);
692             } else {
693                 res.send(404);
694             }
695         });
696         
697         app.put("/nodes/:id", 
698             express.json(),
699             function(req,res) {
700                 if (!settings.available()) {
701                     res.send(400,new Error("Settings unavailable").toString());
702                     return;
703                 }
704                 var body = req.body;
705                 if (!body.hasOwnProperty("enabled")) {
706                     res.send(400,"Invalid request");
707                     return;
708                 }
709                 try {
710                     var info;
711                     var id = req.params.id;
712                     var node = redNodes.getNodeInfo(id);
713                     if (!node) {
714                         res.send(404);
715                     } else if (!node.err && node.enabled === body.enabled) {
716                         res.json(node);
717                     } else {
718                         if (body.enabled) {
719                             info = redNodes.enableNode(id);
720                         } else {
721                             info = redNodes.disableNode(id);
722                         }
723                         if (info.enabled == body.enabled && !info.err) {
724                             comms.publish("node/"+(body.enabled?"enabled":"disabled"),info,false);
725                             util.log("[red] "+(body.enabled?"Enabled":"Disabled")+" node types:");
726                             for (var i=0;i<info.types.length;i++) {
727                                 util.log("[red] - "+info.types[i]);
728                             }
729                         } else if (body.enabled && info.err) {
730                             util.log("[red] Failed to enable node:");
731                             util.log("[red] - "+info.name+" : "+info.err);
732                         }
733                         res.json(info);
734                     }
735                 } catch(err) {
736                     res.send(400,err.toString());
737                 }            
738             }
739         );
740         app.get("/getCodeCloudFlows",function(req,res) {
741                 var userDir=settings.userDir;
742                 var codeCloudDir=userDir + "/codecloud";
743                 var glob = require("glob")
744                 glob(codeCloudDir + "/**/*.json", null, function (er, files) {
745                           // files is an array of filenames.
746                          // If the `nonull` option is set, and nothing
747                         // was found, then files is ["**/*.js"]
748                         // er is an error object or null.
749                         //console.dir(files);
750                         var filesList =[];
751                         for(var i=0;files!= null && i<files.length;i++){
752                                 var f = files[i].replace( new RegExp(codeCloudDir + "/", "g" ), "" );
753                                 filesList.push(f);
754
755                         }
756                         res.json({"files" : filesList});
757                 });
758         });
759
760         app.get("/getCurrentGitBranch",function(req,res) {
761                 var appDir = path.dirname(require.main.filename);
762                 var userDir=settings.userDir;
763                 var settingsFile = appDir + "/" +  userDir + "/customSettings.js"; 
764                 //console.log("settingsFile:" + settingsFile);
765                 var jsonObj = require(settingsFile);
766                 var gitLocalRepository=jsonObj.gitLocalRepository;
767                 if(gitLocalRepository == undefined || gitLocalRepository == null || gitLocalRepository == ''){
768                         res.json({"output" : "GIT_LOCAL_REPOSITORY_NOT_SET"});
769                         return;
770                 }
771                 var exec = require('child_process').exec;
772                 var commandToExec = appDir + "/git_scripts/gitcurbranch " + gitLocalRepository ;
773                         console.log("commandToExec:" + commandToExec);
774                         var child = exec(commandToExec ,function (error,stdout,stderr){
775                                 if(error){
776                                         console.log("Error occured:" + error);
777                                         if(stderr){
778                                                 console.log("stderr:" + stderr);
779                                                 res.json({"output":stderr});
780                                         }else{
781                                                 res.json({"output":error});
782                                         }
783                                 }else{
784                                         if(stderr){
785                                                 console.log("stderr:" + stderr);
786                                         }
787                                         if(stdout){
788                                                 res.json({"output":stdout});
789                                         }
790                                 }
791                         });
792                                 
793         });
794
795         app.get("/getGitLocalFlows",function(req,res) {
796                 var appDir = path.dirname(require.main.filename);
797                 var userDir=settings.userDir;
798                 var settingsFile = appDir + "/" +  userDir + "/customSettings.js"; 
799                 //console.log("settingsFile:" + settingsFile);
800                 var jsonObj = require(settingsFile);
801                 var performGitPull = jsonObj.performGitPull;
802                 if(performGitPull == undefined || performGitPull == null) {
803                         performGitPull="N";
804                 }
805                 var gitLocalRepository=jsonObj.gitLocalRepository;
806                 if(gitLocalRepository == undefined || gitLocalRepository == null || gitLocalRepository == ''){
807                         res.json({"files" : ["GIT_LOCAL_REPOSITORY_NOT_SET"]});
808                         return;
809                                 
810                    }
811
812                 if(performGitPull == "Y"){      
813                         var exec = require('child_process').exec;
814                         var commandToExec = appDir + "/git_scripts/gitpull " + gitLocalRepository ;
815                         console.log("commandToExec:" + commandToExec);
816                         var child = exec(commandToExec ,function (error,stdout,stderr){
817                                 if(error){
818                                         console.log("Error occured:" + error);
819                                         if(stderr){
820                                                 console.log("stderr:" + stderr);
821                                                 res.json({"files":[]});
822                                         }else{
823                                                 res.json({"files":[]});
824                                         }
825                                 }else{
826                                         if(stderr){
827                                                 console.log("stderr:" + stderr);
828                                         }
829                                         if(stdout){
830                                                 var glob = require("glob")
831                                                 glob(gitLocalRepository + "/**/*.json", null, function (er, files) {
832                                                 // files is an array of filenames.
833                                                 // If the `nonull` option is set, and nothing
834                                                 // was found, then files is ["**/*.js"]
835                                                 // er is an error object or null.
836                                                 //console.dir(files);
837                                                 var filesList =[];
838                                                 for(var i=0;files!= null && i<files.length;i++){
839                                                         var f = files[i].replace( new RegExp(gitLocalRepository + "/", "g" ), "" );
840                                                         filesList.push(f);
841
842                                                 }
843                                                 res.json({"files" : filesList});
844                                                 });
845                                         }
846                                 }
847                         });
848                 }else{//git pull not requested
849                         var glob = require("glob")
850                         glob(gitLocalRepository + "/**/*.json", null, function (er, files) {
851                         // files is an array of filenames.
852                         // If the `nonull` option is set, and nothing
853                         // was found, then files is ["**/*.js"]
854                         // er is an error object or null.
855                         //console.dir(files);
856                         var filesList =[];
857                         for(var i=0;files!= null && i<files.length;i++){
858                                 var f = files[i].replace( new RegExp(gitLocalRepository + "/", "g" ), "" );
859                                 filesList.push(f);
860
861                         }
862                         res.json({"files" : filesList});
863                         });
864                 }
865         
866         });
867
868         app.get("/flowShareUsers",function(req,res) {
869             res.json(flowShareUsers);
870         });
871         app.get("/getRelease",function(req,res) {
872                 var userDir = settings.userDir;
873                 //var release = userDir.replace(/releases/g,"release");
874                 res.json({"release" : userDir});
875         });
876         app.post("/getFiles/:id",function(req,res) {
877             var id = req.params.id;
878                 //console.log("id:" + id);
879                 var userDir=settings.userDir;
880                 var flowDir= userDir + "/../" + id + "/flows/shared"; 
881                 //console.log("flowDir:" + flowDir);
882                 fs.readdir(flowDir,function(err, files){
883                         if(err){
884                                 res.json({"files": []});
885                         }else{
886                                 var onlyFilesArr =[];
887                                 if(files != null && files.length>0){
888                                         files.sort(function(a,b){
889                                                 //console.log("file1:" + a);    
890                                                 //console.log("file2:" + b);    
891                                                 var fileStat1=fs.statSync(flowDir+ "/" + a);    
892                                                 var fileStat2=fs.statSync(flowDir+ "/" + b);    
893                                                 if(fileStat1.mtime > fileStat2.mtime){
894                                                         return 1;
895                                                 }else if(fileStat1.mtime < fileStat2.mtime){
896                                                         return -1;
897                                                 }else{
898                                                         return 0;
899                                                 }
900                                         });
901                                         for(var i=0;i<files.length;i++){
902                                                 var fileStat=fs.statSync(flowDir+ "/" + files[i]);
903                                                 if(fileStat.isFile()){
904                                                     onlyFilesArr.push({"filePath":flowDir+ "/" + files[i],"name":files[i]});
905                                                 }
906                                         }
907                                         res.json(onlyFilesArr);
908                                 }else{
909                                         res.json({"files": []});
910                                 }
911                         }
912                 });
913         });
914
915         app.post("/updateConfiguration",
916             express.json(),
917             function(req,res) {
918                 var qs = require('querystring');
919                 //console.log("Received the request:");
920                 var body ="";
921                  req.on('data', function (data) {
922                         body += data;
923                 });
924                 req.on('end',function(){
925                         var post = qs.parse(body);
926                         var dbHost = post["dbHost"];
927                         var dbPort = post["dbPort"];
928                         var dbName = post["dbName"];
929                         var dbUser = post["dbUser"];
930                         var dbPassword = post["dbPassword"];
931                         var gitLocalRepository = post["gitLocalRepository"];
932                         var performGitPull = post["performGitPull"];
933                         var appDir = path.dirname(require.main.filename);
934                         var userDir = appDir + "/" + settings.userDir;
935                         console.log("userDir:" + userDir);
936                         try{
937                                 var settingsFile = userDir + "/customSettings.js"; 
938                                 var jsonObj = require(settingsFile);
939                                 jsonObj.flowFile = jsonObj.flowFile.replace(appDir + "/",'');
940                                 jsonObj.dbHost = dbHost;
941                                 jsonObj.dbPort = dbPort;
942                                 jsonObj.dbName = dbName;
943                                 jsonObj.dbUser = dbUser;
944                                 jsonObj.dbPassword = dbPassword;
945                                 jsonObj.gitLocalRepository = gitLocalRepository;
946                                 jsonObj.performGitPull = performGitPull;
947                                 var updatedSettings = jsonObj;
948
949                                 var settingsStr= "module.exports=" + JSON.stringify(updatedSettings,null,4);
950                                 //console.log("settingsStr:" + settingsStr);
951                                 fs.writeFileSync(settingsFile,settingsStr);
952                                 var svcLogicPropStr = "" ;
953                                         svcLogicPropStr += "org.onap.ccsdk.sli.dbtype=jdbc" + "\n";
954                                         svcLogicPropStr += "org.onap.ccsdk.sli.jdbc.url=jdbc:mysql://" + dbHost + ":" + dbPort + "/" + dbName + "\n";
955                                         svcLogicPropStr += "org.onap.ccsdk.sli.jdbc.database=" + dbName + "\n";
956                                         svcLogicPropStr += "org.onap.ccsdk.sli.jdbc.user=" + dbUser  + "\n";
957                                         svcLogicPropStr += "org.onap.ccsdk.sli.jdbc.password=" + dbPassword;
958                                 
959                                 //create svclogic.properties file in the conf dir
960                                 var svcPropFile = userDir + "/conf/svclogic.properties";
961                                 fs.writeFileSync(svcPropFile,svcLogicPropStr);
962
963                                 res.send({"status": "success"});
964                         }catch(e){
965                                 console.log("Error:" + e);
966                                 res.send({"status": "error"});
967                         }
968                 });
969             }
970         );
971
972         app.post("/deleteYangFile",
973             express.json(),
974             function(req,res) {
975                 var qs = require('querystring');
976                 //console.log("Received the request:");
977                 var body ="";
978                  req.on('data', function (data) {
979                         body += data;
980                 });
981                 req.on('end',function(){
982                         var post = qs.parse(body);
983                         //console.dir(body);
984                         var fileName = post["fileName"];
985                         var appDir = path.dirname(require.main.filename);
986                         var yangFilePath = appDir + "/yangFiles/" + fileName;
987                         try{
988                                 fs.unlinkSync(yangFilePath);
989                                 res.send({"status" :"SUCCESS"});
990                         }catch(err){
991                                 console.log("error" + err);
992                                 res.send({"status" :"ERROR"});
993                         }
994                         //console.log("prevPassword:" + settings.httpAuth.pass );
995                 });
996             }
997         );
998
999         app.post("/updatePassword",
1000             express.json(),
1001             function(req,res) {
1002                 var qs = require('querystring');
1003                 //console.log("Received the request:");
1004                 var body ="";
1005                  req.on('data', function (data) {
1006                         body += data;
1007                 });
1008                 req.on('end',function(){
1009                         var post = qs.parse(body);
1010                         //console.dir(body);
1011                         var password = post["password"];
1012                         //console.log("prevPassword:" + settings.httpAuth.pass );
1013                         //console.log("New password:" + password);
1014                         var crypto = require("crypto");
1015                         var cryptPasswd = crypto.createHash('md5').update(password,'utf8').digest('hex')
1016                         var appDir = path.dirname(require.main.filename);
1017                         var userDir = appDir + "/" + settings.userDir;
1018                         //console.log("userDir:" + userDir);
1019                         /*var newSettings = settings;
1020                         newSettings.httpAuth.pass = cryptPasswd;
1021                         var updatedSettings = JSON.stringify(settings,null,4);
1022                         var settingsStr = "module.exports=" + updatedSettings;
1023                         console.log(updatedSettings);
1024                         */
1025                         try{
1026                                 var settingsFile = userDir + "/customSettings.js"; 
1027                                 //console.log("settingsFile:" + settingsFile);
1028                                 //var buf = fs.readFileSync(settingsFile, "utf8");
1029                                 var jsonObj = require(settingsFile);
1030                                 //console.log("jsonObj:" + JSON.stringify(jsonObj));
1031                                 jsonObj.httpAuth.pass = cryptPasswd;
1032                                 jsonObj.httpAdminAuth.pass = cryptPasswd;
1033                                 jsonObj.httpNodeAuth.pass = cryptPasswd;
1034                                 jsonObj.flowFile = jsonObj.flowFile.replace(appDir + "/",'');
1035                                 var updatedSettings = jsonObj;
1036                                 /*
1037                                 delete updatedSettings.httpRoot;
1038                                 delete updatedSettings.disableEditor;
1039                                 delete updatedSettings.httpAdminRoot;
1040                                 delete updatedSettings.httpAdminAuth;
1041                                 delete updatedSettings.httpNodeRoot;
1042                                 delete updatedSettings.httpNodeAuth;
1043                                 delete updatedSettings.uiHost;
1044                                 delete updatedSettings.version;
1045                                 */
1046                                 var settingsStr= "module.exports=" + JSON.stringify(updatedSettings,null,4);
1047                                 //console.log("settingsStr:" + settingsStr);
1048                                 fs.writeFileSync(settingsFile,settingsStr);
1049                                 settings.httpAuth.pass = cryptPasswd;
1050                                 res.send({"status": "success"});
1051                         }catch(e){
1052                                 console.log("Error:" + e);
1053                                 res.send({"status": "error"});
1054                         }
1055                 });
1056             }
1057         );
1058
1059         var appDir = path.dirname(require.main.filename);
1060         var yangDir = appDir + "/yangFiles" ;
1061         var diskStorage =   multer.diskStorage({
1062                         destination: function (req, file, callback) {
1063                                                 callback(null, yangDir);
1064                         },
1065                         filename: function (req, file, callback) {
1066                                 //callback(null, file.fieldname + '-' + Date.now());
1067                                 callback(null, file.originalname);
1068                         }
1069         });
1070         var upload = multer({ storage : diskStorage}).single('yangFile');
1071
1072         app.post('/api/uploadyang',function(req,res){
1073                 upload(req,res,function(err) {
1074                         if(err) {
1075                                 console.log(err);
1076                                 return res.end("Error uploading file." + err);
1077                         }
1078                         //console.dir(req);     
1079                         var fileName = req.file.originalname;
1080                         var yangFileFullPath =  appDir + "/yangFiles/" + fileName;
1081                         console.log("yangFileFullPath:" + yangFileFullPath);
1082                         var commandToExec =""; 
1083                         if(fileName != null){
1084                                 var matchedArr = fileName.match(/.zip$/);
1085                                 if(matchedArr != null && matchedArr.length >0){
1086                                         console.log("uploaded zip file" + fileName);
1087                                         //commandToExec = appDir + "/tools/generate_props_from_yangs_zip.sh " + yangFileFullPath ;
1088                                         commandToExec = appDir + "/tools/generate_props_from_yang.sh " + yangFileFullPath ;
1089                                 }else{
1090                                         commandToExec = appDir + "/tools/generate_props_from_yang.sh " + yangFileFullPath ;
1091                                         console.log("uploaded file" + fileName);
1092                                 }
1093                         }
1094                         var exec = require('child_process').exec;
1095                         console.log("commandToExec:" + commandToExec);
1096                         var child = exec(commandToExec ,function (error,stdout,stderr){
1097                                 if(error){
1098                                         console.log("Error occured:" + error);
1099                                         var msg = "File " + fileName + " could not be processed successfully.";
1100                                         if(stderr){
1101                                                 console.log("stderr:" + stderr);
1102                                                 res.json({"sliValuesObj" : [],"message":msg});
1103                                         }else{
1104                                                 res.json({"sliValuesObj" : [],"message":msg});
1105                                         }
1106                                 }else{
1107                                         if(stderr){
1108                                                 console.log("stderr:" + stderr);
1109                                         }
1110                                         if(stdout){
1111                                                 console.log("stdout:" + stdout);
1112                                         }
1113                                         var msg = "File " + fileName + " processed successfully.";
1114                                         var generatedJSDir=appDir + "/generatedJS";
1115                                         var sliValuesObj =[];
1116                                         //var glob = require("glob");
1117                                         //glob(generatedJSDir + "/**/*.js", null, function (er, files) {
1118                                         /*
1119                                                 var sliValuesObj =[];
1120                                                 for(var i=0;files!= null && i<files.length;i++){
1121                                                         var f = files[i].replace( new RegExp(generatedJSDir + "/", "g" ), "" );
1122                                                         console.log("loading file " + f);
1123                                                         try{
1124                                                                 sliValuesObj.push(require(files[i]));
1125                                                                 //console.dir(sliValuesObj);
1126                                                         }catch(err){
1127                                                                 console.log("Error:Could not load file " + files[i]);
1128                                                         }
1129                                                 } 
1130                                                 res.json({"sliValuesObj" : sliValuesObj,"message":msg});
1131                                         });
1132                                         */
1133                                         res.json({"sliValuesObj" : sliValuesObj,"message":msg});
1134                                 }
1135                         });
1136                 });
1137         });
1138         app.get("/getYangFiles",function(req,res) {
1139                 var appDir = path.dirname(require.main.filename);
1140                 var yangFilesDir=appDir + "/yangFiles";
1141                 var glob = require("glob")
1142                 glob(yangFilesDir + "/**/*.yang", null, function (er, files) {
1143                         var filesList =[];
1144                         for(var i=0;files!= null && i<files.length;i++){
1145                                 var f = files[i].replace( new RegExp(yangFilesDir + "/", "g" ), "" );
1146                                 filesList.push(f);
1147
1148                         }
1149                         res.json({"files" : filesList});
1150                 });
1151         });
1152         }
1153 }
1154
1155 function reportAddedModules(info) {
1156     comms.publish("node/added",info,false);
1157     if (info.length > 0) {
1158         util.log("[red] Added node types:");
1159         for (var i=0;i<info.length;i++) {
1160             for (var j=0;j<info[i].types.length;j++) {
1161                 util.log("[red] - "+
1162                     (info[i].module?info[i].module+":":"")+
1163                     info[i].types[j]+
1164                     (info[i].err?" : "+info[i].err:"")
1165                     );
1166             }
1167         }
1168     }
1169     return info;
1170 }
1171
1172 function reportRemovedModules(removedNodes) {
1173     comms.publish("node/removed",removedNodes,false);
1174     util.log("[red] Removed node types:");
1175     for (var j=0;j<removedNodes.length;j++) {
1176         for (var i=0;i<removedNodes[j].types.length;i++) {
1177             util.log("[red] - "+(removedNodes[i].module?removedNodes[i].module+":":"")+removedNodes[j].types[i]);
1178         }
1179     }
1180     return removedNodes;
1181 }
1182
1183 function installModule(module) { 
1184     //TODO: ensure module is 'safe'
1185     return when.promise(function(resolve,reject) {
1186         if (/[\s;]/.test(module)) {
1187             reject(new Error("Invalid module name"));
1188             return;
1189         }
1190         util.log("[red] Installing module: "+module);
1191         var child = exec('npm install --production '+module, function(err, stdin, stdout) {
1192             if (err) {
1193                 var lookFor404 = new RegExp(" 404 .*"+module+"$","m");
1194                 if (lookFor404.test(stdout)) {
1195                     util.log("[red] Installation of module "+module+" failed: module not found");
1196                     var e = new Error();
1197                     e.code = 404;
1198                     reject(e);
1199                 } else {
1200                     util.log("[red] Installation of module "+module+" failed:");
1201                     util.log("------------------------------------------");
1202                     console.log(err.toString());
1203                     util.log("------------------------------------------");
1204                     reject(new Error("Install failed"));
1205                 }
1206             } else {
1207                 util.log("[red] Installed module: "+module);
1208                 resolve(redNodes.addModule(module).then(reportAddedModules));
1209             }
1210         });
1211     });
1212 }
1213
1214 function uninstallModule(module) {
1215     var list = redNodes.removeModule(module);
1216     return when.promise(function(resolve,reject) {
1217         if (/[\s;]/.test(module)) {
1218             reject(new Error("Invalid module name"));
1219             return;
1220         }
1221         util.log("[red] Removing module: "+module);
1222         var child = exec('npm remove '+module, function(err, stdin, stdout) {
1223             if (err) {
1224                 util.log("[red] Removal of module "+module+" failed:");
1225                 util.log("------------------------------------------");
1226                 console.log(err.toString());
1227                 util.log("------------------------------------------");
1228                 reject(new Error("Removal failed"));
1229             } else {
1230                 util.log("[red] Removed module: "+module);
1231                 reportRemovedModules(list);
1232                 resolve(list);
1233             }
1234         });
1235     });
1236 }
1237
1238 function start() {
1239     var defer = when.defer();
1240     
1241     storage.init(settings).then(function() {
1242         settings.load(storage).then(function() {
1243             console.log("\nWelcome to Node-RED\n===================\n");
1244             if (settings.version) {
1245                 util.log("[red] Version: "+settings.version);
1246             }
1247             util.log("[red] Loading palette nodes");
1248             redNodes.init(settings,storage);
1249             redNodes.load().then(function() {
1250                 var i;
1251                 var nodes = redNodes.getNodeList();
1252                 var nodeErrors = nodes.filter(function(n) { return n.err!=null;});
1253                 var nodeMissing = nodes.filter(function(n) { return n.module && n.enabled && !n.loaded && !n.err;});
1254                 if (nodeErrors.length > 0) {
1255                     util.log("------------------------------------------");
1256                     if (settings.verbose) {
1257                         for (i=0;i<nodeErrors.length;i+=1) {
1258                             util.log("["+nodeErrors[i].name+"] "+nodeErrors[i].err);
1259                         }
1260                     } else {
1261                         util.log("[red] Failed to register "+nodeErrors.length+" node type"+(nodeErrors.length==1?"":"s"));
1262                         util.log("[red] Run with -v for details");
1263                     }
1264                     util.log("------------------------------------------");
1265                 }
1266                 if (nodeMissing.length > 0) {
1267                     util.log("[red] Missing node modules:");
1268                     var missingModules = {};
1269                     for (i=0;i<nodeMissing.length;i++) {
1270                         var missing = nodeMissing[i];
1271                         missingModules[missing.module] = (missingModules[missing.module]||[]).concat(missing.types);
1272                     }
1273                     var promises = [];
1274                     for (i in missingModules) {
1275                         if (missingModules.hasOwnProperty(i)) {
1276                             util.log("[red] - "+i+": "+missingModules[i].join(", "));
1277                             if (settings.autoInstallModules) {
1278                                 installModule(i).otherwise(function(err) {
1279                                     // Error already reported. Need the otherwise handler
1280                                     // to stop the error propagating any further
1281                                 });
1282                             }
1283                         }
1284                     }
1285                     if (!settings.autoInstallModules) {
1286                         util.log("[red] Removing modules from config");
1287                         redNodes.cleanNodeList();
1288                     }
1289                 }
1290                 defer.resolve();
1291                 
1292                 redNodes.loadFlows();
1293             }).otherwise(function(err) {
1294                 console.log(err);
1295             });
1296             comms.start();
1297         });
1298     }).otherwise(function(err) {
1299         defer.reject(err);
1300     });
1301     
1302     return defer.promise;
1303 }
1304
1305 function stop() {
1306     redNodes.stopFlows();
1307     comms.stop();
1308 }
1309
1310 module.exports = { 
1311     init: createServer,
1312     start: start,
1313     stop: stop
1314 }
1315
1316 module.exports.__defineGetter__("app", function() { return app });
1317 module.exports.__defineGetter__("nodeApp", function() { return nodeApp });
1318 module.exports.__defineGetter__("server", function() { return server });