+
+
-
+
+
+
+
+
+
+
+ {{ configureBackup.mountOptions.diskPath }}
@@ -469,7 +476,7 @@
{{ backupConfig.backupFolder }}
- {{ backupConfig.mountOptions.diskPath || backupConfig.mountPoint }}{{ (backupConfig.prefix ? '/' : '') + backupConfig.prefix }}
+ {{ backupConfig.mountOptions.diskPath || backupConfig.mountPoint }}{{ (backupConfig.prefix ? '/' : '') + backupConfig.prefix }}
{{ backupConfig.mountOptions.host }}:{{ backupConfig.mountOptions.remoteDir }}{{ (backupConfig.prefix ? '/' : '') + backupConfig.prefix }}
diff --git a/dashboard/src/views/backups.js b/dashboard/src/views/backups.js
index 0519c2cfe..e598681b1 100644
--- a/dashboard/src/views/backups.js
+++ b/dashboard/src/views/backups.js
@@ -273,7 +273,7 @@ angular.module('Application').controller('BackupsController', ['$scope', '$locat
};
$scope.mountlike = function (provider) {
- return provider === 'sshfs' || provider === 'cifs' || provider === 'nfs' || provider === 'mountpoint' || provider === 'ext4' || provider === 'xfs';
+ return provider === 'sshfs' || provider === 'cifs' || provider === 'nfs' || provider === 'mountpoint' || provider === 'ext4' || provider === 'xfs' || provider === 'disk';
};
// https://stackoverflow.com/questions/3665115/how-to-create-a-file-in-memory-for-user-to-download-but-not-through-server#18197341
@@ -431,6 +431,11 @@ angular.module('Application').controller('BackupsController', ['$scope', '$locat
}
};
+ $scope.$watch('configureBackup.disk', function (newValue) {
+ if (!newValue) return;
+ $scope.configureBackup.mountOptions.diskPath = '/dev/disk/by-uuid/' + newValue.uuid;
+ });
+
$scope.configureBackup = {
busy: false,
error: {},
@@ -462,6 +467,8 @@ angular.module('Application').controller('BackupsController', ['$scope', '$locat
downloadConcurrency: '',
syncConcurrency: '', // sort of similar to upload
+ blockDevices: [],
+ disk: null,
mountOptions: {
host: '',
remoteDir: '',
@@ -496,6 +503,7 @@ angular.module('Application').controller('BackupsController', ['$scope', '$locat
$scope.configureBackup.syncConcurrency = $scope.configureBackup.provider === 's3' ? 20 : 10;
$scope.configureBackup.copyConcurrency = $scope.configureBackup.provider === 's3' ? 500 : 10;
+ $scope.configureBackup.disk = null;
$scope.configureBackup.mountOptions = { host: '', remoteDir: '', username: '', password: '', diskPath: '', seal: false, user: '', port: 22, privateKey: '' };
},
@@ -562,7 +570,30 @@ angular.module('Application').controller('BackupsController', ['$scope', '$locat
privateKey: mountOptions.privateKey || ''
};
- $('#configureBackupModal').modal('show');
+ Client.getBlockDevices(function (error, result) {
+ if (error) return console.error('Failed to list blockdevices:', error);
+
+ console.log('all',result)
+ // only offer non /, /boot or /home disks
+ result = result.filter(function (d) { return d.mountpoint !== '/' && d.mountpoint !== '/home' && d.mountpoint !== '/boot'; });
+ // only offer xfs and ext4 disks
+ result = result.filter(function (d) { return d.type === 'xfs' || d.type === 'ext4'; });
+ console.log('filtered',result)
+
+ // amend label for UI
+ result.forEach(function (d) {
+ d.label = d.path;
+
+ // pre-select current if set
+ if (d.path === $scope.configureBackup.mountOptions.diskPath || ('/dev/disk/by-uuid/' + d.uuid) === $scope.configureBackup.mountOptions.diskPath) {
+ $scope.configureBackup.disk = d;
+ }
+ });
+
+ $scope.configureBackup.blockDevices = result;
+
+ $('#configureBackupModal').modal('show');
+ });
},
submit: function () {
@@ -666,7 +697,7 @@ angular.module('Application').controller('BackupsController', ['$scope', '$locat
backupConfig.mountOptions.port = $scope.configureBackup.mountOptions.port;
backupConfig.mountOptions.privateKey = $scope.configureBackup.mountOptions.privateKey;
}
- } else if (backupConfig.provider === 'ext4' || backupConfig.provider === 'xfs') {
+ } else if (backupConfig.provider === 'ext4' || backupConfig.provider === 'xfs' || backupConfig.provider === 'disk') {
backupConfig.mountOptions.diskPath = $scope.configureBackup.mountOptions.diskPath;
} else if (backupConfig.provider === 'mountpoint') {
backupConfig.mountPoint = $scope.configureBackup.mountPoint;
diff --git a/src/mounts.js b/src/mounts.js
index c32fd000d..ac1e855ee 100644
--- a/src/mounts.js
+++ b/src/mounts.js
@@ -56,6 +56,7 @@ function validateMountOptions(type, options) {
return null;
case 'ext4':
case 'xfs':
+ case 'disk':
if (typeof options.diskPath !== 'string') return new BoxError(BoxError.BAD_FIELD, 'diskPath is not a string');
return null;
default:
@@ -64,7 +65,7 @@ function validateMountOptions(type, options) {
}
function isManagedProvider(provider) {
- return provider === 'sshfs' || provider === 'cifs' || provider === 'nfs' || provider === 'ext4' || provider === 'xfs';
+ return provider === 'sshfs' || provider === 'cifs' || provider === 'nfs' || provider === 'ext4' || provider === 'xfs' || provider === 'disk';
}
function mountObjectFromBackupConfig(backupConfig) {
@@ -115,6 +116,11 @@ function renderMountFile(mount) {
what = mountOptions.diskPath; // like /dev/disk/by-uuid/uuid or /dev/disk/by-id/scsi-id
options = 'discard,defaults,noatime';
break;
+ case 'disk':
+ type = 'auto';
+ what = mountOptions.diskPath; // like /dev/disk/by-uuid/uuid or /dev/disk/by-id/scsi-id
+ options = 'discard,defaults,noatime';
+ break;
case 'sshfs': {
const keyFilePath = path.join(paths.SSHFS_KEYS_DIR, `id_rsa_${mountOptions.host}`);
if (!safe.fs.writeFileSync(keyFilePath, `${mount.mountOptions.privateKey}\n`, { mode: 0o600 })) throw new BoxError(BoxError.FS_ERROR, `Could not write private key: ${safe.error.message}`);
diff --git a/src/storage.js b/src/storage.js
index 533ee9d88..84a2e88ee 100644
--- a/src/storage.js
+++ b/src/storage.js
@@ -11,6 +11,7 @@ function api(provider) {
case 'cifs': return require('./storage/filesystem.js');
case 'sshfs': return require('./storage/filesystem.js');
case 'mountpoint': return require('./storage/filesystem.js');
+ case 'disk': return require('./storage/filesystem.js');
case 'ext4': return require('./storage/filesystem.js');
case 's3': return require('./storage/s3.js');
case 'gcs': return require('./storage/gcs.js');
diff --git a/src/storage/filesystem.js b/src/storage/filesystem.js
index 97784159d..03f74e5f7 100644
--- a/src/storage/filesystem.js
+++ b/src/storage/filesystem.js
@@ -28,6 +28,7 @@ const PROVIDER_MOUNTPOINT = 'mountpoint';
const PROVIDER_SSHFS = 'sshfs';
const PROVIDER_CIFS = 'cifs';
const PROVIDER_XFS = 'xfs';
+const PROVIDER_DISK = 'disk'; // replaces xfs and ext4
const PROVIDER_NFS = 'nfs';
const PROVIDER_EXT4 = 'ext4';
@@ -54,6 +55,7 @@ function getBackupRootPath(apiConfig) {
case PROVIDER_CIFS:
case PROVIDER_EXT4:
case PROVIDER_XFS:
+ case PROVIDER_DISK:
return path.join(paths.MANAGED_BACKUP_MOUNT_DIR, apiConfig.prefix);
case PROVIDER_MOUNTPOINT:
return path.join(apiConfig.mountPoint, apiConfig.prefix);
@@ -87,6 +89,7 @@ function hasChownSupportSync(apiConfig) {
case PROVIDER_NFS:
case PROVIDER_EXT4:
case PROVIDER_XFS:
+ case PROVIDER_DISK:
case PROVIDER_FILESYSTEM:
return true;
case PROVIDER_SSHFS: