369 lines
12 KiB
JavaScript
369 lines
12 KiB
JavaScript
'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().isAtLeastAdmin) $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.isNetworkProvider = function (provider) {
|
|
return provider === 'sshfs' || provider === 'cifs' || provider === 'nfs';
|
|
};
|
|
|
|
$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: '',
|
|
ext4Disk: null, // { path, type }
|
|
xfsDisk: null, // { path, type }
|
|
user: '',
|
|
seal: true,
|
|
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.ext4Disk = null;
|
|
$scope.volumeAdd.xfsDisk = null;
|
|
$scope.volumeAdd.user = '';
|
|
$scope.volumeAdd.seal = true;
|
|
$scope.volumeAdd.port = 22;
|
|
$scope.volumeAdd.privateKey = '';
|
|
|
|
$scope.volumeAddForm.$setPristine();
|
|
$scope.volumeAddForm.$setUntouched();
|
|
},
|
|
|
|
show: function () {
|
|
$scope.volumeAdd.reset();
|
|
|
|
$scope.ext4BlockDevices = [];
|
|
$scope.xfsBlockDevices = [];
|
|
|
|
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; });
|
|
|
|
$scope.ext4BlockDevices = result.filter(function (d) { return d.type === 'ext4'; });
|
|
$scope.xfsBlockDevices = result.filter(function (d) { return d.type === 'xfs'; });
|
|
|
|
$('#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') {
|
|
mountOptions = {
|
|
diskPath: $scope.volumeAdd.ext4Disk.path
|
|
};
|
|
} else if ($scope.volumeAdd.mountType === 'xfs') {
|
|
mountOptions = {
|
|
diskPath: $scope.volumeAdd.xfsDisk.path
|
|
};
|
|
} else if ($scope.volumeAdd.mountType === 'mountpoint' || $scope.volumeAdd.mountType === 'filesystem') {
|
|
mountOptions = {
|
|
hostPath: $scope.volumeAdd.hostPath
|
|
};
|
|
}
|
|
|
|
Client.addVolume($scope.volumeAdd.name, $scope.volumeAdd.mountType, mountOptions, function (error) {
|
|
$scope.volumeAdd.busy = false;
|
|
if (error) {
|
|
$scope.volumeAdd.error = error.message;
|
|
return;
|
|
}
|
|
|
|
$('#volumeAddModal').modal('hide');
|
|
$scope.volumeAdd.reset();
|
|
|
|
refreshVolumes();
|
|
});
|
|
}
|
|
};
|
|
|
|
$scope.volumeEdit = {
|
|
error: null,
|
|
busy: false,
|
|
|
|
// cannot be changed
|
|
volume: '',
|
|
name: '',
|
|
mountType: 'mountpoint',
|
|
|
|
// can be changed
|
|
host: '',
|
|
remoteDir: '',
|
|
username: '',
|
|
password: '',
|
|
user: '',
|
|
seal: true,
|
|
port: 22,
|
|
privateKey: '',
|
|
|
|
reset: function () {
|
|
$scope.volumeEdit.error = null;
|
|
$scope.volumeEdit.busy = false;
|
|
$scope.volumeEdit.volume = null;
|
|
$scope.volumeEdit.name = '';
|
|
$scope.volumeEdit.mountType = '';
|
|
$scope.volumeEdit.host = '';
|
|
$scope.volumeEdit.seal = true;
|
|
$scope.volumeEdit.port = '';
|
|
$scope.volumeEdit.remoteDir = '';
|
|
$scope.volumeEdit.username = '';
|
|
$scope.volumeEdit.password = '';
|
|
$scope.volumeEdit.user = '';
|
|
$scope.volumeEdit.privateKey = '';
|
|
|
|
$scope.volumeEditForm.$setPristine();
|
|
$scope.volumeEditForm.$setUntouched();
|
|
},
|
|
|
|
show: function (volume) {
|
|
$scope.volumeEdit.reset();
|
|
|
|
Client.getVolume(volume.id, function (error, result) {
|
|
if (error) console.error('Failed to get volume:', error);
|
|
|
|
$scope.volumeEdit.volume = volume;
|
|
$scope.volumeEdit.mountType = result.mountType;
|
|
$scope.volumeEdit.name = result.name;
|
|
$scope.volumeEdit.host = result.mountOptions.host;
|
|
$scope.volumeEdit.seal = result.mountOptions.seal;
|
|
$scope.volumeEdit.port = result.mountOptions.port;
|
|
$scope.volumeEdit.remoteDir = result.mountOptions.remoteDir;
|
|
$scope.volumeEdit.username = result.mountOptions.username;
|
|
$scope.volumeEdit.password = result.mountOptions.password;
|
|
$scope.volumeEdit.user = result.mountOptions.user;
|
|
$scope.volumeEdit.privateKey = result.mountOptions.privateKey;
|
|
|
|
$('#volumeEditModal').modal('show');
|
|
});
|
|
},
|
|
|
|
submit: function () {
|
|
$scope.volumeEdit.busy = true;
|
|
$scope.volumeEdit.error = null;
|
|
|
|
var mountOptions = null;
|
|
|
|
if ($scope.volumeEdit.mountType === 'cifs') {
|
|
mountOptions = {
|
|
host: $scope.volumeEdit.host,
|
|
remoteDir: $scope.volumeEdit.remoteDir,
|
|
username: $scope.volumeEdit.username,
|
|
password: $scope.volumeEdit.password,
|
|
seal: $scope.volumeEdit.seal
|
|
};
|
|
} else if ($scope.volumeEdit.mountType === 'nfs') {
|
|
mountOptions = {
|
|
host: $scope.volumeEdit.host,
|
|
remoteDir: $scope.volumeEdit.remoteDir,
|
|
};
|
|
} else if ($scope.volumeEdit.mountType === 'sshfs') {
|
|
mountOptions = {
|
|
host: $scope.volumeEdit.host,
|
|
port: $scope.volumeEdit.port,
|
|
remoteDir: $scope.volumeEdit.remoteDir,
|
|
user: $scope.volumeEdit.user,
|
|
privateKey: $scope.volumeEdit.privateKey,
|
|
};
|
|
} else {
|
|
console.error('Should not come here. Only network volumes can be edited');
|
|
|
|
$('#volumeEditModal').modal('hide');
|
|
$scope.volumeEdit.reset();
|
|
|
|
return;
|
|
}
|
|
|
|
Client.updateVolume($scope.volumeEdit.volume.id, mountOptions, function (error) {
|
|
$scope.volumeEdit.busy = false;
|
|
if (error) {
|
|
$scope.volumeEdit.error = error.message;
|
|
return;
|
|
}
|
|
|
|
$('#volumeEditModal').modal('hide');
|
|
$scope.volumeEdit.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();
|
|
}]);
|