From 5f97b21824f6d96232fbfb06a1795877c5fba662 Mon Sep 17 00:00:00 2001 From: Florent CARLI Date: Tue, 1 Aug 2023 09:16:14 +0200 Subject: [PATCH] softraid: make lvm2 activate the degraded raid in initramfs Patch for a known limitation of lvm2: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1018730 in prevision of debian 12. Signed-off-by: Florent CARLI --- playbooks/cluster_setup_keys.yaml | 1 - playbooks/cluster_setup_prerequisdebian.yaml | 1 + roles/debian/tasks/main.yml | 9 +- src/debian/69-lvm.rules | 94 ++++++++++++++++++++ 4 files changed, 103 insertions(+), 2 deletions(-) create mode 100644 src/debian/69-lvm.rules diff --git a/playbooks/cluster_setup_keys.yaml b/playbooks/cluster_setup_keys.yaml index 08c6478fa..e5fdff56e 100644 --- a/playbooks/cluster_setup_keys.yaml +++ b/playbooks/cluster_setup_keys.yaml @@ -1,7 +1,6 @@ - name: Configure ssh keys between hosts hosts: cluster_machines become: true - gather_facts: yes tasks: - name: generate SSH key user: diff --git a/playbooks/cluster_setup_prerequisdebian.yaml b/playbooks/cluster_setup_prerequisdebian.yaml index 798d5837a..372783141 100644 --- a/playbooks/cluster_setup_prerequisdebian.yaml +++ b/playbooks/cluster_setup_prerequisdebian.yaml @@ -1,4 +1,5 @@ - name: Prerequis machine debian + gather_facts: True hosts: - cluster_machines - standalone_machine diff --git a/roles/debian/tasks/main.yml b/roles/debian/tasks/main.yml index 578fc7542..1c7ffc7e4 100644 --- a/roles/debian/tasks/main.yml +++ b/roles/debian/tasks/main.yml @@ -515,7 +515,14 @@ dest: /etc/initramfs-tools/scripts/init-premount/lvm_snapshot_rebooter mode: '0755' register: lvm_snapshot_rebooter +- name: "add udev rules for lvm2 limitation" + ansible.builtin.copy: + src: ../src/debian/69-lvm.rules + dest: /etc/udev/rules.d/69-lvm.rules + mode: '0644' + when: ansible_distribution == 'Debian' and ansible_distribution_version | int >= 12 + register: udevlvm - name: "rebuild initramfs if necessary" command: cmd: /usr/sbin/update-initramfs -u - when: lvm_snapshot_rebooter.changed + when: udevlvm.changed or lvm_snapshot_rebooter.changed diff --git a/src/debian/69-lvm.rules b/src/debian/69-lvm.rules new file mode 100644 index 000000000..6544dccf9 --- /dev/null +++ b/src/debian/69-lvm.rules @@ -0,0 +1,94 @@ +# Copyright (C) 2012,2021 Red Hat, Inc. All rights reserved. +# +# This file is part of LVM. +# +# This rule requires blkid to be called on block devices before so only devices +# used as LVM PVs are processed (ID_FS_TYPE="LVM2_member"). + +SUBSYSTEM!="block", GOTO="lvm_end" + + +ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}=="1", GOTO="lvm_end" + +# Only process devices already marked as a PV - this requires blkid to be called before. +ENV{ID_FS_TYPE}!="LVM2_member", GOTO="lvm_end" +ENV{DM_MULTIPATH_DEVICE_PATH}=="1", GOTO="lvm_end" +ACTION=="remove", GOTO="lvm_end" + +# Create /dev/disk/by-id/lvm-pv-uuid- symlink for each PV +ENV{ID_FS_UUID_ENC}=="?*", SYMLINK+="disk/by-id/lvm-pv-uuid-$env{ID_FS_UUID_ENC}" + +# If the PV is a special device listed below, scan only if the device is +# properly activated. These devices are not usable after an ADD event, +# but they require an extra setup and they are ready after a CHANGE event. +# Also support coldplugging with ADD event but only if the device is already +# properly activated. +# This logic should be eventually moved to rules where those particular +# devices are processed primarily (MD and loop). + +# DM device: +KERNEL!="dm-[0-9]*", GOTO="next" +ENV{DM_UDEV_PRIMARY_SOURCE_FLAG}=="1", ENV{DM_ACTIVATION}=="1", GOTO="lvm_scan" +GOTO="lvm_end" + +# MD device: +LABEL="next" +KERNEL!="md[0-9]*", GOTO="next" +IMPORT{db}="LVM_MD_PV_ACTIVATED" +ACTION=="add", ENV{LVM_MD_PV_ACTIVATED}=="1", GOTO="lvm_scan" +ACTION=="change", ENV{LVM_MD_PV_ACTIVATED}!="1", TEST=="md/array_state", ENV{LVM_MD_PV_ACTIVATED}="1", GOTO="lvm_scan" +ACTION=="add", KERNEL=="md[0-9]*p[0-9]*", GOTO="lvm_scan" +ENV{LVM_MD_PV_ACTIVATED}!="1", ENV{SYSTEMD_READY}="0" +GOTO="lvm_end" + +# Loop device: +LABEL="next" +KERNEL!="loop[0-9]*", GOTO="next" +ACTION=="add", ENV{LVM_LOOP_PV_ACTIVATED}=="1", GOTO="lvm_scan" +ACTION=="change", ENV{LVM_LOOP_PV_ACTIVATED}!="1", TEST=="loop/backing_file", ENV{LVM_LOOP_PV_ACTIVATED}="1", GOTO="lvm_scan" +ENV{LVM_LOOP_PV_ACTIVATED}!="1", ENV{SYSTEMD_READY}="0" +GOTO="lvm_end" + +LABEL="next" +ACTION!="add", GOTO="lvm_end" + +LABEL="lvm_scan" + +ENV{SYSTEMD_READY}="1" + +# pvscan will check if this device completes a VG, +# i.e. all PVs in the VG are now present with the +# arrival of this PV. If so, it prints to stdout: +# LVM_VG_NAME_COMPLETE='foo' +# +# When the VG is complete it can be activated, so +# vgchange -aay is run. It is run via +# systemd since it can take longer to run than +# udev wants to block when processing rules. +# (if there are hundreds of LVs to activate, +# the vgchange can take many seconds.) +# +# pvscan only reads the single device specified, +# and uses temp files under /run/lvm to check if +# other PVs in the VG are present. +# +# If event_activation=0 in lvm.conf, this pvscan +# (using checkcomplete) will do nothing, so that +# no event-based autoactivation will be happen. +# +# TODO: adjust the output of vgchange -aay so that +# it's better suited to appearing in the journal. + +IMPORT{program}="/sbin/lvm pvscan --cache --listvg --checkcomplete --vgonline --autoactivation event --udevoutput --journal=output $env{DEVNAME}" +TEST!="/run/systemd/system", GOTO="lvm_direct_vgchange" + +ENV{LVM_VG_NAME_COMPLETE}=="?*", RUN+="/usr/bin/systemd-run --no-block --property DefaultDependencies=no --unit lvm-activate-$env{LVM_VG_NAME_COMPLETE} /sbin/lvm vgchange -aay --autoactivation event $env{LVM_VG_NAME_COMPLETE}" +GOTO="lvm_end" + +LABEL="lvm_direct_vgchange" +ENV{LVM_VG_NAME_COMPLETE}=="?*", RUN+="/sbin/lvm vgchange -aay --autoactivation event $env{LVM_VG_NAME_COMPLETE}" +TEST!="/run/initramfs", GOTO="lvm_end" +ENV{LVM_VG_NAME_INCOMPLETE}=="?*", RUN+="/sbin/lvm vgchange --sysinit -aay --activation degraded $env{LVM_VG_NAME_INCOMPLETE}" +GOTO="lvm_end" + +LABEL="lvm_end"