* [pve-devel] [PATCH v2 pve-manager 0/2] add bulk suspend
@ 2023-11-13 10:20 Hannes Laimer
2023-11-13 10:20 ` [pve-devel] [PATCH v2 pve-manager 1/2] api: add suspendall endpoint Hannes Laimer
` (2 more replies)
0 siblings, 3 replies; 4+ messages in thread
From: Hannes Laimer @ 2023-11-13 10:20 UTC (permalink / raw)
To: pve-devel
Adds support for bulk suspending VMs as it already exists for stop.
v2, thanks @Thomas:
* api: skip CTs + fix permission checks
* ui: disable `suspendall` button if user isn;t allowed to use it
* ui: use new bulk action filtering
Hannes Laimer (2):
api: add suspendall endpoint
ui: add bulk suspend support
PVE/API2/Nodes.pm | 124 ++++++++++++++++++++++++++++++
www/manager6/Utils.js | 1 +
www/manager6/node/CmdMenu.js | 15 ++++
www/manager6/node/Config.js | 14 ++++
www/manager6/window/BulkAction.js | 5 +-
5 files changed, 157 insertions(+), 2 deletions(-)
--
2.39.2
^ permalink raw reply [flat|nested] 4+ messages in thread
* [pve-devel] [PATCH v2 pve-manager 1/2] api: add suspendall endpoint
2023-11-13 10:20 [pve-devel] [PATCH v2 pve-manager 0/2] add bulk suspend Hannes Laimer
@ 2023-11-13 10:20 ` Hannes Laimer
2023-11-13 10:20 ` [pve-devel] [PATCH v2 pve-manager 2/2] ui: add bulk suspend support Hannes Laimer
2023-11-13 13:25 ` [pve-devel] applied-series: [PATCH v2 pve-manager 0/2] add bulk suspend Thomas Lamprecht
2 siblings, 0 replies; 4+ messages in thread
From: Hannes Laimer @ 2023-11-13 10:20 UTC (permalink / raw)
To: pve-devel
Signed-off-by: Hannes Laimer <h.laimer@proxmox.com>
---
PVE/API2/Nodes.pm | 124 ++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 124 insertions(+)
diff --git a/PVE/API2/Nodes.pm b/PVE/API2/Nodes.pm
index a73fca3f..0956eb0a 100644
--- a/PVE/API2/Nodes.pm
+++ b/PVE/API2/Nodes.pm
@@ -289,6 +289,7 @@ __PACKAGE__->register_method ({
{ name => 'stopall' },
{ name => 'storage' },
{ name => 'subscription' },
+ { name => 'suspendall' },
{ name => 'syslog' },
{ name => 'tasks' },
{ name => 'termproxy' },
@@ -2011,6 +2012,129 @@ __PACKAGE__->register_method ({
return $rpcenv->fork_worker('stopall', undef, $authuser, $code);
}});
+my $create_suspend_worker = sub {
+ my ($nodename, $vmid) = @_;
+ return if !PVE::QemuServer::check_running($vmid, 1);
+ print STDERR "Suspending VM $vmid\n";
+ return PVE::API2::Qemu->vm_suspend(
+ { node => $nodename, vmid => $vmid, todisk => 1 }
+ );
+};
+
+__PACKAGE__->register_method ({
+ name => 'suspendall',
+ path => 'suspendall',
+ method => 'POST',
+ protected => 1,
+ permissions => {
+ description => "The 'VM.PowerMgmt' permission is required on '/' or on '/vms/<ID>' for each"
+ ." ID passed via the 'vms' parameter. Additionally, you need 'VM.Config.Disk' on the"
+ ." '/vms/{vmid}' path and 'Datastore.AllocateSpace' for the configured state-storage(s)",
+ user => 'all',
+ },
+ proxyto => 'node',
+ description => "Suspend all VMs.",
+ parameters => {
+ additionalProperties => 0,
+ properties => {
+ node => get_standard_option('pve-node'),
+ vms => {
+ description => "Only consider Guests with these IDs.",
+ type => 'string', format => 'pve-vmid-list',
+ optional => 1,
+ },
+ },
+ },
+ returns => {
+ type => 'string',
+ },
+ code => sub {
+ my ($param) = @_;
+
+ my $rpcenv = PVE::RPCEnvironment::get();
+ my $authuser = $rpcenv->get_user();
+
+ # we cannot really check access to the state-storage here, that's happening per worker.
+ if (!$rpcenv->check($authuser, "/", [ 'VM.PowerMgmt', 'VM.Config.Disk' ], 1)) {
+ my @vms = PVE::Tools::split_list($param->{vms});
+ if (scalar(@vms) > 0) {
+ $rpcenv->check($authuser, "/vms/$_", [ 'VM.PowerMgmt' ]) for @vms;
+ } else {
+ raise_perm_exc("/, VM.PowerMgmt && VM.Config.Disk");
+ }
+ }
+
+ my $nodename = $param->{node};
+ $nodename = PVE::INotify::nodename() if $nodename eq 'localhost';
+
+ my $code = sub {
+
+ $rpcenv->{type} = 'priv'; # to start tasks in background
+
+ my $stopList = $get_start_stop_list->($nodename, undef, $param->{vms});
+
+ my $cpuinfo = PVE::ProcFSTools::read_cpuinfo();
+ my $datacenterconfig = cfs_read_file('datacenter.cfg');
+ # if not set by user spawn max cpu count number of workers
+ my $maxWorkers = $datacenterconfig->{max_workers} || $cpuinfo->{cpus};
+
+ for my $order (sort {$b <=> $a} keys %$stopList) {
+ my $vmlist = $stopList->{$order};
+ my $workers = {};
+
+ my $finish_worker = sub {
+ my $pid = shift;
+ my $worker = delete $workers->{$pid} || return;
+
+ syslog('info', "end task $worker->{upid}");
+ };
+
+ for my $vmid (sort {$b <=> $a} keys %$vmlist) {
+ my $d = $vmlist->{$vmid};
+ if ($d->{type} eq 'lxc') {
+ print STDERR "Skipping $vmid, only VMs can be suspended\n";
+ next;
+ }
+ my $upid = eval {
+ $create_suspend_worker->($nodename, $vmid)
+ };
+ warn $@ if $@;
+ next if !$upid;
+
+ my $task = PVE::Tools::upid_decode($upid, 1);
+ next if !$task;
+
+ my $pid = $task->{pid};
+
+ $workers->{$pid} = { type => $d->{type}, upid => $upid, vmid => $vmid };
+ while (scalar(keys %$workers) >= $maxWorkers) {
+ foreach my $p (keys %$workers) {
+ if (!PVE::ProcFSTools::check_process_running($p)) {
+ $finish_worker->($p);
+ }
+ }
+ sleep(1);
+ }
+ }
+ while (scalar(keys %$workers)) {
+ for my $p (keys %$workers) {
+ if (!PVE::ProcFSTools::check_process_running($p)) {
+ $finish_worker->($p);
+ }
+ }
+ sleep(1);
+ }
+ }
+
+ syslog('info', "all VMs suspended");
+
+ return;
+ };
+
+ return $rpcenv->fork_worker('suspendall', undef, $authuser, $code);
+ }});
+
+
my $create_migrate_worker = sub {
my ($nodename, $type, $vmid, $target, $with_local_disks) = @_;
--
2.39.2
^ permalink raw reply [flat|nested] 4+ messages in thread
* [pve-devel] [PATCH v2 pve-manager 2/2] ui: add bulk suspend support
2023-11-13 10:20 [pve-devel] [PATCH v2 pve-manager 0/2] add bulk suspend Hannes Laimer
2023-11-13 10:20 ` [pve-devel] [PATCH v2 pve-manager 1/2] api: add suspendall endpoint Hannes Laimer
@ 2023-11-13 10:20 ` Hannes Laimer
2023-11-13 13:25 ` [pve-devel] applied-series: [PATCH v2 pve-manager 0/2] add bulk suspend Thomas Lamprecht
2 siblings, 0 replies; 4+ messages in thread
From: Hannes Laimer @ 2023-11-13 10:20 UTC (permalink / raw)
To: pve-devel
Signed-off-by: Hannes Laimer <h.laimer@proxmox.com>
---
www/manager6/Utils.js | 1 +
| 15 +++++++++++++++
www/manager6/node/Config.js | 14 ++++++++++++++
www/manager6/window/BulkAction.js | 5 +++--
4 files changed, 33 insertions(+), 2 deletions(-)
diff --git a/www/manager6/Utils.js b/www/manager6/Utils.js
index be30393e..139064d1 100644
--- a/www/manager6/Utils.js
+++ b/www/manager6/Utils.js
@@ -1996,6 +1996,7 @@ Ext.define('PVE.Utils', {
spiceshell: ['', gettext('Shell') + ' (Spice)'],
startall: ['', gettext('Bulk start VMs and Containers')],
stopall: ['', gettext('Bulk shutdown VMs and Containers')],
+ suspendall: ['', gettext('Suspend all VMs')],
unknownimgdel: ['', gettext('Destroy image from unknown guest')],
wipedisk: ['Device', gettext('Wipe Disk')],
vncproxy: ['VM/CT', gettext('Console')],
--git a/www/manager6/node/CmdMenu.js b/www/manager6/node/CmdMenu.js
index dc56ef08..956adc49 100644
--- a/www/manager6/node/CmdMenu.js
+++ b/www/manager6/node/CmdMenu.js
@@ -56,6 +56,20 @@ Ext.define('PVE.node.CmdMenu', {
});
},
},
+ {
+ text: gettext('Bulk Suspend'),
+ itemId: 'bulksuspend',
+ iconCls: 'fa fa-fw fa-download',
+ handler: function() {
+ Ext.create('PVE.window.BulkAction', {
+ nodename: this.up('menu').nodename,
+ title: gettext('Bulk Suspend'),
+ btnText: gettext('Suspend'),
+ action: 'suspendall',
+ autoShow: true,
+ });
+ },
+ },
{
text: gettext('Bulk Migrate'),
itemId: 'bulkmigrate',
@@ -129,6 +143,7 @@ Ext.define('PVE.node.CmdMenu', {
if (!caps.vms['VM.PowerMgmt']) {
me.getComponent('bulkstart').setDisabled(true);
me.getComponent('bulkstop').setDisabled(true);
+ me.getComponent('bulksuspend').setDisabled(true);
}
if (!caps.nodes['Sys.PowerMgmt']) {
me.getComponent('wakeonlan').setDisabled(true);
diff --git a/www/manager6/node/Config.js b/www/manager6/node/Config.js
index 6ed2172a..ac5e6b25 100644
--- a/www/manager6/node/Config.js
+++ b/www/manager6/node/Config.js
@@ -65,6 +65,20 @@ Ext.define('PVE.node.Config', {
});
},
},
+ {
+ text: gettext('Bulk Suspend'),
+ iconCls: 'fa fa-fw fa-download',
+ disabled: !caps.vms['VM.PowerMgmt'],
+ handler: function() {
+ Ext.create('PVE.window.BulkAction', {
+ autoShow: true,
+ nodename: nodename,
+ title: gettext('Bulk Suspend'),
+ btnText: gettext('Suspend'),
+ action: 'suspendall',
+ });
+ },
+ },
{
text: gettext('Bulk Migrate'),
iconCls: 'fa fa-fw fa-send-o',
diff --git a/www/manager6/window/BulkAction.js b/www/manager6/window/BulkAction.js
index 5f76ef7a..c8132753 100644
--- a/www/manager6/window/BulkAction.js
+++ b/www/manager6/window/BulkAction.js
@@ -10,7 +10,7 @@ Ext.define('PVE.window.BulkAction', {
},
border: false,
- // the action to set, currently there are: `startall`, `migrateall`, `stopall`
+ // the action to set, currently there are: `startall`, `migrateall`, `stopall`, `suspendall`
action: undefined,
submit: function(params) {
@@ -144,6 +144,7 @@ Ext.define('PVE.window.BulkAction', {
};
let defaultStatus = me.action === 'migrateall' ? '' : me.action === 'startall' ? 'stopped' : 'running';
+ let defaultType = me.action === 'suspendall' ? 'qemu' : '';
let statusMap = [];
let poolMap = [];
@@ -318,7 +319,7 @@ Ext.define('PVE.window.BulkAction', {
fieldLabel: gettext("Type"),
emptyText: gettext('All'),
editable: false,
- value: '',
+ value: defaultType,
store: [
['', gettext('All')],
['lxc', gettext('CT')],
--
2.39.2
^ permalink raw reply [flat|nested] 4+ messages in thread
* [pve-devel] applied-series: [PATCH v2 pve-manager 0/2] add bulk suspend
2023-11-13 10:20 [pve-devel] [PATCH v2 pve-manager 0/2] add bulk suspend Hannes Laimer
2023-11-13 10:20 ` [pve-devel] [PATCH v2 pve-manager 1/2] api: add suspendall endpoint Hannes Laimer
2023-11-13 10:20 ` [pve-devel] [PATCH v2 pve-manager 2/2] ui: add bulk suspend support Hannes Laimer
@ 2023-11-13 13:25 ` Thomas Lamprecht
2 siblings, 0 replies; 4+ messages in thread
From: Thomas Lamprecht @ 2023-11-13 13:25 UTC (permalink / raw)
To: Proxmox VE development discussion, Hannes Laimer
Am 13/11/2023 um 11:20 schrieb Hannes Laimer:
> Adds support for bulk suspending VMs as it already exists for stop.
>
> v2, thanks @Thomas:
> * api: skip CTs + fix permission checks
> * ui: disable `suspendall` button if user isn;t allowed to use it
> * ui: use new bulk action filtering
>
> Hannes Laimer (2):
> api: add suspendall endpoint
> ui: add bulk suspend support
>
> PVE/API2/Nodes.pm | 124 ++++++++++++++++++++++++++++++
> www/manager6/Utils.js | 1 +
> www/manager6/node/CmdMenu.js | 15 ++++
> www/manager6/node/Config.js | 14 ++++
> www/manager6/window/BulkAction.js | 5 +-
> 5 files changed, 157 insertions(+), 2 deletions(-)
>
applied series, thanks!
I made the "passed VMID of a CT" case use log_warn though, so it's more
visible that something odd was requested.
And UX style wise it could be nicer if we have "fixed" filters for the
store, as currently one can easily hit the "Clear Filters" button and
then can select all CTs (or stopped VMs) without any hint that suspension
for these won't work.
But it's not a biggie and did not want to block on that, so just for the
record that we can probably improve on this.
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2023-11-13 13:25 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-11-13 10:20 [pve-devel] [PATCH v2 pve-manager 0/2] add bulk suspend Hannes Laimer
2023-11-13 10:20 ` [pve-devel] [PATCH v2 pve-manager 1/2] api: add suspendall endpoint Hannes Laimer
2023-11-13 10:20 ` [pve-devel] [PATCH v2 pve-manager 2/2] ui: add bulk suspend support Hannes Laimer
2023-11-13 13:25 ` [pve-devel] applied-series: [PATCH v2 pve-manager 0/2] add bulk suspend Thomas Lamprecht
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox