api/destroy: repeat early checks after lock

to protect against concurrent changes

Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com>
This commit is contained in:
Fabian Grünbichler 2020-04-27 10:24:26 +02:00 committed by Thomas Lamprecht
parent 8284121451
commit a4c7029dd8

View File

@ -1468,32 +1468,38 @@ __PACKAGE__->register_method({
raise_param_exc({ skiplock => "Only root may use this option." }) raise_param_exc({ skiplock => "Only root may use this option." })
if $skiplock && $authuser ne 'root@pam'; if $skiplock && $authuser ne 'root@pam';
# test if VM exists my $early_checks = sub {
my $conf = PVE::QemuConfig->load_config($vmid); # test if VM exists
my $storecfg = PVE::Storage::config(); my $conf = PVE::QemuConfig->load_config($vmid);
PVE::QemuConfig->check_protection($conf, "can't remove VM $vmid"); PVE::QemuConfig->check_protection($conf, "can't remove VM $vmid");
my $ha_managed = PVE::HA::Config::service_is_configured("vm:$vmid"); my $ha_managed = PVE::HA::Config::service_is_configured("vm:$vmid");
if (!$param->{purge}) { if (!$param->{purge}) {
die "unable to remove VM $vmid - used in HA resources and purge parameter not set.\n" die "unable to remove VM $vmid - used in HA resources and purge parameter not set.\n"
if $ha_managed; if $ha_managed;
# don't allow destroy if with replication jobs but no purge param # don't allow destroy if with replication jobs but no purge param
my $repl_conf = PVE::ReplicationConfig->new(); my $repl_conf = PVE::ReplicationConfig->new();
$repl_conf->check_for_existing_jobs($vmid); $repl_conf->check_for_existing_jobs($vmid);
} }
# early tests (repeat after locking) die "VM $vmid is running - destroy failed\n"
die "VM $vmid is running - destroy failed\n" if PVE::QemuServer::check_running($vmid);
if PVE::QemuServer::check_running($vmid);
return $ha_managed;
};
$early_checks->();
my $realcmd = sub { my $realcmd = sub {
my $upid = shift; my $upid = shift;
my $storecfg = PVE::Storage::config();
syslog('info', "destroy VM $vmid: $upid\n"); syslog('info', "destroy VM $vmid: $upid\n");
PVE::QemuConfig->lock_config($vmid, sub { PVE::QemuConfig->lock_config($vmid, sub {
die "VM $vmid is running - destroy failed\n" # repeat, config might have changed
if (PVE::QemuServer::check_running($vmid)); my $ha_managed = $early_checks->();
PVE::QemuServer::destroy_vm($storecfg, $vmid, $skiplock, { lock => 'destroyed' }); PVE::QemuServer::destroy_vm($storecfg, $vmid, $skiplock, { lock => 'destroyed' });