On Tue, Aug 26, 2025 at 5:00 AM Daniel Kral <d.k...@proxmox.com> wrote: > > Hm, the buttons might be a little ambiguous that these are only for LRM > entries... But I think it's a good start as there isn't a dedicated list > for the LRMs which gives more room for action buttons that can be done > on all items. But let's wait for other feedback.
I wasn't sure where the best place for buttons to go would be, but Thomas Lamprecht suggested in [1] to place in the HA overview, so that's where I figured it would fit best. I agree with his logic on needing to check HA status before enabling/disabling the maintenance. Selectable grid was an easy implementation there and the status was already being polled. [1]: https://lore.proxmox.com/pve-devel/90de8fa6-0e31-4273-adf3-ad337ec39...@proxmox.com/ > On Mon Aug 25, 2025 at 6:11 AM CEST, Thomas Skinner wrote: > > Signed-off-by: Thomas Skinner <tho...@atskinner.net> > > --- > > www/manager6/ha/StatusView.js | 85 +++++++++++++++++++++++++++++++++++ > > 1 file changed, 85 insertions(+) > > > > diff --git a/www/manager6/ha/StatusView.js b/www/manager6/ha/StatusView.js > > index 50ad8e84..79e12df5 100644 > > --- a/www/manager6/ha/StatusView.js > > +++ b/www/manager6/ha/StatusView.js > > @@ -41,12 +41,58 @@ Ext.define( > > }, > > }); > > > > + let sm = Ext.create('Ext.selection.RowModel', {}); > > + > > + let caps = Ext.state.Manager.get('GuiCap'); > > + > > + var node_maintenance_disable = function (disable) { > > var mustn't be used for new code anymore [0], and new variable names > should be in camelCase [1]. > > [0] https://pve.proxmox.com/wiki/Javascript_Style_Guide#Variables > [1] https://pve.proxmox.com/wiki/Javascript_Style_Guide#Casing Some copypasta got the best of me here. Will update for v2. > this could be an arrow function and the function's variable name is > rather fragile as 'disable' can be set and then does a rather different > action to the node maintenance.. Maybe just "setNodeMaintenance"? > > > + let rec = sm.getSelection()[0]; > > + if (!rec || rec.data.type !== "lrm") { > > + return; > > + } > > + let nodename = rec.get('node'); > > + let enableText = disable ? 'Disable' : 'Enable'; > > + let msg = Ext.String.format(gettext("{0} maintenance mode > > on node '{1}'?"), enableText, nodename); > > + Ext.Msg.confirm(gettext('Confirm'), msg, (btn) => { > > + if (btn === 'yes') { > > + Proxmox.Utils.API2Request({ > > + params: { disable: disable ? 1 : 0 }, > > + url: '/cluster/ha/nodes/' + nodename + > > '/maintenance', > > + method: 'POST', > > + waitMsgTarget: me, > > + failure: function (response, opts) { > > + Ext.Msg.alert(gettext('Error'), > > response.htmlStatus); > > + }, > > + }); > > + } > > + }); > > + }; > > + > > Ext.apply(me, { > > store: store, > > + selModel: sm, > > stateful: false, > > viewConfig: { > > trackOver: false, > > }, > > + tbar: [ > > + { > > + text: gettext('Enable Maintenance Mode'), > > + itemId: 'enableMaintBtn', > > + disabled: true, > > + handler: function () { > > + node_maintenance_disable(false); > > + }, > > nit: use an arrow function instead > > handler: () => node_maintenance_disable(false), Oh, I didn't know that was possible. Will fix up this one and the next. > > + }, > > + { > > + text: gettext('Disable Maintenance Mode'), > > + itemId: 'disableMaintBtn', > > + disabled: true, > > + handler: function () { > > + node_maintenance_disable(true); > > nit: same here > > > + }, > > + }, > > + ], > > columns: [ > > { > > header: gettext('Type'), > > @@ -60,12 +106,50 @@ Ext.define( > > dataIndex: 'status', > > }, > > ], > > + listeners: { > > + beforeselect: function (tree, record, index, eopts) { > > + if (!caps.nodes['Sys.Console']) { > > + return; > > + } > > + let enableMaintBtnDisable = true; > > + let disableMaintBtnDisable = true; > > + if (record && record.data.type === "lrm") { > > + if (record.data.lrm_mode && > > record.data.lrm_mode === 'maintenance') { > > + disableMaintBtnDisable = false; > > + } else { > > + enableMaintBtnDisable = false; > > + } > > + } > > + > > me.down('#enableMaintBtn').setDisabled(enableMaintBtnDisable); > > + > > me.down('#disableMaintBtn').setDisabled(disableMaintBtnDisable); > > + }, > > + } > > }); > > > > me.callParent(); > > > > me.on('activate', me.rstore.startUpdate); > > me.on('destroy', me.rstore.stopUpdate); > > + > > + me.mon(me.rstore, 'load', function (curstore, results) { > > + let rec = sm.getSelection()[0]; > > + if (!rec || rec.data.type !== "lrm") { > > + return; > > + } > > + for (const { data } of results) { > > + switch (data.type) { > > + case 'lrm': > > + if (rec.data.node === data.node) { > > + let inMaint = rec.data.lrm_mode === > > 'maintenance'; > > + > > me.down('#enableMaintBtn').setDisabled(inMaint); > > + > > me.down('#disableMaintBtn').setDisabled(!inMaint); > > + } > > + break; > > + default: > > + break; > > + } > > + } > > + }); > > }, > > }, > > function () { > > @@ -88,6 +172,7 @@ Ext.define( > > 'type', > > 'crm_state', > > 'request_state', > > + 'lrm_mode', > > { > > name: 'vname', > > convert: function (value, record) { > > _______________________________________________ pve-devel mailing list pve-devel@lists.proxmox.com https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel