#!/bin/sh # # $Header: https://svn.unixadm.org/repos/tools/qemu-backup.sh 1117 2015-01-25 16:03:49Z phil $ # export PATH="${PATH}:/sbin:/usr/sbin" pki=/home/phil/pki [ -d "${pki}" ] || exit 1 if [ -z "$2" ]; then echo "usage: $0 " exit 1 fi func=${0##*/} host=$1 img=$2 if [ ! -e ${img} ]; then echo "imagefile ${img} does not exist!" exit 2 fi rmmod nbd modprobe nbd nbds_max=8 max_part=8 nbd=-1 for n in {0..7}; do nbd-client -c /dev/nbd${n} if [ $? -eq 1 ]; then nbd=$n break fi done if [ ${nbd} -lt 0 ]; then echo "no (free) nbd device found, exiting" exit 1 fi echo "using nbd${nbd}" tmp=$(mktemp -d) mnt=${tmp}/mnt mkdir -p ${tmp}/mnt probe_dev="/dev/nbd${nbd}" luks_dev="" vg="" mounts="" qemu-nbd -c /dev/nbd${nbd} ${img} sleep 1 p=1 while true; do [ -e /dev/nbd${nbd}p${p} ] || break tuuid=$(blkid -s UUID /dev/nbd${nbd}p${p} | cut -d\" -f2) if [ -n "${tuuid}" ]; then echo "found uuid $tuuid for /dev/nbd${nbd}p${p}" probe_dev="${probe_dev} /dev/nbd${nbd}p${p}" fi btype=$(blkid -s TYPE /dev/nbd${nbd}p${p} | cut -d\" -f2) if [ "${btype}" == "crypto_LUKS" ]; then echo "found luks device" if [ -r ${pki}/UUID=${tuuid} ]; then echo "found key for uuid ${tuuid}, opening" cryptsetup --key-file ${pki}/UUID=${tuuid} luksOpen \ /dev/nbd${nbd}p${p} luks-${host} && \ luks_dev="${luks_dev} luks-${host}" probe_dev="${probe_dev} /dev/mapper/luks-${host}" fi fi let p++ done if [ $p -eq 1 ]; then echo "no partitions found, exiting" nbd-client -d /dev/nbd${nbd} rm -rf --one-file-system ${tmp} exit 13 fi for p in {1..4}; do [ -e /dev/nbd${nbd}p${p} ] || continue mount /dev/nbd${nbd}p${p} ${mnt} >& /dev/null || continue if [ -e ${mnt}/grub/grub.conf ]; then echo "found /boot" root=$(perl -ne 'if (/root=(.+?) /) {print $1; last}' ${mnt}/grub/grub.conf) echo "grub says root is at ${root}" umount ${mnt} break elif [ -d ${mnt}/boot/grub ]; then root=/dev/nbd${nbd}p${p} echo "root found at ${root}" umount ${mnt} break fi umount ${mnt} done if [ -z "${root}" ]; then echo "root not found, exiting" nbd-client -d /dev/nbd${nbd} rm -rf --one-file-system ${tmp} exit 12 fi pvscan --cache /dev/nbd${nbd}p* for pd in ${probe_dev}; do tvg=$(pvdisplay -c ${pd} 2> /dev/null | cut -d: -f2) if [ -n "${tvg}" ]; then echo "found vg ${tvg}, activating" vgchange -a y ${tvg} vg="${vg} ${tvg}" fi done if [ ! -e "${root}" ]; then echo "root device ${root} does not exist. exiting." nbd-client -d /dev/nbd${nbd} rm -rf --one-file-system ${tmp} exit 12 fi fsck -a -f ${root} mount ${root} ${mnt} if [ ! -r "${mnt}/etc/fstab" ]; then echo "fstab not readable. exiting." umount ${mnt} nbd-client -d /dev/nbd${nbd} rm -rf --one-file-system ${tmp} exit 12 fi perl -ne 'next unless /^([^#]+?)\s+(\/[^\s]+?)\s+(?:ext[234]|btrfs|xfs|reiser.*?)\s/; printf "$1 $2\n"' ${mnt}/etc/fstab | while read dev mp; do fsck -a -f ${dev} mount ${dev} ${mnt}${mp} done echo "done, system is mounted at ${mnt}, disk is /dev/nbd${nbd}" if [ "${func}" == "qemu-backup.sh" ]; then ping -c 2 -w 2 -q ${host} >& /dev/null if [ $? -ne 0 ]; then echo "host ${host} unreachable, not rsyncing" read else eval `ssh-agent -s` ssh-add 2>&1 rsync ${3} -azvplHAXP --delete \ --numeric-ids --inplace -e 'ssh -q' \ --exclude=/proc/* --exclude=/sys/* --exclude=/selinux/* --exclude=/dev/* \ --exclude=/var/named/chroot/proc/* --exclude=/tmp/* --exclude=/var/tmp/* \ --exclude=/var/cache/yum/* --exclude=/var/cache/man/* --exclude=/luks/* \ --exclude=/var/lib/imap/shm --exclude=/var/run/**.pid \ --exclude=/multimedia_*/* --exclude=/srv/share/* --exclude=/home/phil/Downloads/* \ ${host}:/ ${mnt} sync kill $SSH_AGENT_PID fi else echo "press play on tape." read fi mount | grep "${mnt}/" | awk '{print $3}' | while read m; do umount -v ${m} done umount -v ${mnt} sync for v in ${vg}; do vgchange -a n ${v} if [ $? -ne 0 ]; then rm -rf --one-file-system ${tmp} exit 255 fi done sleep 1 for l in ${luks_dev}; do cryptsetup luksClose ${l} if [ $? -ne 0 ]; then rm -rf --one-file-system ${tmp} exit 255 fi done sleep 1 nbd-client -d /dev/nbd${nbd} rm -rf --one-file-system ${tmp}