From 324ee36fe31763e507b422ab0a88e4230045e205 Mon Sep 17 00:00:00 2001 From: "Timoney, Daniel (dt5972)" Date: Wed, 15 Feb 2017 10:37:53 -0500 Subject: Initial commit for OpenECOMP SDN-C OA&M Change-Id: I7ab579fd0d206bf356f36d52dcdf4f71f1fa2680 Signed-off-by: Timoney, Daniel (dt5972) Former-commit-id: 2a9f0edd09581f907e62ec4689b5ac94dd5382ba --- dgbuilder/red/cli/lib/config.js | 53 ++ dgbuilder/red/cli/lib/request.js | 51 ++ dgbuilder/red/cli/nr-cli.js | 151 ++++ dgbuilder/red/comms.js | 132 +++ dgbuilder/red/events.js | 19 + dgbuilder/red/library.js | 117 +++ dgbuilder/red/log.js | 39 + dgbuilder/red/nodes/Node.js | 147 ++++ dgbuilder/red/nodes/credentials.js | 208 +++++ dgbuilder/red/nodes/flows.js | 220 +++++ dgbuilder/red/nodes/index.js | 134 +++ dgbuilder/red/nodes/registry.js | 693 ++++++++++++++++ dgbuilder/red/red.js | 68 ++ dgbuilder/red/server.js | 1317 ++++++++++++++++++++++++++++++ dgbuilder/red/settings.js | 84 ++ dgbuilder/red/sla.js | 249 ++++++ dgbuilder/red/storage/index.js | 107 +++ dgbuilder/red/storage/localfilesystem.js | 309 +++++++ dgbuilder/red/ui.js | 77 ++ dgbuilder/red/util.js | 43 + 20 files changed, 4218 insertions(+) create mode 100644 dgbuilder/red/cli/lib/config.js create mode 100644 dgbuilder/red/cli/lib/request.js create mode 100755 dgbuilder/red/cli/nr-cli.js create mode 100644 dgbuilder/red/comms.js create mode 100644 dgbuilder/red/events.js create mode 100644 dgbuilder/red/library.js create mode 100644 dgbuilder/red/log.js create mode 100644 dgbuilder/red/nodes/Node.js create mode 100644 dgbuilder/red/nodes/credentials.js create mode 100644 dgbuilder/red/nodes/flows.js create mode 100644 dgbuilder/red/nodes/index.js create mode 100644 dgbuilder/red/nodes/registry.js create mode 100644 dgbuilder/red/red.js create mode 100644 dgbuilder/red/server.js create mode 100644 dgbuilder/red/settings.js create mode 100644 dgbuilder/red/sla.js create mode 100644 dgbuilder/red/storage/index.js create mode 100644 dgbuilder/red/storage/localfilesystem.js create mode 100644 dgbuilder/red/ui.js create mode 100644 dgbuilder/red/util.js (limited to 'dgbuilder/red') diff --git a/dgbuilder/red/cli/lib/config.js b/dgbuilder/red/cli/lib/config.js new file mode 100644 index 00000000..3cd5244d --- /dev/null +++ b/dgbuilder/red/cli/lib/config.js @@ -0,0 +1,53 @@ +/** + * Copyright 2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +var path = require("path"); +var fs = require("fs"); + +var userHome = process.env.HOME || process.env.HOMEPATH || process.env.USERPROFILE; + +var configDir = path.join(userHome,".nodered"); +var configFile = path.join(configDir,"config.json"); + +var config; + +function load() { + if (config == null) { + try { + config = JSON.parse(fs.readFileSync(configFile)); + } catch(err) { + config = {}; + } + } +} + +function save() { + try { + fs.mkdirSync(configDir); + } catch(err) { + if (err.code != "EEXIST") { + throw err; + } + } + fs.writeFileSync(configFile,JSON.stringify(config,null,4)); +} +module.exports = { + unload: function() { + config = null; + } +}; +module.exports.__defineGetter__('target',function() { load(); return config.target|| "http://localhost:1880" }); +module.exports.__defineSetter__('target',function(v) { load(); config.target = v; save();}); diff --git a/dgbuilder/red/cli/lib/request.js b/dgbuilder/red/cli/lib/request.js new file mode 100644 index 00000000..fbbe3dc6 --- /dev/null +++ b/dgbuilder/red/cli/lib/request.js @@ -0,0 +1,51 @@ +/** + * Copyright 2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +var when = require("when"); +var request = require("request"); +var config = require("./config"); + +module.exports = function(path, options) { + var basePath = config.target; + return when.promise(function(resolve,reject) { + options.headers = options.headers||{}; + options.headers['Accept'] = 'application/json'; + if (options.method == 'PUT' || options.method == "POST") { + options.headers['content-type'] = 'application/json'; + } + options.url = basePath+path; + + // Pull out the request function so we can stub it in the tests + var requestFunc = request.get; + + if (options.method == 'PUT') { + requestFunc = request.put; + } else if (options.method == 'POST') { + requestFunc = request.post; + } else if (options.method == 'DELETE') { + requestFunc = request.del; + } + requestFunc(options, function(error,response,body) { + if (!error && response.statusCode == 200) { + resolve(JSON.parse(body)); + } else if (error) { + reject(error.toString()); + } else { + reject(response.statusCode+": "+body) + } + }); + }); +} diff --git a/dgbuilder/red/cli/nr-cli.js b/dgbuilder/red/cli/nr-cli.js new file mode 100755 index 00000000..6d62f05f --- /dev/null +++ b/dgbuilder/red/cli/nr-cli.js @@ -0,0 +1,151 @@ +#!/usr/bin/env node +;(function() { +/** + * Copyright 2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +var util = require("util"); +var request = require("request"); +var colors = require('colors'); +var apiRequest = require("./lib/request"); +var config = require("./lib/config"); + +var commands = { + "target": function() { + var target = process.argv[3]; + if (target) { + if (!/^https?:\/\/.+/.test(target)) { + console.warn("Invalid target url"); + return; + } + if (target.slice(-1) == "/") { + target = target.slice(0,target.length-1); + } + var oldTarget = config.target; + config.target = target; + } else { + console.log("Target: ".yellow+config.target); + } + + }, + "nodes": function() { + apiRequest('/nodes',{}).then(logNodeList).otherwise(logFailure); + }, + "node": function() { + apiRequest('/nodes/'+process.argv[3],{}).then(logNodeList).otherwise(logFailure); + }, + "enable-node": function() { + apiRequest('/nodes/'+process.argv[3],{ + method: "PUT", + body: JSON.stringify({enabled:true}) + }).then(logNodeList).otherwise(logFailure); + }, + "disable-node": function() { + apiRequest('/nodes/'+process.argv[3],{ + method: "PUT", + body: JSON.stringify({enabled:false}) + }).then(logNodeList).otherwise(logFailure); + }, + "install": function() { + apiRequest('/nodes',{ + method: "POST", + body: JSON.stringify({module:process.argv[3]}) + }).then(logNodeList).otherwise(logFailure); + }, + "remove": function() { + apiRequest('/nodes/'+process.argv[3],{ + method: "DELETE" + }).then(logNodeList).otherwise(logFailure); + }, + "search": function() { + var options = { + method: "GET", + url: 'https://registry.npmjs.org/-/_view/byKeyword?startkey=["node-red"]&endkey=["node-red",{}]&group_level=3' , + headers: { + 'Accept': 'application/json', + } + }; + request(options, function (error, response, body) { + if (!error && response.statusCode == 200) { + var info = (JSON.parse(body)).rows; + var filter = null; + if (process.argv[3]) { + filter = new RegExp(process.argv[3]); + } + for (var i=0;i webSocketKeepAliveTime) { + publish("hb",lastSentTime); + } + }, webSocketKeepAliveTime); + } +} + +function stop() { + if (heartbeatTimer) { + clearInterval(heartbeatTimer); + } + if (wsServer) { + wsServer.close(); + } +} + +function publish(topic,data,retain) { + if (retain) { + retained[topic] = data; + } else { + delete retained[topic]; + } + lastSentTime = Date.now(); + activeConnections.forEach(function(conn) { + publishTo(conn,topic,data); + }); +} + +function publishTo(ws,topic,data) { + var msg = JSON.stringify({topic:topic,data:data}); + try { + ws.send(msg); + } catch(err) { + util.log("[red:comms] send error : "+err.toString()); + } +} + +function handleRemoteSubscription(ws,topic) { + var re = new RegExp("^"+topic.replace(/([\[\]\?\(\)\\\\$\^\*\.|])/g,"\\$1").replace(/\+/g,"[^/]+").replace(/\/#$/,"(\/.*)?")+"$"); + for (var t in retained) { + if (re.test(t)) { + publishTo(ws,t,retained[t]); + } + } +} + + +module.exports = { + init:init, + start:start, + stop:stop, + publish:publish, +} diff --git a/dgbuilder/red/events.js b/dgbuilder/red/events.js new file mode 100644 index 00000000..89590494 --- /dev/null +++ b/dgbuilder/red/events.js @@ -0,0 +1,19 @@ +/** + * Copyright 2013 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +var events = require("events"); + +module.exports = new events.EventEmitter(); diff --git a/dgbuilder/red/library.js b/dgbuilder/red/library.js new file mode 100644 index 00000000..cc4199f2 --- /dev/null +++ b/dgbuilder/red/library.js @@ -0,0 +1,117 @@ +/** + * Copyright 2013 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +var util = require("util"); + +var redApp = null; +var storage = null; + +function init() { + redApp = require("./server").app; + storage = require("./storage"); + + // -------- Flow Library -------- + redApp.post(new RegExp("/library/flows\/(.*)"), function(req,res) { + var fullBody = ''; + req.on('data', function(chunk) { + fullBody += chunk.toString(); + }); + req.on('end', function() { + storage.saveFlow(req.params[0],fullBody).then(function() { + res.send(204); + }).otherwise(function(err) { + util.log("[red] Error loading flow '"+req.params[0]+"' : "+err); + if (err.message.indexOf('forbidden') === 0) { + res.send(403); + return; + } + res.send(500); + }); + }); + }); + + redApp.get("/library/flows",function(req,res) { + storage.getAllFlows().then(function(flows) { + res.json(flows); + }); + }); + + redApp.get(new RegExp("/library/flows\/(.*)"), function(req,res) { + storage.getFlow(req.params[0]).then(function(data) { + res.set('Content-Type', 'application/json'); + res.send(data); + }).otherwise(function(err) { + if (err) { + util.log("[red] Error loading flow '"+req.params[0]+"' : "+err); + if (err.message.indexOf('forbidden') === 0) { + res.send(403); + return; + } + } + res.send(404); + }); + }); + + // ------------------------------ +} + +function createLibrary(type) { + + redApp.get(new RegExp("/library/"+type+"($|\/(.*))"),function(req,res) { + var path = req.params[1]||""; + storage.getLibraryEntry(type,path).then(function(result) { + if (typeof result === "string") { + res.writeHead(200, {'Content-Type': 'text/plain'}); + res.write(result); + res.end(); + } else { + res.json(result); + } + }).otherwise(function(err) { + if (err) { + util.log("[red] Error loading library entry '"+path+"' : "+err); + if (err.message.indexOf('forbidden') === 0) { + res.send(403); + return; + } + } + res.send(404); + }); + }); + + redApp.post(new RegExp("/library/"+type+"\/(.*)"),function(req,res) { + var path = req.params[0]; + var fullBody = ''; + req.on('data', function(chunk) { + fullBody += chunk.toString(); + }); + req.on('end', function() { + storage.saveLibraryEntry(type,path,req.query,fullBody).then(function() { + res.send(204); + }).otherwise(function(err) { + util.log("[red] Error saving library entry '"+path+"' : "+err); + if (err.message.indexOf('forbidden') === 0) { + res.send(403); + return; + } + res.send(500); + }); + }); + }); +} + +module.exports.init = init; +module.exports.register = createLibrary; diff --git a/dgbuilder/red/log.js b/dgbuilder/red/log.js new file mode 100644 index 00000000..236e6df0 --- /dev/null +++ b/dgbuilder/red/log.js @@ -0,0 +1,39 @@ +/** + * Copyright 2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +var util = require("util"); +var EventEmitter = require("events").EventEmitter; + +var logHandlers = []; + +var ConsoleLogHandler = new EventEmitter(); +ConsoleLogHandler.on("log",function(msg) { + util.log("["+msg.level+"] ["+msg.type+":"+(msg.name||msg.id)+"] "+msg.msg); +}); + +var log = module.exports = { + addHandler: function(func) { + logHandlers.push(func); + }, + + log: function(msg) { + logHandlers.forEach(function(handler) { + handler.emit("log",msg); + }); + } +} + +log.addHandler(ConsoleLogHandler); diff --git a/dgbuilder/red/nodes/Node.js b/dgbuilder/red/nodes/Node.js new file mode 100644 index 00000000..0e6fc525 --- /dev/null +++ b/dgbuilder/red/nodes/Node.js @@ -0,0 +1,147 @@ +/** + * Copyright 2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +var util = require("util"); +var EventEmitter = require("events").EventEmitter; +var clone = require("clone"); +var when = require("when"); + +var flows = require("./flows"); +var comms = require("../comms"); + +function Node(n) { + this.id = n.id; + flows.add(this); + this.type = n.type; + if (n.name) { + this.name = n.name; + } + this.wires = n.wires||[]; +} + +util.inherits(Node,EventEmitter); + +Node.prototype._on = Node.prototype.on; + +Node.prototype.on = function(event,callback) { + var node = this; + if (event == "close") { + if (callback.length == 1) { + this.close = function() { + return when.promise(function(resolve) { + callback.call(node,function() { + resolve(); + }); + }); + } + } else { + this.close = callback; + } + } else { + this._on(event,callback); + } +} + +Node.prototype.close = function() { +} + +Node.prototype.send = function(msg) { + // instanceof doesn't work for some reason here + if (msg == null) { + return; + } else if (!util.isArray(msg)) { + msg = [msg]; + } + for (var i=0;i 0) { + var i = missingTypes.indexOf(type); + if (i != -1) { + missingTypes.splice(i,1); + util.log("[red] Missing type registered: "+type); + if (missingTypes.length === 0) { + parseConfig(); + } + } + } +}); + +/** + * Parses the current activeConfig and creates the required node instances + */ +function parseConfig() { + var i; + var nt; + missingTypes = []; + + // Scan the configuration for any unknown node types + for (i=0;i 0) { + util.log("[red] Waiting for missing types to be registered:"); + for (i=0;i 0) { + util.log("[red] Stopping flows"); + } + return flowNodes.clear(); +} + +var flowNodes = module.exports = { + init: function(_storage) { + storage = _storage; + }, + + /** + * Load the current activeConfig from storage and start it running + * @return a promise for the loading of the config + */ + load: function() { + return storage.getFlows().then(function(flows) { + return credentials.load().then(function() { + activeConfig = flows; + if (activeConfig && activeConfig.length > 0) { + parseConfig(); + } + }); + }).otherwise(function(err) { + util.log("[red] Error loading flows : "+err); + }); + }, + + /** + * Add a node to the current active set + * @param n the node to add + */ + add: function(n) { + nodes[n.id] = n; + n.on("log",log.log); + }, + + /** + * Get a node + * @param i the node id + * @return the node + */ + get: function(i) { + return nodes[i]; + }, + + /** + * Stops all active nodes and clears the active set + * @return a promise for the stopping of all active nodes + */ + clear: function() { + return when.promise(function(resolve) { + events.emit("nodes-stopping"); + var promises = []; + for (var n in nodes) { + if (nodes.hasOwnProperty(n)) { + try { + var p = nodes[n].close(); + if (p) { + promises.push(p); + } + } catch(err) { + nodes[n].error(err); + } + } + } + when.settle(promises).then(function() { + events.emit("nodes-stopped"); + nodes = {}; + resolve(); + }); + }); + }, + + /** + * Provides an iterator over the active set of nodes + * @param cb a function to be called for each node in the active set + */ + each: function(cb) { + for (var n in nodes) { + if (nodes.hasOwnProperty(n)) { + cb(nodes[n]); + } + } + }, + + /** + * @return the active configuration + */ + getFlows: function() { + return activeConfig; + }, + + /** + * Sets the current active config. + * @param config the configuration to enable + * @return a promise for the starting of the new flow + */ + setFlows: function (config) { + // Extract any credential updates + for (var i=0; i 0) { + var msg = nodesInUse.join(", "); + throw new Error("Type in use: "+msg); + } +} + +function removeNode(id) { + checkTypeInUse(id); + return registry.removeNode(id); +} + +function removeModule(module) { + var info = registry.getNodeModuleInfo(module); + for (var i=0;i -1) { + nodeList.splice(i,1); + } + config.types.forEach(function(t) { + delete nodeConstructors[t]; + delete nodeTypeToId[t]; + }); + config.enabled = false; + config.loaded = false; + nodeConfigCache = null; + return filterNodeInfo(config); + }, + removeModule: function(module) { + if (!settings.available()) { + throw new Error("Settings unavailable"); + } + var nodes = nodeModules[module]; + if (!nodes) { + throw new Error("Unrecognised module: "+module); + } + var infoList = []; + for (var i=0;i 0) { + result += ''; + } + nodeConfigCache = result; + } + return nodeConfigCache; + }, + + getNodeConfig: function(id) { + var config = nodeConfigs[id]; + if (config) { + var result = config.config; + if (config.script) { + result += ''; + } + return result; + } else { + return null; + } + }, + + getNodeConstructor: function(type) { + var config = nodeConfigs[nodeTypeToId[type]]; + if (!config || (config.enabled && !config.err)) { + return nodeConstructors[type]; + } + return null; + }, + + clear: function() { + nodeConfigCache = null; + nodeConfigs = {}; + nodeList = []; + nodeConstructors = {}; + nodeTypeToId = {}; + }, + + getTypeId: function(type) { + return nodeTypeToId[type]; + }, + + getModuleInfo: function(type) { + return nodeModules[type]; + }, + + enableNodeSet: function(id) { + if (!settings.available()) { + throw new Error("Settings unavailable"); + } + var config = nodeConfigs[id]; + if (config) { + delete config.err; + config.enabled = true; + if (!config.loaded) { + // TODO: honour the promise this returns + loadNodeModule(config); + } + nodeConfigCache = null; + saveNodeList(); + } else { + throw new Error("Unrecognised id: "+id); + } + return filterNodeInfo(config); + }, + + disableNodeSet: function(id) { + if (!settings.available()) { + throw new Error("Settings unavailable"); + } + var config = nodeConfigs[id]; + if (config) { + // TODO: persist setting + config.enabled = false; + nodeConfigCache = null; + saveNodeList(); + } else { + throw new Error("Unrecognised id: "+id); + } + return filterNodeInfo(config); + }, + + saveNodeList: saveNodeList, + + cleanNodeList: function() { + var removed = false; + for (var id in nodeConfigs) { + if (nodeConfigs.hasOwnProperty(id)) { + if (nodeConfigs[id].module && !nodeModules[nodeConfigs[id].module]) { + registry.removeNode(id); + removed = true; + } + } + } + if (removed) { + saveNodeList(); + } + } + } +})(); + + + +function init(_settings) { + Node = require("./Node"); + settings = _settings; + registry.init(); +} + +/** + * Synchronously walks the directory looking for node files. + * Emits 'node-icon-dir' events for an icon dirs found + * @param dir the directory to search + * @return an array of fully-qualified paths to .js files + */ +function getNodeFiles(dir) { + var result = []; + var files = []; + try { + files = fs.readdirSync(dir); + } catch(err) { + return result; + } + files.sort(); + files.forEach(function(fn) { + var stats = fs.statSync(path.join(dir,fn)); + if (stats.isFile()) { + if (/\.js$/.test(fn)) { + var valid = true; + if (settings.nodesExcludes) { + for (var i=0;i]*)data-template-name=['"]([^'"]*)['"]/gi; + var match = null; + + while((match = regExp.exec(content)) !== null) { + types.push(match[2]); + } + node.types = types; + node.config = content; + + // TODO: parse out the javascript portion of the template + node.script = ""; + + for (var i=0;i0){ + files.sort(function(a,b){ + //console.log("file1:" + a); + //console.log("file2:" + b); + var fileStat1=fs.statSync(flowDir+ "/" + a); + var fileStat2=fs.statSync(flowDir+ "/" + b); + if(fileStat1.mtime > fileStat2.mtime){ + return 1; + }else if(fileStat1.mtime < fileStat2.mtime){ + return -1; + }else{ + return 0; + } + }); + for(var i=0;i0){ + console.log("uploaded zip file" + fileName); + commandToExec = appDir + "/tools/generate_props_from_yangs_zip.sh " + yangFileFullPath ; + }else{ + commandToExec = appDir + "/tools/generate_props_from_yang.sh " + yangFileFullPath ; + console.log("uploaded file" + fileName); + } + } + var exec = require('child_process').exec; + console.log("commandToExec:" + commandToExec); + var child = exec(commandToExec ,function (error,stdout,stderr){ + if(error){ + console.log("Error occured:" + error); + var msg = "File " + fileName + " could not be processed successfully."; + if(stderr){ + console.log("stderr:" + stderr); + res.json({"sliValuesObj" : [],"message":msg}); + }else{ + res.json({"sliValuesObj" : [],"message":msg}); + } + }else{ + if(stderr){ + console.log("stderr:" + stderr); + } + if(stdout){ + console.log("stdout:" + stdout); + } + var msg = "File " + fileName + " processed successfully."; + var generatedJSDir=appDir + "/generatedJS"; + var sliValuesObj =[]; + //var glob = require("glob"); + //glob(generatedJSDir + "/**/*.js", null, function (er, files) { + /* + var sliValuesObj =[]; + for(var i=0;files!= null && i 0) { + util.log("[red] Added node types:"); + for (var i=0;i 0) { + util.log("------------------------------------------"); + if (settings.verbose) { + for (i=0;i 0) { + util.log("[red] Missing node modules:"); + var missingModules = {}; + for (i=0;i 0 ) + { + res.send({ 'rows': rows,'dbHost':settings.dbHost } ); + }else{ + res.send({'rows': [],'dbHost':settings.dbHost}); + } + } else { + console.log("error:" + err); + res.send({error: "Connection to DB failed.",'dbHost':settings.dbHost}); + } + //console.dir(rows); + connection.end(); + }); //end query +}catch(error){ + console.log(error); + res.send({'error': "Connection to DB failed.",'dbHost':settings.dbHost}); +} +} + +exports.listCurrentDGs = function(settings,req,res) { + var _module = req.query.module; + var rpc = req.query.rpc; + console.log("_module:" + _module); + console.log("rpc:" + rpc); +try{ + var mysql = require('mysql'); + + //console.dir(settings); + + var connection = mysql.createConnection( + { + host : settings.dbHost, + port : settings.dbPort, + user : settings.dbUser, + password : settings.dbPassword, + database : settings.dbName + }); + + var rows=[]; + + var sqlQuery = "SELECT module,rpc,version,mode,active FROM SVC_LOGIC where module ='" + _module + "' and rpc ='" + rpc + "'"; + console.log("sqlQuery:" + sqlQuery); + connection.query(sqlQuery, function(err, rows) { + if(!err) { + if ( rows.length > 0 ) + { + res.send({ 'rows': rows,'dbHost':settings.dbHost } ); + }else{ + res.send({'rows': [],'dbHost':settings.dbHost}); + } + } else { + console.log("error:" + err); + res.send({error: "Connection to DB failed.",'dbHost':settings.dbHost}); + } + //console.dir(rows); + connection.end(); + }); //end query +}catch(error){ + console.log(error); + res.send({'error': "Connection to DB failed.",'dbHost':settings.dbHost}); +} +} + +exports.activateDG = function(settings,req,res){ + var _module = req.query.module; + var rpc = req.query.rpc; + var version = req.query.version; + var mode = req.query.mode; + var displayOnlyCurrent = req.query.displayOnlyCurrent; + +try{ + var mysql = require('mysql'); + + var connection = mysql.createConnection( + { + host : settings.dbHost, + port : settings.dbPort, + user : settings.dbUser, + password : settings.dbPassword, + database : settings.dbName + }); + + var rows=[]; + + var updateStmt = "UPDATE SVC_LOGIC SET active=\'Y\' WHERE module=\'" + + _module + "' AND rpc=\'" + + rpc + "' AND version=\'" + + version + "' AND mode=\'" + + mode + "'"; + + connection.query(updateStmt, function(err, result) { + var nextUpdateStmt = "UPDATE SVC_LOGIC SET active=\'N\' WHERE module=\'" + + _module + "' AND rpc=\'" + + rpc + "' AND version !=\'" + + version + "'"; + connection.query(nextUpdateStmt, function(err, result) { + var query = "SELECT module,rpc,version,mode,active FROM SVC_LOGIC"; + if(displayOnlyCurrent == 'true'){ + query = "SELECT module,rpc,version,mode,active FROM SVC_LOGIC WHERE module=\'" + + _module + "' and rpc=\'" + rpc + "'"; + } + connection.query(query, function(err, rows) { + if(!err) { + if ( rows.length > 0 ) + { + res.send({ 'rows': rows,'dbHost':settings.dbHost } ); + }else{ + res.send({'rows': [],'dbHost':settings.dbHost}); + } + } else { + res.send({'error': "Connection to DB failed.",'dbHost':settings.dbHost}); + } + connection.end(); + }); //end query + }); //end query + }); //end query +}catch(error){ + res.send({'error': "Connection to DB failed.",'dbHost':settings.dbHost}); +} +} + + +exports.deActivateDG = function(settings,req,res){ + + var _module = req.query.module; + var rpc = req.query.rpc; + var version = req.query.version; + var mode = req.query.mode; + var displayOnlyCurrent = req.query.displayOnlyCurrent; + +try{ + var mysql = require('mysql'); + + var connection = mysql.createConnection( + { + host : settings.dbHost, + port : settings.dbPort, + user : settings.dbUser, + password : settings.dbPassword, + database : settings.dbName + }); + + var rows=[]; + + var updateStmt = "UPDATE SVC_LOGIC SET active=\'N\' WHERE module=\'" + + _module + "' AND rpc=\'" + + rpc + "' AND version=\'" + + version + "' AND mode=\'" + + mode + "'"; + + connection.query(updateStmt, function(err, result) { + var query = "SELECT module,rpc,version,mode,active FROM SVC_LOGIC"; + if(displayOnlyCurrent == 'true'){ + query = "SELECT module,rpc,version,mode,active FROM SVC_LOGIC WHERE module=\'" + + _module + "' and rpc=\'" + rpc + "'"; + } + connection.query(query, function(err, rows) { + if(!err) { + if ( rows.length > 0 ) + { + res.send({ 'rows': rows,'dbHost':settings.dbHost } ); + }else{ + res.send({'rows': [],'dbHost':settings.dbHost}); + } + } else { + res.send({'error': "Connection to DB failed.",'dbHost':settings.dbHost}); + } + connection.end(); + }); //end query + }); //end query +}catch(error){ + res.send({'error': "Connection to DB failed.",'dbHost':settings.dbHost}); +} +} + +exports.deleteDG = function(settings,req,res){ + + var _module = req.query.module; + var rpc = req.query.rpc; + var version = req.query.version; + var mode = req.query.mode; + var displayOnlyCurrent = req.query.displayOnlyCurrent; + +try{ + var mysql = require('mysql'); + + var connection = mysql.createConnection( + { + host : settings.dbHost, + port : settings.dbPort, + user : settings.dbUser, + password : settings.dbPassword, + database : settings.dbName + }); + + var rows=[]; + + var deleteStmt = "DELETE FROM SVC_LOGIC WHERE module=\'" + + _module + "' AND rpc=\'" + + rpc + "' AND version=\'" + + version + "' AND mode=\'" + + mode + "'"; + console.log(deleteStmt); + + connection.query(deleteStmt, function(err, result) { + var query = "SELECT module,rpc,version,mode,active FROM SVC_LOGIC"; + if(displayOnlyCurrent == 'true'){ + query = "SELECT module,rpc,version,mode,active FROM SVC_LOGIC WHERE module=\'" + + _module + "' and rpc=\'" + rpc + "'"; + } + connection.query(query, function(err, rows) { + if(!err) { + if ( rows.length > 0 ) + { + res.send({ 'rows': rows,'dbHost':settings.dbHost } ); + }else{ + res.send({'rows': [],'dbHost':settings.dbHost}); + } + } else { + res.send({'error': "Connection to DB failed.",'dbHost':settings.dbHost}); + } + connection.end(); + }); //end query + }); //end query +}catch(error){ + res.send({'error': "Connection to DB failed.",'dbHost':settings.dbHost}); +} +} diff --git a/dgbuilder/red/storage/index.js b/dgbuilder/red/storage/index.js new file mode 100644 index 00000000..ba939627 --- /dev/null +++ b/dgbuilder/red/storage/index.js @@ -0,0 +1,107 @@ +/** + * Copyright 2013, 2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +var when = require('when'); + +var storageModule; +var settingsAvailable; + +function moduleSelector(aSettings) { + var toReturn; + if (aSettings.storageModule) { + if (typeof aSettings.storageModule === "string") { + // TODO: allow storage modules to be specified by absolute path + toReturn = require("./"+aSettings.storageModule); + } else { + toReturn = aSettings.storageModule; + } + } else { + toReturn = require("./localfilesystem"); + } + return toReturn; +} + +function is_malicious(path) { + return path.indexOf('../') != -1 || path.indexOf('..\\') != -1; +} + +var storageModuleInterface = { + init: function(settings) { + try { + storageModule = moduleSelector(settings); + settingsAvailable = storageModule.hasOwnProperty("getSettings") && storageModule.hasOwnProperty("saveSettings"); + } catch (e) { + return when.reject(e); + } + return storageModule.init(settings); + }, + getFlows: function() { + return storageModule.getFlows(); + }, + saveFlows: function(flows) { + return storageModule.saveFlows(flows); + }, + getCredentials: function() { + return storageModule.getCredentials(); + }, + saveCredentials: function(credentials) { + return storageModule.saveCredentials(credentials); + }, + getSettings: function() { + if (settingsAvailable) { + return storageModule.getSettings(); + } else { + return when.resolve(null); + } + }, + saveSettings: function(settings) { + if (settingsAvailable) { + return storageModule.saveSettings(settings); + } else { + return when.resolve(); + } + }, + /* Library Functions */ + getAllFlows: function() { + return storageModule.getAllFlows(); + }, + getFlow: function(fn) { + if (is_malicious(fn)) { + return when.reject(new Error('forbidden flow name')); + } + return storageModule.getFlow(fn); + }, + saveFlow: function(fn, data) { + if (is_malicious(fn)) { + return when.reject(new Error('forbidden flow name')); + } + return storageModule.saveFlow(fn, data); + }, + getLibraryEntry: function(type, path) { + if (is_malicious(path)) { + return when.reject(new Error('forbidden flow name')); + } + return storageModule.getLibraryEntry(type, path); + }, + saveLibraryEntry: function(type, path, meta, body) { + if (is_malicious(path)) { + return when.reject(new Error('forbidden flow name')); + } + return storageModule.saveLibraryEntry(type, path, meta, body); + } +} + +module.exports = storageModuleInterface; diff --git a/dgbuilder/red/storage/localfilesystem.js b/dgbuilder/red/storage/localfilesystem.js new file mode 100644 index 00000000..48255332 --- /dev/null +++ b/dgbuilder/red/storage/localfilesystem.js @@ -0,0 +1,309 @@ +/** + * Copyright 2013, 2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +var fs = require('fs'); +var when = require('when'); +var nodeFn = require('when/node/function'); +var keys = require('when/keys'); +var util = require('util'); +var fspath = require("path"); +var mkdirp = require("mkdirp"); + +var promiseDir = nodeFn.lift(mkdirp); + +var settings; +var flowsFile; +var flowsFullPath; +var flowsPrev; +var credentialsFile; +var oldCredentialsFile; +var userDir; +var libDir; +var libFlowsDir; +var globalSettingsFile; + +function listFiles(dir) { + var dirs = {}; + var files = []; + var dirCount = 0; + return nodeFn.call(fs.readdir, dir).then(function (contents) { + contents.sort().forEach(function(fn) { + var stats = fs.lstatSync(dir+"/"+fn); + if (stats.isDirectory()) { + dirCount += 1; + dirs[fn] = listFiles(dir+"/"+fn) + } else { + files.push(fn.split(".")[0]); + } + }) + var result = {}; + if (dirCount > 0) { result.d = keys.all(dirs); } + if (files.length > 0) { result.f = when.resolve(files); } + return keys.all(result); + }) +} + +function getFileMeta(root,path) { + var fn = fspath.join(root,path); + var fd = fs.openSync(fn,"r"); + var size = fs.fstatSync(fd).size; + var meta = {}; + var read = 0; + var length = 10; + var remaining = ""; + var buffer = Buffer(length); + while(read < size) { + read+=fs.readSync(fd,buffer,0,length); + var data = remaining+buffer.toString(); + var parts = data.split("\n"); + remaining = parts.splice(-1); + for (var i=0;i