* [PATCH manager 1/5] ui: integrate new VM.Reboot permission
2026-09-16 9:06 [PATCH access-control/docs/manager/qemu-server 0/5] Add new permission VM.Reboot Jonas Theisen
@ 2026-09-16 9:06 ` Jonas Theisen
2026-09-16 9:06 ` [PATCH manager 2/5] ui: align VM context menu to permissions Jonas Theisen
` (3 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Jonas Theisen @ 2026-09-16 9:06 UTC (permalink / raw)
To: pve-devel
To allow users with this restriced VM PowerMgmt permission
to still intuitively use the interface this commit rearranges
and introduces a few new UI elements.
If the user only has the VM.Reboot permission:
* The default Shutdown Button is replaced by a Reboot button to
not hide the first available functino to the user behind
a dropdown menu.
* The Start button is hidden as long as the user does not have
the VM.PowerMgmt permission.
* The new Reboot button is updated similar to the Shutdown and
Start button if the guest state changes.
For regular users with VM.PowerMgmt permission this should not
change anything.
Signed-off-by: Jonas Theisen <j.theisen@proxmox.com>
---
www/manager6/qemu/Config.js | 51 +++++++++++++++++++++++++++++++------
1 file changed, 43 insertions(+), 8 deletions(-)
diff --git a/www/manager6/qemu/Config.js b/www/manager6/qemu/Config.js
index 842d35de..b22b52fe 100644
--- a/www/manager6/qemu/Config.js
+++ b/www/manager6/qemu/Config.js
@@ -57,7 +57,7 @@ Ext.define('PVE.qemu.Config', {
var startBtn = Ext.create('Ext.Button', {
text: gettext('Start'),
disabled: !caps.vms['VM.PowerMgmt'] || running,
- hidden: template,
+ hidden: !caps.vms['VM.PowerMgmt'] || template,
handler: function () {
vm_command('start');
},
@@ -153,7 +153,7 @@ Ext.define('PVE.qemu.Config', {
var shutdownBtn = Ext.create('PVE.button.Split', {
text: gettext('Shutdown'),
disabled: !caps.vms['VM.PowerMgmt'] || !running,
- hidden: template,
+ hidden: !caps.vms['VM.PowerMgmt'] || template,
confirmMsg: PVE.Utils.formatGuestTaskConfirmation('qmshutdown', vmid, vm.name),
handler: function () {
vm_command('shutdown');
@@ -228,6 +228,35 @@ Ext.define('PVE.qemu.Config', {
iconCls: 'fa fa-power-off',
});
+ var rebootBtn = Ext.create('PVE.button.Split', {
+ text: gettext('Reboot'),
+ disabled: !running || !!caps.vms['VM.PowerMgmt'] || !caps.vms['VM.Reboot'],
+ hidden: !!caps.vms['VM.PowerMgmt'] || !caps.vms['VM.Reboot'],
+ tooltip: Ext.String.format(
+ gettext('Shutdown, apply pending changes and reboot {0}'),
+ 'VM',
+ ),
+ confirmMsg: PVE.Utils.formatGuestTaskConfirmation('qmreboot', vmid, vm.name),
+ handler: function () {
+ vm_command('reboot');
+ },
+ iconCls: 'fa fa-refresh',
+ menu: {
+ items: [
+ {
+ text: gettext('Reset'),
+ disabled: !(caps.vms['VM.PowerMgmt'] || caps.vms['VM.Reboot']),
+ tooltip: Ext.String.format(gettext('Reset {0} immediately'), 'VM'),
+ confirmMsg: PVE.Utils.formatGuestTaskConfirmation('qmreset', vmid, vm.name),
+ handler: function () {
+ vm_command('reset');
+ },
+ iconCls: 'fa fa-bolt',
+ },
+ ],
+ },
+ });
+
var consoleBtn = Ext.create('PVE.button.ConsoleButton', {
disabled: !caps.vms['VM.Console'],
hidden: template,
@@ -287,6 +316,7 @@ Ext.define('PVE.qemu.Config', {
resumeBtn,
startBtn,
shutdownBtn,
+ rebootBtn,
migrateBtn,
consoleBtn,
moreBtn,
@@ -486,12 +516,14 @@ Ext.define('PVE.qemu.Config', {
var resume = ['prelaunch', 'paused', 'suspended'].indexOf(qmpstatus) !== -1;
- if (resume || lock === 'suspended') {
- startBtn.setVisible(false);
- resumeBtn.setVisible(true);
- } else {
- startBtn.setVisible(true);
- resumeBtn.setVisible(false);
+ if (caps.vms['VM.PowerMgmt']) {
+ if (resume || lock === 'suspended') {
+ startBtn.setVisible(false);
+ resumeBtn.setVisible(true);
+ } else {
+ startBtn.setVisible(true);
+ resumeBtn.setVisible(false);
+ }
}
consoleBtn.setEnableSpice(spice);
@@ -504,6 +536,9 @@ Ext.define('PVE.qemu.Config', {
startBtn.setDisabled(!caps.vms['VM.PowerMgmt'] || template || guest_running);
shutdownBtn.setDisabled(!caps.vms['VM.PowerMgmt'] || status !== 'running');
+
+ rebootBtn.setDisabled(!caps.vms['VM.Reboot'] || status !== 'running');
+
me.down('#removeBtn').setDisabled(!caps.vms['VM.Allocate'] || status !== 'stopped');
consoleBtn.setDisabled(template);
--
2.47.3
^ permalink raw reply related [flat|nested] 6+ messages in thread* [PATCH manager 2/5] ui: align VM context menu to permissions
2026-09-16 9:06 [PATCH access-control/docs/manager/qemu-server 0/5] Add new permission VM.Reboot Jonas Theisen
2026-09-16 9:06 ` [PATCH manager 1/5] ui: integrate new VM.Reboot permission Jonas Theisen
@ 2026-09-16 9:06 ` Jonas Theisen
2026-09-16 9:06 ` [PATCH access-control 3/5] acl: Add new privilege VM.Reboot Jonas Theisen
` (2 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Jonas Theisen @ 2026-09-16 9:06 UTC (permalink / raw)
To: pve-devel
This patch better aligns the VM context / command menu
to the users permissions by hiding commands which are not available.
This is similar to what is already being done on the VM status page.
Signed-off-by: Jonas Theisen <j.theisen@proxmox.com>
---
| 26 +++++++++++++++-----------
1 file changed, 15 insertions(+), 11 deletions(-)
--git a/www/manager6/qemu/CmdMenu.js b/www/manager6/qemu/CmdMenu.js
index df6045bf..54ab86b1 100644
--- a/www/manager6/qemu/CmdMenu.js
+++ b/www/manager6/qemu/CmdMenu.js
@@ -60,41 +60,43 @@ Ext.define('PVE.qemu.CmdMenu', {
{
text: gettext('Start'),
iconCls: 'fa fa-fw fa-play',
- hidden: running || suspended,
- disabled: running || suspended,
+ hidden: running || suspended || !caps.vms['VM.PowerMgmt'],
+ disabled: running || suspended || !caps.vms['VM.PowerMgmt'],
handler: () => vm_command('start'),
},
{
text: gettext('Pause'),
iconCls: 'fa fa-fw fa-pause',
- hidden: stopped || suspended,
- disabled: stopped || suspended,
+ hidden: stopped || suspended || !caps.vms['VM.PowerMgmt'],
+ disabled: stopped || suspended || !caps.vms['VM.PowerMgmt'],
handler: () => confirmedVMCommand('suspend', undefined, 'qmpause'),
},
{
text: gettext('Hibernate'),
iconCls: 'fa fa-fw fa-download',
- hidden: stopped || suspended,
- disabled: stopped || suspended,
+ hidden: stopped || suspended || !caps.vms['VM.PowerMgmt'],
+ disabled: stopped || suspended || !caps.vms['VM.PowerMgmt'],
tooltip: gettext('Suspend to disk'),
handler: () => confirmedVMCommand('suspend', { todisk: 1 }),
},
{
text: gettext('Resume'),
iconCls: 'fa fa-fw fa-play',
- hidden: !suspended,
+ hidden: !suspended || !caps.vms['VM.PowerMgmt'],
handler: () => vm_command('resume'),
},
{
text: gettext('Shutdown'),
iconCls: 'fa fa-fw fa-power-off',
- disabled: stopped || suspended,
+ disabled: stopped || suspended || !caps.vms['VM.PowerMgmt'],
+ hidden: !caps.vms['VM.PowerMgmt'],
handler: () => confirmedVMCommand('shutdown'),
},
{
text: gettext('Stop'),
iconCls: 'fa fa-fw fa-stop',
- disabled: stopped,
+ disabled: stopped || !caps.vms['VM.PowerMgmt'],
+ hidden: !caps.vms['VM.PowerMgmt'],
tooltip: Ext.String.format(gettext('Stop {0} immediately'), 'VM'),
handler: () => {
Ext.create('PVE.GuestStop', {
@@ -107,14 +109,16 @@ Ext.define('PVE.qemu.CmdMenu', {
{
text: gettext('Reboot'),
iconCls: 'fa fa-fw fa-refresh',
- disabled: stopped,
+ disabled: stopped || !(caps.vms['VM.Reboot'] || caps.vms['VM.PowerMgmt']),
+ hidden: !(caps.vms['VM.Reboot'] || caps.vms['VM.PowerMgmt']),
tooltip: Ext.String.format(gettext('Reboot {0}'), 'VM'),
handler: () => confirmedVMCommand('reboot'),
},
{
text: gettext('Reset'),
iconCls: 'fa fa-fw fa-bolt',
- disabled: stopped,
+ disabled: stopped || !(caps.vms['VM.Reboot'] || caps.vms['VM.PowerMgmt']),
+ hidden: !(caps.vms['VM.Reboot'] || caps.vms['VM.PowerMgmt']),
tooltip: Ext.String.format(gettext('Reset {0}'), 'VM'),
handler: () => confirmedVMCommand('reset'),
},
--
2.47.3
^ permalink raw reply related [flat|nested] 6+ messages in thread* [PATCH access-control 3/5] acl: Add new privilege VM.Reboot
2026-09-16 9:06 [PATCH access-control/docs/manager/qemu-server 0/5] Add new permission VM.Reboot Jonas Theisen
2026-09-16 9:06 ` [PATCH manager 1/5] ui: integrate new VM.Reboot permission Jonas Theisen
2026-09-16 9:06 ` [PATCH manager 2/5] ui: align VM context menu to permissions Jonas Theisen
@ 2026-09-16 9:06 ` Jonas Theisen
2026-09-16 9:06 ` [PATCH qemu-server 4/5] api: Integrate " Jonas Theisen
2026-09-16 9:06 ` [PATCH docs 5/5] pveum: VM permissions: add VM.Reboot Jonas Theisen
4 siblings, 0 replies; 6+ messages in thread
From: Jonas Theisen @ 2026-09-16 9:06 UTC (permalink / raw)
To: pve-devel
Add a new custom privilege to allow Users to Reboot and
Reset VMs but not start or shut them down.
Signed-off-by: Jonas Theisen <j.theisen@proxmox.com>
---
src/PVE/AccessControl.pm | 1 +
src/test/perm-test1.pl | 4 ++--
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/src/PVE/AccessControl.pm b/src/PVE/AccessControl.pm
index 0d632b3..b5f5115 100644
--- a/src/PVE/AccessControl.pm
+++ b/src/PVE/AccessControl.pm
@@ -1165,6 +1165,7 @@ my $privgroups = {
my $valid_privs = {
'Permissions.Modify' => 1, # not contained in a group
+ 'VM.Reboot' => 1, # Custom permission only needed in special cases
};
my $special_roles = {
diff --git a/src/test/perm-test1.pl b/src/test/perm-test1.pl
index d323447..713095e 100755
--- a/src/test/perm-test1.pl
+++ b/src/test/perm-test1.pl
@@ -86,8 +86,8 @@ check_permission(
. 'VM.Allocate,VM.Audit,VM.Backup,VM.Clone,VM.Config.CDROM,VM.Config.CPU,VM.Config.Cloudinit,'
. 'VM.Config.Disk,VM.Config.HWType,VM.Config.Memory,VM.Config.Network,VM.Config.Options,'
. 'VM.Console,VM.GuestAgent.Audit,VM.GuestAgent.FileRead,VM.GuestAgent.FileSystemMgmt,'
- . 'VM.GuestAgent.FileWrite,VM.GuestAgent.Unrestricted,VM.Migrate,VM.PowerMgmt,VM.Replicate,'
- . 'VM.Snapshot,VM.Snapshot.Rollback',
+ . 'VM.GuestAgent.FileWrite,VM.GuestAgent.Unrestricted,VM.Migrate,VM.PowerMgmt,VM.Reboot,'
+ . 'VM.Replicate,VM.Snapshot,VM.Snapshot.Rollback',
);
check_roles('max@pve', '/vms/200', 'storage_manager');
--
2.47.3
^ permalink raw reply related [flat|nested] 6+ messages in thread* [PATCH qemu-server 4/5] api: Integrate new privilege VM.Reboot
2026-09-16 9:06 [PATCH access-control/docs/manager/qemu-server 0/5] Add new permission VM.Reboot Jonas Theisen
` (2 preceding siblings ...)
2026-09-16 9:06 ` [PATCH access-control 3/5] acl: Add new privilege VM.Reboot Jonas Theisen
@ 2026-09-16 9:06 ` Jonas Theisen
2026-09-16 9:06 ` [PATCH docs 5/5] pveum: VM permissions: add VM.Reboot Jonas Theisen
4 siblings, 0 replies; 6+ messages in thread
From: Jonas Theisen @ 2026-09-16 9:06 UTC (permalink / raw)
To: pve-devel
Allow users with the new VM.Reboot privilege to reboot and
reset a VM but not start or shut it down.
Signed-off-by: Jonas Theisen <j.theisen@proxmox.com>
---
src/PVE/API2/Qemu.pm | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/src/PVE/API2/Qemu.pm b/src/PVE/API2/Qemu.pm
index 71247eec..ae8ce40f 100644
--- a/src/PVE/API2/Qemu.pm
+++ b/src/PVE/API2/Qemu.pm
@@ -3808,7 +3808,11 @@ __PACKAGE__->register_method({
proxyto => 'node',
description => "Reset virtual machine.",
permissions => {
- check => ['perm', '/vms/{vmid}', ['VM.PowerMgmt']],
+ check => [
+ 'or',
+ ['perm', '/vms/{vmid}', ['VM.PowerMgmt']],
+ ['perm', '/vms/{vmid}', ['VM.Reboot']],
+ ],
},
parameters => {
additionalProperties => 0,
@@ -3978,7 +3982,11 @@ __PACKAGE__->register_method({
description =>
"Reboot the VM by shutting it down, and starting it again. Applies pending changes.",
permissions => {
- check => ['perm', '/vms/{vmid}', ['VM.PowerMgmt']],
+ check => [
+ 'or',
+ ['perm', '/vms/{vmid}', ['VM.PowerMgmt']],
+ ['perm', '/vms/{vmid}', ['VM.Reboot']],
+ ],
},
parameters => {
additionalProperties => 0,
--
2.47.3
^ permalink raw reply related [flat|nested] 6+ messages in thread* [PATCH docs 5/5] pveum: VM permissions: add VM.Reboot
2026-09-16 9:06 [PATCH access-control/docs/manager/qemu-server 0/5] Add new permission VM.Reboot Jonas Theisen
` (3 preceding siblings ...)
2026-09-16 9:06 ` [PATCH qemu-server 4/5] api: Integrate " Jonas Theisen
@ 2026-09-16 9:06 ` Jonas Theisen
4 siblings, 0 replies; 6+ messages in thread
From: Jonas Theisen @ 2026-09-16 9:06 UTC (permalink / raw)
To: pve-devel
Add new 'VM.Reboot' permission to list of available permissions
Signed-off-by: Jonas Theisen <j.theisen@proxmox.com>
---
pveum.adoc | 1 +
1 file changed, 1 insertion(+)
diff --git a/pveum.adoc b/pveum.adoc
index d089cb6..2d18883 100644
--- a/pveum.adoc
+++ b/pveum.adoc
@@ -921,6 +921,7 @@ Virtual machine related privileges::
* `VM.GuestAgent.Unrestricted`: issue arbitrary QEMU guest agent commands
* `VM.Migrate`: migrate VM to alternate server on cluster
* `VM.PowerMgmt`: power management (start, stop, reset, shutdown, ...)
+* `VM.Reboot`: limited power management (only reboot and reset)
* `VM.Replicate`: configure and run guest replication
* `VM.Snapshot.Rollback`: rollback VM to one of its snapshots
* `VM.Snapshot`: create/delete VM snapshots
--
2.47.3
^ permalink raw reply related [flat|nested] 6+ messages in thread