From f81908eb58939b75ee4eb7abcde4ed078e84edac Mon Sep 17 00:00:00 2001 From: Fabian Ebner Date: Mon, 25 Oct 2021 15:47:48 +0200 Subject: [PATCH] api: disks: delete: add flag for wiping disks For ZFS and directory storages, clean up the whole disk when the layout is as usual to avoid left-overs. Signed-off-by: Fabian Ebner --- PVE/API2/Disks/Directory.pm | 26 +++++++++++++++++++++++ PVE/API2/Disks/LVM.pm | 23 +++++++++++++++++++++ PVE/API2/Disks/LVMThin.pm | 25 ++++++++++++++++++++++ PVE/API2/Disks/ZFS.pm | 41 +++++++++++++++++++++++++++++++++++++ 4 files changed, 115 insertions(+) diff --git a/PVE/API2/Disks/Directory.pm b/PVE/API2/Disks/Directory.pm index e9b05be..c9dcb52 100644 --- a/PVE/API2/Disks/Directory.pm +++ b/PVE/API2/Disks/Directory.pm @@ -314,6 +314,12 @@ __PACKAGE__->register_method ({ properties => { node => get_standard_option('pve-node'), name => get_standard_option('pve-storage-id'), + 'cleanup-disks' => { + description => "Also wipe disk so it can be repurposed afterwards.", + type => 'boolean', + optional => 1, + default => 0, + }, }, }, returns => { type => 'string' }, @@ -331,10 +337,30 @@ __PACKAGE__->register_method ({ my $mountunitpath = "/etc/systemd/system/$mountunitname"; PVE::Diskmanage::locked_disk_action(sub { + my $to_wipe; + if ($param->{'cleanup-disks'}) { + my $unit = $read_ini->($mountunitpath); + + my $dev = PVE::Diskmanage::verify_blockdev_path($unit->{'Mount'}->{'What'}); + $to_wipe = $dev; + + # clean up whole device if this is the only partition + $dev =~ s|^/dev/||; + my $info = PVE::Diskmanage::get_disks($dev, 1, 1); + die "unable to obtain information for disk '$dev'\n" if !$info->{$dev}; + $to_wipe = $info->{$dev}->{parent} + if $info->{$dev}->{parent} && scalar(keys $info->%*) == 2; + } + run_command(['systemctl', 'stop', $mountunitname]); run_command(['systemctl', 'disable', $mountunitname]); unlink $mountunitpath or $! == ENOENT or die "cannot remove $mountunitpath - $!\n"; + + if ($to_wipe) { + PVE::Diskmanage::wipe_blockdev($to_wipe); + PVE::Diskmanage::udevadm_trigger($to_wipe); + } }); }; diff --git a/PVE/API2/Disks/LVM.pm b/PVE/API2/Disks/LVM.pm index 1b88af2..1af3d43 100644 --- a/PVE/API2/Disks/LVM.pm +++ b/PVE/API2/Disks/LVM.pm @@ -198,6 +198,12 @@ __PACKAGE__->register_method ({ properties => { node => get_standard_option('pve-node'), name => get_standard_option('pve-storage-id'), + 'cleanup-disks' => { + description => "Also wipe disks so they can be repurposed afterwards.", + type => 'boolean', + optional => 1, + default => 0, + }, }, }, returns => { type => 'string' }, @@ -211,7 +217,24 @@ __PACKAGE__->register_method ({ my $worker = sub { PVE::Diskmanage::locked_disk_action(sub { + my $vgs = PVE::Storage::LVMPlugin::lvm_vgs(1); + die "no such volume group '$name'\n" if !$vgs->{$name}; + PVE::Storage::LVMPlugin::lvm_destroy_volume_group($name); + + if ($param->{'cleanup-disks'}) { + my $wiped = []; + eval { + for my $pv ($vgs->{$name}->{pvs}->@*) { + my $dev = PVE::Diskmanage::verify_blockdev_path($pv->{name}); + PVE::Diskmanage::wipe_blockdev($dev); + push $wiped->@*, $dev; + } + }; + my $err = $@; + PVE::Diskmanage::udevadm_trigger($wiped->@*); + die "cleanup failed - $err" if $err; + } }); }; diff --git a/PVE/API2/Disks/LVMThin.pm b/PVE/API2/Disks/LVMThin.pm index 23f262a..ea36ce2 100644 --- a/PVE/API2/Disks/LVMThin.pm +++ b/PVE/API2/Disks/LVMThin.pm @@ -177,6 +177,12 @@ __PACKAGE__->register_method ({ node => get_standard_option('pve-node'), name => get_standard_option('pve-storage-id'), 'volume-group' => get_standard_option('pve-storage-id'), + 'cleanup-disks' => { + description => "Also wipe disks so they can be repurposed afterwards.", + type => 'boolean', + optional => 1, + default => 0, + }, }, }, returns => { type => 'string' }, @@ -197,6 +203,25 @@ __PACKAGE__->register_method ({ if !grep { $_->{lv} eq $lv && $_->{vg} eq $vg } $thinpools->@*; run_command(['lvremove', '-y', "${vg}/${lv}"]); + + if ($param->{'cleanup-disks'}) { + my $vgs = PVE::Storage::LVMPlugin::lvm_vgs(1); + + die "no such volume group '$vg'\n" if !$vgs->{$vg}; + die "volume group '$vg' still in use\n" if $vgs->{$vg}->{lvcount} > 0; + + my $wiped = []; + eval { + for my $pv ($vgs->{$vg}->{pvs}->@*) { + my $dev = PVE::Diskmanage::verify_blockdev_path($pv->{name}); + PVE::Diskmanage::wipe_blockdev($dev); + push $wiped->@*, $dev; + } + }; + my $err = $@; + PVE::Diskmanage::udevadm_trigger($wiped->@*); + die "cleanup failed - $err" if $err; + } }); }; diff --git a/PVE/API2/Disks/ZFS.pm b/PVE/API2/Disks/ZFS.pm index e892712..10b73a5 100644 --- a/PVE/API2/Disks/ZFS.pm +++ b/PVE/API2/Disks/ZFS.pm @@ -460,6 +460,12 @@ __PACKAGE__->register_method ({ properties => { node => get_standard_option('pve-node'), name => get_standard_option('pve-storage-id'), + 'cleanup-disks' => { + description => "Also wipe disks so they can be repurposed afterwards.", + type => 'boolean', + optional => 1, + default => 0, + }, }, }, returns => { type => 'string' }, @@ -473,12 +479,47 @@ __PACKAGE__->register_method ({ my $worker = sub { PVE::Diskmanage::locked_disk_action(sub { + my $to_wipe = []; + if ($param->{'cleanup-disks'}) { + # Using -o name does not only output the name in combination with -v. + run_command(['zpool', 'list', '-vHPL', $name], outfunc => sub { + my ($line) = @_; + + my ($name) = PVE::Tools::split_list($line); + return if $name !~ m|^/dev/.+|; + + my $dev = PVE::Diskmanage::verify_blockdev_path($name); + my $wipe = $dev; + + $dev =~ s|^/dev/||; + my $info = PVE::Diskmanage::get_disks($dev, 1, 1); + die "unable to obtain information for disk '$dev'\n" if !$info->{$dev}; + + # Wipe whole disk if usual ZFS layout with partition 9 as ZFS reserved. + my $parent = $info->{$dev}->{parent}; + if ($parent && scalar(keys $info->%*) == 3) { + $parent =~ s|^/dev/||; + my $info9 = $info->{"${parent}9"}; + + $wipe = $info->{$dev}->{parent} # need leading /dev/ + if $info9 && $info9->{used} && $info9->{used} =~ m/^ZFS reserved/; + } + + push $to_wipe->@*, $wipe; + }); + } + if (-e '/lib/systemd/system/zfs-import@.service') { my $importunit = 'zfs-import@' . PVE::Systemd::escape_unit($name) . '.service'; run_command(['systemctl', 'disable', $importunit]); } run_command(['zpool', 'destroy', $name]); + + eval { PVE::Diskmanage::wipe_blockdev($_) for $to_wipe->@*; }; + my $err = $@; + PVE::Diskmanage::udevadm_trigger($to_wipe->@*); + die "cleanup failed - $err" if $err; }); }; -- 2.39.2