From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [IPv6:2a01:7e0:0:424::9]) by lore.proxmox.com (Postfix) with ESMTPS id C73A71FF15C for ; Fri, 14 Nov 2025 15:59:20 +0100 (CET) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 739F716650; Fri, 14 Nov 2025 16:00:04 +0100 (CET) From: Dominik Csapak To: pve-devel@lists.proxmox.com Date: Fri, 14 Nov 2025 15:59:20 +0100 Message-ID: <20251114145927.3766668-6-d.csapak@proxmox.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20251114145927.3766668-1-d.csapak@proxmox.com> References: <20251114145927.3766668-1-d.csapak@proxmox.com> MIME-Version: 1.0 X-SPAM-LEVEL: Spam detection results: 0 AWL 0.029 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 SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record Subject: [pve-devel] [PATCH manager v4 3/3] ui: add bulk actions to the datacenter level X-BeenThere: pve-devel@lists.proxmox.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Proxmox VE development discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: Proxmox VE development discussion Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Errors-To: pve-devel-bounces@lists.proxmox.com Sender: "pve-devel" reuse the BulkAction window as much as possible. There are only a few adaptions needed: * the api call endpoinst are slightly different: (e.g. start vs startall) * we have to handle a missing nodename * some parameters are different: - start does not have a 'force' - migrate needs the 'online' parameter - the 'vms' list is expected to be an array for the new api calls Signed-off-by: Dominik Csapak --- www/manager6/dc/Config.js | 68 +++++++++++++++++++++++++++++++ www/manager6/window/BulkAction.js | 50 +++++++++++++++++++---- 2 files changed, 109 insertions(+), 9 deletions(-) diff --git a/www/manager6/dc/Config.js b/www/manager6/dc/Config.js index 60fea4b6..b5e27a21 100644 --- a/www/manager6/dc/Config.js +++ b/www/manager6/dc/Config.js @@ -15,9 +15,77 @@ Ext.define('PVE.dc.Config', { me.items = []; + let actionBtn = Ext.create('Ext.Button', { + text: gettext('Bulk Actions'), + iconCls: 'fa fa-fw fa-ellipsis-v', + disabled: !caps.vms['VM.PowerMgmt'] && !caps.vms['VM.Migrate'], + menu: new Ext.menu.Menu({ + items: [ + { + text: gettext('Bulk Start'), + iconCls: 'fa fa-fw fa-play', + disabled: !caps.vms['VM.PowerMgmt'], + handler: function () { + Ext.create('PVE.window.BulkAction', { + autoShow: true, + vmsAsArray: true, + title: gettext('Bulk Start'), + btnText: gettext('Start'), + action: 'start', + }); + }, + }, + { + text: gettext('Bulk Shutdown'), + iconCls: 'fa fa-fw fa-stop', + disabled: !caps.vms['VM.PowerMgmt'], + handler: function () { + Ext.create('PVE.window.BulkAction', { + autoShow: true, + vmsAsArray: true, + title: gettext('Bulk Shutdown'), + btnText: gettext('Shutdown'), + action: 'shutdown', + }); + }, + }, + { + text: gettext('Bulk Suspend'), + iconCls: 'fa fa-fw fa-download', + disabled: !caps.vms['VM.PowerMgmt'], + handler: function () { + Ext.create('PVE.window.BulkAction', { + autoShow: true, + vmsAsArray: true, + title: gettext('Bulk Suspend'), + btnText: gettext('Suspend'), + action: 'suspend', + }); + }, + }, + { + text: gettext('Bulk Migrate'), + iconCls: 'fa fa-fw fa-send-o', + disabled: !caps.vms['VM.Migrate'], + hidden: PVE.Utils.isStandaloneNode(), + handler: function () { + Ext.create('PVE.window.BulkAction', { + autoShow: true, + vmsAsArray: true, + title: gettext('Bulk Migrate'), + btnText: gettext('Migrate'), + action: 'migrate', + }); + }, + }, + ], + }), + }); + Ext.apply(me, { title: gettext('Datacenter'), hstateid: 'dctab', + tbar: [actionBtn], }); if (caps.dc['Sys.Audit']) { diff --git a/www/manager6/window/BulkAction.js b/www/manager6/window/BulkAction.js index 0223740f..b2d82bd3 100644 --- a/www/manager6/window/BulkAction.js +++ b/www/manager6/window/BulkAction.js @@ -13,12 +13,27 @@ Ext.define('PVE.window.BulkAction', { // the action to set, currently there are: `startall`, `migrateall`, `stopall`, `suspendall` action: undefined, + // if set to true, the 'vms' parameter will be sent as an array' + // necessary for the cluster-wide api call + vmsAsArray: false, + submit: function (params) { let me = this; + let url; + if (me.nodename) { + url = `/nodes/${me.nodename}/${me.action}`; + } else { + url = `/cluster/bulk-action/guest/${me.action}`; + } + + if (me.vmsAsArray) { + params.vms = params.vms.split(/[,; ]/); + } + Proxmox.Utils.API2Request({ params: params, - url: `/nodes/${me.nodename}/${me.action}`, + url, waitMsgTarget: me, method: 'POST', failure: (response) => Ext.Msg.alert('Error', response.htmlStatus), @@ -38,9 +53,6 @@ Ext.define('PVE.window.BulkAction', { initComponent: function () { let me = this; - if (!me.nodename) { - throw 'no node name specified'; - } if (!me.action) { throw 'no action specified'; } @@ -52,7 +64,11 @@ Ext.define('PVE.window.BulkAction', { } let items = []; - if (me.action === 'migrateall') { + if (me.action === 'migrateall' || me.action === 'migrate') { + let disallowedNodes = []; + if (me.nodename) { + disallowedNodes.push(me.nodename); + } items.push( { xtype: 'fieldcontainer', @@ -62,7 +78,7 @@ Ext.define('PVE.window.BulkAction', { flex: 1, xtype: 'pveNodeSelector', name: 'target', - disallowedNodes: [me.nodename], + disallowedNodes, fieldLabel: gettext('Target node'), labelWidth: 200, allowBlank: false, @@ -106,13 +122,20 @@ Ext.define('PVE.window.BulkAction', { ], }, ); + if (me.action === 'migrate') { + items.push({ + xtype: 'hiddenfield', + name: 'online', + value: 1, + }); + } } else if (me.action === 'startall') { items.push({ xtype: 'hiddenfield', name: 'force', value: 1, }); - } else if (me.action === 'stopall') { + } else if (me.action === 'stopall' || me.action === 'shutdown') { items.push({ xtype: 'fieldcontainer', layout: 'hbox', @@ -152,8 +175,17 @@ Ext.define('PVE.window.BulkAction', { me.down('#lxcwarning').setVisible(showWarning); }; - let defaultStatus = - me.action === 'migrateall' ? '' : me.action === 'startall' ? 'stopped' : 'running'; + let defaulStatusMap = { + migrateall: '', + migrate: '', + startall: 'stopped', + start: 'stopped', + stopall: 'running', + shutdown: 'running', + suspendall: 'running', + suspend: 'running', + }; + let defaultStatus = defaulStatusMap[me.action] ?? ''; let defaultType = me.action === 'suspendall' ? 'qemu' : ''; let statusMap = []; -- 2.47.3 _______________________________________________ pve-devel mailing list pve-devel@lists.proxmox.com https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel