UNPKG

jchaos

Version:

module to access chaos resources

1,296 lines (1,158 loc) 185 kB
/** * !CHAOS REST Library *@fileOverview *@version 1.1.92 *@author Andrea Michelotti *@module jchaos */ /** * Callback in asynchronous operations called when the operation is ok * @callback okcb * @param {object} data depend on the operation (typically a dataset) */ /** * Callback in asynchronous operations called when the operation is fails * @callback badcb * @param {string|object} data description of the error */ /** * The command object for sendCU commands * @typedef {Object} cmdPar * @property {string} cmd - command name * @property {integer} prio - Priority * @property {integer} mode - mode */ /** * CU variable path * @typedef {Object} varpath * @property {string} cu CU PATH * @property {string} dir direction (input,output) * @property {string} var variable dataset name * @property {string} const constantco:String * @property {string} origin full path */ /** * Channel identification mapping: * -1 : all * 0: output * 1: input * 2: custom * 3: system * 4: health * 5: cu alarms * 6: device alarms * 128: status * 255: health+system+ alarams * @typedef {integer} channelid */ /** * @typedef ChaosOption * @type {object} * @property {boolean} updateEachCall history update each call * @property {string} uri address:port of the REST server */ (function () { /** * Creates a new jchaos object. * @class */ function createLibrary() { var jchaos = {}; jchaos['latency'] = 0; jchaos['latency_avg'] = 0; jchaos['latency_tot'] = 0; jchaos['errors'] = 0; jchaos['timeouts'] = 0; jchaos['nops'] = 0; jchaos['logops_enable'] = false; jchaos['maxlogops'] = 100; jchaos['ops_list'] = []; jchaos['numok'] = 0; jchaos['implementation_map'] = { "powersupply": ["SCPowerSupply", "RTMG1PowerSupply"], "motor": ["SCActuator"], "camera": ["RTCamera", "cameraGFIT"], "bpm": ["SCLibera"] }; jchaos.extendJson = function (key, n) { // Filtraggio delle proprietà if (Number(n) === n && n % 1 !== 0) { var obj = { $numberDouble: n.toString() }; return obj; } return n; } jchaos.logops = function (request, logop) { var enable = logop || jchaos['logops_enable']; if (enable) { request['jchaos_status'] = request.status; if (jchaos['ops_list'].length < jchaos['maxlogops']) { jchaos['ops_list'].push(JSON.stringify(request)); } else { jchaos['ops_list'].shift(); jchaos['ops_list'].push(JSON.stringify(request)); } } } jchaos.channelToString = function (id) { switch (id) { case 0: return "output"; case 1: return "input"; case 2: return "custom"; case 3: return "system"; case 4: return "health"; case 5: return "device_alarms"; case 6: return "cu_alarms"; case 7: return "log"; default: return "UKNOWN CHANNEL" } } jchaos.extendStringKey = function (obj, key) { if (obj.hasOwnProperty(key) && (typeof obj[key] === "string")) { try { var o = JSON.parse(obj[key]); obj[key] = JSON.stringify(o, jchaos.extendJson); } catch (e) { } return obj; } // Filtraggio delle proprietà if (Number(n) === n && n % 1 !== 0) { var obj = { $numberDouble: n.toString() }; return obj; } return n; } jchaos.ops_on_going = 0; jchaos.ops_abort = false; jchaos.lastChannel = {}; /** * @prop {boolean} updateEachCall=true choose if update each call of history operation * @prop {string} uri=localhost:8081 REST server URI * @prop {boolean} async=true if false force the call to be synchronous, otherwise depend if the callback is definedd * @prop {integer} limit_on_going=10000 limits the concurrent operations * @prop {integer} history_page_len=1000 default history page len * @prop {integer} timeout=5000 default timeout for operation * @prop {callback} console_log redirected on console.log * @prop {callback} console_err redirected on console.error */ jchaos.socket = null; jchaos.options = { updateEachCall: false, uri: "http://localhost:8081", socketio: { url: "ws://localhost:4000", opt: {} }, async: true, limit_on_going: 10000, history_page_len: 1000, timeout: 10000, console_log: function (str) { console.log(str); }, console_err: function (str) { console.error(str); }, io_onconnect: function (sock) { console.log("Connected to " + jchaos.options['socketio'] + " id:" + sock.id); }, io_disconnect: function (sock) { console.log("Disconnected from:" + jchaos.options['socketio'] + " id:" + sock.id); }, io_onmessage: function (msg) { console.log("incoming kafka message without handler, unsubscribe all"); }, io_onerror: function (msg) { console.log("Error: " + JSON.stringify(msg)); }, io_onchat: function (msg) { console.log("Chat: " + msg); }, on_restTimeout: function (msg) { jchaos.perror("Timeout:" + msg); }, on_restOk: function (msg) { }, io_heartbeat: 0 }; jchaos.ioconnect = function (uri, opt) { var ws = uri || jchaos.options['socketio'].url; jchaos.options['socketio'] = ws; if (opt === undefined) { opt = {}; } opt['transports'] = ['websocket']; jchaos.socket = io(ws, opt); jchaos.socket.on("connect", () => { jchaos.options.io_onconnect(jchaos.socket); jchaos.options.io_heartbeat = setInterval(function () { jchaos.socket.emit('heartbeat', { data: jchaos.getDateTime() }); }, 60000); }); jchaos.socket.on("connect_error", () => { jchaos.options.io_onerror("Connection error:" + jchaos.options['socketio']); }); jchaos.socket.on("disconnect", () => { jchaos.options.io_disconnect(jchaos.socket); clearInterval(jchaos.options.io_heartbeat); }); jchaos.socket.on("msg", (msg) => { jchaos.options.io_onmessage(msg); }); jchaos.socket.on("chaos_web_log", (msg) => { try { jchaos.options.io_onchat(JSON.parse(msg)); jchaos.print("Server message :'" + msg + "'"); } catch (e) { jchaos.perror("error parsing message :'" + JSON.stringify(msg) + "' error:" + e); } }); jchaos.socket.on("error", (msg) => { jchaos.options.io_onerror(msg); }); } jchaos.iomessage = function (msg, user, type, dst) { var nmesg = {}; if (typeof msg === "object") { nmesg = msg; } else { if ((typeof msg !== "string") || (msg == "")) { jchaos.perror("empty messages not allowed"); return; } nmesg['username'] = user; nmesg['msg'] = msg || ""; nmesg['type'] = type || "user"; } nmesg['date'] = jchaos.getDateTime(); nmesg['dst'] = dst || "broadcast"; nmesg['src'] = location.host; jchaos.print("sending:" + JSON.stringify(nmesg)); jchaos.socket.emit("chaos_web_log", nmesg); } jchaos.chaosDatasetToFullDS = function (ds) { var obj = {}; if (ds.dpck_ds_type == 0) { obj['output'] = ds; } else if (ds.dpck_ds_type == 1) { obj['input'] = ds; } else if (ds.dpck_ds_type == 2) { obj['custom'] = ds; } else if (ds.dpck_ds_type == 3) { obj['system'] = ds; } else if (ds.dpck_ds_type == 4) { obj['health'] = ds; } if (ds.dpck_ds_type == 5) { obj['device_alarms'] = ds; } else if (ds.dpck_ds_type == 6) { obj['cu_alarms'] = ds; } else if (ds.dpck_ds_type == 7) { obj['log'] = ds; } return obj; } jchaos.ioclose = function () { console.log("Closing I/O"); jchaos.socket.emit("close", "all"); // jchaos['io_onconnect']=(sock)=> {console.log("Connected to "+jchaos.options['socketio']+" id:"+sock.id);}; // jchaos['io_disconnect']=(sock)=> {console.log("Disconnected from:"+jchaos.options['socketio']+" id:"+sock.id);}; jchaos['io_onmessage'] = (msg) => { console.log("incoming kafka message "); } } jchaos.unsubscribeall=function(){ jchaos.iosubscribeCU("all",false); } /** * Subscribe/unsubscribe a list of CU with their dataset * @param {array} culist list of cu * @param {boolean} subscribe true to subscribe,false to unsubscribe * @param {array} chans array of channels if not defined all channels. */ jchaos.iosubscribeCU = function (culist, subscribe, opt) { var topics = []; var options={} if(typeof opt==="object"){ options=opt; } if ((typeof culist === "string")) { if ((culist == "all")) { if ((subscribe !== undefined) && (subscribe == false)) { jchaos.socket.emit("unsubscribeall", ""); return; } } else { culist = [culist]; } } topics = jchaos.keysToTopic(culist); options['topics']=topics; if (subscribe !== undefined && (subscribe === false)) { jchaos.socket.emit("unsubscribe", JSON.stringify(options)); } else { jchaos.socket.emit("subscribe", JSON.stringify(options)); } } /** * Return an object with the zone, group and uid of the path * return null if not valid * @param {string} cupath */ jchaos.pathToZoneGroupId = function (cupath) { var regex = /(.*)\/(.*)\/(.*)$/; var match = regex.exec(cupath); if (match != null) { return { 'zone': match[1], 'group': match[2], 'id': match[3] }; } return null } jchaos.getDateTime = function (t) { if (typeof t === "string") { t = parseInt(t); return new Date(t).toLocaleString('it-IT', { year: 'numeric', month: 'numeric', day: 'numeric', hour: 'numeric', minute: 'numeric', second: 'numeric' }); } else if (typeof t === "number") { return new Date(t).toLocaleString('it-IT', { year: 'numeric', month: 'numeric', day: 'numeric', hour: 'numeric', minute: 'numeric', second: 'numeric' }); } return new Date().toLocaleString('it-IT', { year: 'numeric', month: 'numeric', day: 'numeric', hour: 'numeric', minute: 'numeric', second: 'numeric' }); } jchaos.keysToTopic = function (arr, postfix) { var ret = []; arr.forEach(elem => { if (typeof postfix === "string") { ret.push(elem.replaceAll('/', '.') + postfix); } else { ret.push(elem.replaceAll('/', '.')); } }) return ret; } jchaos.generateUID = function () { var dt = new Date().getTime(); var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { var r = (dt + Math.random() * 16) % 16 | 0; dt = Math.floor(dt / 16); return (c == 'x' ? r : (r & 0x3 | 0x8)).toString(16); }); return uuid; } /** * Decode a CU dataset element path and return an object * @param {string} cupath * @function decodeCUPath * @return {varpath} */ jchaos.decodeCUPath = function (cupath) { var regex_vect = /(.*)\/(.*)\/(.*)\[([-\d]+)\]$/; var regex = /(.*)\/(.*)\/(.*)$/; var tmp = { cu: null, dir: null, var: null, const: null, origin: cupath }; if ($.isNumeric(cupath)) { tmp = { cu: null, dir: null, var: null, const: Number(cupath), index: null, // in case of vectors origin: cupath }; return tmp; } var match = regex_vect.exec(cupath); if (match != null) { tmp = { cu: match[1], dir: match[2], var: match[3], const: null, index: match[4], origin: cupath }; return tmp; } match = regex.exec(cupath); if (match != null) { tmp = { cu: match[1], dir: match[2], var: match[3], const: null, index: null, origin: cupath }; } else if ((match = /(.*)\/(.*)/.exec(cupath))) { tmp = { cu: match[1], dir: "", var: match[2], const: null, index: null, origin: cupath }; } return tmp; } jchaos.jsonDiff = function (ob1, ob2) { var deepDiffMapper = function () { return { VALUE_CREATED: 'created', VALUE_UPDATED: 'updated', VALUE_DELETED: 'deleted', VALUE_UNCHANGED: 'unchanged', map: function (obj1, obj2) { if (this.isFunction(obj1) || this.isFunction(obj2)) { throw 'Invalid argument. Function given, object expected.'; } if (this.isValue(obj1) || this.isValue(obj2)) { if (this.compareValues(obj1, obj2) == this.VALUE_UPDATED) { return (obj1 === undefined) ? obj2 : obj1 } else { return null; } } var diff = {}; for (var key in obj1) { if (this.isFunction(obj1[key])) { continue; } var value2 = undefined; if (obj2[key] !== undefined) { value2 = obj2[key]; } var o = this.map(obj1[key], value2); if ((o != null) && (JSON.stringify(o) !== "{}")) { diff[key] = o; } } for (var key in obj2) { if (this.isFunction(obj2[key]) || diff[key] !== undefined) { continue; } var o = this.map(undefined, obj2[key]); if ((o != null) && (JSON.stringify(o) !== "{}")) { diff[key] = o; } } return diff; }, compareValues: function (value1, value2) { if (value1 === value2) { return this.VALUE_UNCHANGED; } if (this.isDate(value1) && this.isDate(value2) && value1.getTime() === value2.getTime()) { return this.VALUE_UNCHANGED; } if (value1 === undefined) { return this.VALUE_CREATED; } if (value2 === undefined) { return this.VALUE_DELETED; } return this.VALUE_UPDATED; }, isFunction: function (x) { return Object.prototype.toString.call(x) === '[object Function]'; }, isArray: function (x) { return Object.prototype.toString.call(x) === '[object Array]'; }, isDate: function (x) { return Object.prototype.toString.call(x) === '[object Date]'; }, isObject: function (x) { return Object.prototype.toString.call(x) === '[object Object]'; }, isValue: function (x) { return !this.isObject(x) && !this.isArray(x); } } }(); return deepDiffMapper.map(ob1, ob2); } jchaos.isCollapsable = function (arg) { return arg instanceof Object && Object.keys(arg).length > 0; } /** * translate seconds in days hours minutes seconds string * @function toHHMMSS * @param {integer} sec_num * @return {string} return string xx days hh:mm:ss */ jchaos.toHHMMSS = function (sec_num) { // var sec_num = parseInt(this, 10); // don't forget the second param var days = Math.floor(sec_num / 86400); var hours = Math.floor((sec_num - (days * 86400)) / 3600); var minutes = Math.floor((sec_num - (days * 86400) - (hours * 3600)) / 60); var seconds = sec_num - (days * 86400) - (hours * 3600) - (minutes * 60); if (days < 10) { days = "0" + days; } if (hours < 10) { hours = "0" + hours; } if (minutes < 10) { minutes = "0" + minutes; } if (seconds < 10) { seconds = "0" + seconds; } return days + ' days ' + hours + ':' + minutes + ':' + seconds; } /********** */ class ChaosNode { syncDesc() { var prom = new Promise((resolve, reject) => { jchaos.node(this.uid, "desc", "all", (data) => { this.desc = data; resolve(this.desc); }, (bad) => { reject(bad); }); }); return prom; } syncDS() { var prom = new Promise((resolve, reject) => { jchaos.getChannel(this.uid, -1, (data) => { this.ds = data[0]; /* this.ds['output'] = data[0]; this.ds['input'] = data[1]; this.ds['custom'] = data[2]; this.ds['system'] = data[3]; this.ds['health'] = data[4]; this.ds['calarm'] = data[5]; this.ds['dalarm'] = data[6];*/ resolve(this.ds); }, (bad) => { reject(bad); }); }); return prom; } constructor(uid, okfn, badfn) { this.uid = uid; this.storage = 2; // live this.ds = {}; this.desc = {}; this.methods = []; console.log("Chaos Node " + uid); this.syncDS().then((ok) => { var prom = this.syncDesc(); prom.then((d) => { var promise = import('./interface/' + this.impl() + ".js"); promise.then((obj) => { console.log("Adding interface " + this.impl()); if (typeof obj === "object") { for (var k in obj) { if (typeof obj[k] === "function") { this.__proto__[k] = obj[k]; } else { this[k] = obj[k]; } } } if (typeof okfn === "function") { okfn(this); } }).catch(err => { jchaos.perror("error:" + err.message); if (typeof badfn === "function") { badfn(err); } }); }); return prom; }, (bad) => { console.error("DS error:" + JSON.stringify(bad)); }); } set(attrname, value, ok, bad) { if (typeof value === "number") { value = value.toString(); } jchaos.setAttribute(this.uid, attrname, value, k => { if (typeof ok === "function") { ok(k); } else { jchaos.print(this.uid + "] set attr " + attrname + " =" + value); } }, b => { if (typeof bad === "function") { bad(b); } else { jchaos.perror(this.uid + "= Error setting attr " + attrname + " =" + value); } }); } async _get() { var prom = this.syncDS(); return await prom; } get(ok, bad) { this._get().then(ok); return this.ds; } schedule(us, ok, bad) { jchaos.setSched(this.uid, us, ok, bad); } calibrate() { jchaos.command(this.uid, { "act_name": "calibrateNodeUnit" }, function (data) { jchaos.print("Calibration done"); }, function (data) { jchaos.error("Error calibrating:" + JSON.stringify(data)); }); } setDrvProp(props, ok) { var msg = { "act_msg": props, "act_name": "cu_prop_drv_set" }; jchaos.command(this.cu, msg, function (data) { if (typeof ok === "function") { ok(data); } else { jchaos.print("Props set:" + JSON.stringify(props)); } }, (bad) => { jchaos.perror("Error setting driver prop:" + JSON.stringify(bad)); }) } getDrvProp(ok, bad) { jchaos.command(this.cu, { "act_name": "cu_prop_drv_get" }, function (dd) { this['drv_prop'] = dd; if (typeof ok === "function") { ok(dd); } }, bad); } setCUProp(props, ok) { var msg = { "act_msg": props, "act_name": "ndk_set_prop" }; jchaos.command(this.cu, msg, function (data) { jchaos.print("Props set:" + JSON.stringify(props)); if (typeof ok === "function") { ok(data); } }, (bad) => { jchaos.perror("Error setting CU prop:" + JSON.stringify(bad)); }) } getCUProp(ok, bad) { jchaos.command(tmpObj.node_multi_selected, { "act_name": "ndk_get_prop" }, function (dd) { this['cu_prop'] = dd; if (typeof ok === "function") { ok(dd); } }, bad); } /** * return the parent of the node (i.e. US or agent) */ parent() { if (this.desc.hasOwnProperty("ndk_parent")) { return this.desc.ndk_parent; } else if (this.desc.hasOwnProperty("instance_description") && this.desc.instance_description.hasOwnProperty("ndk_parent")) { return this.desc.instance_description.ndk_parent; } return ""; } /** * return the implementation name */ impl() { if (this.desc.hasOwnProperty("instance_description") && this.desc.instance_description.hasOwnProperty("control_unit_implementation")) { var impl = this.desc.instance_description.control_unit_implementation var regex = /\w+$/; impl = regex.exec(impl); return impl[0]; } return ""; } liveEnable(val, ok, bad) { if (val) { this.storage |= 2; // live } else { this.storage &= (~2); // live } jchaos.setProperty(this.uid, [{ "dsndk_storage_type": this.storage }], ok, bad); } logEnable(val, ok, bad) { if (val) { this.storage |= 16; // log } else { this.storage &= (~16); } jchaos.setProperty(this.uid, [{ "dsndk_storage_type": this.storage }], ok, bad); } histoEnable(val, ok, bad) { if (val) { this.storage |= 1; // histo } else { this.storage &= (~1); } jchaos.setProperty(this.uid, [{ "dsndk_storage_type": this.storage }], ok, bad); } /** * Send a command to the node * @param {string} name command name * @param {object} param comman parameters (if any) * @param {okcb} ok handler on success * @param {badcb} bad handler on failure */ cmd(name, param, ok, bad) { jchaos.sendCUCmd(this.uid, name, param, ok, bad); } /** * Start tagging for a given time * @param {string} tagname tag name * @param {intefer} ms * @param {okcb} ok * @param {badcb} bad */ tagForMS(tagname, ms, ok, bad) { jchaos.tag(tagname, this.uid, 2, ms, ok, bad); } /** * Start tagging for a given number of cycles * @param {string} tagname tag name * @param {intefer} ms * @param {okcb} ok * @param {badcb} bad */ tagForCycle(tagname, cycles, ok, bad) { jchaos.tag(tagname, this.uid, 1, cycles, ok, bad); } init(ok, bad) { jchaos.node(this.uid, "init", "cu", ok, bad); } start(ok, bad) { jchaos.node(this.uid, "start", "cu", ok, bad); } stop(ok, bad) { jchaos.node(this.uid, "stop", "cu", ok, bad); } deinit(ok, bad) { jchaos.node(this.uid, "deinit", "cu", ok, bad); } load(ok, bad) { jchaos.loadUnload(this.uid, true, ok, bad); } unload(ok, bad) { jchaos.loadUnload(this.uid, false, ok, bad); } help() { var methods = Object.getOwnPropertyNames(this.__proto__); this['methods'] = methods; // var methods = Object.keys(obj).filter((key) => typeof obj[key] === 'function'); return JSON.stringify(this.methods); } }; /** * Create a basic instance of the node, with set/get init/deinit/unload/load * it tries to load the specific interface if found * @param {string} uid of node */ jchaos.chaosNodeCreate = function (uid, ok, bad) { //createNode(uid).then(ok=>{console.log("HERE"); var obj = new ChaosNode(uid, ok, bad); var methods = Object.getOwnPropertyNames(obj.__proto__); obj['methods'] = methods; return obj; } async function createNode(uid) { const prom = new Promise((resolve, reject) => { jchaos.node(uid, "desc", "all", (data) => { if (data.hasOwnProperty("instance_description") && data.instance_description.hasOwnProperty("control_unit_implementation")) { var impl = data.instance_description.control_unit_implementation; var regex = /\w+$/; impl = regex.exec(impl); var promise = import('./interface/' + impl + ".js"); promise.then(obj => { console.log("Adding interface " + impl); resolve(new obj.default(uid)); }).catch(bad => { console.log("Adding base interface, because:" + JSON.stringify(bad)); resolve(new ChaosNode(uid)); }); } else { resolve(new ChaosNode(uid)); } }, (bad) => { reject(bad); }) }); const obj = await prom; return obj; } /** * Set Library options options * @param {object} opt * @function setOption */ jchaos.setOptions = function (opt) { for (var attrname in opt) { jchaos.options[attrname] = opt[attrname]; } } jchaos.filterAlarmObject = function (dev_alarm, includeall) { var obj = {} var all = true; if (includeall !== undefined) { all = includeall; } for (var key in dev_alarm) { var value = dev_alarm[key]; if (!jchaos.isReservedKey(key)) { if ((typeof value === "string") || (typeof value === "number" && ((value > 0) || all))) { obj[key] = value; } } } return obj; } /** * Prints a String on the configured console * @param {string} str */ jchaos.print = function (str) { jchaos.options['console_log'](str); } /** * Prints a String on the configured console error * @param {string} str */ jchaos.perror = function (str) { jchaos.options['console_err'](str); } jchaos.exit = function (str) { alert(str) } /******* REMOTE PROCESS MANAGEMENT ****/ /** * Helper function to post commands on the process remote management * @param {string} server rest process remote management server * @param {string} func REST function * @param {object} param REST function parameters * @param {okcb} handler handler on success * @param {badcb} badhandler handler on failure * @function basicRmt */ jchaos.basicRmt = function (server, func, param, handler, badhandler) { if (typeof param === "object") { param['server'] = server; } else { param = {}; param['server'] = server; } param["api"] = "api/v1/restconsole/" + func; //return jchaos.basicPost("/api/v1/restconsole/" + func, JSON.stringify(param), handler,badhandler,server); return jchaos.basicPost("proxy", param, handler, badhandler); } /** * Retrive a given environemnt variable * @param {string} server rest p * rocess remote management server * @param {string} varname environment variable name * @param {okcb} handler handler on success * @param {badcb} badhandler handler on failure * @returns the value on the specified handler. * @function rmtGetEnvironment */ jchaos.rmtGetEnvironment = function (server, varname, handler, badhandler) { var param = {}; param['variable'] = varname; return jchaos.basicRmt(server, "getenv", param, handler, badhandler); } /** * Set the specified propery * @param {string} server rest process remote management server * @param { {uid:String, propname:String} } prop property name * @param {okcb} handler handler on success * @param {badcb} badhandler handler on failure * @returns the value on the specified handler. * @function rmtSetProp */ jchaos.rmtSetProp = function (server, prop, handler, badhandler) { return jchaos.basicRmt(server, "setprop", prop, handler, badhandler); } /** * */ /** * Launch a process the specified process on the given remote server * return a process structure * @param {string} server rest process remote management server * @param {string} name program name * @param {string} cmdline command line * @param {string} ptype type ("exec": binary, "C++": C++ script") * @param {string} workdir remote local directory * @param {okcb} handler handler on success * @param {badcb} badhandler handler on failure * @returns {object} return a process object with many status and information * @function rmtCreateProcess */ jchaos.rmtCreateProcess = function (server, name, cmdline, ptype, workdir, handler, badhandler) { var param = {}; param['cmdline'] = cmdline; param['ptype'] = ptype; param['pname'] = name; if (workdir != null && workdir != "") { param['workdir'] = workdir; } console.log("create process:" + JSON.stringify(param)); return jchaos.basicRmt(server, "create", param, handler, badhandler); } /** * Retrive a process working directory * return a zip file */ /** * Return a zip file contaning the working directory of the specified process * can be used to retrieve outputs of remote runs * @param {string} server rest process remote management server * @param {string} uid the process uid returned by the rmtCreateProcess * @param {string} workdir working dir to retrieve and zip * @param {okcb} handler handler on success * @param {badcb} badhandler handler on failure * @function rmtCreateProcess */ jchaos.rmtDownload = function (server, uid, workdir, handler, badhandler) { var param = {}; param['uid'] = uid; if (workdir != null && workdir != "") { param['workdir'] = workdir; } console.log("Download process outputs:" + JSON.stringify(param)); return jchaos.basicRmt(server, "download", param, handler, badhandler); } /** */ /** * Upload a script/executable on the remote server * return the path * @param {string} server rest process remote management server * @param {string} name program name * @param {string} ptype type ("exec": binary, "C++": C++ script") * @param {string} content base64 encoded content to upload * @returns {object} return the path of the remote process * @param {okcb} handler handler on success * @param {badcb} badhandler handler on failure * @function rmtUploadScript */ jchaos.rmtUploadScript = function (server, name, ptype, content, handler, badhandler) { if ((name instanceof Object) && (ptype instanceof Function) && (content instanceof Function)) { return jchaos.basicRmt(server, "load", name, ptype, content); } var param = {}; param['script_name'] = name; param['eudk_script_language'] = ptype; param['eudk_script_content'] = btoa(unescape(encodeURIComponent(content))); return jchaos.basicRmt(server, "load", param, handler, badhandler); } /** * Return a list of process on the given server * @param {string} server rest process remote management server * @param {okcb} handler handler on success * @param {badcb} badhandler handler on failure * @returns {object[]} return a list of process descriptors * @function rmtListProcess */ jchaos.rmtListProcess = function (server, handler, badhandler) { var param = {}; console.log("List process on: " + server); return jchaos.basicRmt(server, "list", param, handler, badhandler); } /** * Write on the remote console of the specified process * @param {string} server rest process remote management server * @param {string} uid the process uid returned by the rmtCreateProcess * @param {string} str line to send * @param {okcb} handler handler on success * @param {badcb} badhandler handler on failure * @dfunction rmtSetConsole */ jchaos.rmtSetConsole = function (server, uid, str, handler, badhandler) { var param = {}; param['uid'] = uid; param['data'] = btoa(unescape(encodeURIComponent(str + "\n"))); return jchaos.basicRmt(server, "setconsole", param, handler, badhandler); } /** * Reads the console of the specified process uid * @param {string} server rest process remote management server * @param {string} uid the process uid returned by the rmtCreateProcess * @param {integer} fromline get from this line * @param {integer} toline until this line (-1 means end) * @param {okcb} handler handler on success * @param {badcb} badhandler handler on failure * @dfunction rmtGetConsole */ jchaos.rmtGetConsole = function (server, uid, fromline, toline, handler, badhandler) { var param = {}; param['uid'] = uid; param['fromline'] = fromline; param['toline'] = toline; return jchaos.basicRmt(server, "getconsole", param, handler, badhandler); } /** * Kill the specified process * @param {string} server rest process remote management server * @param {string} uid the process uid returned by the rmtCreateProcess * @param {okcb} handler handler on success * @param {badcb} badhandler handler on failure * @function rmtKill */ jchaos.rmtKill = function (server, uid, handler, badhandler) { var param = {}; param['uid'] = uid; return jchaos.basicRmt(server, "kill", param, handler, badhandler); } /** * Purge a list of process to a given level (0 soft (EXCEPTION), 1 medium (ENDED and EXCEPTION), 2 hard (ALL) * @param {string} server rest process remote management server * @param {integer} level purge level * @param {okcb} [handler] handler on success * @param {badcb} [badhandler] handler on failure * @function rmtPurge */ jchaos.rmtPurge = function (server, level, handler, badhandler) { var param = {}; param['level'] = level; return jchaos.basicRmt(server, "purge", param, handler, badhandler); } /******************************/ /****** WIDGET */ /** * @hide */ jchaos.progressBar = function (msg, id, lab) { var progressbar; var instant = $('<div></div>').html('<div id="' + id + '"><div class="progress-label">' + lab + '</div></div>').dialog({ title: msg, position: "top", open: function () { progressbar = $("#" + id) var progressLabel = $(".progress-label"); progressbar.progressbar({ value: false, change: function () { var val = progressbar.progressbar("value"); progressLabel.text(val + "%"); }, complete: function () { $(this).parent().dialog("close"); } }); }, close: function () { $(this).remove(); } }); } /***** */ /** * Helper function that is the base of all commands to the !CHAOS REST SERVER * the server is specified in the option * @param {string} func REST function to perform * @param {string} params parameters * @param {okcb} [handler] handler on success, if present the call will be asynchronous * @param {badcb} [badhandler] handler on failure * @param {string} [server] override the default server * @function basicPost */ jchaos.basicPost = function (func, oparam, handleFunc, handleFuncErr, server, logop) { var request; var now = (new Date()).getTime(); var params = oparam; request = new XMLHttpRequest(); var srv = jchaos.options.uri; XMLHttpRequest.responseType = "json"; if (typeof server === "string") { srv = server; } var url = srv + "/" + func; var could_make_async = (typeof handleFunc === "function"); jchaos['nops']++; request['jchaos_ts'] = now; request['jchaos_uid'] = jchaos['nops']; request['jchaos_url'] = url; if (typeof oparam === "object") { if (oparam.hasOwnProperty("devs") && (oparam.devs instanceof Array)) { if (oparam.devs.length == 0) { return; } } request['jchaos_param'] = oparam; } else { alert("NO JSON POST") request['jchaos_param'] = params; } if (could_make_async == false) { request.open("POST", url, false); request.send(JSON.stringify(params)); if (request.status == 200) { try { var json = JSON.parse(request.responseText); jchaos.logops(request, logop); return json; } catch (err) { var str = "jchaos.basicPost Error parsing json '" + err + "' body returned:'" + request.responseText + "' post:'" + params + "'"; jchaos.perror(str); request['jchaos_error'] = str; jchaos.logops(request, logop); return null; } } jchaos.perror("bad status:" + request.status + " error:" + request.responseText); return null; } request.open("POST", url, (jchaos.ops_on_going > jchaos.options.limit_on_going) ? false : (jchaos.options.async)); request.timeout = jchaos.options.timeout; jchaos.ops_on_going++; request.onreadystatechange = function (e) { request['jchaos_answer_ts'] = (new Date()).getTime(); if (request.readyState == 4) { jchaos.ops_on_going--; if (request.status == 200) { var json; try { json = JSON.parse(request.responseText); jchaos.logops(request, logop); } catch (err) { var str = "jchaos.basicPost Error parsing json '" + err + "' body returned:'" + request.responseText + "'" + "' post:'" + params + "'";; request['jchaos_error'] = str; jchaos.logops(request, logop); if ((typeof handleFuncErr === "function")) { return handleFuncErr(str, request); } else { jchaos.perror(str); return str; } } if (could_make_async) { var lat = (new Date()).getTime() - now; jchaos['latency'] = lat; jchaos['latency_tot'] += lat; jchaos['numok'] = jchaos['numok'] + 1; if(jchaos['numok']%10==0){ jchaos['latency_avg'] = jchaos['latency_tot'] / 10; jchaos['latency_tot']=0; } handleFunc(json, request); jchaos.options.on_restOk(request); } return json; } else { var json; var str; jchaos['errors']++; try { json = JSON.parse(request.responseText); str = "Error '" + request.status + "' API '" + params + "' returned:'" + request.responseText + "'"; } catch (pr) { json = request.responseText; str = "jchaos.basicPost Error parsing json body returned:'" + request.responseText + "'" + "' post:'" + params + "'";; } var str = "POST " + url + " body:\"" + params + "\" went wrong, result:" + request.status + " state:" + request.readyState; // jchaos.perror(str); request['jchaos_error'] = str; jchaos.logops(request, logop); if ((typeof handleFuncErr === "function")) { handleFuncErr(json, request); } else { if ((typeof json === "object")) { if (json.hasOwnProperty('error_status')) { jchaos.perror("Error:" + json.error_status); } } } } } } request.onerror = function (e) { jchaos.perror("request error:" + request.statusText); //throw