diff --git a/src/backups.js b/src/backups.js index 7427c9053..50b65265e 100644 --- a/src/backups.js +++ b/src/backups.js @@ -884,15 +884,12 @@ function backupApp(app, progressCallback, callback) { } // this function expects you to have a lock. Unlike other progressCallback this also has a progress field -function backupBoxAndApps(auditSource, progressCallback, callback) { - assert.strictEqual(typeof auditSource, 'object'); +function backupBoxAndApps(progressCallback, callback) { assert.strictEqual(typeof progressCallback, 'function'); assert.strictEqual(typeof callback, 'function'); var timestamp = (new Date()).toISOString().replace(/[T.]/g, '-').replace(/[:Z]/g,''); - eventlog.add(eventlog.ACTION_BACKUP_START, auditSource, { }); - apps.getAll(function (error, allApps) { if (error) return callback(new BackupsError(BackupsError.INTERNAL_ERROR, error)); @@ -926,11 +923,7 @@ function backupBoxAndApps(auditSource, progressCallback, callback) { progressCallback({ percent: percent, message: 'Backing up system data' }); percent += step; - backupBoxWithAppBackupIds(backupIds, timestamp, (progress) => progressCallback({ percent: percent, message: progress.message }), function (error, backupId) { - eventlog.add(eventlog.ACTION_BACKUP_FINISH, auditSource, { errorMessage: error ? error.message : null, backupId: backupId, timestamp: timestamp }); - - callback(error, backupId); - }); + backupBoxWithAppBackupIds(backupIds, timestamp, (progress) => progressCallback({ percent: percent, message: progress.message }), callback); }); }); } @@ -942,7 +935,7 @@ function startBackupTask(auditSource, callback) { let error = locker.lock(locker.OP_FULL_BACKUP); if (error) return callback(new BackupsError(BackupsError.BAD_STATE, error.message)); - tasks.setProgress(tasks.TASK_BACKUP, { percent: 0, message: 'Starting' }, NOOP_CALLBACK); + tasks.clearProgress(tasks.TASK_BACKUP, NOOP_CALLBACK); let fd = safe.fs.openSync(paths.BACKUP_LOG_FILE, 'a'); // will autoclose if (!fd) { @@ -954,31 +947,26 @@ function startBackupTask(auditSource, callback) { debug(`starting backuptask. logs at ${paths.BACKUP_LOG_FILE}`); // when parent process dies, this process is killed because KillMode=control-group in systemd unit file - assert.strictEqual(gBackupTask, null); - let result = ''; - gBackupTask = child_process.fork(__dirname + '/tasks/backuptask.js', [ JSON.stringify(auditSource) ], { stdio: [ 'pipe', fd, fd, 'ipc' ]}); + assert(!gBackupTask, 'Previous backup task already running!'); + eventlog.add(eventlog.ACTION_BACKUP_START, auditSource, { }); + + gBackupTask = child_process.fork(__dirname + '/tasks/backuptask.js', [ ], { stdio: [ 'pipe', fd, fd, 'ipc' ]}); gBackupTask.once('exit', function (code, signal) { debug(`startBackupTask: completed with code ${code} and signal ${signal}`); - let error; - if (code === null /* signal */ || (code !== 0 && code !== 50)) { // apptask crashed - error = new Error(`backuptask completed with code ${code} and signal ${signal}`); - } else if (code === 50) { - error = new Error(result); - } + tasks.getProgress(tasks.TASK_BACKUP, function (error, progress) { + if (!error && progress.errorMessage) error = new Error(progress.errorMessage); - gBackupTask = null; + eventlog.add(eventlog.ACTION_BACKUP_FINISH, auditSource, { errorMessage: error ? error.message : null, backupId: progress ? progress.result : null }); - tasks.setProgress(tasks.TASK_BACKUP, { percent: 100, errorMessage: error ? error.message : '' }, NOOP_CALLBACK); + locker.unlock(locker.OP_FULL_BACKUP); - locker.unlock(locker.OP_FULL_BACKUP); + if (error) mailer.backupFailed(error); - if (error) mailer.backupFailed(error); + gBackupTask = null; - debug('startBackupTask: backup done'); - }); - gBackupTask.on('message', function (message) { - result = message.result; + debug('startBackupTask: backup done'); + }); }); callback(null); } diff --git a/src/caas.js b/src/caas.js index 70b7bed55..a2ecb8067 100644 --- a/src/caas.js +++ b/src/caas.js @@ -133,7 +133,7 @@ function doMigrate(options, caasConfig, callback) { tasks.setProgress(tasks.TASK_MIGRATE, { percent: 10, message: 'Backing up for migration' }, NOOP_CALLBACK); // initiate the migration in the background - backups.backupBoxAndApps({ userId: null, username: 'migrator' }, (progress) => tasks.setProgress(tasks.TASK_MIGRATE, { percent: 10+progress.percent*30/100, message: progress.message }, NOOP_CALLBACK), function (error) { + backups.backupBoxAndApps((progress) => tasks.setProgress(tasks.TASK_MIGRATE, { percent: 10+progress.percent*30/100, message: progress.message }, NOOP_CALLBACK), function (error) { if (error) return unlock(error); debug('migrate: domain: %s size %s region %s', options.domain, options.size, options.region); diff --git a/src/tasks.js b/src/tasks.js index 7bd294697..2b0f4b065 100644 --- a/src/tasks.js +++ b/src/tasks.js @@ -3,6 +3,7 @@ exports = module.exports = { setProgress: setProgress, getProgress: getProgress, + clearProgress: clearProgress, stopTask: stopTask, @@ -70,6 +71,13 @@ function getProgress(id, callback) { }); } +function clearProgress(id, callback) { + assert.strictEqual(typeof id, 'string'); + assert.strictEqual(typeof callback, 'function'); + + setProgress(id, { percent: 0, message: 'Starting', result: '', errorMessage: '' }, callback); +} + function stopTask(id, auditSource, callback) { assert.strictEqual(typeof id, 'string'); assert.strictEqual(typeof auditSource, 'object'); diff --git a/src/tasks/backuptask.js b/src/tasks/backuptask.js index 67afdea8f..a0f05de8e 100755 --- a/src/tasks/backuptask.js +++ b/src/tasks/backuptask.js @@ -13,32 +13,20 @@ var assert = require('assert'), debug = require('debug')('box:backuptask'), tasks = require('../tasks.js'); -function initialize(callback) { - assert.strictEqual(typeof callback, 'function'); - - database.initialize(callback); -} - -// Main process starts here const NOOP_CALLBACK = function (error) { if (error) debug(error); }; -const auditSource = JSON.parse(process.argv[2]); - -debug('Staring complete backup'); process.on('SIGTERM', function () { process.exit(0); }); -initialize(function (error) { - if (error) throw error; +// Main process starts here +debug('Staring backup'); +database.initialize(function (error) { + if (error) return process.exit(50); - backups.backupBoxAndApps(auditSource, (progress) => tasks.setProgress(tasks.TASK_BACKUP, progress, NOOP_CALLBACK), function (error) { - if (error) debug('backup failed.', error); + backups.backupBoxAndApps((progress) => tasks.setProgress(tasks.TASK_BACKUP, progress, NOOP_CALLBACK), function (error, backupId) { + const progress = { percent: 100, result: backupId || '', errorMessage: error ? error.message : '' }; - process.send({ result: error ? error.message : '' }); - - // https://nodejs.org/api/process.html are exit codes used by node. apps.js uses the value below - // to check apptask crashes - process.exit(error ? 50 : 0); + tasks.setProgress(tasks.TASK_BACKUP, progress, () => process.exit(error ? 50 : 0)); }); }); diff --git a/src/test/backups-test.js b/src/test/backups-test.js index f05d1f5d7..47d0cd469 100644 --- a/src/test/backups-test.js +++ b/src/test/backups-test.js @@ -32,7 +32,8 @@ function createBackup(callback) { if (p.percent !== 100) return setTimeout(waitForBackup, 1000); - if (p.result) return callback(new Error('backup failed:' + p.result)); + if (p.errorMessage) return callback(new Error('backup failed:' + p)); + if (!p.result) return callback(new Error('backup has no result:' + p)); backups.getByStatePaged(backupdb.BACKUP_STATE_NORMAL, 1, 1, function (error, result) { if (error) return callback(error); diff --git a/src/updater.js b/src/updater.js index 6a34b5015..cc00d7a0f 100644 --- a/src/updater.js +++ b/src/updater.js @@ -167,7 +167,7 @@ function doUpdate(boxUpdateInfo, callback) { tasks.setProgress(tasks.TASK_UPDATE, { percent: 10, message: 'Backing up' }, NOOP_CALLBACK); - backups.backupBoxAndApps({ userId: null, username: 'updater' }, (progress) => tasks.setProgress(tasks.TASK_MIGRATE, { percent: 10+progress.percent*70/100, message: progress.message }, NOOP_CALLBACK), function (error) { + backups.backupBoxAndApps((progress) => tasks.setProgress(tasks.TASK_MIGRATE, { percent: 10+progress.percent*70/100, message: progress.message }, NOOP_CALLBACK), function (error) { if (error) return updateError(error); debug('updating box %s', boxUpdateInfo.sourceTarballUrl);