public inbox for pve-devel@lists.proxmox.com
 help / color / mirror / Atom feed
* [PATCH manager] ui: ha: add disarm/re-arm button
@ 2026-04-14 11:51 Dominik Rusovac
  2026-04-14 13:30 ` Daniel Kral
  2026-04-15  6:44 ` Dominik Rusovac
  0 siblings, 2 replies; 4+ messages in thread
From: Dominik Rusovac @ 2026-04-14 11:51 UTC (permalink / raw)
  To: pve-devel

The button to disarm HA in either of the resource modes ('freeze' or
'ignore') is disabled as long as HA is disarmed. Analogously, the
re-arming button is disabled as long as HA is not disarmed.

The icons ('unlink' and 'link') are chosen to emphasize that
"Disarm HA" and "Re-arm HA" are complements. There may be more
suitable pairs of icons though.

Signed-off-by: Dominik Rusovac <d.rusovac@proxmox.com>
---
 www/manager6/ha/Status.js     | 106 ++++++++++++++++++++++++++++++++++
 www/manager6/ha/StatusView.js |   8 +++
 2 files changed, 114 insertions(+)

diff --git a/www/manager6/ha/Status.js b/www/manager6/ha/Status.js
index b0b0feb9..d955452d 100644
--- a/www/manager6/ha/Status.js
+++ b/www/manager6/ha/Status.js
@@ -8,6 +8,107 @@ Ext.define('PVE.ha.Status', {
         align: 'stretch',
     },
 
+    viewModel: {
+        data: {
+            haDisarmed: false,
+        },
+    },
+
+    controller: {
+        xclass: 'Ext.app.ViewController',
+
+        check_ha_status: function (isDisarmed) {
+            let vm = this.getViewModel();
+            vm.set('haDisarmed', isDisarmed);
+        },
+
+        disarm: function (comp) {
+            let me = this;
+            let view = me.getView();
+            let mode = comp.mode;
+
+            Ext.Msg.confirm(
+                gettext('Confirm'),
+                mode === 'freeze'
+                    ? gettext("Are you sure you want to disarm HA with resource mode 'freeze'?")
+                    : gettext("Are you sure you want to disarm HA with resource mode 'ignore'?"),
+                function (btn) {
+                    if (btn !== 'yes') {
+                        return;
+                    }
+                    Proxmox.Utils.API2Request({
+                        url: '/cluster/ha/status/disarm-ha',
+                        params: { 'resource-mode': mode },
+                        method: 'POST',
+                        waitMsgTarget: view,
+                        failure: (response) => Ext.Msg.alert(gettext('Error'), response.htmlStatus),
+                    });
+                },
+            );
+        },
+
+        rearm: function () {
+            let me = this;
+            let view = me.getView();
+
+            Ext.Msg.confirm(
+                gettext('Confirm'),
+                gettext('Are you sure you want to re-arm HA?'),
+                function (btn) {
+                    if (btn !== 'yes') {
+                        return;
+                    }
+                    Proxmox.Utils.API2Request({
+                        url: '/cluster/ha/status/arm-ha',
+                        params: {},
+                        method: 'POST',
+                        waitMsgTarget: view,
+                        failure: (response) => Ext.Msg.alert(gettext('Error'), response.htmlStatus),
+                    });
+                },
+            );
+        },
+    },
+
+    dockedItems: [
+        {
+            xtype: 'toolbar',
+            dock: 'top',
+            items: [
+                {
+                    text: gettext('Disarm HA'),
+                    iconCls: 'fa fa-unlink',
+                    bind: {
+                        disabled: '{haDisarmed}',
+                    },
+                    menu: [
+                        {
+                            text: gettext('Freeze'),
+                            iconCls: 'fa fa-snowflake-o',
+                            mode: 'freeze',
+                            handler: 'disarm',
+                        },
+                        {
+                            text: gettext('Ignore'),
+                            iconCls: 'fa fa-eye-slash',
+                            mode: 'ignore',
+                            handler: 'disarm',
+                        },
+                    ],
+                },
+                {
+                    text: gettext('Re-arm HA'),
+                    iconCls: 'fa fa-link',
+                    bind: {
+                        disabled: '{!haDisarmed}',
+                    },
+                    handler: 'rearm',
+                },
+            ],
+        },
+    ],
+
+
     initComponent: function () {
         var me = this;
 
@@ -30,6 +131,11 @@ Ext.define('PVE.ha.Status', {
                 border: 0,
                 collapsible: true,
                 padding: '0 0 20 0',
+                listeners: {
+                    hastatuschange: function (isDisarmed) {
+                        me.getController().check_ha_status(isDisarmed);
+                    },
+                },
             },
             {
                 xtype: 'pveHAResourcesView',
diff --git a/www/manager6/ha/StatusView.js b/www/manager6/ha/StatusView.js
index bc2da71f..4cbe85a1 100644
--- a/www/manager6/ha/StatusView.js
+++ b/www/manager6/ha/StatusView.js
@@ -42,6 +42,13 @@ Ext.define(
                 },
             });
 
+            me.rstore.on('load', function () {
+                let fencing = store.findRecord('type', 'fencing');
+                let disarmed = fencing && fencing.get('armed-state') === 'disarmed';
+
+                me.fireEvent('hastatuschange', disarmed);
+            });
+
             Ext.apply(me, {
                 store: store,
                 stateful: false,
@@ -105,6 +112,7 @@ Ext.define(
                         return PVE.data.ResourceStore.guestName(vmid);
                     },
                 },
+                'armed-state',
             ],
             idProperty: 'id',
         });
