From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [212.224.123.68]) by lore.proxmox.com (Postfix) with ESMTPS id C3EA81FF137 for ; Tue, 14 Apr 2026 13:51:47 +0200 (CEST) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id B8B3716254; Tue, 14 Apr 2026 13:52:35 +0200 (CEST) From: Dominik Rusovac To: pve-devel@lists.proxmox.com Subject: [PATCH manager] ui: ha: add disarm/re-arm button Date: Tue, 14 Apr 2026 13:51:56 +0200 Message-ID: <20260414115156.188522-1-d.rusovac@proxmox.com> X-Mailer: git-send-email 2.47.3 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Bm-Milter-Handled: 55990f41-d878-4baa-be0a-ee34c49e34d2 X-Bm-Transport-Timestamp: 1776167445192 X-SPAM-LEVEL: Spam detection results: 0 AWL 0.496 Adjusted score from AWL reputation of From: address BAYES_00 -1.9 Bayes spam probability is 0 to 1% DMARC_MISSING 0.1 Missing DMARC policy KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment RCVD_IN_VALIDITY_CERTIFIED_BLOCKED 0.001 ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. RCVD_IN_VALIDITY_RPBL_BLOCKED 0.001 ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. RCVD_IN_VALIDITY_SAFE_BLOCKED 0.001 ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record Message-ID-Hash: AK5A7DHL5P566CGSYIBJCXK3CAGVVG44 X-Message-ID-Hash: AK5A7DHL5P566CGSYIBJCXK3CAGVVG44 X-MailFrom: d.rusovac@proxmox.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header X-Mailman-Version: 3.3.10 Precedence: list List-Id: Proxmox VE development discussion List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: 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 --- 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