migrate old providers as generic mountpoint provider

This commit is contained in:
Girish Ramakrishnan
2021-05-17 12:51:23 -07:00
parent 53dce1e7aa
commit 124954d490
3 changed files with 43 additions and 16 deletions

View File

@@ -21,6 +21,7 @@ exports = module.exports = {
};
const PROVIDER_FILESYSTEM = 'filesystem';
const PROVIDER_MOUNTPOINT = 'mountpoint';
const PROVIDER_SSHFS = 'sshfs';
const PROVIDER_CIFS = 'cifs';
const PROVIDER_NFS = 'nfs';
@@ -43,11 +44,15 @@ var assert = require('assert'),
function getBackupPath(apiConfig) {
assert.strictEqual(typeof apiConfig, 'object');
if (apiConfig.provider === PROVIDER_SSHFS) return path.join(apiConfig.mountPoint, apiConfig.prefix);
if (apiConfig.provider === PROVIDER_CIFS) return path.join(apiConfig.mountPoint, apiConfig.prefix);
if (apiConfig.provider === PROVIDER_NFS) return path.join(apiConfig.mountPoint, apiConfig.prefix);
return apiConfig.backupFolder;
switch (apiConfig.provider) {
case PROVIDER_SSHFS:
case PROVIDER_MOUNTPOINT:
case PROVIDER_NFS:
case PROVIDER_CIFS:
return path.join(apiConfig.mountPoint, apiConfig.prefix);
default:
return apiConfig.backupFolder;
}
}
// the du call in the function below requires root
@@ -71,7 +76,7 @@ function checkPreconditions(apiConfig, dataLayout, callback) {
// Check filesystem is mounted so we don't write into the actual folder on disk
if (apiConfig.provider === PROVIDER_SSHFS || apiConfig.provider === PROVIDER_CIFS || apiConfig.provider === PROVIDER_NFS) {
if (result.mountpoint !== apiConfig.mountPoint) return callback(new BoxError(BoxError.FS_ERROR, `${apiConfig.mountPoint} is not mounted`));
} else if (apiConfig.provider === PROVIDER_FILESYSTEM && apiConfig.externalDisk) {
} else if (apiConfig.provider === PROVIDER_MOUNTPOINT) {
if (result.mountpoint === '/') return callback(new BoxError(BoxError.FS_ERROR, `${apiConfig.backupFolder} is not mounted`));
}
@@ -112,7 +117,7 @@ function upload(apiConfig, backupFilePath, sourceStream, callback) {
const BACKUP_UID = parseInt(process.env.SUDO_UID, 10) || process.getuid();
// sshfs and cifs handle ownership through the mount args
if (apiConfig.provider === PROVIDER_FILESYSTEM || apiConfig.provider === PROVIDER_NFS) {
if (apiConfig.provider === PROVIDER_FILESYSTEM || apiConfig.provider === PROVIDER_NFS || (apiConfig.provider === PROVIDER_MOUNTPOINT && apiConfig.chown)) {
if (!safe.fs.chownSync(backupFilePath, BACKUP_UID, BACKUP_UID)) return callback(new BoxError(BoxError.EXTERNAL_ERROR, 'Unable to chown:' + safe.error.message));
if (!safe.fs.chownSync(path.dirname(backupFilePath), BACKUP_UID, BACKUP_UID)) return callback(new BoxError(BoxError.EXTERNAL_ERROR, 'Unable to chown:' + safe.error.message));
}
@@ -194,7 +199,7 @@ function copy(apiConfig, oldFilePath, newFilePath) {
events.emit('progress', `Copying ${oldFilePath} to ${newFilePath}`);
// sshfs and cifs do not allow preserving attributes
var cpOptions = apiConfig.provider === PROVIDER_FILESYSTEM ? '-a' : '-dR';
let cpOptions = (apiConfig.provider === PROVIDER_FILESYSTEM || apiConfig.provider === PROVIDER_NFS || (apiConfig.provider === PROVIDER_MOUNTPOINT && apiConfig.preserveAttributes)) ? '-a' : '-dR';
// this will hardlink backups saving space
cpOptions += apiConfig.noHardlinks ? '' : 'l';
@@ -267,11 +272,9 @@ function testConfig(apiConfig, callback) {
if (!apiConfig.backupFolder || typeof apiConfig.backupFolder !== 'string') return callback(new BoxError(BoxError.BAD_FIELD, 'backupFolder must be non-empty string', { field: 'backupFolder' }));
let error = validateBackupTarget(apiConfig.backupFolder);
if (error) return callback(error);
if ('externalDisk' in apiConfig && typeof apiConfig.externalDisk !== 'boolean') return callback(new BoxError(BoxError.BAD_FIELD, 'externalDisk must be boolean', { field: 'externalDisk' }));
}
if (apiConfig.provider === PROVIDER_SSHFS || apiConfig.provider === PROVIDER_CIFS || apiConfig.provider === PROVIDER_NFS) {
if (apiConfig.provider === PROVIDER_MOUNTPOINT) {
if (!apiConfig.mountPoint || typeof apiConfig.mountPoint !== 'string') return callback(new BoxError(BoxError.BAD_FIELD, 'mountPoint must be non-empty string', { field: 'mountPoint' }));
let error = validateBackupTarget(apiConfig.mountPoint);
if (error) return callback(error);
@@ -285,10 +288,6 @@ function testConfig(apiConfig, callback) {
const mounts = safe.fs.readFileSync('/proc/mounts', 'utf8');
const mountInfo = mounts.split('\n').filter(function (l) { return l.indexOf(apiConfig.mountPoint) !== -1; })[0];
if (!mountInfo) return callback(new BoxError(BoxError.BAD_FIELD, `${apiConfig.mountPoint} is not mounted`, { field: 'mountPoint' }));
if (apiConfig.provider === PROVIDER_SSHFS && !mountInfo.split(' ').find(i => i === 'fuse.sshfs' || i === 'autofs')) return callback(new BoxError(BoxError.BAD_FIELD, 'mountPoint must be a "fuse.sshfs" filesystem', { field: 'mountPoint' }));
if (apiConfig.provider === PROVIDER_CIFS && !mountInfo.split(' ').find(i => i === 'cifs' || i === 'autofs')) return callback(new BoxError(BoxError.BAD_FIELD, 'mountPoint must be a "cifs" filesystem', { field: 'mountPoint' }));
if (apiConfig.provider === PROVIDER_NFS && !mountInfo.split(' ').find(i => i === 'nfs' || i === 'nfs4' || i === 'autofs')) return callback(new BoxError(BoxError.BAD_FIELD, 'mountPoint must be a "nfs" filesystem', { field: 'mountPoint' }));
}
// common checks