[pve-devel] [PATCH container 5/6] clone_vm: refactor locking further
Fabian Grünbichler
f.gruenbichler at proxmox.com
Fri Jun 18 14:51:22 CEST 2021
introduce a new helper handling
- obtaining the flock
- (re)loading the config
- checking that the 'create' lock is still there
before calling a passed-in sub with the current config, since this
pattern was used quite a lot here.
intentionally changed behaviour:
- flock is now held for the post_clone hook call
- failure to remove the 'create' lock or to move the config to the
target node if applicable will not undo the clone, since either is
trivially fixable ('pct unlock' or a no-op migration), and copying all
those volumes might have been quite expensive..
Signed-off-by: Fabian Grünbichler <f.gruenbichler at proxmox.com>
---
there are probably quite a few places in the container/qemu-server code
where we should employ this or a similar mechanism with digest tracking
to be 100% on the safe side..
src/PVE/API2/LXC.pm | 76 ++++++++++++++++++++++++---------------------
1 file changed, 41 insertions(+), 35 deletions(-)
diff --git a/src/PVE/API2/LXC.pm b/src/PVE/API2/LXC.pm
index 5406923..4877dd9 100644
--- a/src/PVE/API2/LXC.pm
+++ b/src/PVE/API2/LXC.pm
@@ -1395,6 +1395,16 @@ __PACKAGE__->register_method({
PVE::LXC::Config->create_and_lock_config($newid, 0);
+ my $lock_and_reload = sub {
+ my ($vmid, $code) = @_;
+ return PVE::LXC::Config->lock_config($vmid, sub {
+ my $conf = PVE::LXC::Config->load_config($vmid);
+ die "Lost 'create' config lock, aborting.\n"
+ if !PVE::LXC::Config->has_lock($conf, 'create');
+
+ return $code->($conf);
+ });
+ };
my $src_conf = PVE::LXC::Config->set_lock($vmid, 'disk');
@@ -1481,12 +1491,7 @@ __PACKAGE__->register_method({
$newconf->{description} = $param->{description};
}
- PVE::LXC::Config->lock_config($newid, sub {
- # read empty config, lock needs to be still here
- my $conf = PVE::LXC::Config->load_config($newid);
- die "Lost 'create' config lock, aborting.\n"
- if !PVE::LXC::Config->has_lock($conf, 'create');
- # write the actual new config now to disk
+ $lock_and_reload->($newid, sub {
PVE::LXC::Config->write_config($newid, $newconf);
});
};
@@ -1495,10 +1500,7 @@ __PACKAGE__->register_method({
warn "Failed to remove source CT config lock - $@\n" if $@;
eval {
- PVE::LXC::Config->lock_config($newid, sub {
- my $conf = PVE::LXC::Config->load_config($newid);
- die "Lost 'create' config lock, aborting.\n"
- if !PVE::LXC::Config->has_lock($conf, 'create');
+ $lock_and_reload->($newid, sub {
PVE::LXC::Config->destroy_config($newid);
});
};
@@ -1509,10 +1511,8 @@ __PACKAGE__->register_method({
my $update_conf = sub {
my ($key, $value) = @_;
- return PVE::LXC::Config->lock_config($newid, sub {
- my $conf = PVE::LXC::Config->load_config($newid);
- die "Lost 'create' config lock, aborting.\n"
- if !PVE::LXC::Config->has_lock($conf, 'create');
+ return $lock_and_reload->($newid, sub {
+ my $conf = shift;
$conf->{$key} = $value;
PVE::LXC::Config->write_config($newid, $conf);
});
@@ -1559,23 +1559,20 @@ __PACKAGE__->register_method({
PVE::AccessControl::add_vm_to_pool($newid, $pool) if $pool;
- $newconf = PVE::LXC::Config->load_config($newid);
- die "Lost 'create' config lock, aborting.\n"
- if !PVE::LXC::Config->has_lock($newconf, 'create');
- my $rootdir = PVE::LXC::mount_all($newid, $storecfg, $newconf, 1);
- my $lxc_setup = PVE::LXC::Setup->new($newconf, $rootdir);
- $lxc_setup->post_clone_hook($newconf);
- PVE::LXC::umount_all($newid, $storecfg, $newconf, 1);
-
- PVE::LXC::Config->remove_lock($newid, 'create');
-
- PVE::LXC::Config->lock_config($newid, sub {
- if ($target) {
- # always deactivate volumes - avoid lvm LVs to be active on several nodes
- PVE::Storage::deactivate_volumes($storecfg, $vollist, $snapname) if !$running;
- PVE::Storage::deactivate_volumes($storecfg, $newvollist);
-
- PVE::LXC::Config->move_config_to_node($newid, $target);
+ $lock_and_reload->($newid, sub {
+ my $conf = shift;
+ my $rootdir = PVE::LXC::mount_all($newid, $storecfg, $conf, 1);
+ eval {
+ my $lxc_setup = PVE::LXC::Setup->new($conf, $rootdir);
+ $lxc_setup->post_clone_hook($conf);
+ };
+ my $err = $@;
+ eval { PVE::LXC::umount_all($newid, $storecfg, $conf, 1); };
+ if ($err) {
+ warn "$@\n" if $@;
+ die $err;
+ } else {
+ die $@ if $@;
}
});
};
@@ -1594,10 +1591,7 @@ __PACKAGE__->register_method({
}
eval {
- PVE::LXC::Config->lock_config($newid, sub {
- my $conf = PVE::LXC::Config->load_config($newid);
- die "Lost 'create' config lock, aborting.\n"
- if !PVE::LXC::Config->has_lock($conf, 'create');
+ $lock_and_reload->($newid, sub {
PVE::LXC::Config->destroy_config($newid);
});
};
@@ -1606,6 +1600,18 @@ __PACKAGE__->register_method({
die "clone failed: $err";
}
+ $lock_and_reload->($newid, sub {
+ PVE::LXC::Config->remove_lock($newid, 'create');
+
+ if ($target) {
+ # always deactivate volumes - avoid lvm LVs to be active on several nodes
+ PVE::Storage::deactivate_volumes($storecfg, $vollist, $snapname) if !$running;
+ PVE::Storage::deactivate_volumes($storecfg, $newvollist);
+
+ PVE::LXC::Config->move_config_to_node($newid, $target);
+ }
+ });
+
PVE::Firewall::clone_vmfw_conf($vmid, $newid);
return;
};
--
2.30.2
More information about the pve-devel
mailing list