-- 
2.47.3





^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH manager] ui: ha: add disarm/re-arm button
  2026-04-14 11:51 [PATCH manager] ui: ha: add disarm/re-arm button Dominik Rusovac
@ 2026-04-14 13:30 ` Daniel Kral
  2026-04-14 13:49   ` Dominik Rusovac
  2026-04-15  6:44 ` Dominik Rusovac
  1 sibling, 1 reply; 4+ messages in thread
From: Daniel Kral @ 2026-04-14 13:30 UTC (permalink / raw)
  To: Dominik Rusovac, pve-devel

Nice work, looks great!

I added some inline comments, but functionality-wise this works as
expected already.

On Tue Apr 14, 2026 at 1:51 PM CEST, Dominik Rusovac wrote:
> The button to disarm HA in either of the resource modes ('freeze' or
> 'ignore') is disabled as long as HA is disarmed. Analogously, the
> re-arming button is disabled as long as HA is not disarmed.
>
> The icons ('unlink' and 'link') are chosen to emphasize that
> "Disarm HA" and "Re-arm HA" are complements. There may be more
> suitable pairs of icons though.
>
> Signed-off-by: Dominik Rusovac <d.rusovac@proxmox.com>
> ---
>  www/manager6/ha/Status.js     | 106 ++++++++++++++++++++++++++++++++++
>  www/manager6/ha/StatusView.js |   8 +++
>  2 files changed, 114 insertions(+)
>
> diff --git a/www/manager6/ha/Status.js b/www/manager6/ha/Status.js
> index b0b0feb9..d955452d 100644
> --- a/www/manager6/ha/Status.js
> +++ b/www/manager6/ha/Status.js
> @@ -8,6 +8,107 @@ Ext.define('PVE.ha.Status', {
>          align: 'stretch',
>      },
>  
> +    viewModel: {
> +        data: {
> +            haDisarmed: false,
> +        },
> +    },
> +
> +    controller: {
> +        xclass: 'Ext.app.ViewController',
> +
> +        check_ha_status: function (isDisarmed) {

new method names should use cameCase according to our JS Style Guide [0]

> +            let vm = this.getViewModel();
> +            vm.set('haDisarmed', isDisarmed);
> +        },
> +
> +        disarm: function (comp) {

nit: maybe s/comp/menuItem/ would make it a little clearer where the
     information is coming from?

nit: maybe s/disarm/handleDisarmButton/ would also make it clearer where
     it is supposed to be used (instead of a generic method here)

> +            let me = this;
> +            let view = me.getView();
> +            let mode = comp.mode;
> +
> +            Ext.Msg.confirm(
> +                gettext('Confirm'),
> +                mode === 'freeze'
> +                    ? gettext("Are you sure you want to disarm HA with resource mode 'freeze'?")
> +                    : gettext("Are you sure you want to disarm HA with resource mode 'ignore'?"),

nit: the translation keys could be deduplicated with something like

    Ext.Msg.confirm(
        gettext('Confirm'),
        Ext.String.format(
            gettext("Are you sure you want to disarm HA with resource mode '{0}'?"),
            mode
        )
        ...
    );

Feel free to restructure the code snippet if you consider using it.

I also removed the mode === 'freeze' condition with just emplacing the
content of `mode`, but it would be nicer to use the same translation
keys as for the menu items (i.e., gettext('Freeze') and
gettext('Ignore')).

> +                function (btn) {
> +                    if (btn !== 'yes') {
> +                        return;
> +                    }
> +                    Proxmox.Utils.API2Request({
> +                        url: '/cluster/ha/status/disarm-ha',
> +                        params: { 'resource-mode': mode },
> +                        method: 'POST',
> +                        waitMsgTarget: view,
> +                        failure: (response) => Ext.Msg.alert(gettext('Error'), response.htmlStatus),
> +                    });
> +                },
> +            );
> +        },
> +
> +        rearm: function () {

nit: maybe s/rearm/handleRearmButton/ here as well?

> +            let me = this;
> +            let view = me.getView();
> +
> +            Ext.Msg.confirm(
> +                gettext('Confirm'),
> +                gettext('Are you sure you want to re-arm HA?'),
> +                function (btn) {
> +                    if (btn !== 'yes') {
> +                        return;
> +                    }
> +                    Proxmox.Utils.API2Request({
> +                        url: '/cluster/ha/status/arm-ha',
> +                        params: {},

nit: the params is not needed here

> +                        method: 'POST',
> +                        waitMsgTarget: view,
> +                        failure: (response) => Ext.Msg.alert(gettext('Error'), response.htmlStatus),
> +                    });
> +                },
> +            );
> +        },
> +    },
> +
> +    dockedItems: [
> +        {
> +            xtype: 'toolbar',
> +            dock: 'top',
> +            items: [
> +                {
> +                    text: gettext('Disarm HA'),
> +                    iconCls: 'fa fa-unlink',
> +                    bind: {
> +                        disabled: '{haDisarmed}',
> +                    },
> +                    menu: [
> +                        {
> +                            text: gettext('Freeze'),
> +                            iconCls: 'fa fa-snowflake-o',
> +                            mode: 'freeze',
> +                            handler: 'disarm',
> +                        },
> +                        {
> +                            text: gettext('Ignore'),
> +                            iconCls: 'fa fa-eye-slash',
> +                            mode: 'ignore',
> +                            handler: 'disarm',
> +                        },
> +                    ],
> +                },
> +                {
> +                    text: gettext('Re-arm HA'),

nit: wondering whether this should just be called 'Arm HA', but no hard
     feelings about this. If we go for that, should be changed for the
     other instances as well.

> +                    iconCls: 'fa fa-link',
> +                    bind: {
> +                        disabled: '{!haDisarmed}',
> +                    },
> +                    handler: 'rearm',
> +                },
> +            ],
> +        },
> +    ],
> +
> +

extra new-line that is removed with a `make -C www/manager6 tidy`

>      initComponent: function () {
>          var me = this;
>  
> @@ -30,6 +131,11 @@ Ext.define('PVE.ha.Status', {
>                  border: 0,
>                  collapsible: true,
>                  padding: '0 0 20 0',
> +                listeners: {
> +                    hastatuschange: function (isDisarmed) {
> +                        me.getController().check_ha_status(isDisarmed);
> +                    },
> +                },
>              },
>              {
>                  xtype: 'pveHAResourcesView',

[0] https://pve.proxmox.com/wiki/Javascript_Style_Guide#Casing




^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH manager] ui: ha: add disarm/re-arm button
  2026-04-14 13:30 ` Daniel Kral
