mirror of
https://github.com/vincentmli/bpfire.git
synced 2026-04-17 06:23:00 +02:00
Please see the header of the script for more details. Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
170 lines
4.6 KiB
Bash
170 lines
4.6 KiB
Bash
#!/bin/bash
|
|
###############################################################################
|
|
# #
|
|
# IPFire.org - A linux based firewall #
|
|
# Copyright (C) 2022 IPFire Team <info@ipfire.org> #
|
|
# #
|
|
# This program is free software: you can redistribute it and/or modify #
|
|
# it under the terms of the GNU General Public License as published by #
|
|
# the Free Software Foundation, either version 3 of the License, or #
|
|
# (at your option) any later version. #
|
|
# #
|
|
# This program is distributed in the hope that it will be useful, #
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
|
# GNU General Public License for more details. #
|
|
# #
|
|
# You should have received a copy of the GNU General Public License #
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
|
|
# #
|
|
###############################################################################
|
|
#
|
|
# This script is supposed to repair any broken RAID installations
|
|
# where the system has been booted from only one of the RAID devices
|
|
# without the software RAID being activated first.
|
|
#
|
|
# This script does as follows:
|
|
#
|
|
# * It tries to find an inactive RAID called "ipfire:0"
|
|
# * It will then destroy any devices that are still part of this RAID.
|
|
# This is required because if the RAID is being assembled correctly,
|
|
# data from the disk that has NOT been mounted will be replicated
|
|
# back to the device that has been changed. That causes that any
|
|
# data that has been written to the mounted disk will be lost.
|
|
# To avoid this, we will partially destroy the RAID.
|
|
# * We will then erase any partition tables and destroy any filesystems
|
|
# on the devices so that they do not get accidentially mounted again.
|
|
# * The system will then need to be rebooted where the RAID will be
|
|
# mounted again in a degraded state which might take some extra
|
|
# time at boot (the system stands still for about a minute).
|
|
# * After the system has been booted up correctly, we will re-add
|
|
# the devices back to the RAID which will resync and the system
|
|
# will be back to its intended configuration.
|
|
|
|
find_inactive_raid() {
|
|
local status
|
|
local device
|
|
local arg
|
|
local args
|
|
|
|
while read -r status device args; do
|
|
if [ "${status}" = "INACTIVE-ARRAY" ]; then
|
|
for arg in ${args}; do
|
|
case "${arg}" in
|
|
name=ipfire:0)
|
|
echo "${device}"
|
|
return 0
|
|
;;
|
|
esac
|
|
done
|
|
fi
|
|
done <<< "$(mdadm --detail --scan)"
|
|
|
|
return 1
|
|
}
|
|
|
|
find_root() {
|
|
local device
|
|
local mp
|
|
local fs
|
|
local args
|
|
|
|
while read -r device mp fs args; do
|
|
if [ "${mp}" = "/" ]; then
|
|
echo "${device:0:-1}"
|
|
return 0
|
|
fi
|
|
done < /proc/mounts
|
|
|
|
return 1
|
|
}
|
|
|
|
find_raid_devices() {
|
|
local raid="${1}"
|
|
|
|
local IFS=,
|
|
|
|
local device
|
|
for device in $(mdadm -v --detail --scan "${raid}" | awk -F= '/^[ ]+devices/ { print $2 }'); do
|
|
echo "${device}"
|
|
done
|
|
|
|
return 0
|
|
}
|
|
|
|
destroy_everything() {
|
|
local device="${1}"
|
|
local part
|
|
|
|
# Destroy the RAID superblock
|
|
mdadm --zero-superblock "${device}"
|
|
|
|
# Wipe the partition table
|
|
wipefs -a "${device}"
|
|
|
|
# Wipe any partition signatures
|
|
for part in ${device}*; do
|
|
wipefs -a "${part}"
|
|
done
|
|
}
|
|
|
|
raid_rebuild() {
|
|
local devices=( "$@" )
|
|
|
|
cat > /etc/rc.d/rcsysinit.d/S99fix-raid <<EOF
|
|
#!/bin/bash
|
|
|
|
case "\${1}" in
|
|
start)
|
|
if [ -e "/dev/md/ipfire:0" ]; then
|
|
for device in ${devices[@]}; do
|
|
mdadm --add "/dev/md/ipfire:0" "\${device}"
|
|
done
|
|
|
|
# Delete this script
|
|
rm "\${0}"
|
|
fi
|
|
;;
|
|
esac
|
|
EOF
|
|
|
|
chmod a+x /etc/rc.d/rcsysinit.d/S99fix-raid
|
|
}
|
|
|
|
main() {
|
|
local raid="$(find_inactive_raid)"
|
|
|
|
# Nothing to do if no RAID device found
|
|
if [ -z "${raid}" ]; then
|
|
return 0
|
|
fi
|
|
|
|
echo "Fixing RAID ${raid}..."
|
|
|
|
local root="$(find_root)"
|
|
|
|
# Finding any devices in this RAID
|
|
local devices=(
|
|
$(find_raid_devices "${raid}")
|
|
)
|
|
|
|
# Stop the RAID
|
|
mdadm --stop "${raid}" &>/dev/null
|
|
|
|
# Destroy any useful data on all remaining RAID devices
|
|
local device
|
|
for device in ${devices[@]}; do
|
|
# Skip root
|
|
[ "${device}" = "${root}" ] && continue
|
|
|
|
destroy_everything "${device}"
|
|
done &>/dev/null
|
|
|
|
# Re-add devices to the RAID
|
|
raid_rebuild "${device}"
|
|
|
|
return 0
|
|
}
|
|
|
|
main "$@" || return $?
|