X-Git-Url: https://git.proxmox.com/?p=pve-common.git;a=blobdiff_plain;f=src%2FPVE%2FAbstractConfig.pm;h=7395768bc3b9e0e50aac4982b0769f140f448580;hp=be6eb5cbb535b9d3fd42c65e6297f5737cfe2fb7;hb=e4ae11709910abb5eab43ae6b845a3e197bb62b1;hpb=53c255218ebec327f881a479a7be1e04646ae2e9 diff --git a/src/PVE/AbstractConfig.pm b/src/PVE/AbstractConfig.pm index be6eb5c..7395768 100644 --- a/src/PVE/AbstractConfig.pm +++ b/src/PVE/AbstractConfig.pm @@ -136,9 +136,10 @@ sub remove_lock { $class->lock_config($vmid, sub { my $conf = $class->load_config($vmid); if (!$conf->{lock}) { - die "no lock found trying to remove lock '$lock'\n"; + my $lockstring = defined($lock) ? "'$lock' " : "any"; + die "no lock found trying to remove $lockstring lock\n"; } elsif (defined($lock) && $conf->{lock} ne $lock) { - die "found lock '$conf->{lock}' trying to remove lock '$lock'\n"; + die "found lock '$conf->{lock}' trying to remove '$lock' lock\n"; } delete $conf->{lock}; $class->write_config($vmid, $conf); @@ -221,6 +222,14 @@ sub __snapshot_freeze { die "abstract method - implement me\n"; } +# Code run before and after creating all the volume snapshots +# base: noop +sub __snapshot_create_vol_snapshots_hook { + my ($class, $vmid, $snap, $running, $hook) = @_; + + return; +} + # Create the volume snapshots for the VM/CT. sub __snapshot_create_vol_snapshot { my ($class, $vmid, $vs, $volume, $snapname) = @_; @@ -230,7 +239,7 @@ sub __snapshot_create_vol_snapshot { # Remove a drive from the snapshot config. sub __snapshot_delete_remove_drive { - my ($class, $snap, $remove_drive) = @_; + my ($class, $snap, $drive) = @_; die "abstract method - implement me\n"; } @@ -277,6 +286,13 @@ sub __snapshot_rollback_vm_start { die "abstract method - implement me\n"; } +# Get list of volume IDs which are referenced in $conf, but not in $snap. +sub __snapshot_rollback_get_unused { + my ($class, $conf, $snap) = @_; + + die "abstract method - implement me\n"; +} + # Iterate over all configured volumes, calling $func for each key/value pair. sub __snapshot_foreach_volume { my ($class, $conf, $func) = @_; @@ -413,6 +429,8 @@ sub snapshot_create { $class->__snapshot_freeze($vmid, 0); } + $class->__snapshot_create_vol_snapshots_hook($vmid, $snap, $running, "before"); + $class->__snapshot_foreach_volume($snap, sub { my ($vs, $volume) = @_; @@ -423,9 +441,11 @@ sub snapshot_create { my $err = $@; if ($running) { + $class->__snapshot_create_vol_snapshots_hook($vmid, $snap, $running, "after"); if ($freezefs) { $class->__snapshot_freeze($vmid, 1); } + $class->__snapshot_create_vol_snapshots_hook($vmid, $snap, $running, "after-unfreeze"); } if ($err) { @@ -448,6 +468,9 @@ sub snapshot_delete { my $snap; my $unused = []; + $class->set_lock($vmid, 'snapshot-delete') + if (!$drivehash); # doesn't already have a 'snapshot' lock + my $unlink_parent = sub { my ($confref, $new_parent) = @_; @@ -460,55 +483,39 @@ sub snapshot_delete { } }; - my $updatefn = sub { - my ($remove_drive) = @_; + my $remove_drive = sub { + my ($drive) = @_; my $conf = $class->load_config($vmid); + $snap = $conf->{snapshots}->{$snapname}; + die "snapshot '$snapname' does not exist\n" if !defined($snap); - if (!$drivehash) { - $class->check_lock($conf); - die "you can't delete a snapshot if vm is a template\n" - if $class->is_template($conf); - } + $class->__snapshot_delete_remove_drive($snap, $drive); - $snap = $conf->{snapshots}->{$snapname}; + $class->write_config($vmid, $conf); + }; - die "snapshot '$snapname' does not exist\n" if !defined($snap); + #prepare + $class->lock_config($vmid, sub { + my $conf = $class->load_config($vmid); - # remove parent refs - if (!$prepare) { - &$unlink_parent($conf, $snap->{parent}); - foreach my $sn (keys %{$conf->{snapshots}}) { - next if $sn eq $snapname; - &$unlink_parent($conf->{snapshots}->{$sn}, $snap->{parent}); - } - } + die "you can't delete a snapshot if vm is a template\n" + if $class->is_template($conf); - if ($remove_drive) { - $class->__snapshot_delete_remove_drive($snap, $remove_drive); - } + $snap = $conf->{snapshots}->{$snapname}; + die "snapshot '$snapname' does not exist\n" if !defined($snap); - if ($prepare) { - $snap->{snapstate} = 'delete'; - } else { - delete $conf->{snapshots}->{$snapname}; - delete $conf->{lock} if $drivehash; - foreach my $volid (@$unused) { - $class->add_unused_volume($conf, $volid); - } - } + $snap->{snapstate} = 'delete'; $class->write_config($vmid, $conf); - }; - - $class->lock_config($vmid, $updatefn); + }); # now remove vmstate file if ($snap->{vmstate}) { $class->__snapshot_delete_vmstate_file($snap, $force); # save changes (remove vmstate from snapshot) - $class->lock_config($vmid, $updatefn, 'vmstate') if !$force; + $class->lock_config($vmid, $remove_drive, 'vmstate') if !$force; }; # now remove all volume snapshots @@ -517,21 +524,39 @@ sub snapshot_delete { return if $snapname eq 'vzdump' && $vs ne 'rootfs' && !$volume->{backup}; if (!$drivehash || $drivehash->{$vs}) { - eval { $class->__snapshot_delete_vol_snapshot($vmid, $vs, $volume, $snapname); }; + eval { $class->__snapshot_delete_vol_snapshot($vmid, $vs, $volume, $snapname, $unused); }; if (my $err = $@) { die $err if !$force; warn $err; } } - # save changes (remove mp from snapshot) - $class->lock_config($vmid, $updatefn, $vs) if !$force; - push @$unused, $volume->{volume}; + # save changes (remove drive from snapshot) + $class->lock_config($vmid, $remove_drive, $vs) if !$force; }); # now cleanup config - $prepare = 0; - $class->lock_config($vmid, $updatefn); + $class->lock_config($vmid, sub { + my $conf = $class->load_config($vmid); + $snap = $conf->{snapshots}->{$snapname}; + die "snapshot '$snapname' does not exist\n" if !defined($snap); + + # remove parent refs + &$unlink_parent($conf, $snap->{parent}); + foreach my $sn (keys %{$conf->{snapshots}}) { + next if $sn eq $snapname; + &$unlink_parent($conf->{snapshots}->{$sn}, $snap->{parent}); + } + + + delete $conf->{snapshots}->{$snapname}; + delete $conf->{lock}; + foreach my $volid (@$unused) { + $class->add_unused_volume($conf, $volid); + } + + $class->write_config($vmid, $conf); + }); } # Rolls back to a given snapshot. @@ -591,6 +616,12 @@ sub snapshot_rollback { my $forcemachine; if (!$prepare) { + my $unused = $class->__snapshot_rollback_get_unused($conf, $snap); + + foreach my $volid (@$unused) { + $class->add_unused_volume($conf, $volid); + } + my $has_machine_config = defined($conf->{machine}); # copy snapshot config to current config