From a573f66a2ecc6b2ccbee9d7088c05f9e81dc592d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20Gr=C3=BCnbichler?= Date: Fri, 29 Nov 2019 12:00:37 +0100 Subject: [PATCH] rbd: unprotect all snapshots on image removal MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit we need to unprotect more snapshots than just the base one, since we allow linked clones of regular VM snapshots. unprotection will only work if no linked clones exist anymore. Signed-off-by: Fabian Grünbichler --- PVE/Storage/RBDPlugin.pm | 39 +++++++++++++++++++++++++++++++++++---- 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/PVE/Storage/RBDPlugin.pm b/PVE/Storage/RBDPlugin.pm index 538d6bb..f237113 100644 --- a/PVE/Storage/RBDPlugin.pm +++ b/PVE/Storage/RBDPlugin.pm @@ -227,6 +227,38 @@ sub rbd_ls { return $list; } +sub rbd_ls_snap { + my ($scfg, $storeid, $name) = @_; + + my $cmd = &$rbd_cmd($scfg, $storeid, 'snap', 'ls', $name, '--format', 'json'); + + my $raw = ''; + run_rbd_command($cmd, errmsg => "rbd error", errfunc => sub {}, outfunc => sub { $raw .= shift; }); + + my $list; + if ($raw =~ m/^(\[.*\])$/s) { # untaint + $list = eval { JSON::decode_json($1) }; + die "invalid JSON output from 'rbd snap ls $name': $@\n" if $@; + } else { + die "got unexpected data from 'rbd snap ls $name': '$raw'\n"; + } + + $list = [] if !defined($list); + + my $res = {}; + foreach my $el (@$list) { + my $snap = $el->{name}; + my $protected = defined($el->{protected}) && $el->{protected} eq "true" ? 1 : undef; + $res->{$snap} = { + name => $snap, + id => $el->{id} // undef, + size => $el->{size} // 0, + protected => $protected, + }; + } + return $res; +} + sub rbd_volume_info { my ($scfg, $storeid, $volname, $snap) = @_; @@ -483,10 +515,9 @@ sub free_image { my ($vtype, $name, $vmid, undef, undef, undef) = $class->parse_volname($volname); - if ($isBase) { - my $snap = '__base__'; - my (undef, undef, undef, $protected) = rbd_volume_info($scfg, $storeid, $name, $snap); - if ($protected){ + my $snaps = rbd_ls_snap($scfg, $storeid, $name); + foreach my $snap (keys %$snaps) { + if ($snaps->{$snap}->{protected}) { my $cmd = &$rbd_cmd($scfg, $storeid, 'snap', 'unprotect', $name, '--snap', $snap); run_rbd_command($cmd, errmsg => "rbd unprotect $name snap '$snap' error"); }