diff --git a/src/collectd/volume.ejs b/src/collectd/volume.ejs new file mode 100644 index 000000000..4d7d8274a --- /dev/null +++ b/src/collectd/volume.ejs @@ -0,0 +1,9 @@ + + + + Instance "<%= volumeId %>" + Dir "<%= hostPath %>" + + + + diff --git a/src/system.js b/src/system.js index 00f04758c..08e1cbf90 100644 --- a/src/system.js +++ b/src/system.js @@ -1,9 +1,9 @@ 'use strict'; exports = module.exports = { - getDisks: getDisks, - checkDiskSpace: checkDiskSpace, - getMemory: getMemory + getDisks, + checkDiskSpace, + getMemory }; const apps = require('./apps.js'), @@ -17,13 +17,74 @@ const apps = require('./apps.js'), os = require('os'), paths = require('./paths.js'), safe = require('safetydance'), - settings = require('./settings.js'); + settings = require('./settings.js'), + volumes = require('./volumes.js'); + +const dfAsync = async.asyncify(df), dfFileAsync = async.asyncify(df.file); + +function getVolumeDisks(callback) { + assert.strictEqual(typeof callback, 'function'); + + let volumeDisks = {}; + + volumes.list(function (error, allVolumes) { + if (error) return callback(error); + + async.eachSeries(allVolumes, function (volume, iteratorDone) { + dfFileAsync(volume.hostPath, function (error, result) { + volumeDisks[volume.id] = error ? volumeDisks.appsDataDisk : result.filesystem; // ignore any errors + + iteratorDone(); + }); + }, function (error) { + callback(error, volumeDisks); + }); + }); +} + +function getAppDisks(callback) { + assert.strictEqual(typeof callback, 'function'); + + let appDisks = {}; + + apps.getAll(function (error, allApps) { + if (error) return callback(error); + + async.eachSeries(allApps, function (app, iteratorDone) { + if (!app.dataDir) { + appDisks[app.id] = appDisks.appsDataDisk; + return iteratorDone(); + } + + dfFileAsync(app.dataDir, function (error, result) { + appDisks[app.id] = error ? appDisks.appsDataDisk : result.filesystem; // ignore any errors + iteratorDone(); + }); + }, function (error) { + callback(error, appDisks); + }); + }); +} + +function getBackupDisk(callback) { + assert.strictEqual(typeof callback, 'function'); + + settings.getBackupConfig(function (error, backupConfig) { + if (error) return callback(error); + + if (backupConfig.provider !== 'filesystem') return callback(null, null); + + dfFileAsync(backupConfig.backupFolder, function (error, result) { + if (error) return callback(error); + + callback(null, result.filesystem); + }); + }); +} function getDisks(callback) { assert.strictEqual(typeof callback, 'function'); - const dfAsync = async.asyncify(df), dfFileAsync = async.asyncify(df.file); - docker.info(function (error, info) { if (error) return callback(error); @@ -32,7 +93,10 @@ function getDisks(callback) { dfFileAsync.bind(null, paths.BOX_DATA_DIR), dfFileAsync.bind(null, paths.PLATFORM_DATA_DIR), dfFileAsync.bind(null, paths.APPS_DATA_DIR), - dfFileAsync.bind(null, info.DockerRootDir) + dfFileAsync.bind(null, info.DockerRootDir), + getBackupDisk, + getAppDisks, + getVolumeDisks, ], function (error, values) { if (error) return callback(new BoxError(BoxError.FS_ERROR, error)); @@ -46,40 +110,12 @@ function getDisks(callback) { platformDataDisk: values[2].filesystem, appsDataDisk: values[3].filesystem, dockerDataDisk: values[4].filesystem, - backupsDisk: null, - apps: {} + backupsDisk: values[5], + apps: values[6], + volumes: values[7] }; - apps.getAll(function (error, allApps) { - if (error) return callback(error); - - async.eachSeries(allApps, function (app, iteratorDone) { - if (!app.dataDir) { - disks.apps[app.id] = disks.appsDataDisk; - return iteratorDone(); - } - - dfFileAsync(app.dataDir, function (error, result) { - disks.apps[app.id] = error ? disks.appsDataDisk : result.filesystem; // ignore any errors - iteratorDone(); - }); - }, function (error) { - if (error) return callback(error); - - settings.getBackupConfig(function (error, backupConfig) { - if (error) return callback(error); - - if (backupConfig.provider !== 'filesystem') return callback(null, disks); - - dfFileAsync(backupConfig.backupFolder, function (error, result) { - if (error) return callback(error); - - disks.backupsDisk = result.filesystem; - callback(null, disks); - }); - }); - }); - }); + callback(null, disks); }); }); } diff --git a/src/volumes.js b/src/volumes.js index 995462077..cb20e6808 100644 --- a/src/volumes.js +++ b/src/volumes.js @@ -9,14 +9,20 @@ exports = module.exports = { const assert = require('assert'), BoxError = require('./boxerror.js'), + collectd = require('./collectd.js'), debug = require('debug')('box:volumes'), + ejs = require('ejs'), eventlog = require('./eventlog.js'), + fs = require('fs'), path = require('path'), safe = require('safetydance'), sftp = require('./sftp.js'), uuid = require('uuid'), volumedb = require('./volumedb.js'); +const COLLECTD_CONFIG_EJS = fs.readFileSync(__dirname + '/collectd/volume.ejs', { encoding: 'utf8' }); +const NOOP_CALLBACK = function (error) { if (error) debug(error); }; + function validateName(name) { assert.strictEqual(typeof name, 'string'); @@ -63,7 +69,10 @@ function add(name, hostPath, auditSource, callback) { if (error) return callback(error); eventlog.add(eventlog.ACTION_VOLUME_ADD, auditSource, { id, name, hostPath }); - sftp.rebuild((error) => { if (error) debug('Unable to rebuild sftp:', error); }); + sftp.rebuild(NOOP_CALLBACK); + + const collectdConf = ejs.render(COLLECTD_CONFIG_EJS, { volumeId: id, hostPath }); + collectd.addProfile(id, collectdConf, NOOP_CALLBACK); callback(null, id); }); @@ -99,7 +108,8 @@ function del(volume, auditSource, callback) { if (error) return callback(error); eventlog.add(eventlog.ACTION_VOLUME_REMOVE, auditSource, { volume }); - sftp.rebuild((error) => { if (error) debug('Unable to rebuild sftp:', error); }); + sftp.rebuild(NOOP_CALLBACK); + collectd.removeProfile(volume.id, NOOP_CALLBACK); return callback(null); });