backups: add backup multiple targets
This commit is contained in:
@@ -9,7 +9,6 @@ exports = module.exports = {
|
||||
downloadApp,
|
||||
backupApp,
|
||||
|
||||
backupMail,
|
||||
downloadMail,
|
||||
|
||||
upload,
|
||||
@@ -36,17 +35,17 @@ const apps = require('./apps.js'),
|
||||
|
||||
const BACKUP_UPLOAD_CMD = path.join(__dirname, 'scripts/backupupload.js');
|
||||
|
||||
async function checkPreconditions(backupConfig, dataLayout) {
|
||||
assert.strictEqual(typeof backupConfig, 'object');
|
||||
async function checkPreconditions(backupTarget, dataLayout) {
|
||||
assert.strictEqual(typeof backupTarget, 'object');
|
||||
assert(dataLayout instanceof DataLayout, 'dataLayout must be a DataLayout');
|
||||
|
||||
// check mount status before uploading
|
||||
const status = await backupTargets.ensureMounted();
|
||||
const status = await backupTargets.ensureMounted(backupTarget);
|
||||
debug(`checkPreconditions: mount point status is ${JSON.stringify(status)}`);
|
||||
if (status.state !== 'active') throw new BoxError(BoxError.MOUNT_ERROR, `Backup endpoint is not active: ${status.message}`);
|
||||
|
||||
// check availabe size. this requires root for df to work
|
||||
const available = await storage.api(backupConfig.provider).getAvailableSize(backupConfig);
|
||||
const available = await storage.api(backupTarget.provider).getAvailableSize(backupTarget.config);
|
||||
let used = 0;
|
||||
for (const localPath of dataLayout.localPaths()) {
|
||||
debug(`checkPreconditions: getting disk usage of ${localPath}`);
|
||||
@@ -64,20 +63,22 @@ async function checkPreconditions(backupConfig, dataLayout) {
|
||||
}
|
||||
|
||||
// this function is called via backupupload (since it needs root to traverse app's directory)
|
||||
async function upload(remotePath, format, dataLayoutString, progressCallback) {
|
||||
async function upload(remotePath, targetId, dataLayoutString, progressCallback) {
|
||||
assert.strictEqual(typeof remotePath, 'string');
|
||||
assert.strictEqual(typeof format, 'string');
|
||||
assert.strictEqual(typeof targetId, 'string');
|
||||
assert.strictEqual(typeof dataLayoutString, 'string');
|
||||
assert.strictEqual(typeof progressCallback, 'function');
|
||||
|
||||
debug(`upload: path ${remotePath} format ${format} dataLayout ${dataLayoutString}`);
|
||||
debug(`upload: path ${remotePath} target ${targetId} dataLayout ${dataLayoutString}`);
|
||||
|
||||
const backupTarget = await backupTargets.get(targetId);
|
||||
if (!backupTarget) throw new BoxError(BoxError.NOT_FOUND, 'Backup target not found');
|
||||
|
||||
const dataLayout = DataLayout.fromString(dataLayoutString);
|
||||
const backupConfig = await backupTargets.getConfig();
|
||||
|
||||
await checkPreconditions(backupConfig, dataLayout);
|
||||
await checkPreconditions(backupTarget, dataLayout);
|
||||
|
||||
await backupFormat.api(format).upload(backupConfig, remotePath, dataLayout, progressCallback);
|
||||
await backupFormat.api(backupTarget.format).upload(backupTarget, remotePath, dataLayout, progressCallback);
|
||||
}
|
||||
|
||||
async function download(backupConfig, remotePath, format, dataLayout, progressCallback) {
|
||||
@@ -131,16 +132,16 @@ async function runBackupUpload(uploadConfig, progressCallback) {
|
||||
assert.strictEqual(typeof uploadConfig, 'object');
|
||||
assert.strictEqual(typeof progressCallback, 'function');
|
||||
|
||||
const { remotePath, backupConfig, dataLayout, progressTag } = uploadConfig;
|
||||
const { remotePath, backupTarget, dataLayout, progressTag } = uploadConfig;
|
||||
assert.strictEqual(typeof remotePath, 'string');
|
||||
assert.strictEqual(typeof backupConfig, 'object');
|
||||
assert.strictEqual(typeof backupTarget, 'object');
|
||||
assert.strictEqual(typeof progressTag, 'string');
|
||||
assert(dataLayout instanceof DataLayout, 'dataLayout must be a DataLayout');
|
||||
|
||||
// https://stackoverflow.com/questions/48387040/node-js-recommended-max-old-space-size
|
||||
const envCopy = Object.assign({}, process.env);
|
||||
if (backupConfig.limits?.memoryLimit >= 2*1024*1024*1024) {
|
||||
const heapSize = Math.min((backupConfig.limits.memoryLimit/1024/1024) - 256, 8192);
|
||||
if (backupTarget.limits?.memoryLimit >= 2*1024*1024*1024) {
|
||||
const heapSize = Math.min((backupTarget.limits.memoryLimit/1024/1024) - 256, 8192);
|
||||
debug(`runBackupUpload: adjusting heap size to ${heapSize}M`);
|
||||
envCopy.NODE_OPTIONS = `--max-old-space-size=${heapSize}`;
|
||||
}
|
||||
@@ -153,7 +154,7 @@ async function runBackupUpload(uploadConfig, progressCallback) {
|
||||
}
|
||||
|
||||
// do not use debug for logging child output because it already has timestamps via it's own debug
|
||||
const [error] = await safe(shell.sudo([ BACKUP_UPLOAD_CMD, remotePath, backupConfig.format, dataLayout.toString() ], { env: envCopy, preserveEnv: true, onMessage, logger: process.stdout.write }));
|
||||
const [error] = await safe(shell.sudo([ BACKUP_UPLOAD_CMD, remotePath, backupTarget.id, dataLayout.toString() ], { env: envCopy, preserveEnv: true, onMessage, logger: process.stdout.write }));
|
||||
if (error && (error.code === null /* signal */ || (error.code !== 0 && error.code !== 50))) { // backuptask crashed
|
||||
debug(`runBackupUpload: backuptask crashed`, error);
|
||||
throw new BoxError(BoxError.INTERNAL_ERROR, 'Backuptask crashed');
|
||||
@@ -173,8 +174,8 @@ async function snapshotBox(progressCallback) {
|
||||
debug(`snapshotBox: took ${(new Date() - startTime)/1000} seconds`);
|
||||
}
|
||||
|
||||
async function uploadBoxSnapshot(backupConfig, progressCallback) {
|
||||
assert.strictEqual(typeof backupConfig, 'object');
|
||||
async function uploadBoxSnapshot(backupTarget, progressCallback) {
|
||||
assert.strictEqual(typeof backupTarget, 'object');
|
||||
assert.strictEqual(typeof progressCallback, 'function');
|
||||
|
||||
await snapshotBox(progressCallback);
|
||||
@@ -184,7 +185,7 @@ async function uploadBoxSnapshot(backupConfig, progressCallback) {
|
||||
|
||||
const uploadConfig = {
|
||||
remotePath: 'snapshot/box',
|
||||
backupConfig,
|
||||
backupTarget,
|
||||
dataLayout: new DataLayout(boxDataDir, []),
|
||||
progressTag: 'box'
|
||||
};
|
||||
@@ -197,21 +198,21 @@ async function uploadBoxSnapshot(backupConfig, progressCallback) {
|
||||
|
||||
debug(`uploadBoxSnapshot: took ${(new Date() - startTime)/1000} seconds`);
|
||||
|
||||
await backupTargets.setSnapshotInfo('box', { timestamp: new Date().toISOString(), format: backupConfig.format });
|
||||
await backupTargets.setSnapshotInfo('box', { timestamp: new Date().toISOString(), format: backupTarget.format });
|
||||
}
|
||||
|
||||
async function copy(backupConfig, srcRemotePath, destRemotePath, progressCallback) {
|
||||
assert.strictEqual(typeof backupConfig, 'object');
|
||||
async function copy(backupTarget, srcRemotePath, destRemotePath, progressCallback) {
|
||||
assert.strictEqual(typeof backupTarget, 'object');
|
||||
assert.strictEqual(typeof srcRemotePath, 'string');
|
||||
assert.strictEqual(typeof destRemotePath, 'string');
|
||||
assert.strictEqual(typeof progressCallback, 'function');
|
||||
|
||||
const { provider, format } = backupConfig;
|
||||
const oldFilePath = backupFormat.api(format).getBackupFilePath(backupConfig, srcRemotePath);
|
||||
const newFilePath = backupFormat.api(format).getBackupFilePath(backupConfig, destRemotePath);
|
||||
const { config, format } = backupTarget;
|
||||
const oldFilePath = backupFormat.api(format).getBackupFilePath(backupTarget, srcRemotePath);
|
||||
const newFilePath = backupFormat.api(format).getBackupFilePath(backupTarget, destRemotePath);
|
||||
|
||||
const startTime = new Date();
|
||||
const [copyError] = await safe(storage.api(provider).copy(backupConfig, oldFilePath, newFilePath, progressCallback));
|
||||
const [copyError] = await safe(storage.api(config.provider).copy(config, oldFilePath, newFilePath, progressCallback));
|
||||
if (copyError) {
|
||||
debug(`copy: copied to ${destRemotePath} errored. error: ${copyError.message}`);
|
||||
throw copyError;
|
||||
@@ -219,8 +220,8 @@ async function copy(backupConfig, srcRemotePath, destRemotePath, progressCallbac
|
||||
debug(`copy: copied successfully to ${destRemotePath}. Took ${(new Date() - startTime)/1000} seconds`);
|
||||
}
|
||||
|
||||
async function rotateBoxBackup(backupConfig, tag, options, dependsOn, progressCallback) {
|
||||
assert.strictEqual(typeof backupConfig, 'object');
|
||||
async function rotateBoxBackup(backupTarget, tag, options, dependsOn, progressCallback) {
|
||||
assert.strictEqual(typeof backupTarget, 'object');
|
||||
assert.strictEqual(typeof tag, 'string');
|
||||
assert.strictEqual(typeof options, 'object');
|
||||
assert(Array.isArray(dependsOn));
|
||||
@@ -232,7 +233,7 @@ async function rotateBoxBackup(backupConfig, tag, options, dependsOn, progressCa
|
||||
|
||||
const data = {
|
||||
remotePath,
|
||||
encryptionVersion: backupConfig.encryption ? 2 : null,
|
||||
encryptionVersion: backupTarget.encryption ? 2 : null,
|
||||
packageVersion: constants.VERSION,
|
||||
type: backupListing.BACKUP_TYPE_BOX,
|
||||
state: backupListing.BACKUP_STATE_CREATING,
|
||||
@@ -244,7 +245,7 @@ async function rotateBoxBackup(backupConfig, tag, options, dependsOn, progressCa
|
||||
};
|
||||
|
||||
const id = await backupListing.add(data);
|
||||
const [error] = await safe(copy(backupConfig, 'snapshot/box', remotePath, progressCallback));
|
||||
const [error] = await safe(copy(backupTarget, 'snapshot/box', remotePath, progressCallback));
|
||||
const state = error ? backupListing.BACKUP_STATE_ERROR : backupListing.BACKUP_STATE_NORMAL;
|
||||
await backupListing.setState(id, state);
|
||||
if (error) throw error;
|
||||
@@ -252,20 +253,19 @@ async function rotateBoxBackup(backupConfig, tag, options, dependsOn, progressCa
|
||||
return id;
|
||||
}
|
||||
|
||||
async function backupBox(dependsOn, tag, options, progressCallback) {
|
||||
async function backupBox(backupTarget, dependsOn, tag, options, progressCallback) {
|
||||
assert.strictEqual(typeof backupTarget, 'object');
|
||||
assert(Array.isArray(dependsOn));
|
||||
assert.strictEqual(typeof tag, 'string');
|
||||
assert.strictEqual(typeof options, 'object');
|
||||
assert.strictEqual(typeof progressCallback, 'function');
|
||||
|
||||
const backupConfig = await backupTargets.getConfig();
|
||||
|
||||
await uploadBoxSnapshot(backupConfig, progressCallback);
|
||||
return await rotateBoxBackup(backupConfig, tag, options, dependsOn, progressCallback);
|
||||
await uploadBoxSnapshot(backupTarget, progressCallback);
|
||||
return await rotateBoxBackup(backupTarget, tag, options, dependsOn, progressCallback);
|
||||
}
|
||||
|
||||
async function rotateAppBackup(backupConfig, app, tag, options, progressCallback) {
|
||||
assert.strictEqual(typeof backupConfig, 'object');
|
||||
async function rotateAppBackup(backupTarget, app, tag, options, progressCallback) {
|
||||
assert.strictEqual(typeof backupTarget, 'object');
|
||||
assert.strictEqual(typeof app, 'object');
|
||||
assert.strictEqual(typeof tag, 'string');
|
||||
assert.strictEqual(typeof options, 'object');
|
||||
@@ -280,7 +280,7 @@ async function rotateAppBackup(backupConfig, app, tag, options, progressCallback
|
||||
|
||||
const data = {
|
||||
remotePath,
|
||||
encryptionVersion: backupConfig.encryption ? 2 : null,
|
||||
encryptionVersion: backupTarget.encryption ? 2 : null,
|
||||
packageVersion: manifest.version,
|
||||
type: backupListing.BACKUP_TYPE_APP,
|
||||
state: backupListing.BACKUP_STATE_CREATING,
|
||||
@@ -292,7 +292,7 @@ async function rotateAppBackup(backupConfig, app, tag, options, progressCallback
|
||||
};
|
||||
|
||||
const id = await backupListing.add(data);
|
||||
const [error] = await safe(copy(backupConfig, `snapshot/app_${app.id}`, remotePath, progressCallback));
|
||||
const [error] = await safe(copy(backupTarget, `snapshot/app_${app.id}`, remotePath, progressCallback));
|
||||
const state = error ? backupListing.BACKUP_STATE_ERROR : backupListing.BACKUP_STATE_NORMAL;
|
||||
await backupListing.setState(id, state);
|
||||
if (error) throw error;
|
||||
@@ -300,8 +300,9 @@ async function rotateAppBackup(backupConfig, app, tag, options, progressCallback
|
||||
return id;
|
||||
}
|
||||
|
||||
async function backupApp(app, options, progressCallback) {
|
||||
async function backupApp(app, backupTarget, options, progressCallback) {
|
||||
assert.strictEqual(typeof app, 'object');
|
||||
assert.strictEqual(typeof backupTarget, 'object');
|
||||
assert.strictEqual(typeof options, 'object');
|
||||
assert.strictEqual(typeof progressCallback, 'function');
|
||||
|
||||
@@ -311,7 +312,7 @@ async function backupApp(app, options, progressCallback) {
|
||||
await snapshotApp(app, progressCallback);
|
||||
} else {
|
||||
const tag = (new Date()).toISOString().replace(/[T.]/g, '-').replace(/[:Z]/g,'');
|
||||
backupId = await backupAppWithTag(app, tag, options, progressCallback);
|
||||
backupId = await backupAppWithTag(app, backupTarget, tag, options, progressCallback);
|
||||
}
|
||||
await locks.release(`${locks.TYPE_APP_BACKUP_PREFIX}${app.id}`);
|
||||
|
||||
@@ -331,8 +332,8 @@ async function snapshotApp(app, progressCallback) {
|
||||
debug(`snapshotApp: ${app.fqdn} took ${(new Date() - startTime)/1000} seconds`);
|
||||
}
|
||||
|
||||
async function uploadAppSnapshot(backupConfig, app, progressCallback) {
|
||||
assert.strictEqual(typeof backupConfig, 'object');
|
||||
async function uploadAppSnapshot(backupTarget, app, progressCallback) {
|
||||
assert.strictEqual(typeof backupTarget, 'object');
|
||||
assert.strictEqual(typeof app, 'object');
|
||||
assert.strictEqual(typeof progressCallback, 'function');
|
||||
|
||||
@@ -348,7 +349,7 @@ async function uploadAppSnapshot(backupConfig, app, progressCallback) {
|
||||
|
||||
const uploadConfig = {
|
||||
remotePath,
|
||||
backupConfig,
|
||||
backupTarget,
|
||||
dataLayout,
|
||||
progressTag: app.fqdn
|
||||
};
|
||||
@@ -359,11 +360,12 @@ async function uploadAppSnapshot(backupConfig, app, progressCallback) {
|
||||
|
||||
debug(`uploadAppSnapshot: ${app.fqdn} uploaded to ${remotePath}. ${(new Date() - startTime)/1000} seconds`);
|
||||
|
||||
await backupTargets.setSnapshotInfo(app.id, { timestamp: new Date().toISOString(), manifest: app.manifest, format: backupConfig.format });
|
||||
await backupTargets.setSnapshotInfo(app.id, { timestamp: new Date().toISOString(), manifest: app.manifest, format: backupTarget.format });
|
||||
}
|
||||
|
||||
async function backupAppWithTag(app, tag, options, progressCallback) {
|
||||
async function backupAppWithTag(app, backupTarget, tag, options, progressCallback) {
|
||||
assert.strictEqual(typeof app, 'object');
|
||||
assert.strictEqual(typeof backupTarget, 'object');
|
||||
assert.strictEqual(typeof tag, 'string');
|
||||
assert.strictEqual(typeof options, 'object');
|
||||
assert.strictEqual(typeof progressCallback, 'function');
|
||||
@@ -375,14 +377,12 @@ async function backupAppWithTag(app, tag, options, progressCallback) {
|
||||
return results[0].id;
|
||||
}
|
||||
|
||||
const backupConfig = await backupTargets.getConfig();
|
||||
|
||||
await uploadAppSnapshot(backupConfig, app, progressCallback);
|
||||
return await rotateAppBackup(backupConfig, app, tag, options, progressCallback);
|
||||
await uploadAppSnapshot(backupTarget, app, progressCallback);
|
||||
return await rotateAppBackup(backupTarget, app, tag, options, progressCallback);
|
||||
}
|
||||
|
||||
async function uploadMailSnapshot(backupConfig, progressCallback) {
|
||||
assert.strictEqual(typeof backupConfig, 'object');
|
||||
async function uploadMailSnapshot(backupTarget, progressCallback) {
|
||||
assert.strictEqual(typeof backupTarget, 'object');
|
||||
assert.strictEqual(typeof progressCallback, 'function');
|
||||
|
||||
const mailDataDir = safe.fs.realpathSync(paths.MAIL_DATA_DIR);
|
||||
@@ -390,7 +390,7 @@ async function uploadMailSnapshot(backupConfig, progressCallback) {
|
||||
|
||||
const uploadConfig = {
|
||||
remotePath: 'snapshot/mail',
|
||||
backupConfig,
|
||||
backupTarget,
|
||||
dataLayout: new DataLayout(mailDataDir, []),
|
||||
progressTag: 'mail'
|
||||
};
|
||||
@@ -403,11 +403,11 @@ async function uploadMailSnapshot(backupConfig, progressCallback) {
|
||||
|
||||
debug(`uploadMailSnapshot: took ${(new Date() - startTime)/1000} seconds`);
|
||||
|
||||
await backupTargets.setSnapshotInfo('mail', { timestamp: new Date().toISOString(), format: backupConfig.format });
|
||||
await backupTargets.setSnapshotInfo('mail', { timestamp: new Date().toISOString(), format: backupTarget.format });
|
||||
}
|
||||
|
||||
async function rotateMailBackup(backupConfig, tag, options, progressCallback) {
|
||||
assert.strictEqual(typeof backupConfig, 'object');
|
||||
async function rotateMailBackup(target, tag, options, progressCallback) {
|
||||
assert.strictEqual(typeof target, 'object');
|
||||
assert.strictEqual(typeof tag, 'string');
|
||||
assert.strictEqual(typeof options, 'object');
|
||||
assert.strictEqual(typeof progressCallback, 'function');
|
||||
@@ -418,7 +418,7 @@ async function rotateMailBackup(backupConfig, tag, options, progressCallback) {
|
||||
|
||||
const data = {
|
||||
remotePath,
|
||||
encryptionVersion: backupConfig.encryption ? 2 : null,
|
||||
encryptionVersion: target.encryption ? 2 : null,
|
||||
packageVersion: constants.VERSION,
|
||||
type: backupListing.BACKUP_TYPE_MAIL,
|
||||
state: backupListing.BACKUP_STATE_CREATING,
|
||||
@@ -430,7 +430,7 @@ async function rotateMailBackup(backupConfig, tag, options, progressCallback) {
|
||||
};
|
||||
|
||||
const id = await backupListing.add(data);
|
||||
const [error] = await safe(copy(backupConfig, 'snapshot/mail', remotePath, progressCallback));
|
||||
const [error] = await safe(copy(target, 'snapshot/mail', remotePath, progressCallback));
|
||||
const state = error ? backupListing.BACKUP_STATE_ERROR : backupListing.BACKUP_STATE_NORMAL;
|
||||
await backupListing.setState(id, state);
|
||||
if (error) throw error;
|
||||
@@ -438,25 +438,16 @@ async function rotateMailBackup(backupConfig, tag, options, progressCallback) {
|
||||
return id;
|
||||
}
|
||||
|
||||
async function backupMailWithTag(tag, options, progressCallback) {
|
||||
async function backupMailWithTag(target, tag, options, progressCallback) {
|
||||
assert.strictEqual(typeof target, 'object');
|
||||
assert.strictEqual(typeof tag, 'string');
|
||||
assert.strictEqual(typeof options, 'object');
|
||||
assert.strictEqual(typeof progressCallback, 'function');
|
||||
|
||||
debug(`backupMailWithTag: backing up mail with tag ${tag}`);
|
||||
|
||||
const backupConfig = await backupTargets.getConfig();
|
||||
await uploadMailSnapshot(backupConfig, progressCallback);
|
||||
return await rotateMailBackup(backupConfig, tag, options, progressCallback);
|
||||
}
|
||||
|
||||
async function backupMail(options, progressCallback) {
|
||||
assert.strictEqual(typeof options, 'object');
|
||||
assert.strictEqual(typeof progressCallback, 'function');
|
||||
|
||||
const tag = (new Date()).toISOString().replace(/[T.]/g, '-').replace(/[:Z]/g,'');
|
||||
debug(`backupMail: backing up mail with tag ${tag}`);
|
||||
return await backupMailWithTag(tag, options, progressCallback);
|
||||
await uploadMailSnapshot(target, progressCallback);
|
||||
return await rotateMailBackup(target, tag, options, progressCallback);
|
||||
}
|
||||
|
||||
async function downloadMail(restoreConfig, progressCallback) {
|
||||
@@ -474,10 +465,14 @@ async function downloadMail(restoreConfig, progressCallback) {
|
||||
}
|
||||
|
||||
// this function is called from external process. calling process is expected to have a lock
|
||||
async function fullBackup(options, progressCallback) {
|
||||
async function fullBackup(backupTargetId, options, progressCallback) {
|
||||
assert.strictEqual(typeof backupTargetId, 'string');
|
||||
assert.strictEqual(typeof options, 'object');
|
||||
assert.strictEqual(typeof progressCallback, 'function');
|
||||
|
||||
const backupTarget = await backupTargets.get(backupTargetId);
|
||||
if (!backupTarget) throw new BoxError(BoxError.EXTERNAL_ERROR, 'Backup target not found');
|
||||
|
||||
const tag = (new Date()).toISOString().replace(/[T.]/g, '-').replace(/[:Z]/g,''); // unique tag under which all apps/mail/box backs up
|
||||
|
||||
const allApps = await apps.list();
|
||||
@@ -498,7 +493,7 @@ async function fullBackup(options, progressCallback) {
|
||||
progressCallback({ percent, message: `Backing up ${app.fqdn} (${i+1}/${allApps.length}). Waiting for lock` });
|
||||
await locks.wait(`${locks.TYPE_APP_BACKUP_PREFIX}${app.id}`);
|
||||
const startTime = new Date();
|
||||
const [appBackupError, appBackupId] = await safe(backupAppWithTag(app, tag, options, (progress) => progressCallback({ percent, message: progress.message })));
|
||||
const [appBackupError, appBackupId] = await safe(backupAppWithTag(app, backupTarget, tag, options, (progress) => progressCallback({ percent, message: progress.message })));
|
||||
debug(`fullBackup: app ${app.fqdn} backup finished. Took ${(new Date() - startTime)/1000} seconds`);
|
||||
await locks.release(`${locks.TYPE_APP_BACKUP_PREFIX}${app.id}`);
|
||||
if (appBackupError) throw appBackupError;
|
||||
@@ -507,18 +502,18 @@ async function fullBackup(options, progressCallback) {
|
||||
|
||||
progressCallback({ percent, message: 'Backing up mail' });
|
||||
percent += step;
|
||||
const mailBackupId = await backupMailWithTag(tag, options, (progress) => progressCallback({ percent, message: progress.message }));
|
||||
const mailBackupId = await backupMailWithTag(backupTarget, tag, options, (progress) => progressCallback({ percent, message: progress.message }));
|
||||
|
||||
progressCallback({ percent, message: 'Backing up system data' });
|
||||
percent += step;
|
||||
|
||||
const dependsOn = appBackupIds.concat(mailBackupId);
|
||||
const backupId = await backupBox(dependsOn, tag, options, (progress) => progressCallback({ percent, message: progress.message }));
|
||||
const backupId = await backupBox(backupTarget, dependsOn, tag, options, (progress) => progressCallback({ percent, message: progress.message }));
|
||||
return backupId;
|
||||
}
|
||||
|
||||
// this function is called from external process
|
||||
async function appBackup(appId, options, progressCallback) {
|
||||
async function appBackup(appId, backupTargetId, options, progressCallback) {
|
||||
assert.strictEqual(typeof appId, 'string');
|
||||
assert.strictEqual(typeof options, 'object');
|
||||
assert.strictEqual(typeof progressCallback, 'function');
|
||||
@@ -526,9 +521,12 @@ async function appBackup(appId, options, progressCallback) {
|
||||
const app = await apps.get(appId);
|
||||
if (!app) throw new BoxError(BoxError.BAD_FIELD, 'App not found');
|
||||
|
||||
const backupTarget = await backupTargets.get(backupTargetId);
|
||||
if (!backupTarget) throw new BoxError(BoxError.EXTERNAL_ERROR, 'Backup target not found');
|
||||
|
||||
await progressCallback({ percent: 1, message: `Backing up ${app.fqdn}. Waiting for lock` });
|
||||
const startTime = new Date();
|
||||
const backupId = await backupApp(app, options, progressCallback);
|
||||
const backupId = await backupApp(app, backupTarget, options, progressCallback);
|
||||
await progressCallback({ percent: 100, message: `app ${app.fqdn} backup finished. Took ${(new Date() - startTime)/1000} seconds` });
|
||||
return backupId;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user