diff --git a/dashboard/src/js/client.js b/dashboard/src/js/client.js index 81f10c95c..79da2472c 100644 --- a/dashboard/src/js/client.js +++ b/dashboard/src/js/client.js @@ -1848,6 +1848,15 @@ angular.module('Application').service('Client', ['$http', '$interval', '$timeout }); }; + Client.prototype.getProvisionBlockDevices = function (callback) { + get('/api/v1/cloudron/block_devices', null, function (error, data, status) { + if (error) return callback(error); + if (status !== 200) return callback(new ClientError(status, data)); + + callback(null, data.devices); + }); + }; + Client.prototype.createAdmin = function (data, callback) { var that = this; diff --git a/dashboard/src/js/restore.js b/dashboard/src/js/restore.js index cd988e624..0451fcb6a 100644 --- a/dashboard/src/js/restore.js +++ b/dashboard/src/js/restore.js @@ -41,6 +41,8 @@ app.controller('RestoreController', ['$scope', 'Client', function ($scope, Clien $scope.encrypted = false; // only used if a backup config contains that flag $scope.setupToken = ''; $scope.skipDnsSetup = false; + $scope.disk = null; + $scope.blockDevices = []; $scope.mountOptions = { host: '', @@ -54,6 +56,11 @@ app.controller('RestoreController', ['$scope', 'Client', function ($scope, Clien privateKey: '' }; + $scope.$watch('disk', function (newValue) { + if (!newValue) return; + $scope.mountOptions.diskPath = '/dev/disk/by-uuid/' + newValue.uuid; + }); + $scope.sysinfo = { provider: 'generic', ipv4: '', @@ -358,10 +365,26 @@ app.controller('RestoreController', ['$scope', 'Client', function ($scope, Clien return; } - $scope.status = status; - $scope.instanceId = search.instanceId; - $scope.setupToken = search.setupToken; - $scope.initialized = true; + Client.getProvisionBlockDevices(function (error, result) { + if (error) { + console.error('Failed to list blockdevices:', error); + } else { + // 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'; }); + + // amend label for UI + result.forEach(function (d) { d.label = d.path; }); + } + + $scope.blockDevices = result; + + $scope.status = status; + $scope.instanceId = search.instanceId; + $scope.setupToken = search.setupToken; + $scope.initialized = true; + }); }); } diff --git a/dashboard/src/restore.html b/dashboard/src/restore.html index f9375611f..f16e477a7 100644 --- a/dashboard/src/restore.html +++ b/dashboard/src/restore.html @@ -137,6 +137,12 @@ + +
+ + +
+
diff --git a/dashboard/src/views/backups.html b/dashboard/src/views/backups.html index 152ede6d3..bbbc73ffb 100644 --- a/dashboard/src/views/backups.html +++ b/dashboard/src/views/backups.html @@ -217,7 +217,6 @@
- {{ configureBackup.mountOptions.diskPath }}
diff --git a/src/routes/provision.js b/src/routes/provision.js index 47b403da3..b8933ef91 100644 --- a/src/routes/provision.js +++ b/src/routes/provision.js @@ -6,7 +6,8 @@ exports = module.exports = { activate, restore, getStatus, - setupTokenAuth + setupTokenAuth, + getBlockDevices }; const assert = require('assert'), @@ -17,7 +18,9 @@ const assert = require('assert'), paths = require('../paths.js'), provision = require('../provision.js'), safe = require('safetydance'), - superagent = require('superagent'); + superagent = require('superagent'), + system = require('../system.js'), + users = require('../users.js'); function setupTokenAuth(req, res, next) { assert.strictEqual(typeof req.body, 'object'); @@ -129,3 +132,13 @@ async function getStatus(req, res, next) { next(new HttpSuccess(200, status)); } + +async function getBlockDevices(req, res, next) { + const activated = await users.isActivated(); + if (activated) throw new BoxError(BoxError.NOT_ALLOWED, 'Only available during restore.'); + + const [error, devices] = await safe(system.getBlockDevices()); + if (error) return next(new HttpError(500, error)); + + next(new HttpSuccess(200, { devices })); +} diff --git a/src/server.js b/src/server.js index 4c225c5e2..02fe62d92 100644 --- a/src/server.js +++ b/src/server.js @@ -97,6 +97,7 @@ async function initializeExpressSync() { router.post('/api/v1/cloudron/restore', json, routes.provision.setupTokenAuth, routes.provision.restore); // only available until activated router.post('/api/v1/cloudron/activate', json, routes.provision.setupTokenAuth, routes.provision.activate); router.get ('/api/v1/cloudron/status', routes.provision.getStatus); + router.get ('/api/v1/cloudron/block_devices', routes.provision.getBlockDevices); router.get ('/api/v1/cloudron/languages', routes.cloudron.getLanguages); router.get ('/api/v1/cloudron/avatar', routes.branding.getCloudronAvatar); // this is a public alias for /api/v1/branding/cloudron_avatar