[pbs-devel] [PATCH proxmox-backup v3 2/2] ui/cli: added support for the removal of mount-units
Hannes Laimer
h.laimer at proxmox.com
Thu Aug 13 12:58:53 CEST 2020
Signed-off-by: Hannes Laimer <h.laimer at proxmox.com>
---
src/bin/proxmox_backup_manager/disk.rs | 29 +++-
www/DirectoryList.js | 150 ++++++++++--------
www/Makefile | 1 +
www/window/SafeRemove.js | 209 +++++++++++++++++++++++++
4 files changed, 325 insertions(+), 64 deletions(-)
create mode 100644 www/window/SafeRemove.js
diff --git a/src/bin/proxmox_backup_manager/disk.rs b/src/bin/proxmox_backup_manager/disk.rs
index a93a6f6b..b7eec592 100644
--- a/src/bin/proxmox_backup_manager/disk.rs
+++ b/src/bin/proxmox_backup_manager/disk.rs
@@ -319,6 +319,32 @@ async fn create_datastore_disk(
Ok(Value::Null)
}
+#[api(
+ input: {
+ properties: {
+ name: {
+ schema: DATASTORE_SCHEMA,
+ },
+ },
+ },
+)]
+/// Remove a Filesystem mounted under '/mnt/datastore/<name>'.".
+async fn delete_datastore_disk(
+ mut param: Value,
+ rpcenv: &mut dyn RpcEnvironment,
+) -> Result<Value, Error> {
+
+ param["node"] = "localhost".into();
+
+ let info = &api2::node::disks::directory::API_METHOD_DELETE_DATASTORE_DISK;
+ match info.handler {
+ ApiHandler::Sync(handler) => (handler)(param, info, rpcenv)?,
+ _ => unreachable!(),
+ };
+
+ Ok(Value::Null)
+}
+
pub fn filesystem_commands() -> CommandLineInterface {
let cmd_def = CliCommandMap::new()
@@ -327,7 +353,8 @@ pub fn filesystem_commands() -> CommandLineInterface {
CliCommand::new(&API_METHOD_CREATE_DATASTORE_DISK)
.arg_param(&["name"])
.completion_cb("disk", complete_disk_name)
- );
+ ).insert("remove", CliCommand::new(&API_METHOD_DELETE_DATASTORE_DISK)
+ .arg_param(&["name"]));
cmd_def.into()
}
diff --git a/www/DirectoryList.js b/www/DirectoryList.js
index 00531fd0..6ec91e6a 100644
--- a/www/DirectoryList.js
+++ b/www/DirectoryList.js
@@ -8,83 +8,107 @@ Ext.define('PBS.admin.Directorylist', {
emptyText: gettext('No Mount-Units found'),
controller: {
- xclass: 'Ext.app.ViewController',
+ xclass: 'Ext.app.ViewController',
- createDirectory: function() {
- let me = this;
- Ext.create('PBS.window.CreateDirectory', {
- listeners: {
- destroy: function() {
- me.reload();
- },
- },
- }).show();
- },
+ createDirectory: function () {
+ console.log(this);
+ let me = this;
+ Ext.create('PBS.window.CreateDirectory', {
+ listeners: {
+ destroy: function () {
+ me.reload();
+ },
+ },
+ }).show();
+ },
- reload: function() {
- let me = this;
- let store = me.getView().getStore();
- store.load();
- store.sort();
- },
+ removeDir: function () {
+ let me = this;
+ let view = me.getView();
+ let rec = view.getSelection();
+ let dialog = Ext.create('PBS.window.SafeDestroy', {
+ url: rec[0].data.path.replace(
+ '/mnt/datastore/',
+ '/nodes/localhost/disks/directory/'),
+ item: {type: 'Dir', id: rec[0].data.path.replace('/mnt/datastore/', '')},
+ note: 'Data and partitions on the disk will be left untouched.'
+ });
+ dialog.on('destroy', function() {
+ me.reload();
+ });
+ dialog.show();
+ },
- init: function(view) {
- let me = this;
- Proxmox.Utils.monStoreErrors(view, view.getStore(), true);
- me.reload();
- },
- },
+ reload: function () {
+ let me = this;
+ let store = me.getView().getStore();
+ store.load();
+ store.sort();
+ },
+ init: function (view) {
+ let me = this;
+ Proxmox.Utils.monStoreErrors(view, view.getStore(), true);
+ me.reload();
+ },
+ },
rootVisible: false,
useArrows: true,
tbar: [
- {
- text: gettext('Reload'),
- iconCls: 'fa fa-refresh',
- handler: 'reload',
- },
- {
- text: gettext('Create') + ': Directory',
- handler: 'createDirectory',
- },
+ {
+ text: gettext('Reload'),
+ iconCls: 'fa fa-refresh',
+ handler: 'reload',
+ },
+ {
+ text: gettext('Create') + ': Directory',
+ handler: 'createDirectory',
+ },
+ {
+ xtype: 'proxmoxButton',
+ text: gettext('Remove'),
+ handler: 'removeDir',
+ disabled: true,
+ iconCls: 'fa fa-trash-o'
+ }
],
columns: [
- {
- text: gettext('Path'),
- dataIndex: 'path',
- flex: 1,
- },
- {
- header: gettext('Device'),
- flex: 1,
- dataIndex: 'device',
- },
- {
- header: gettext('Filesystem'),
- width: 100,
- dataIndex: 'filesystem',
- },
- {
- header: gettext('Options'),
- width: 100,
- dataIndex: 'options',
- },
- {
- header: gettext('Unit File'),
- hidden: true,
- dataIndex: 'unitfile',
- },
+ {
+ text: gettext('Path'),
+ dataIndex: 'path',
+ flex: 1,
+ },
+ {
+ header: gettext('Device'),
+ flex: 1,
+ dataIndex: 'device',
+ },
+ {
+ header: gettext('Filesystem'),
+ width: 100,
+ dataIndex: 'filesystem',
+ },
+ {
+ header: gettext('Options'),
+ width: 100,
+ dataIndex: 'options',
+ },
+ {
+ header: gettext('Unit File'),
+ hidden: true,
+ dataIndex: 'unitfile',
+ },
],
store: {
- fields: ['path', 'device', 'filesystem', 'options', 'unitfile'],
- proxy: {
- type: 'proxmox',
- url: '/api2/json/nodes/localhost/disks/directory',
- },
- sorters: 'path',
+ fields: ['path', 'device', 'filesystem', 'options', 'unitfile'],
+ proxy: {
+ type: 'proxmox',
+ url: '/api2/json/nodes/localhost/disks/directory',
+ },
+ sorters: 'path',
},
});
diff --git a/www/Makefile b/www/Makefile
index edce8cb3..57db54ee 100644
--- a/www/Makefile
+++ b/www/Makefile
@@ -23,6 +23,7 @@ JSSRC= \
window/SyncJobEdit.js \
window/ACLEdit.js \
window/DataStoreEdit.js \
+ window/SafeRemove.js \
window/CreateDirectory.js \
window/ZFSCreate.js \
window/FileBrowser.js \
diff --git a/www/window/SafeRemove.js b/www/window/SafeRemove.js
new file mode 100644
index 00000000..fdbefeae
--- /dev/null
+++ b/www/window/SafeRemove.js
@@ -0,0 +1,209 @@
+/* Popup a message window
+ * where the user has to manually enter the resource ID
+ * to enable the destroy button
+ * (mostly taken from PVE-Manager(git.proxmox.com/git/pve-manager.git))
+ */
+Ext.define('PBS.window.SafeDestroy', {
+ extend: 'Ext.window.Window',
+
+ title: gettext('Confirm'),
+ modal: true,
+ buttonAlign: 'center',
+ bodyPadding: 10,
+ width: 450,
+ layout: {type: 'hbox'},
+ defaultFocus: 'confirmField',
+ showProgress: false,
+
+ config: {
+ item: {
+ id: undefined,
+ type: undefined
+ },
+ url: undefined,
+ note: undefined,
+ params: {}
+ },
+
+ getParams: function () {
+ var me = this;
+ var wipeCheckbox = me.lookupReference('wipeCheckbox');
+ if (wipeCheckbox.checked) {
+ me.params.wipe = 1;
+ }
+ if (Ext.Object.isEmpty(me.params)) {
+ return '';
+ }
+ return '?' + Ext.Object.toQueryString(me.params);
+ },
+
+ controller: {
+
+ xclass: 'Ext.app.ViewController',
+
+ control: {
+ 'field[name=confirm]': {
+ change: function (f, value) {
+ var view = this.getView();
+ var removeButton = this.lookupReference('removeButton');
+ if (value === view.getItem().id.toString()) {
+ removeButton.enable();
+ } else {
+ removeButton.disable();
+ }
+ },
+ specialkey: function (field, event) {
+ var removeButton = this.lookupReference('removeButton');
+ if (!removeButton.isDisabled() && event.getKey() == event.ENTER) {
+ removeButton.fireEvent('click', removeButton, event);
+ }
+ }
+ },
+ 'button[reference=removeButton]': {
+ click: function () {
+ var view = this.getView();
+ Proxmox.Utils.API2Request({
+ url: view.getUrl() + view.getParams(),
+ method: 'DELETE',
+ waitMsgTarget: view,
+ failure: function (response, opts) {
+ view.close();
+ Ext.Msg.alert('Error', response.htmlStatus);
+ },
+ success: function (response, options) {
+ var hasProgressBar = view.showProgress &&
+ response.result.data ? true : false;
+
+ if (hasProgressBar) {
+ // stay around so we can trigger our close events
+ // when background action is completed
+ view.hide();
+
+ var upid = response.result.data;
+ var win = Ext.create('Proxmox.window.TaskProgress', {
+ upid: upid,
+ listeners: {
+ destroy: function () {
+ view.close();
+ }
+ }
+ });
+ win.show();
+ } else {
+ view.close();
+ }
+ }
+ });
+ }
+ }
+ }
+ },
+
+ items: [
+ {
+ xtype: 'component',
+ cls: [Ext.baseCSSPrefix + 'message-box-icon',
+ Ext.baseCSSPrefix + 'message-box-warning',
+ Ext.baseCSSPrefix + 'dlg-icon']
+ },
+ {
+ xtype: 'container',
+ flex: 1,
+ layout: {
+ type: 'vbox',
+ align: 'stretch'
+ },
+ items: [
+ {
+ xtype: 'component',
+ reference: 'messageCmp'
+ },
+ {
+ itemId: 'confirmField',
+ reference: 'confirmField',
+ xtype: 'textfield',
+ name: 'confirm',
+ labelWidth: 300,
+ hideTrigger: true,
+ allowBlank: false
+ },
+ {
+ xtype: 'proxmoxcheckbox',
+ name: 'wipe',
+ reference: 'wipeCheckbox',
+ boxLabel: gettext('Wipe'),
+ checked: false,
+ autoEl: {
+ tag: 'div',
+ 'data-qtip': gettext('Wipe disk after the removal of mountpoint')
+ }
+ },
+ {
+ xtype: 'container',
+ flex: 1,
+ layout: {
+ type: 'vbox',
+ align: 'middle'
+ },
+ height: 25,
+ items: [
+ {
+ xtype: 'component',
+ reference: 'noteCmp'
+ },
+ ]
+ },
+ ]
+ }
+ ],
+ buttons: [
+ {
+ reference: 'removeButton',
+ text: gettext('Remove'),
+ disabled: true
+ }
+ ],
+
+ initComponent: function () {
+ var me = this;
+
+ me.callParent();
+
+ var item = me.getItem();
+
+ if (!Ext.isDefined(item.id)) {
+ throw "no ID specified";
+ }
+
+ if (!Ext.isDefined(item.type)) {
+ throw "no Disk type specified";
+ }
+
+ var messageCmp = me.lookupReference('messageCmp');
+ var noteCmp = me.lookupReference('noteCmp');
+ var msg;
+
+ if (item.type === 'Dir') {
+ msg = `Directory ${item.id} - Remove`
+ } else {
+ throw "unknown item type specified";
+ }
+
+ if(me.getNote()) {
+ noteCmp.setHtml(`<small>${me.getNote()}</small>`);
+ }
+
+ messageCmp.setHtml(msg);
+
+ if (item.type === 'Dir') {
+ let wipeCheckbox = me.lookupReference('wipeCheckbox');
+ wipeCheckbox.setDisabled(true);
+ wipeCheckbox.setHidden(true);
+ }
+
+ var confirmField = me.lookupReference('confirmField');
+ msg = gettext('Please enter the ID to confirm') +
+ ' (' + item.id + ')';
+ confirmField.setFieldLabel(msg);
+ }
+});
--
2.20.1
More information about the pbs-devel
mailing list