]> git.proxmox.com Git - pve-storage.git/commitdiff
api: disks: delete: add flag for wiping disks
authorFabian Ebner <f.ebner@proxmox.com>
Mon, 25 Oct 2021 13:47:48 +0000 (15:47 +0200)
committerFabian Grünbichler <f.gruenbichler@proxmox.com>
Wed, 10 Nov 2021 11:35:25 +0000 (12:35 +0100)
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 <f.ebner@proxmox.com>
PVE/API2/Disks/Directory.pm
PVE/API2/Disks/LVM.pm
PVE/API2/Disks/LVMThin.pm
PVE/API2/Disks/ZFS.pm

index e9b05be7ea67533c0607b78071a15f1de2b612b5..c9dcb526bfc5f88ef4b86ac9711480f5488b56f0 100644 (file)
@@ -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);
+               }
            });
        };
 
index 1b88af2ff03fbaacc00e50d14f772d7e46950d47..1af3d43a586d9a1ecbc6a90d4278b7e819a726d6 100644 (file)
@@ -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;
+               }
            });
        };
 
index 23f262a5dfdbf026a6254a04c34455ef2533527a..ea36ce23b693da6e5635ab15694cd7ab7ed722fc 100644 (file)
@@ -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;
+               }
            });
        };
 
index e8927123da265b7ea72404bee1608cbd609e4e96..10b73a5cf3d78aa66a46b6be94df49feabc1f4d9 100644 (file)
@@ -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;
            });
        };