2020-10-28 16:14:32 -07:00
|
|
|
'use strict';
|
|
|
|
|
|
|
|
|
|
/* global angular */
|
|
|
|
|
/* global $ */
|
2021-05-14 10:46:31 -07:00
|
|
|
/* global async */
|
2020-10-28 16:14:32 -07:00
|
|
|
|
|
|
|
|
angular.module('Application').controller('VolumesController', ['$scope', '$location', '$timeout', 'Client', function ($scope, $location, $timeout, Client) {
|
|
|
|
|
Client.onReady(function () { if (!Client.getUserInfo().isAtLeastUserManager) $location.path('/'); });
|
|
|
|
|
|
2021-05-14 10:46:31 -07:00
|
|
|
var refreshVolumesTimerId = null;
|
|
|
|
|
|
2020-10-28 16:14:32 -07:00
|
|
|
$scope.config = Client.getConfig();
|
|
|
|
|
$scope.volumes = [];
|
2023-01-23 18:43:54 +01:00
|
|
|
$scope.devices = [];
|
2020-10-28 16:14:32 -07:00
|
|
|
$scope.ready = false;
|
|
|
|
|
|
2021-05-12 21:40:30 -07:00
|
|
|
$scope.mountTypes = [
|
|
|
|
|
{ name: 'CIFS', value: 'cifs' },
|
|
|
|
|
{ name: 'EXT4', value: 'ext4' },
|
2021-06-24 23:01:35 -07:00
|
|
|
{ name: 'Filesystem', value: 'filesystem' },
|
|
|
|
|
{ name: 'Filesystem (Mountpoint)', value: 'mountpoint' },
|
2021-05-12 21:40:30 -07:00
|
|
|
{ name: 'NFS', value: 'nfs' },
|
|
|
|
|
{ name: 'SSHFS', value: 'sshfs' },
|
2022-06-08 10:38:54 -07:00
|
|
|
{ name: 'XFS', value: 'xfs' },
|
2021-05-12 21:40:30 -07:00
|
|
|
];
|
|
|
|
|
|
2020-10-28 16:14:32 -07:00
|
|
|
function refreshVolumes(callback) {
|
2021-05-14 10:46:31 -07:00
|
|
|
let refreshAgain = false;
|
|
|
|
|
|
2020-10-28 16:14:32 -07:00
|
|
|
Client.getVolumes(function (error, results) {
|
|
|
|
|
if (error) return console.error(error);
|
|
|
|
|
|
|
|
|
|
$scope.volumes = results;
|
2021-05-13 15:33:07 -07:00
|
|
|
|
2021-05-14 10:46:31 -07:00
|
|
|
async.eachSeries($scope.volumes, function (volume, iteratorDone) {
|
2021-05-13 15:33:07 -07:00
|
|
|
Client.getVolumeStatus(volume.id, function (error, result) {
|
2021-05-14 10:46:31 -07:00
|
|
|
if (error) {
|
|
|
|
|
console.error('Failed to fetch volume status', volume.name, error);
|
|
|
|
|
iteratorDone();
|
|
|
|
|
}
|
2021-05-13 15:33:07 -07:00
|
|
|
|
|
|
|
|
volume.status = result;
|
2021-05-14 10:46:31 -07:00
|
|
|
if (volume.status.state === 'activating') refreshAgain = true;
|
|
|
|
|
|
|
|
|
|
iteratorDone();
|
2021-05-13 15:33:07 -07:00
|
|
|
});
|
2021-05-14 10:46:31 -07:00
|
|
|
}, function () {
|
|
|
|
|
if (!refreshAgain) {
|
|
|
|
|
clearTimeout(refreshVolumesTimerId);
|
|
|
|
|
refreshVolumesTimerId = null;
|
|
|
|
|
} else if (!refreshVolumesTimerId) {
|
|
|
|
|
refreshVolumesTimerId = setTimeout(refreshVolumes, 5000);
|
|
|
|
|
}
|
2021-05-13 15:33:07 -07:00
|
|
|
|
2021-05-14 10:46:31 -07:00
|
|
|
if (callback) callback();
|
|
|
|
|
});
|
2020-10-28 16:14:32 -07:00
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-11 15:51:26 +02:00
|
|
|
// same as box/mounts.js
|
|
|
|
|
$scope.isMountProvider = function (provider) {
|
2022-06-08 10:38:54 -07:00
|
|
|
return provider === 'sshfs' || provider === 'cifs' || provider === 'nfs' || provider === 'ext4' || provider === 'xfs';
|
2021-10-11 15:51:26 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
$scope.remount = function (volume) {
|
|
|
|
|
volume.remounting = true;
|
|
|
|
|
|
|
|
|
|
Client.remountVolume(volume.id, function (error) {
|
|
|
|
|
if (error) console.error(error);
|
|
|
|
|
|
|
|
|
|
// give the backend some time
|
|
|
|
|
$timeout(function () {
|
|
|
|
|
volume.remounting = false;
|
|
|
|
|
refreshVolumes(function (error) { if (error) console.error('Failed to refresh volume states.', error); });
|
2021-10-11 17:45:55 +02:00
|
|
|
}, 2000);
|
2021-10-11 15:51:26 +02:00
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
2021-06-21 16:23:34 -07:00
|
|
|
$scope.volumeAdd = {
|
2020-10-28 16:14:32 -07:00
|
|
|
error: null,
|
|
|
|
|
busy: false,
|
|
|
|
|
|
|
|
|
|
name: '',
|
|
|
|
|
hostPath: '',
|
|
|
|
|
|
2021-06-24 23:01:35 -07:00
|
|
|
mountType: 'mountpoint',
|
2021-05-12 21:40:30 -07:00
|
|
|
host: '',
|
|
|
|
|
remoteDir: '',
|
|
|
|
|
username: '',
|
|
|
|
|
password: '',
|
|
|
|
|
diskPath: '',
|
2021-05-18 17:20:59 +02:00
|
|
|
user: '',
|
2022-01-10 16:45:58 +01:00
|
|
|
seal: false,
|
2021-05-18 17:20:59 +02:00
|
|
|
port: 22,
|
|
|
|
|
privateKey: '',
|
2020-10-28 16:14:32 -07:00
|
|
|
|
|
|
|
|
reset: function () {
|
2021-06-21 16:23:34 -07:00
|
|
|
$scope.volumeAdd.error = null;
|
|
|
|
|
$scope.volumeAdd.busy = false;
|
|
|
|
|
$scope.volumeAdd.name = '';
|
|
|
|
|
$scope.volumeAdd.hostPath = '';
|
2021-06-24 23:01:35 -07:00
|
|
|
$scope.volumeAdd.mountType = 'mountpoint';
|
2021-06-21 16:23:34 -07:00
|
|
|
$scope.volumeAdd.host = '';
|
|
|
|
|
$scope.volumeAdd.remoteDir = '';
|
|
|
|
|
$scope.volumeAdd.username = '';
|
|
|
|
|
$scope.volumeAdd.password = '';
|
|
|
|
|
$scope.volumeAdd.diskPath = '';
|
2023-01-23 18:43:54 +01:00
|
|
|
$scope.volumeAdd.customDiskPath = '';
|
2021-06-21 16:23:34 -07:00
|
|
|
$scope.volumeAdd.user = '';
|
2022-01-10 16:45:58 +01:00
|
|
|
$scope.volumeAdd.seal = false;
|
2021-06-21 16:23:34 -07:00
|
|
|
$scope.volumeAdd.port = 22;
|
|
|
|
|
$scope.volumeAdd.privateKey = '';
|
|
|
|
|
|
|
|
|
|
$scope.volumeAddForm.$setPristine();
|
|
|
|
|
$scope.volumeAddForm.$setUntouched();
|
2020-10-28 16:14:32 -07:00
|
|
|
},
|
|
|
|
|
|
2021-06-21 16:23:34 -07:00
|
|
|
show: function () {
|
|
|
|
|
$scope.volumeAdd.reset();
|
2020-10-28 16:14:32 -07:00
|
|
|
|
2023-01-23 18:43:54 +01:00
|
|
|
$scope.blockDevices = [];
|
|
|
|
|
|
|
|
|
|
Client.getBlockDevices(function (error, result) {
|
|
|
|
|
if (error) console.error('Failed to list blockdevices:', error);
|
|
|
|
|
|
|
|
|
|
// only offer unmounted disks
|
|
|
|
|
result = result.filter(function (d) { return !d.mountpoint; });
|
|
|
|
|
|
|
|
|
|
// amend label for UI
|
|
|
|
|
result.forEach(function (d) { d.label = d.path; });
|
|
|
|
|
|
|
|
|
|
// add custom fake option
|
|
|
|
|
result.push({ path: 'custom', label: 'Custom' });
|
|
|
|
|
|
|
|
|
|
$scope.blockDevices = result;
|
|
|
|
|
$scope.volumeAdd.diskPath = $scope.blockDevices[0].path;
|
|
|
|
|
|
|
|
|
|
$('#volumeAddModal').modal('show');
|
|
|
|
|
});
|
2020-10-28 16:14:32 -07:00
|
|
|
},
|
|
|
|
|
|
|
|
|
|
submit: function () {
|
2021-06-21 16:23:34 -07:00
|
|
|
$scope.volumeAdd.busy = true;
|
|
|
|
|
$scope.volumeAdd.error = null;
|
2020-10-28 16:14:32 -07:00
|
|
|
|
2021-05-12 21:40:30 -07:00
|
|
|
var mountOptions = null;
|
|
|
|
|
|
2021-06-21 16:23:34 -07:00
|
|
|
if ($scope.volumeAdd.mountType === 'cifs') {
|
2021-05-12 21:40:30 -07:00
|
|
|
mountOptions = {
|
2021-06-21 16:23:34 -07:00
|
|
|
host: $scope.volumeAdd.host,
|
|
|
|
|
remoteDir: $scope.volumeAdd.remoteDir,
|
|
|
|
|
username: $scope.volumeAdd.username,
|
2022-01-10 16:45:58 +01:00
|
|
|
password: $scope.volumeAdd.password,
|
|
|
|
|
seal: $scope.volumeAdd.seal
|
2021-05-12 21:40:30 -07:00
|
|
|
};
|
2021-06-21 16:23:34 -07:00
|
|
|
} else if ($scope.volumeAdd.mountType === 'nfs') {
|
2021-05-12 21:40:30 -07:00
|
|
|
mountOptions = {
|
2021-06-21 16:23:34 -07:00
|
|
|
host: $scope.volumeAdd.host,
|
|
|
|
|
remoteDir: $scope.volumeAdd.remoteDir,
|
2021-05-12 21:40:30 -07:00
|
|
|
};
|
2021-06-21 16:23:34 -07:00
|
|
|
} else if ($scope.volumeAdd.mountType === 'sshfs') {
|
2021-05-18 17:20:59 +02:00
|
|
|
mountOptions = {
|
2021-06-21 16:23:34 -07:00
|
|
|
host: $scope.volumeAdd.host,
|
|
|
|
|
port: $scope.volumeAdd.port,
|
|
|
|
|
remoteDir: $scope.volumeAdd.remoteDir,
|
|
|
|
|
user: $scope.volumeAdd.user,
|
|
|
|
|
privateKey: $scope.volumeAdd.privateKey,
|
2021-05-18 17:20:59 +02:00
|
|
|
};
|
2022-06-08 10:38:54 -07:00
|
|
|
} else if ($scope.volumeAdd.mountType === 'ext4' || $scope.volumeAdd.mountType === 'xfs') {
|
2021-05-12 21:40:30 -07:00
|
|
|
mountOptions = {
|
2023-01-23 18:43:54 +01:00
|
|
|
diskPath: $scope.volumeAdd.diskPath === 'custom' ? $scope.volumeAdd.customDiskPath : $scope.volumeAdd.diskPath
|
2021-05-12 21:40:30 -07:00
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
2021-06-21 00:05:39 -07:00
|
|
|
var hostPath;
|
2021-06-24 23:01:35 -07:00
|
|
|
if ($scope.volumeAdd.mountType === 'mountpoint' || $scope.volumeAdd.mountType === 'filesystem') {
|
|
|
|
|
hostPath = $scope.volumeAdd.hostPath;
|
2021-05-13 09:14:34 -07:00
|
|
|
} else {
|
2021-06-24 16:59:13 -07:00
|
|
|
hostPath = null;
|
2021-05-13 09:14:34 -07:00
|
|
|
}
|
|
|
|
|
|
2021-06-24 16:59:13 -07:00
|
|
|
Client.addVolume($scope.volumeAdd.name, $scope.volumeAdd.mountType, hostPath, mountOptions, function (error) {
|
2021-06-21 16:23:34 -07:00
|
|
|
$scope.volumeAdd.busy = false;
|
2020-10-28 16:14:32 -07:00
|
|
|
if (error) {
|
2021-06-21 16:23:34 -07:00
|
|
|
$scope.volumeAdd.error = error.message;
|
2020-10-28 16:14:32 -07:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2021-06-21 16:23:34 -07:00
|
|
|
$('#volumeAddModal').modal('hide');
|
|
|
|
|
$scope.volumeAdd.reset();
|
2020-10-28 16:14:32 -07:00
|
|
|
|
|
|
|
|
refreshVolumes();
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
$scope.volumeRemove = {
|
|
|
|
|
busy: false,
|
|
|
|
|
error: null,
|
|
|
|
|
volume: null,
|
|
|
|
|
|
|
|
|
|
reset: function () {
|
|
|
|
|
$scope.volumeRemove.busy = false;
|
|
|
|
|
$scope.volumeRemove.error = null;
|
|
|
|
|
$scope.volumeRemove.volume = null;
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
show: function (volume) {
|
|
|
|
|
$scope.volumeRemove.reset();
|
|
|
|
|
|
|
|
|
|
$scope.volumeRemove.volume = volume;
|
|
|
|
|
|
|
|
|
|
$('#volumeRemoveModal').modal('show');
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
submit: function () {
|
|
|
|
|
$scope.volumeRemove.busy = true;
|
|
|
|
|
$scope.volumeRemove.error = null;
|
|
|
|
|
|
|
|
|
|
Client.removeVolume($scope.volumeRemove.volume.id, function (error) {
|
|
|
|
|
if (error && (error.statusCode === 403 || error.statusCode === 409)) {
|
|
|
|
|
$scope.volumeRemove.error = error.message;
|
|
|
|
|
} else if (error) {
|
|
|
|
|
Client.error(error);
|
|
|
|
|
} else {
|
|
|
|
|
$('#volumeRemoveModal').modal('hide');
|
|
|
|
|
$scope.volumeRemove.reset();
|
|
|
|
|
|
|
|
|
|
refreshVolumes();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$scope.volumeRemove.busy = false;
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
Client.onReady(function () {
|
|
|
|
|
refreshVolumes(function (error) {
|
|
|
|
|
if (error) return console.error(error);
|
|
|
|
|
|
|
|
|
|
$scope.ready = true;
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// setup all the dialog focus handling
|
2021-06-21 16:23:34 -07:00
|
|
|
['volumeAddModal', 'volumeRemoveModal'].forEach(function (id) {
|
2020-10-28 16:14:32 -07:00
|
|
|
$('#' + id).on('shown.bs.modal', function () {
|
|
|
|
|
$(this).find('[autofocus]:first').focus();
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
$('.modal-backdrop').remove();
|
|
|
|
|
}]);
|