From: "Max R. Carrara" <m.carrara@proxmox.com>
To: pve-devel@lists.proxmox.com
Subject: [pve-devel] [PATCH pve-manager master v2 2/2] fix #6652: d/postinst: enable autoactivation for Ceph OSD LVs
Date: Wed, 13 Aug 2025 15:40:26 +0200 [thread overview]
Message-ID: <20250813134028.292213-3-m.carrara@proxmox.com> (raw)
In-Reply-To: <20250813134028.292213-1-m.carrara@proxmox.com>
Introduce a new helper script named pve-osd-lvm-enable-autoactivation,
which silently enables autoactivation for certain logical volumes
used by Ceph OSDs. The helper script is called in debian/postinst when
upgrading from a version >= '9.0~~' and < '9.0.6'. This means that
only OSD LVs that were created on PVE 9 up until version 9.0.6 of
pve-manager are touched. This is done to limit the amount of
installations on which the script is executed.
Additionally, each LV used by an OSD must belong to either an OSD WAL
or OSD DB. Ensure this by checking whether the LV's name and its VG's
name match the format we use in our API on creation [0][1].
For VGs, the name must begin with "ceph-" and be followed by a
UUID4. For example, "ceph-31a0a43c-990a-40dc-9027-6412b0f6673c" is a
matching VG name.
For LVs, the name must begin with either "osd-db-" or "osd-wal-" and
be followed by a UUID4. For example,
"osd-db-2947e348-fe1b-4c38-b9d0-d24f3b8de70f" and
"osd-wal-20db00cf-b3c2-491a-bf17-4fd7c29aba6a" are matching LV names.
To prevent users from getting worried (or the like) by spurious or
unwarranted errors / warnings that might occur, the script itself does
not produce any output. The STDERR of all commands the script calls is
only dumped if the invoked command itself fails. If a call to
`ceph-volume`, `lvs` or `lvchange` fails, something is definitely
wrong with the user's cluster anyway.
[0]: https://git.proxmox.com/?p=pve-manager.git;a=blob;f=PVE/API2/Ceph/OSD.pm;h=23e187ce1884cef705daa3bda7e3800b05518f3d;hb=refs/heads/master#l442
[1]: https://git.proxmox.com/?p=pve-manager.git;a=blob;f=PVE/API2/Ceph/OSD.pm;h=23e187ce1884cef705daa3bda7e3800b05518f3d;hb=refs/heads/master#l476
Fixes: #6652
Signed-off-by: Max R. Carrara <m.carrara@proxmox.com>
---
bin/Makefile | 3 +-
bin/pve-osd-lvm-enable-autoactivation | 176 ++++++++++++++++++++++++++
debian/postinst | 16 +++
3 files changed, 194 insertions(+), 1 deletion(-)
create mode 100644 bin/pve-osd-lvm-enable-autoactivation
diff --git a/bin/Makefile b/bin/Makefile
index 777e6759..0a0df34d 100644
--- a/bin/Makefile
+++ b/bin/Makefile
@@ -32,7 +32,8 @@ HELPERS = \
pve-startall-delay \
pve-init-ceph-crash \
pve-firewall-commit \
- pve-sdn-commit
+ pve-sdn-commit \
+ pve-osd-lvm-enable-autoactivation
MIGRATIONS = \
pve-lvm-disable-autoactivation \
diff --git a/bin/pve-osd-lvm-enable-autoactivation b/bin/pve-osd-lvm-enable-autoactivation
new file mode 100644
index 00000000..e2e222bd
--- /dev/null
+++ b/bin/pve-osd-lvm-enable-autoactivation
@@ -0,0 +1,176 @@
+#!/usr/bin/perl
+
+use v5.36;
+
+use JSON qw(decode_json);
+
+use PVE::Tools;
+
+my sub ceph_volume_lvm_osd_info : prototype() () {
+ my $cmd = [
+ "/usr/sbin/ceph-volume", "lvm", "list", "--format", "json",
+ ];
+
+ my $stdout = '';
+ my $outfunc = sub($line) {
+ $stdout .= "$line\n";
+ };
+
+ my $stderr = '';
+ my $errfunc = sub($line) {
+ $stderr .= "$line\n";
+ };
+
+ eval {
+ PVE::Tools::run_command(
+ $cmd,
+ timeout => 10,
+ outfunc => $outfunc,
+ errfunc => $errfunc,
+ );
+ };
+ if (my $err = $@) {
+ $err = "$err\n" if $err !~ m/\n$/;
+
+ print STDERR $stderr;
+ *STDERR->flush();
+
+ die $err;
+ }
+
+ my $osd_info = decode_json($stdout);
+
+ return $osd_info;
+}
+
+my sub lvs : prototype() () {
+ my $cmd = [
+ "/usr/sbin/lvs",
+ "--noheadings",
+ "--separator",
+ ":",
+ "--options",
+ "lv_name,vg_name,autoactivation",
+ ];
+
+ my $all_lvs = {};
+
+ my $outfunc = sub($line) {
+ $line = PVE::Tools::trim($line);
+
+ my ($lv_name, $vg_name, $autoactivation) = split(':', $line, -1);
+
+ return undef if ($lv_name eq '' || $vg_name eq '');
+
+ $all_lvs->{"$vg_name/$lv_name"} = {
+ autoactivation => $autoactivation,
+ };
+ };
+
+ my $stderr = '';
+ my $errfunc = sub($line) {
+ $stderr .= "$line\n";
+ };
+
+ eval {
+ PVE::Tools::run_command(
+ $cmd,
+ timeout => 10,
+ outfunc => $outfunc,
+ errfunc => $errfunc,
+ );
+ };
+ if (my $err = $@) {
+ $err = "$err\n" if $err !~ m/\n$/;
+
+ print STDERR $stderr;
+ *STDERR->flush();
+
+ die $err;
+ }
+
+ return $all_lvs;
+}
+
+my sub main : prototype() () {
+ my $osd_info = ceph_volume_lvm_osd_info();
+ my $all_lvs = lvs();
+
+ my $re_uuid4 = qr/
+ \b
+ [0-9a-fA-F]{8}
+ - [0-9a-fA-F]{4}
+ - [0-9a-fA-F]{4}
+ - [0-9a-fA-F]{4}
+ - [0-9a-fA-F]{12}
+ \b
+ /x;
+
+ # $re_lv_name and $re_vg_name specifically match the LV and VG names we
+ # assign in OSD.pm in order to avoid modifying LVs created through means
+ # other than our API
+ my $re_lv_name = qr/^ (osd-db|osd-wal) - $re_uuid4 $/nx;
+ my $re_vg_name = qr/^ (ceph) - $re_uuid4 $/nx;
+
+ my @osd_lvs_no_autoactivation = ();
+
+ for my $osd (keys $osd_info->%*) {
+ for my $osd_lv ($osd_info->{$osd}->@*) {
+ my ($lv_name, $vg_name) = $osd_lv->@{qw(lv_name vg_name)};
+
+ next if $all_lvs->{$osd_lv}->{autoactivation};
+
+ next if $lv_name !~ $re_lv_name;
+ next if $vg_name !~ $re_vg_name;
+
+ my $osd_lv = "$vg_name/$lv_name";
+
+ push(@osd_lvs_no_autoactivation, $osd_lv) if !$all_lvs->{$osd_lv}->{autoactivation};
+ }
+ }
+
+ my $has_err = 0;
+
+ # Logical volumes are formatted as "vg_name/lv_name", which is necessary for lvchange
+ for my $lv (@osd_lvs_no_autoactivation) {
+ my $log = '';
+ my $logfunc = sub($line) {
+ $log .= "$line\n";
+ };
+
+ eval {
+ my $cmd = [
+ '/usr/sbin/lvchange', '--setautoactivation', 'y', $lv,
+ ];
+
+ PVE::Tools::run_command(
+ $cmd,
+ logfunc => $logfunc,
+ timeout => 10,
+ );
+ };
+ if (my $err = $@) {
+ $has_err = 1;
+
+ $err = "$err\n" if $err !~ m/\n$/;
+
+ print STDERR $log;
+ *STDERR->flush();
+
+ warn("Error: Failed to enable autoactivation for Ceph OSD logical volume '$lv'\n");
+ warn("$err");
+
+ next;
+ }
+
+ }
+
+ if ($has_err) {
+ warn("Couldn't enable autoactivation for all Ceph OSD DB/WAL logical volumes.\n");
+ exit 1;
+ }
+
+ return undef;
+}
+
+main();
diff --git a/debian/postinst b/debian/postinst
index b6e07fd9..8e8f1a07 100755
--- a/debian/postinst
+++ b/debian/postinst
@@ -133,6 +133,18 @@ migrate_apt_auth_conf() {
fi
}
+ceph_osd_lvm_enable_autoactivation() {
+ if ! test -e /usr/sbin/ceph-volume; then
+ return
+ fi
+
+ if ! /usr/share/pve-manager/helpers/pve-osd-lvm-enable-autoactivation; then
+ printf "\nEnabling autoactivation for logical volumes used by Ceph OSDs failed.";
+ printf " Check the output above for errors and try to enable autoactivation for OSD LVs";
+ printf " manually by running '/usr/share/pve-manager/helpers/pve-osd-lvm-enable-autoactivation'";
+ fi
+}
+
# Copied from dh_installtmpfiles/13.24.2
if [ "$1" = "configure" ] || [ "$1" = "abort-upgrade" ] || [ "$1" = "abort-deconfigure" ] || [ "$1" = "abort-remove" ] ; then
if [ -x "$(command -v systemd-tmpfiles)" ]; then
@@ -246,6 +258,10 @@ case "$1" in
fi
fi
+ if test -n "$2" && dpkg --compare-versions "$2" 'ge' '9.0~~' && dpkg --compare-versions "$2" 'lt' '9.0.6'; then
+ ceph_osd_lvm_enable_autoactivation
+ fi
+
;;
abort-upgrade|abort-remove|abort-deconfigure)
--
2.47.2
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
next prev parent reply other threads:[~2025-08-13 13:38 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-08-13 13:40 [pve-devel] [PATCH pve-manager master v2 0/2] Fix #6652: LVM Autoactivation Missing " Max R. Carrara
2025-08-13 13:40 ` [pve-devel] [PATCH pve-manager master v2 1/2] fix #6652: ceph: osd: enable autoactivation for OSD LVs on creation Max R. Carrara
2025-08-13 13:40 ` Max R. Carrara [this message]
2025-08-13 14:14 ` [pve-devel] applied: (subset) [PATCH pve-manager master v2 0/2] Fix #6652: LVM Autoactivation Missing for Ceph OSD LVs Fabian Grünbichler
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250813134028.292213-3-m.carrara@proxmox.com \
--to=m.carrara@proxmox.com \
--cc=pve-devel@lists.proxmox.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.