'use strict'; /* global angular */ /* global $ */ /* global async */ angular.module('Application').controller('VolumesController', ['$scope', '$location', '$timeout', 'Client', function ($scope, $location, $timeout, Client) { Client.onReady(function () { if (!Client.getUserInfo().isAtLeastUserManager) $location.path('/'); }); var refreshVolumesTimerId = null; $scope.config = Client.getConfig(); $scope.volumes = []; $scope.devices = []; $scope.ready = false; $scope.mountTypes = [ { name: 'CIFS', value: 'cifs' }, { name: 'EXT4', value: 'ext4' }, { name: 'Filesystem', value: 'filesystem' }, { name: 'Filesystem (Mountpoint)', value: 'mountpoint' }, { name: 'NFS', value: 'nfs' }, { name: 'SSHFS', value: 'sshfs' }, { name: 'XFS', value: 'xfs' }, ]; function refreshVolumes(callback) { let refreshAgain = false; Client.getVolumes(function (error, results) { if (error) return console.error(error); $scope.volumes = results; async.eachSeries($scope.volumes, function (volume, iteratorDone) { Client.getVolumeStatus(volume.id, function (error, result) { if (error) { console.error('Failed to fetch volume status', volume.name, error); iteratorDone(); } volume.status = result; if (volume.status.state === 'activating') refreshAgain = true; iteratorDone(); }); }, function () { if (!refreshAgain) { clearTimeout(refreshVolumesTimerId); refreshVolumesTimerId = null; } else if (!refreshVolumesTimerId) { refreshVolumesTimerId = setTimeout(refreshVolumes, 5000); } if (callback) callback(); }); }); } // same as box/mounts.js $scope.isMountProvider = function (provider) { return provider === 'sshfs' || provider === 'cifs' || provider === 'nfs' || provider === 'ext4' || provider === 'xfs'; }; $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); }); }, 2000); }); }; $scope.volumeAdd = { error: null, busy: false, name: '', hostPath: '', mountType: 'mountpoint', host: '', remoteDir: '', username: '', password: '', diskPath: '', user: '', seal: false, port: 22, privateKey: '', reset: function () { $scope.volumeAdd.error = null; $scope.volumeAdd.busy = false; $scope.volumeAdd.name = ''; $scope.volumeAdd.hostPath = ''; $scope.volumeAdd.mountType = 'mountpoint'; $scope.volumeAdd.host = ''; $scope.volumeAdd.remoteDir = ''; $scope.volumeAdd.username = ''; $scope.volumeAdd.password = ''; $scope.volumeAdd.diskPath = ''; $scope.volumeAdd.customDiskPath = ''; $scope.volumeAdd.user = ''; $scope.volumeAdd.seal = false; $scope.volumeAdd.port = 22; $scope.volumeAdd.privateKey = ''; $scope.volumeAddForm.$setPristine(); $scope.volumeAddForm.$setUntouched(); }, show: function () { $scope.volumeAdd.reset(); $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'); }); }, submit: function () { $scope.volumeAdd.busy = true; $scope.volumeAdd.error = null; var mountOptions = null; if ($scope.volumeAdd.mountType === 'cifs') { mountOptions = { host: $scope.volumeAdd.host, remoteDir: $scope.volumeAdd.remoteDir, username: $scope.volumeAdd.username, password: $scope.volumeAdd.password, seal: $scope.volumeAdd.seal }; } else if ($scope.volumeAdd.mountType === 'nfs') { mountOptions = { host: $scope.volumeAdd.host, remoteDir: $scope.volumeAdd.remoteDir, }; } else if ($scope.volumeAdd.mountType === 'sshfs') { mountOptions = { host: $scope.volumeAdd.host, port: $scope.volumeAdd.port, remoteDir: $scope.volumeAdd.remoteDir, user: $scope.volumeAdd.user, privateKey: $scope.volumeAdd.privateKey, }; } else if ($scope.volumeAdd.mountType === 'ext4' || $scope.volumeAdd.mountType === 'xfs') { mountOptions = { diskPath: $scope.volumeAdd.diskPath === 'custom' ? $scope.volumeAdd.customDiskPath : $scope.volumeAdd.diskPath }; } var hostPath; if ($scope.volumeAdd.mountType === 'mountpoint' || $scope.volumeAdd.mountType === 'filesystem') { hostPath = $scope.volumeAdd.hostPath; } else { hostPath = null; } Client.addVolume($scope.volumeAdd.name, $scope.volumeAdd.mountType, hostPath, mountOptions, function (error) { $scope.volumeAdd.busy = false; if (error) { $scope.volumeAdd.error = error.message; return; } $('#volumeAddModal').modal('hide'); $scope.volumeAdd.reset(); 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 ['volumeAddModal', 'volumeRemoveModal'].forEach(function (id) { $('#' + id).on('shown.bs.modal', function () { $(this).find('[autofocus]:first').focus(); }); }); $('.modal-backdrop').remove(); }]);