diff --git a/lib/agent/actions.js b/lib/agent/actions.js index a40b5f611..cef30ec1e 100644 --- a/lib/agent/actions.js +++ b/lib/agent/actions.js @@ -45,9 +45,12 @@ var start = function(type, name, opts, cb){ } logger.info('Starting ' + type + ': '+ name); - loader.load(type, name, function(err, action){ + loader.load(type, name, function(err, action) { if (err) return hooks.trigger('error', err); + action.type = type; + action.options = typeof opts == 'function' ? {} : opts; + action.start(opts, function(err, emitter) { cb && cb(err); @@ -89,4 +92,15 @@ actions.stop_all = function() { this.stop(name); } +actions.running = function() { + var list = []; + for (var key in running) { + if (running[key].type == 'action') { + var obj = { name: key, options: running[key].options || {} } + list.push(obj); + } + } + return list; +} + module.exports = actions; diff --git a/lib/agent/index.js b/lib/agent/index.js index 2809d8b35..236ef3675 100644 --- a/lib/agent/index.js +++ b/lib/agent/index.js @@ -11,6 +11,7 @@ var common = require('./common'), reports = require('./reports'), triggers = require('./triggers'), connection = require('./connection'), + storage = require('./storage'), exceptions = require('./exceptions'); var config = common.config, @@ -96,6 +97,8 @@ var boot = function() { if (err) handle_error(err); connection.watch(); + run_stored_commands(); + logger.info('Initialized.'); }); }); @@ -238,11 +241,56 @@ var wait_for_config = function() { }, 10000); } +//////////////////////////////////////////////////////////////////// +// command persistence +//////////////////////////////////////////////////////////////////// + +run_stored_commands = function(cb) { + storage.all(function(err, commands) { + if (err) return; + + for (var key in commands) + perform_command(commands[key]); + }) + storage.clear(); +} + +store_running_commands = function(cb) { + var running_actions = actions.running(), + running_reports = reports.running(), + count = running_actions.length + running_reports.length; + + if (count == 0) + return cb && cb() + + logger.info(count + ' active actions/reports.') + + var done = function() { + --count || (cb && cb()) + } + + var store = function(type, name, opts) { + var key = [type, name].join('-'); + storage.set(key, { command: type, name: name, options: opts }, done) + } + + running_actions.forEach(function(action) { + store('action', action.name, action.options) + }) + + running_reports.forEach(function(report) { + store('report', report.name, report.options) + }) +} + //////////////////////////////////////////////////////////////////// // shutdown //////////////////////////////////////////////////////////////////// var shutdown = function() { + logger.debug('Saving running commands...') + store_running_commands(); + logger.debug('Unloading drivers.'); unload_drivers(); diff --git a/lib/agent/reports.js b/lib/agent/reports.js index 9eeb77c0c..253f45b2d 100644 --- a/lib/agent/reports.js +++ b/lib/agent/reports.js @@ -96,11 +96,12 @@ var get = function(report_name, options, callback) { gather(report_name, list, cb); // get one immediately if (options.interval) - queue(report_name, list, options.interval); + queue(report_name, list, options || {}); }); }; -var queue = function(report_name, list, interval) { +var queue = function(report_name, list, opts) { + var interval = opts.interval; if (!interval) return; // interval reporting triggered, so force auto connect to true @@ -108,11 +109,12 @@ var queue = function(report_name, list, interval) { // in case the delay is sent in minutes if (interval < 1000) interval = interval * 60 * 1000; - - active[report_name] = setInterval(function(){ + + var timer = setInterval(function(){ gather(report_name, list); }, interval); + active[report_name] = { timer: timer, options: opts }; }; var gather = function(report_name, list, cb) { @@ -155,7 +157,8 @@ var cancel = function(report_name){ logger.warn('Cancelling ' + report_name + ' report.'); config.set('auto_connect', prev_auto_connect); // restore original value - clearInterval(active[report_name]); + var timer = active[report_name].timer; + clearInterval(timer); // this.removeAllListeners(report_name); delete(active[report_name]); }; @@ -165,7 +168,17 @@ var cancel_all = function(){ cancel(report_name); }; +var running = function() { + var list = []; + for (var key in active) { + var obj = { name: key, options: active[key].options }; + list.push(obj); + } + return list; +} + exports.map = map; exports.get = get; +exports.running = running; exports.cancel = cancel; exports.cancel_all = cancel_all; diff --git a/lib/agent/storage.js b/lib/agent/storage.js new file mode 100644 index 000000000..8977efd6a --- /dev/null +++ b/lib/agent/storage.js @@ -0,0 +1,61 @@ +var fs = require('fs'), + common = require('./common'), + db_path = common.system.tempfile_path('local.db'); + +var db; + +var load = function(cb) { + if (db) return cb(); + + fs.readFile(db_path, 'utf8', function(err, data) { + if (err || data.trim() == '') return cb(err); + + try { + db = JSON.parse(data); + } catch(e) { + db = {}; + err = e; + } + cb(err); + }) +} + +var save = function(cb) { + var err, str = JSON.stringify(db, null, 0); + try { + fs.writeFileSync(db_path, str); + } catch(e) { + err = e; + } + cb(err); +} + +exports.set = function(key, data, cb) { + load(function(err) { + if (err) return cb(err); + db[key] = data; + save(cb); + }) +} + +exports.get = function(key, cb) { + load(function(err) { + if (err) return cb(err); + + cb(null, db[key]); + }) +} + +exports.all = function(cb) { + load(function(err) { + if (err) return cb(err); + + cb(null, db); + }) +} + +exports.clear = function(cb) { + db = {}; + // fs.writeFile(db_path, '', cb); + fs.unlink(db_path); +} \ No newline at end of file