From a8e2f942bde57901527685ce126faa8a97496274 Mon Sep 17 00:00:00 2001 From: Dietmar Maurer Date: Tue, 28 May 2013 12:02:29 +0200 Subject: [PATCH] fix unused disk handling Show unused disks even if disk is used inside snapshots. But do not allow to remove those disks. --- PVE/API2/Qemu.pm | 15 ++++++++++++--- PVE/QemuServer.pm | 48 +++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 56 insertions(+), 7 deletions(-) diff --git a/PVE/API2/Qemu.pm b/PVE/API2/Qemu.pm index 2df6d88..3526e44 100644 --- a/PVE/API2/Qemu.pm +++ b/PVE/API2/Qemu.pm @@ -660,10 +660,19 @@ my $delete_drive = sub { if (!PVE::QemuServer::drive_is_cdrom($drive)) { my $volid = $drive->{file}; + if (&$vm_is_volid_owner($storecfg, $vmid, $volid)) { - if ($force || $key =~ m/^unused/) { - # fixme: aliases!! - eval { PVE::Storage::vdisk_free($storecfg, $volid); }; + if ($force || $key =~ m/^unused/) { + eval { + # check if the disk is really unused + my $used_paths = PVE::QemuServer::get_used_paths($vmid, $storecfg, $conf, 1, $key); + my $path = PVE::Storage::path($storecfg, $volid); + + die "unable to delete '$volid' - volume is still in use (snapshot?)\n" + if $used_paths->{$path}; + + PVE::Storage::vdisk_free($storecfg, $volid); + }; die $@ if $@; } else { PVE::QemuServer::add_unused_volume($conf, $volid, $vmid); diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm index db767d6..666e282 100644 --- a/PVE/QemuServer.pm +++ b/PVE/QemuServer.pm @@ -1696,9 +1696,8 @@ sub write_vm_config { my $used_volids = {}; - # fixme: allow to add unused disk even if disk is used inside snapshot my $cleanup_config = sub { - my ($cref) = @_; + my ($cref, $snapname) = @_; foreach my $key (keys %$cref) { next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots' || @@ -1709,7 +1708,7 @@ sub write_vm_config { $cref->{$key} = $value; - if (valid_drivename($key)) { + if (!$snapname && valid_drivename($key)) { my $drive = parse_drive($key, $value); $used_volids->{$drive->{file}} = 1 if $drive && $drive->{file}; } @@ -1718,7 +1717,7 @@ sub write_vm_config { &$cleanup_config($conf); foreach my $snapname (keys %{$conf->{snapshots}}) { - &$cleanup_config($conf->{snapshots}->{$snapname}); + &$cleanup_config($conf->{snapshots}->{$snapname}, $snapname); } # remove 'unusedX' settings if we re-add a volume @@ -3614,6 +3613,47 @@ sub scan_volids { return $volid_hash; } +sub get_used_paths { + my ($vmid, $storecfg, $conf, $scan_snapshots, $skip_drive) = @_; + + my $used_path = {}; + + my $scan_config = sub { + my ($cref, $snapname) = @_; + + foreach my $key (keys %$cref) { + my $value = $cref->{$key}; + if (valid_drivename($key)) { + next if $skip_drive && $key eq $skip_drive; + my $drive = parse_drive($key, $value); + next if !$drive || !$drive->{file} || drive_is_cdrom($drive); + if ($drive->{file} =~ m!^/!) { + $used_path->{$drive->{file}}++; # = 1; + } else { + my ($storeid, $volname) = PVE::Storage::parse_volume_id($drive->{file}, 1); + next if !$storeid; + my $scfg = PVE::Storage::storage_config($storecfg, $storeid, 1); + next if !$scfg; + my $path = PVE::Storage::path($storecfg, $drive->{file}, $snapname); + $used_path->{$path}++; # = 1; + } + } + } + }; + + &$scan_config($conf); + + undef $skip_drive; + + if ($scan_snapshots) { + foreach my $snapname (keys %{$conf->{snapshots}}) { + &$scan_config($conf->{snapshots}->{$snapname}, $snapname); + } + } + + return $used_path; +} + sub update_disksize { my ($vmid, $conf, $volid_hash) = @_; -- 2.39.2