From: Fabian Ebner <f.ebner@proxmox.com>
To: pve-devel@lists.proxmox.com
Subject: [pve-devel] [PATCH manager 4/6] ui: node: add destroy menu for directory, lvm, lvmthin, zfs
Date: Mon, 25 Oct 2021 15:47:53 +0200 [thread overview]
Message-ID: <20211025134755.169491-11-f.ebner@proxmox.com> (raw)
In-Reply-To: <20211025134755.169491-1-f.ebner@proxmox.com>
Signed-off-by: Fabian Ebner <f.ebner@proxmox.com>
---
Dependency bump for pve-storage needed.
www/manager6/node/Directory.js | 82 ++++++++++++++++++++++++++++++
www/manager6/node/LVM.js | 83 ++++++++++++++++++++++++++++++
www/manager6/node/LVMThin.js | 93 ++++++++++++++++++++++++++++++++++
www/manager6/node/ZFS.js | 81 ++++++++++++++++++++++++++++-
4 files changed, 337 insertions(+), 2 deletions(-)
diff --git a/www/manager6/node/Directory.js b/www/manager6/node/Directory.js
index 67f56870..c3dba2ef 100644
--- a/www/manager6/node/Directory.js
+++ b/www/manager6/node/Directory.js
@@ -63,6 +63,43 @@ Ext.define('PVE.node.Directorylist', {
extend: 'Ext.grid.Panel',
xtype: 'pveDirectoryList',
+ viewModel: {
+ data: {
+ path: '',
+ },
+ formulas: {
+ dirName: (get) => get('path')?.replace('/mnt/pve/', '') || undefined,
+ },
+ },
+
+ controller: {
+ xclass: 'Ext.app.ViewController',
+
+ destroyDirectory: function() {
+ let me = this;
+ let vm = me.getViewModel();
+ let view = me.getView();
+
+ const dirName = vm.get('dirName');
+
+ if (!view.nodename) {
+ throw "no node name specified";
+ }
+
+ if (!dirName) {
+ throw "no directory name specified";
+ }
+
+ Ext.create('Proxmox.window.SafeDestroy', {
+ url: `/nodes/${view.nodename}/disks/directory/${dirName}`,
+ item: { id: dirName },
+ showProgress: true,
+ taskName: 'dirremove',
+ taskDone: () => { view.reload(); },
+ }).show();
+ },
+ },
+
stateful: true,
stateId: 'grid-node-directory',
columns: [
@@ -117,6 +154,45 @@ Ext.define('PVE.node.Directorylist', {
});
},
},
+ '->',
+ {
+ xtype: 'tbtext',
+ data: {
+ dirName: undefined,
+ },
+ bind: {
+ data: {
+ dirName: "{dirName}",
+ },
+ },
+ tpl: [
+ '<tpl if="dirName">',
+ gettext('Directory') + ' {dirName}:',
+ '<tpl else>',
+ Ext.String.format(gettext('No {0} selected'), gettext('directory')),
+ '</tpl>',
+ ],
+ },
+ {
+ text: gettext('More'),
+ iconCls: 'fa fa-bars',
+ disabled: true,
+ bind: {
+ disabled: '{!dirName}',
+ },
+ menu: [
+ {
+ text: gettext('Destroy'),
+ itemId: 'remove',
+ iconCls: 'fa fa-fw fa-trash-o',
+ handler: 'destroyDirectory',
+ disabled: true,
+ bind: {
+ disabled: '{!dirName}',
+ },
+ },
+ ],
+ },
],
reload: function() {
@@ -129,6 +205,12 @@ Ext.define('PVE.node.Directorylist', {
activate: function() {
this.reload();
},
+ selectionchange: function(model, selected) {
+ let me = this;
+ let vm = me.getViewModel();
+
+ vm.set('path', selected[0]?.data.path || '');
+ },
},
initComponent: function() {
diff --git a/www/manager6/node/LVM.js b/www/manager6/node/LVM.js
index 4b5225d8..70ddf451 100644
--- a/www/manager6/node/LVM.js
+++ b/www/manager6/node/LVM.js
@@ -52,6 +52,40 @@ Ext.define('PVE.node.LVMList', {
extend: 'Ext.tree.Panel',
xtype: 'pveLVMList',
+ viewModel: {
+ data: {
+ volumeGroup: '',
+ },
+ },
+
+ controller: {
+ xclass: 'Ext.app.ViewController',
+
+ destroyVolumeGroup: function() {
+ let me = this;
+ let vm = me.getViewModel();
+ let view = me.getView();
+
+ const volumeGroup = vm.get('volumeGroup');
+
+ if (!view.nodename) {
+ throw "no node name specified";
+ }
+
+ if (!volumeGroup) {
+ throw "no volume group specified";
+ }
+
+ Ext.create('Proxmox.window.SafeDestroy', {
+ url: `/nodes/${view.nodename}/disks/lvm/${volumeGroup}`,
+ item: { id: volumeGroup },
+ showProgress: true,
+ taskName: 'lvmremove',
+ taskDone: () => { view.reload(); },
+ }).show();
+ },
+ },
+
emptyText: gettext('No Volume Groups found'),
stateful: true,
@@ -120,6 +154,45 @@ Ext.define('PVE.node.LVMList', {
});
},
},
+ '->',
+ {
+ xtype: 'tbtext',
+ data: {
+ volumeGroup: undefined,
+ },
+ bind: {
+ data: {
+ volumeGroup: "{volumeGroup}",
+ },
+ },
+ tpl: [
+ '<tpl if="volumeGroup">',
+ 'Volume group {volumeGroup}:',
+ '<tpl else>',
+ Ext.String.format(gettext('No {0} selected'), 'volume group'),
+ '</tpl>',
+ ],
+ },
+ {
+ text: gettext('More'),
+ iconCls: 'fa fa-bars',
+ disabled: true,
+ bind: {
+ disabled: '{!volumeGroup}',
+ },
+ menu: [
+ {
+ text: gettext('Destroy'),
+ itemId: 'remove',
+ iconCls: 'fa fa-fw fa-trash-o',
+ handler: 'destroyVolumeGroup',
+ disabled: true,
+ bind: {
+ disabled: '{!volumeGroup}',
+ },
+ },
+ ],
+ },
],
reload: function() {
@@ -142,6 +215,16 @@ Ext.define('PVE.node.LVMList', {
activate: function() {
this.reload();
},
+ selectionchange: function(model, selected) {
+ let me = this;
+ let vm = me.getViewModel();
+
+ if (selected.length < 1 || selected[0].data.parentId !== 'root') {
+ vm.set('volumeGroup', '');
+ } else {
+ vm.set('volumeGroup', selected[0].data.name);
+ }
+ },
},
selModel: 'treemodel',
diff --git a/www/manager6/node/LVMThin.js b/www/manager6/node/LVMThin.js
index 4a0b21ba..ca32bb3b 100644
--- a/www/manager6/node/LVMThin.js
+++ b/www/manager6/node/LVMThin.js
@@ -50,6 +50,47 @@ Ext.define('PVE.node.LVMThinList', {
extend: 'Ext.grid.Panel',
xtype: 'pveLVMThinList',
+ viewModel: {
+ data: {
+ thinPool: '',
+ volumeGroup: '',
+ },
+ },
+
+ controller: {
+ xclass: 'Ext.app.ViewController',
+
+ destroyThinPool: function() {
+ let me = this;
+ let vm = me.getViewModel();
+ let view = me.getView();
+
+ const thinPool = vm.get('thinPool');
+ const volumeGroup = vm.get('volumeGroup');
+
+ if (!view.nodename) {
+ throw "no node name specified";
+ }
+
+ if (!thinPool) {
+ throw "no thin pool specified";
+ }
+
+ if (!volumeGroup) {
+ throw "no volume group specified";
+ }
+
+ Ext.create('Proxmox.window.SafeDestroy', {
+ url: `/nodes/${view.nodename}/disks/lvmthin/${thinPool}`,
+ params: { 'volume-group': volumeGroup },
+ item: { id: `${volumeGroup}/${thinPool}` },
+ showProgress: true,
+ taskName: 'lvmthinremove',
+ taskDone: () => { view.reload(); },
+ }).show();
+ },
+ },
+
emptyText: gettext('No thinpools found'),
stateful: true,
@@ -142,6 +183,51 @@ Ext.define('PVE.node.LVMThinList', {
});
},
},
+ '->',
+ {
+ xtype: 'tbtext',
+ data: {
+ thinPool: undefined,
+ volumeGroup: undefined,
+ },
+ bind: {
+ data: {
+ thinPool: "{thinPool}",
+ volumeGroup: "{volumeGroup}",
+ },
+ },
+ tpl: [
+ '<tpl if="thinPool">',
+ '<tpl if="volumeGroup">',
+ 'Thinpool {volumeGroup}/{thinPool}:',
+ '<tpl else>', // volumeGroup
+ 'Missing volume group (node running old version?)',
+ '</tpl>',
+ '<tpl else>', // thinPool
+ Ext.String.format(gettext('No {0} selected'), 'thinpool'),
+ '</tpl>',
+ ],
+ },
+ {
+ text: gettext('More'),
+ iconCls: 'fa fa-bars',
+ disabled: true,
+ bind: {
+ disabled: '{!volumeGroup || !thinPool}',
+ },
+ menu: [
+ {
+ text: gettext('Destroy'),
+ itemId: 'remove',
+ iconCls: 'fa fa-fw fa-trash-o',
+ handler: 'destroyThinPool',
+ disabled: true,
+ bind: {
+ disabled: '{!volumeGroup || !thinPool}',
+ },
+ },
+ ],
+ },
],
reload: function() {
@@ -154,6 +240,13 @@ Ext.define('PVE.node.LVMThinList', {
activate: function() {
this.reload();
},
+ selectionchange: function(model, selected) {
+ let me = this;
+ let vm = me.getViewModel();
+
+ vm.set('volumeGroup', selected[0]?.data.vg || '');
+ vm.set('thinPool', selected[0]?.data.lv || '');
+ },
},
initComponent: function() {
diff --git a/www/manager6/node/ZFS.js b/www/manager6/node/ZFS.js
index 8ea364bf..c5c5aac8 100644
--- a/www/manager6/node/ZFS.js
+++ b/www/manager6/node/ZFS.js
@@ -297,6 +297,40 @@ Ext.define('PVE.node.ZFSList', {
extend: 'Ext.grid.Panel',
xtype: 'pveZFSList',
+ viewModel: {
+ data: {
+ pool: '',
+ },
+ },
+
+ controller: {
+ xclass: 'Ext.app.ViewController',
+
+ destroyPool: function() {
+ let me = this;
+ let vm = me.getViewModel();
+ let view = me.getView();
+
+ const pool = vm.get('pool');
+
+ if (!view.nodename) {
+ throw "no node name specified";
+ }
+
+ if (!pool) {
+ throw "no pool specified";
+ }
+
+ Ext.create('Proxmox.window.SafeDestroy', {
+ url: `/nodes/${view.nodename}/disks/zfs/${pool}`,
+ item: { id: pool },
+ showProgress: true,
+ taskName: 'zfsremove',
+ taskDone: () => { view.reload(); },
+ }).show();
+ },
+ },
+
stateful: true,
stateId: 'grid-node-zfs',
columns: [
@@ -378,6 +412,45 @@ Ext.define('PVE.node.ZFSList', {
}
},
},
+ '->',
+ {
+ xtype: 'tbtext',
+ data: {
+ pool: undefined,
+ },
+ bind: {
+ data: {
+ pool: "{pool}",
+ },
+ },
+ tpl: [
+ '<tpl if="pool">',
+ 'Pool {pool}:',
+ '<tpl else>',
+ Ext.String.format(gettext('No {0} selected'), 'pool'),
+ '</tpl>',
+ ],
+ },
+ {
+ text: gettext('More'),
+ iconCls: 'fa fa-bars',
+ disabled: true,
+ bind: {
+ disabled: '{!pool}',
+ },
+ menu: [
+ {
+ text: gettext('Destroy'),
+ itemId: 'remove',
+ iconCls: 'fa fa-fw fa-trash-o',
+ handler: 'destroyPool',
+ disabled: true,
+ bind: {
+ disabled: '{!pool}',
+ },
+ },
+ ],
+ },
],
show_detail: function(zpool) {
@@ -445,8 +518,12 @@ Ext.define('PVE.node.ZFSList', {
activate: function() {
this.reload();
},
- selectionchange: function() {
- this.down('#detailbtn').setDisabled(this.getSelection().length === 0);
+ selectionchange: function(model, selected) {
+ let me = this;
+ let vm = me.getViewModel();
+
+ me.down('#detailbtn').setDisabled(selected.length === 0);
+ vm.set('pool', selected[0]?.data.name || '');
},
itemdblclick: function(grid, record) {
this.show_detail(record.get('name'));
--
2.30.2
next prev parent reply other threads:[~2021-10-25 13:48 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-10-25 13:47 [pve-devel] [PATCH-SERIES storage/manager] disk-level storage removal for directory, LVM, LVM-thin, ZFS Fabian Ebner
2021-10-25 13:47 ` [pve-devel] [PATCH storage 1/6] LVM: add lvm_destroy_volume_group Fabian Ebner
2021-10-25 13:47 ` [pve-devel] [PATCH storage 2/6] api: disks: add DELETE endpoint for directory, lvm, lvmthin, zfs Fabian Ebner
2021-10-25 13:47 ` [pve-devel] [PATCH storage 3/6] api: list thin pools: add volume group to properties Fabian Ebner
2021-10-25 13:47 ` [pve-devel] [PATCH storage 4/6] diskmanage: add helper for udev workaround Fabian Ebner
2021-10-25 13:47 ` [pve-devel] [PATCH storage 5/6] api: disks: delete: add flag for wiping disks Fabian Ebner
2021-10-25 13:47 ` [pve-devel] [PATCH storage 6/6] api: disks: delete: add flag for cleaning up storage config Fabian Ebner
2021-10-25 13:47 ` [pve-devel] [PATCH manager 1/6] ui: node: directory: use gettext for 'Directory' Fabian Ebner
2021-10-25 13:47 ` [pve-devel] [PATCH manager 2/6] ui: node: lvmthin: add volume group to columns Fabian Ebner
2021-10-25 13:47 ` [pve-devel] [PATCH manager 3/6] ui: utils: add task descriptions for disk removal Fabian Ebner
2021-10-25 13:47 ` Fabian Ebner [this message]
2021-10-25 13:47 ` [pve-devel] [PATCH manager 5/6] ui: node: storage removal: add checkbox for cleaning up disks Fabian Ebner
2021-10-25 13:47 ` [pve-devel] [PATCH manager 6/6] ui: node: storage removal: add checkbox for cleaning up storage config Fabian Ebner
2021-11-10 13:30 ` [pve-devel] applied-series: [PATCH-SERIES storage/manager] disk-level storage removal for directory, LVM, LVM-thin, ZFS Fabian Grünbichler
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20211025134755.169491-11-f.ebner@proxmox.com \
--to=f.ebner@proxmox.com \
--cc=pve-devel@lists.proxmox.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox