From: Dominik Csapak Date: Mon, 9 Dec 2019 14:26:59 +0000 (+0100) Subject: suspend to disk: check more permissions X-Git-Url: https://git.proxmox.com/?p=qemu-server.git;a=commitdiff_plain;h=75c24bba0a520f310fa9a70a19a11dbc3281f1fa suspend to disk: check more permissions only VM.PowerMgmt is not enough, since we allocate space on a storage, so we need VM.Config.Disk on the vm and Datastore.AllocateSpace on the storage Signed-off-by: Dominik Csapak --- diff --git a/PVE/API2/Qemu.pm b/PVE/API2/Qemu.pm index b28373e..25c2836 100644 --- a/PVE/API2/Qemu.pm +++ b/PVE/API2/Qemu.pm @@ -2387,6 +2387,9 @@ __PACKAGE__->register_method({ proxyto => 'node', description => "Suspend virtual machine.", permissions => { + description => "You need 'VM.PowerMgmt' on /vms/{vmid}, and if you have set 'todisk',". + " you need also 'VM.Config.Disk' on /vms/{vmid} and 'Datastore.AllocateSpace'". + " on the storage for the vmstate.", check => ['perm', '/vms/{vmid}', [ 'VM.PowerMgmt' ]], }, parameters => { @@ -2435,6 +2438,20 @@ __PACKAGE__->register_method({ die "Cannot suspend HA managed VM to disk\n" if $todisk && PVE::HA::Config::vm_is_ha_managed($vmid); + # early check for storage permission, for better user feedback + if ($todisk) { + $rpcenv->check_vm_perm($authuser, $vmid, undef, ['VM.Config.Disk']); + + if (!$statestorage) { + # get statestorage from config if none is given + my $conf = PVE::QemuConfig->load_config($vmid); + my $storecfg = PVE::Storage::config(); + $statestorage = PVE::QemuServer::find_vmstate_storage($conf, $storecfg); + } + + $rpcenv->check($authuser, "/storage/$statestorage", ['Datastore.AllocateSpace']); + } + my $realcmd = sub { my $upid = shift; diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm index 7bcdb61..549ce30 100644 --- a/PVE/QemuServer.pm +++ b/PVE/QemuServer.pm @@ -5742,6 +5742,7 @@ sub vm_reboot { }); } +# note: if using the statestorage parameter, the caller has to check privileges sub vm_suspend { my ($vmid, $skiplock, $includestate, $statestorage) = @_; @@ -5765,6 +5766,17 @@ sub vm_suspend { $conf->{lock} = 'suspending'; my $date = strftime("%Y-%m-%d", localtime(time())); $storecfg = PVE::Storage::config(); + if (!$statestorage) { + $statestorage = find_vmstate_storage($conf, $storecfg); + # check permissions for the storage + my $rpcenv = PVE::RPCEnvironment::get(); + if ($rpcenv->{type} ne 'cli') { + my $authuser = $rpcenv->get_user(); + $rpcenv->check($authuser, "/storage/$statestorage", ['Datastore.AllocateSpace']); + } + } + + $vmstate = PVE::QemuConfig->__snapshot_save_vmstate($vmid, $conf, "suspend-$date", $storecfg, $statestorage, 1); $path = PVE::Storage::path($storecfg, $vmstate); PVE::QemuConfig->write_config($vmid, $conf);