# -*- mode: sh; sh-basic-offset: 3; indent-tabs-mode: nil; -*-
#
# this handler will save various reports of vital system information.
-# by default, all the reports are enabled and are saved in /var/backups.
+# by default, all the reports are saved in /var/backups.
#
# (1) a capture of the debconf package selection states. This file
# can be used to restore the answers to debconf questions for
# (4) hardware information.
# write to a text file the important things which hwinfo can gleen.
#
+# (5) the Luks header of every Luks block device, if option luksheaders
+# is enabled.
+# in case you (have to) scramble such a Luks header (for some time),
+# and restore it later by running "dd if=luksheader.sda2.bin of=/dev/sda2"
+# (MAKE SURE YOU PASS THE CORRECT DEVICE AS of= !!!)
+#
+# (6) LVM metadata for every detected volume group, if "lvm = yes"
+#
if [ -f /etc/debian_version ]
then
getconf sfdisk_options ""
getconf hwinfo_options ""
+getconf CRYPTSETUP `which cryptsetup`
+getconf DD `which dd`
+getconf luksheaders no
+getconf luksheadersfile $parentdir/luksheader.__star__.bin
+
+getconf VGS `which vgs`
+getconf VGCFGBACKUP `which vgcfgbackup`
+getconf lvm no
+
getconf vsnames all
# If vservers are configured, check that the ones listed in $vsnames are running.
usevserver=yes
fi
+## SANITY CHECKS #########################
+
+if [ "$luksheaders" == "yes" ]; then
+ if [ ! -x "$DD" ]; then
+ warning "can't find dd, skipping backup of Luks headers."
+ luksheaders="no"
+ fi
+ if [ ! -x "$CRYPTSETUP" ]; then
+ warning "can't find cryptsetup, skipping backup of Luks headers."
+ luksheaders="no"
+ fi
+fi
+
+if [ "$lvm" == "yes" ]; then
+ if [ ! -x "$VGS" ]; then
+ warning "can't find vgs, skipping backup of LVM metadata"
+ lvm="no"
+ fi
+ if [ ! -x "$VGCFGBACKUP" ]; then
+ warning "can't find vgcfgbackup, skipping backup of LVM metadata"
+ lvm="no"
+ fi
+fi
+
## PACKAGES ##############################
#
continue
fi
# is $packagemgr available inside $vserver ?
- if [ ! -x "$VROOTDIR/$vserver`$VSERVER $vserver exec which $packagemgr`" ]; then
+ if [ ! -x "${VROOTDIR}/${vserver}${packagemgr}" ]; then
warning "can't find $packagemgr in vserver $vserver, skipping installed packages report."
else
# don't expand * since it can be used in $packagemgroptions
set +o noglob
fi
# is $debconfgetselections available inside $vserver ?
- if [ -z "`$VSERVER $vserver exec which debconf-get-selections`" ]; then
- warning "can't find debconf-get-selections in vserver $vserver, skipping package selection states."
+ found=no
+ # case #1: it is available on the host, is it available inside $vserver ?
+ if [ -n "$debconfgetselections" ]; then
+ [ -x "${VROOTDIR}/${vserver}${debconfgetselections}" ] && found=yes
+ # case #2: it is not available on the host, is it available inside $vserver ?
+ else
+ [ -n "`$VSERVER $vserver exec which debconf-get-selections`" ] && found=yes
+ fi
+ if [ "$found" != yes ]; then
+ warning "can't find debconf-get-selections in vserver $vserver, skipping package selection states. You may want to install the debconf-utils package."
else
debug "$VSERVER $vserver exec $debconfgetselections > $VROOTDIR/$vserver$selectionsfile"
$VSERVER $vserver exec $debconfgetselections > $VROOTDIR/$vserver$selectionsfile || fatal "can not save debconf-get-selections info to $selectionsfile"
fi
+ unset found
done
fi
set +o noglob
fi
if [ -z "$debconfgetselections" ]; then
- warning "can't find debconf-get-selections, skipping package selection states."
+ warning "can't find debconf-get-selections, skipping package selection states. You might want to install the debconf-utils package."
else
debug "$debconfgetselections > $selectionsfile"
$debconfgetselections > $selectionsfile || fatal "can not save $debconfgetselections info to $selectionsfile"
STATUS="Collecting what services run at what run level:"
if [ $os = "redhat" ]; then
- catifexec "/sbin/chkconfig --list"
+ catifexec "/sbin/chkconfig" "--list"
STATUS="Collecting information about /etc/rc.d:"
catiffile "/bin/ls /etc/rc.d/rc*.d/"
fi
STATUS="Getting bootloader information:"
-catifexec "/bin/ls -alR /boot"
+catifexec "/bin/ls" "-alR /boot"
# This covers sparc, alpha, and intel (respectively)
# updated for grub -mpg
if [ -f /etc/lilo.conf ]; then
STATUS="Collecting information about the boot process (lilo):"
catiffile "/etc/lilo.conf"
- catifexec "/sbin/lilo -q"
+ catifexec "/sbin/lilo" "-q"
fi
if [ -d /boot/grub -a -f /boot/grub/grub.conf -a -f /boot/grub/device.map ]; then
STATUS="Collecting information about the boot process (grub.conf):"
catiffile "/etc/sysctl.conf"
STATUS="Gathering IP information (/sbin/ifconfig):"
-catifexec "/sbin/ifconfig -a"
+catifexec "/sbin/ifconfig" "-a"
STATUS="Gathering additional IP information (/bin/ip addr list):"
-catifexec "/bin/ip addr list"
+catifexec "/bin/ip" "addr list"
STATUS="Checking network routes:"
-catifexec "/sbin/route -n"
+catifexec "/sbin/route" "-n"
STATUS="Collecting Name Service Switch config information:"
catiffile "/etc/nsswitch.conf"
for x in $(/sbin/lsmod | /bin/cut -f1 -d" " 2>/dev/null | /bin/grep -v Module 2>/dev/null
) ; do
STATUS="Checking module information $x:"
- catifexec "/sbin/modinfo $x"
+ catifexec "/sbin/modinfo" "$x"
done
STATUS="Gathering information about your filesystems:"
catiffile "/etc/fstab"
STATUS="Collecting disk partition information:"
-catifexec "/sbin/fdisk -l"
+catifexec "/sbin/fdisk" "-l"
STATUS="Checking mounted file systems (mount) "
catifexec "/bin/mount"
elif [ $os = "debian" ]; then
catifexec "/sbin/vgdisplay" "-vv"
fi
+
+STATUS="Collecting device-mapper (dm) information:"
+catifexec '/sbin/dmsetup' 'info'
STATUS="Collecting SCSI Tape information (/etc/stinit.def)"
catiffile "/etc/stinit.def"
fi
fi
-
## PARTITIONS #############################
# here we use sfdisk to dump a listing of all the partitions.
$HWINFO --disk >> $hardwarefile
fi
fi
+
+if [ "$luksheaders" == "yes" ]; then
+ devices=`LC_ALL=C $SFDISK -l 2>/dev/null | grep "^Disk /dev" | @AWK@ '{print $2}' | cut -d: -f1`
+ [ -n "$devices" ] || warning "No block device found"
+ targetdevices=""
+ for dev in $devices; do
+ [ -b $dev ] || continue
+ debug "$CRYPTSETUP isLuks $dev"
+ $CRYPTSETUP isLuks $dev
+ [ $? -eq 0 ] && targetdevices="$targetdevices $dev"
+ done
+ for dev in $targetdevices; do
+ label=${dev#/dev/}
+ label=${label//\//-}
+ outputfile=${luksheadersfile//__star__/$label}
+ # the following sizes are expressed in terms of 512-byte sectors
+ debug "Let us find out the Luks header size for $dev"
+ debug "$CRYPTSETUP luksDump \"$dev\" | grep '^Payload offset:' | @AWK@ '{print $3}'"
+ headersize=`$CRYPTSETUP luksDump "$dev" | grep '^Payload offset:' | @AWK@ '{print $3}'`
+ if [ $? -ne 0 ]; then
+ warning "Could not compute the size of Luks header, skipping device $dev"
+ continue
+ elif [ -z "$headersize" -o -n "`echo \"$headersize\" | sed 's/[0-9]*//g'`" ]; then
+ warning "The computed size of Luks header is not an integer, skipping device $dev"
+ continue
+ fi
+ debug "Let us backup the Luks header of device $dev"
+ debug "$DD if=\"${dev}\" of=\"${outputfile}\" bs=512 count=\"${headersize}\""
+ output=`$DD if="${dev}" of="${outputfile}" bs=512 count="${headersize}" 2>&1`
+ exit_code=$?
+ if [ $exit_code -eq 0 ]; then
+ debug $output
+ info "The Luks header of $dev was saved to $outputfile."
+ else
+ debug $output
+ fatal "The Luks header of $dev could not be saved."
+ fi
+ done
+fi
+
+## LVM ####################################
+
+# returns 0 on success, 1 on error, 2 if not tried
+# outputs error message if error, reason if not tried
+function doLvmBackup () {
+ local lvmdir="$1"
+ if [ ! -d "$lvmdir" ]; then
+ if ! mkdir "$lvmdir"; then
+ echo "could not create $lvmdir"
+ return 2
+ else
+ info "successfully created $lvmdir"
+ fi
+ fi
+ if [ ! -w "$lvmdir" ]; then
+ echo "can not write to directory $lvmdir"
+ return 2
+ fi
+ debug "Let's try to gather the list of LVM volume groups"
+ debug "$VGS --options vg_name --noheadings | @SED@ 's/^[ ]*//' | @SED@ 's/[ ]*$//' | tr '\n' ' '"
+ vgs=`$VGS --options vg_name --noheadings | @SED@ 's/^[ ]*//' | @SED@ 's/[ ]*$//' | tr '\n' ' '`
+ debug "Let's try to backup LVM metadata for detected volume groups: $vgs"
+ debug "$VGCFGBACKUP --file \"${lvmdir}\"/\'%s\' $vgs"
+ output=`$VGCFGBACKUP --file "${lvmdir}"/'%s' $vgs`
+ exit_code=$?
+ debug $output
+ case $exit_code in
+ 0)
+ info "LVM metadata was saved to $lvmdir for volume groups: $vgs"
+ return 0
+ ;;
+ *)
+ echo "LVM metadata could not be saved for at least one of these volume groups: $vgs"
+ return 1
+ ;;
+ esac
+}
+
+if [ "$lvm" == "yes" ]; then
+ output=`doLvmBackup "${parentdir}/lvm"`
+ exit_code=$?
+ case $exit_code in
+ 0) # success. info message has already been displayed
+ true
+ ;;
+ 1) # error
+ fatal "$output"
+ ;;
+ 2) # could not even try
+ fatal "LVM metadata backup was not tried: $output"
+ ;;
+ *) # should never happen
+ fatal "Unhandled error ($exit_code) while trying to backup LVM metadata, please report a bug"
+ ;;
+ esac
+fi