UNPKG

pads_app

Version:

playground of algorithms for Distributed Systems(PADS)

426 lines (358 loc) 14.3 kB
/*globals define*/ /*jshint node:true, browser:true*/ /** * Generated by PluginGenerator 1.7.0 from webgme on Fri Feb 03 2017 15:27:19 GMT+0000 (UTC). * A plugin that inherits from the PluginBase. To see source code documentation about available * properties and methods visit %host%/docs/source/PluginBase.html. */ define([ 'plugin/PluginConfig', 'text!./metadata.json', 'plugin/PluginBase', 'common/util/ejs', 'pads_app/modelLoader', 'q', 'CreateTopology/Templates/Templates', ], function (PluginConfig, pluginMetadata, PluginBase, ejs, loader, Q, TEMPLATES) { 'use strict'; pluginMetadata = JSON.parse(pluginMetadata); /** * Initializes a new instance of CreateTopology. * @class * @augments {PluginBase} * @classdesc This class represents the plugin CreateTopology. * @constructor */ var CreateTopology = function () { // Call base class' constructor. PluginBase.call(this); this.pluginMetadata = pluginMetadata; }; /** * Metadata associated with the plugin. Contains id, name, version, description, icon, configStructue etc. * This is also available at the instance at this.pluginMetadata. * @type {object} */ CreateTopology.metadata = pluginMetadata; // Prototypical inheritance from PluginBase. CreateTopology.prototype = Object.create(PluginBase.prototype); CreateTopology.prototype.constructor = CreateTopology; CreateTopology.prototype.notify = function (level, msg) { var self = this; var prefix = self.projectId + '::' + self.projectName + '::' + level + '::'; var max_msg_len = 100; if (level == 'error') self.logger.error(msg); else if (level == 'debug') self.logger.debug(msg); else if (level == 'info') self.logger.info(msg); else if (level == 'warning') self.logger.warn(msg); self.createMessage(self.activeNode, msg, level); if (msg.length < max_msg_len) self.sendNotification(prefix + msg); else { var splitMsgs = utils.chunkString(msg, max_msg_len); splitMsgs.map(function (splitMsg) { self.sendNotification(prefix + splitMsg); }); } }; CreateTopology.prototype.convertNode = function (node) { var attrs = this.core.getAttributeNames(node); // TODO if (!this.core.getBaseType(node)) debugger; // console.log('node is', node) return { name: this.core.getAttribute(node, 'name'), type: this.core.getAttribute(this.core.getBaseType(node), 'name') }; }; CreateTopology.prototype.generateDataModel = function (modelNode) { var self = this, //deferred = new Q.defer(), dataModel = {} return self.core.loadSubTree(modelNode) .then(function (nodes) { // Convert the nodes to the desired structure for the template // TODO return nodes.map(function (node) { return self.convertNode(node); }); }); }; CreateTopology.prototype.generateFiles = function (nodes) { console.log('generating files...') console.log(nodes) // Use the datamodel to generate any artifacts from templates // TODO return ''; }; CreateTopology.prototype.generateArtifacts = function() { var self = this, filesToAdd = {}, deferred = new Q.defer(), artifact = self.blobClient.createArtifact('GeneratedFiles'); filesToAdd['metadata.json'] = JSON.stringify({ timeStamp: (new Date()).toISOString(), }, null, 2); filesToAdd['topology.py'] = self.topologyFileData; filesToAdd['command.txt'] = self.commandFileData artifact.addFiles(filesToAdd, function (err) { if (err) { deferred.reject(new Error(err)); return; } self.blobClient.saveAllArtifacts(function (err, hashes) { if (err) { deferred.reject(new Error(err)); return; } self.result.addArtifact(hashes[0]); deferred.resolve(); }); }); return deferred.promise; }; CreateTopology.prototype.renderTopology = function () { // render docker compose file with federate type + shared folder name + command //type = PubSubNetwork var self = this; self.nodeLink_listInfo = [] if(self.pads_datamodel.SwitchSwitchConnection_list){ self.pads_datamodel.SwitchSwitchConnection_list.map((m_switchlink) => { self.nodeLink_listInfo.push({ name: m_switchlink.name, type: m_switchlink.type, src_name: m_switchlink.src.name, dst_name: m_switchlink.dst.name, Bandwidth_Mbps: m_switchlink.Bandwidth_Mbps, Delay_ms:m_switchlink.Delay_ms, Loss:m_switchlink.Loss }) }) } if(self.pads_datamodel.HostSwitchConnection_list){ self.pads_datamodel.HostSwitchConnection_list.map((m_hostswitchlink) => { self.nodeLink_listInfo.push({ name: m_hostswitchlink.name, type: m_hostswitchlink.type, src_name: m_hostswitchlink.src.name, dst_name: m_hostswitchlink.dst.name, Bandwidth_Mbps: m_hostswitchlink.Bandwidth_Mbps, Delay_ms:m_hostswitchlink.Delay_ms, Loss:m_hostswitchlink.Loss }) }) } self.AppHostList = {}; self.hostInfo = []; if(self.pads_datamodel.Host_list){ self.pads_datamodel.Host_list.map((m_host) => { self.hostInfo.push({ name: m_host.name, type: m_host.type, app_path: [] }) }) } //! Make Sure to Call this after we have a host list if(self.pads_datamodel.PubConnection_list){ self.pads_datamodel.PubConnection_list.map((m_pubLink) => { self.AppHostList[m_pubLink.src.path] =m_pubLink.dst.name; }) } //! Make Sure to Call this after we have a host list if(self.pads_datamodel.BrokerConnection_list){ self.pads_datamodel.BrokerConnection_list.map((m_brokLink) => { self.AppHostList[m_brokLink.src.path] =m_brokLink.dst.name; }) } //! Make Sure to Call this after we have a host list if(self.pads_datamodel.SubConnection_list){ self.pads_datamodel.SubConnection_list.map((m_subLink) => { self.AppHostList[m_subLink.src.path] = m_subLink.dst.name; }) } self.brokerInfo = [] if(self.pads_datamodel.BrokerApp_list){ self.pads_datamodel.BrokerApp_list.map((m_broker) => { self.brokerInfo.push({ name: m_broker.name, type: m_broker.type, path:m_broker.path, scriptName: m_broker.FileName, args: m_broker.args }) }) } self.publisherInfo = [] if(self.pads_datamodel.PublisherApp_list){ self.pads_datamodel.PublisherApp_list.map((m_pub) => { self.publisherInfo.push({ name: m_pub.name, type: m_pub.type, path: m_pub.path, scriptName: m_pub.FileName, args: m_pub.args }) }) } self.subscriberInfo = [] if(self.pads_datamodel.SubsriberApp_list){ self.pads_datamodel.SubsriberApp_list.map((m_sub) => { self.subscriberInfo.push({ name: m_sub.name, type:m_sub.type, path: m_sub.path, scriptName: m_sub.FileName, args: m_sub.args, }) }) } self.switchInfo = []; if(self.pads_datamodel.SwitchS_list){ self.pads_datamodel.SwitchS_list.map((m_switch) => { self.switchInfo.push({ name: m_switch.name, type: m_switch.type }) }) } self.topologyFileData = ejs.render( TEMPLATES['topologyFileTemplate.ejs'], { hostInfo: self.hostInfo, switchInfo: self.switchInfo, brokerInfo: self.brokerInfo, publisherInfo : self.publisherInfo, subscriberInfo: self.subscriberInfo, nodeLink_listInfo: self.nodeLink_listInfo } ); self.commandFileData = ejs.render( TEMPLATES['commandFileTemplate.ejs'], { hostInfo: self.hostInfo, switchInfo: self.switchInfo, brokerInfo: self.brokerInfo, publisherInfo : self.publisherInfo, subscriberInfo: self.subscriberInfo, nodeLink_listInfo: self.nodeLink_listInfo, AppHostList: self.AppHostList } ); var topowrite = function() { var path = require('path'), filendir = require('filendir'), fileName = 'topology.py' var basePath = process.cwd(); var deferred = Q.defer(); filendir.writeFile(path.join(basePath, fileName), self.topologyFileData, function(err) { if (err){ console.error("not able to create the file") deferred.reject(err); } else{ console.log("done writing file to", path.join(basePath,fileName) ) deferred.resolve(); } }); return deferred.promise; }; var commandwrite = function() { var path = require('path'), filendir = require('filendir'), fileName = 'command.txt' var basePath = process.cwd(); var deferred = Q.defer(); filendir.writeFile(path.join(basePath, fileName), self.commandFileData, function(err) { if (err){ console.error("not able to create the file") deferred.reject(err); } else{ console.log("done writing file to", path.join(basePath,fileName) ) deferred.resolve(); } }); return deferred.promise; }; return self.commandFileData; // return topowrite().then(commandwrite); }; /** * Main function for the plugin to execute. This will perform the execution. * Notes: * - Always log with the provided logger.[error,warning,info,debug]. * - Do NOT put any user interaction logic UI, etc. inside this method. * - callback always has to be called even if error happened. * * @param {function(string, plugin.PluginResult)} callback - the result callback */ CreateTopology.prototype.main = function (callback) { // Use self to access core, project, result, logger etc from PluginBase. // These are all instantiated at this point. var self = this, nodeObject; // if (typeof WebGMEGlobal !== 'undefined') { // var msg = 'You must run this plugin on the server!'; // self.notify('error', msg); // callback(new Error(msg), self.result); // } // Using the coreAPI to make changes. // nodeObject = self.activeNode; var currentConfig = self.getCurrentConfig(); self.projectName = self.core.getAttribute(self.rootNode, 'name'); var modelNode = self.activeNode; self.modelName = self.core.getAttribute(modelNode, 'name'); // self.generateDataModel(self.activeNode) // Convert subtree to template-friendly format // .then(function (dataModel) { // self.logger.info('Converted subtree to temp[late-friendcly forfamat'); // self.logger.info(JSON.stringify(dataModel, null, 4)); // return self.generateFiles(dataModel); // }) // .then(function () { // // TODO: Add the files as an artifact // self.result.setSuccess(true); // callback(null, self.result); // }) // .catch(function (err) { // self.logger.error(err); // self.createMessage(null, err.message, 'error'); // self.result.setSuccess(false); // callback(null, self.result); // }) // .done(); return loader.loadModel(self.core, modelNode) .then(function (pads_datamodel) { console.log(pads_datamodel) self.pads_datamodel = pads_datamodel; }) .then(function() { return self.renderTopology(); }) .then(function() { return self.generateArtifacts(); }) .then(function () { self.result.success = true; self.notify('info', 'Simulation Complete.'); callback(null, self.result); }) .catch(function (err) { self.notify('error', err); self.result.success = false; callback(err, self.result); }); }; return CreateTopology; }) ;