[pve-devel] [PATCH manager 2/2] add UI for node maintenance enable/disable

Daniel Kral d.kral at proxmox.com
Tue Aug 26 12:00:19 CEST 2025


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.

On Mon Aug 25, 2025 at 6:11 AM CEST, Thomas Skinner wrote:
> Signed-off-by: Thomas Skinner <thomas at 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

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),

> +                    },
> +                    {
> +                        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) {





More information about the pve-devel mailing list