@ 2026-04-14 13:49   ` Dominik Rusovac
  0 siblings, 0 replies; 4+ messages in thread
From: Dominik Rusovac @ 2026-04-14 13:49 UTC (permalink / raw)
  To: Daniel Kral, pve-devel

On Tue Apr 14, 2026 at 3:30 PM CEST, Daniel Kral wrote:
> Nice work, looks great!
>
> I added some inline comments, but functionality-wise this works as
> expected already.
>

thx! will incorporate your suggestions in a v2.

> On Tue Apr 14, 2026 at 1:51 PM CEST, Dominik Rusovac wrote:
>> The button to disarm HA in either of the resource modes ('freeze' or
>> 'ignore') is disabled as long as HA is disarmed. Analogously, the
>> re-arming button is disabled as long as HA is not disarmed.
>>
>> The icons ('unlink' and 'link') are chosen to emphasize that
>> "Disarm HA" and "Re-arm HA" are complements. There may be more
>> suitable pairs of icons though.
>>
>> Signed-off-by: Dominik Rusovac <d.rusovac@proxmox.com>
>> ---
>>  www/manager6/ha/Status.js     | 106 ++++++++++++++++++++++++++++++++++
>>  www/manager6/ha/StatusView.js |   8 +++
>>  2 files changed, 114 insertions(+)
>>

[snip]




^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH manager] ui: ha: add disarm/re-arm button
  2026-04-14 11:51 [PATCH manager] ui: ha: add disarm/re-arm button Dominik Rusovac
  2026-04-14 13:30 ` Daniel Kral
@ 2026-04-15  6:44 ` Dominik Rusovac
  1 sibling, 0 replies; 4+ messages in thread
From: Dominik Rusovac @ 2026-04-15  6:44 UTC (permalink / raw)
  To: Dominik Rusovac, pve-devel

Superseded-by: https://lore.proxmox.com/all/20260415064118.33290-1-d.rusovac@proxmox.com/T/#u

On Tue Apr 14, 2026 at 1:51 PM CEST, Dominik Rusovac wrote:
> The button to disarm HA in either of the resource modes ('freeze' or
> 'ignore') is disabled as long as HA is disarmed. Analogously, the
> re-arming button is disabled as long as HA is not disarmed.
>
> The icons ('unlink' and 'link') are chosen to emphasize that
> "Disarm HA" and "Re-arm HA" are complements. There may be more
> suitable pairs of icons though.
>
> Signed-off-by: Dominik Rusovac <d.rusovac@proxmox.com>
> ---
>  www/manager6/ha/Status.js     | 106 ++++++++++++++++++++++++++++++++++
>  www/manager6/ha/StatusView.js |   8 +++
>  2 files changed, 114 insertions(+)
>

[snip]




^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2026-04-15  6:44 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-04-14 11:51 [PATCH manager] ui: ha: add disarm/re-arm button Dominik Rusovac
2026-04-14 13:30 ` Daniel Kral
2026-04-14 13:49   ` Dominik Rusovac
2026-04-15  6:44 ` Dominik Rusovac

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal