Starting with PVE 9, the LVM and LVM-thin plugins create new LVs with
the `--setautoactivation n` flag to fix #4997 [1]. However, this does
not affect already existing LVs of setups upgrading from PVE 8.

Hence, add a new `updatelvm` subcommand to `pve8to9` that finds guest
volume LVs with autoactivation enabled on LVM and LVM-thin storages,
and disables autoactivation on each of them. This is done while
holding a lock on the storage, to avoid metadata update conflicts for
shared LVM storages.

Also, check for guest volume LVs with autoactivation enabled during
the `checklist` command, and suggest to run `updatelvm` if necessary.
The check is done without a lock, as taking a lock doesn't have
advantages here.

While some users may have disabled autoactivation on the VG level to
work around #4997, consciously do not take this into account:
Disabling autoactivation on LVs too does not hurt, and avoids issues
in case the user decides to re-enable autoactivation on the VG level
in the future.

[1] https://bugzilla.proxmox.com/show_bug.cgi?id=4997

Signed-off-by: Friedrich Weber <f.we...@proxmox.com>
---

Notes:
    open questions:
    
    - if users create new LVs on PVE 8 nodes after running `pve8to9
      updatelvm` but before actually upgrading to PVE 9, these will still
      be created with autoactivation enabled. Is this a case we want to
      consider? If yes, we could suggest running `pve8to updatelvm` (only)
      post-upgrade on all nodes, but users may forget this...
    
    - `updatelvm` will disable autoactivation on all guest volumes,
      regardless of the guest owner. In other words, it will disable
      autoactivation on LVs owned by a different node. Is this a problem?
      My tests suggests it's unproblematic, but may be worth a second
      look. We can change `updatelvm` to only update LVs owned by the
      local node, but then might miss LVs that are migrated between
      `updatelvm` runs on different nodes.
    
    new in v3

 PVE/CLI/pve8to9.pm | 152 ++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 151 insertions(+), 1 deletion(-)

diff --git a/PVE/CLI/pve8to9.pm b/PVE/CLI/pve8to9.pm
index fbb96491..972c91ea 100644
--- a/PVE/CLI/pve8to9.pm
+++ b/PVE/CLI/pve8to9.pm
@@ -22,7 +22,7 @@ use PVE::NodeConfig;
 use PVE::RPCEnvironment;
 use PVE::Storage;
 use PVE::Storage::Plugin;
-use PVE::Tools qw(run_command split_list file_get_contents);
+use PVE::Tools qw(run_command split_list file_get_contents trim);
 use PVE::QemuConfig;
 use PVE::QemuServer;
 use PVE::VZDump::Common;
@@ -1372,6 +1372,95 @@ sub check_dkms_modules {
     }
 }
 
+my $query_lvm_lv_autoactivation = sub {
+    my ($vg_name) = @_;
+
+    my $cmd = [
+       '/sbin/lvs',
+       '--separator', ':',
+       '--noheadings',
+       '--unbuffered',
+       '--options', "lv_name,autoactivation",
+       $vg_name,
+    ];
+
+    my $result;
+    eval {
+       run_command($cmd, outfunc => sub {
+           my $line = shift;
+           $line = trim($line);
+
+           my ($name, $autoactivation_flag) = split(':', $line);
+           return if !$name;
+
+           $result->{$name} = $autoactivation_flag eq 'enabled';
+       });
+    };
+    die "could not list LVM logical volumes: $@\n" if $@;
+    return $result;
+};
+
+my $foreach_lvm_vg_with_autoactivated_guest_volumes = sub {
+    my ($with_lock, $code) = @_;
+
+    my $cfg = PVE::Storage::config();
+    my $storage_info = PVE::Storage::storage_info($cfg);
+
+    for my $storeid (sort keys %$storage_info) {
+       my $scfg = PVE::Storage::storage_config($cfg, $storeid);
+       my $vgname = $scfg->{vgname};
+       my $type = $scfg->{type};
+       next if $type ne 'lvm' && $type ne 'lvmthin';
+
+       my $info = $storage_info->{$storeid};
+       if (!$info->{enabled} || !$info->{active}) {
+           log_skip("storage '$storeid' ($type) is disabled or inactive");
+           next;
+       }
+
+       my $find_autoactivated_lvs = sub {
+           my $lvs_autoactivation = $query_lvm_lv_autoactivation->($vgname);
+           my $vollist = PVE::Storage::volume_list($cfg, $storeid);
+
+           my $autoactivated_guest_lvs = [];
+           for my $volinfo (@$vollist) {
+               my $volname = 
(PVE::Storage::parse_volume_id($volinfo->{volid}))[1];
+               push @$autoactivated_guest_lvs, $volname if 
$lvs_autoactivation->{$volname};
+           }
+
+           $code->($storeid, $vgname, $autoactivated_guest_lvs);
+       };
+
+       if ($with_lock) {
+           my $plugin = PVE::Storage::Plugin->lookup($scfg->{type});
+           $plugin->cluster_lock_storage($storeid, $scfg->{shared}, undef,
+               $find_autoactivated_lvs);
+       } else {
+           $find_autoactivated_lvs->();
+       }
+    };
+};
+
+sub check_lvm_autoactivation {
+    log_info("Check for LVM autoactivation settings on 'lvm' and 'lvmthin' 
storages...");
+
+    my $needs_fix = 0;
+    $foreach_lvm_vg_with_autoactivated_guest_volumes->(0, sub {
+       my ($storeid, $vgname, $autoactivated_lvs) = @_;
+
+       if (scalar(@$autoactivated_lvs) > 0) {
+           log_warn("storage '$storeid' has guest volumes with autoactivation 
enabled");
+           $needs_fix = 1;
+       } else {
+           log_pass("all guest volumes on storage '$storeid' have 
autoactivation disabled");
+       }
+    });
+    log_warn("please run 'pve8to9 updatelvm' to disable autoactivation on LVM 
guest volumes")
+       if $needs_fix;
+
+    return undef;
+}
+
 sub check_misc {
     print_header("MISCELLANEOUS CHECKS");
     my $ssh_config = eval { PVE::Tools::file_get_contents('/root/.ssh/config') 
};
@@ -1474,6 +1563,7 @@ sub check_misc {
     check_nvidia_vgpu_service();
     check_bootloader();
     check_dkms_modules();
+    check_lvm_autoactivation();
 }
 
 my sub colored_if {
@@ -1538,8 +1628,68 @@ __PACKAGE__->register_method ({
        return undef;
     }});
 
+__PACKAGE__->register_method ({
+    name => 'updatelvm',
+    path => 'updatelvm',
+    method => 'POST',
+    description => 'disable autoactivation for all LVM guest volumes',
+    parameters => {
+       additionalProperties => 0,
+    },
+    returns => { type => 'null' },
+    code => sub {
+       my ($param) = @_;
+
+       my $did_work = 0;
+       eval {
+           $foreach_lvm_vg_with_autoactivated_guest_volumes->(1, sub {
+               my ($storeid, $vgname, $autoactivated_lvs) = @_;
+
+               if (scalar(@$autoactivated_lvs) == 0) {
+                   log_pass("all guest volumes on storage '$storeid' have 
autoactivation disabled");
+                   return;
+               }
+
+               log_info("disabling autoactivation on storage '$storeid'...");
+               die "unexpected empty VG name (storage '$storeid')\n" if 
!$vgname;
+
+               for my $lvname (@$autoactivated_lvs) {
+                   log_info("disabling autoactivation for $vgname/$lvname"
+                       ." on storage '$storeid'...");
+                   my $cmd = [
+                       '/sbin/lvchange',
+                       '--setautoactivation', 'n',
+                       "$vgname/$lvname",
+                   ];
+
+                   eval { run_command($cmd); };
+                   my $err = $@;
+                   die "could not disable autoactivation on $vgname/$lvname: 
$err\n" if $err;
+
+                   $did_work = 1;
+               }
+           });
+       };
+       my $err = $@;
+       if ($err) {
+           log_fail("could not disable autoactivation on enabled and active 
LVM storages");
+           die $err;
+       }
+
+       if($did_work) {
+           log_pass("successfully disabled autoactivation on guest volumes on 
all"
+               ." enabled and active LVM storages");
+       } else {
+           log_pass("all guest volumes on enabled and active LVM storages"
+               ." have autoactivation disabled");
+       };
+
+       return undef;
+    }});
+
 our $cmddef = {
     checklist => [ __PACKAGE__, 'checklist', []],
+    updatelvm => [ __PACKAGE__, 'updatelvm', []],
 };
 
 1;
-- 
2.39.5



_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel

Reply via email to