#!/bin/bash

########################################################################
## Antud skripti eesmärk on teha käivitatav koopia kogu süsteemist selleks
## Eraldatud eemaldatavale andmekandjale. Skript ei ole ette nähtud ja teeb
## ettenägematuid tempe kui kasutada loop seadmetega või muul erilisel viisil.
#
## Skript eeldab, et käivitatakse juurkasutajana ja ei tee selle kohta
## ühtegi kontrolloperatsiooni.
#
## Skripti kasutamiseks võiks selle kopeerida /usr/local/sbin kataloogi
## ja siis tegema skriptis vajalikud muudatused.
#
## Skript eeldab LUKS krüpteeritud partitsiooni varukoopiate tarvis ja
## krüptovõtit hakkab buutimisel küsima grub.
## <nurksulgudes olev osa tuleb asendada vastavalt olukorrale>
#
# cryptsetup luksFormat <partitsioon>
# cryptsetup luksUUID <partitsioon>
## Viimase käsuga saadud UUID tuleb kopeerida siia faili vastavale reale.
#
## Soovi korral on võimalus teha võtmefail, ka see tuleb siia faili kirja panna.
## Kaval oleks aga valida sama võtmefail, mis on juurpartitsioonil...
# dd if=/dev/urandom of=<võtmefail> bs=1M count=1
# cryptsetup luksAddKey <partitsioon> <võtmefail>
#
# cryptsetup open --type luks --allow-discards --key-file <võtmefail> <partitsioon> <varukoopianimi>
# mkfs.ext4 /dev/mapper/<varukoopianimi>
# cryptsetup close <varukoopianimi>
#
## Kui käivitada skripti kujul:
# systembackup.sh auto
## ..siis skript midagi ei küsi ja väljund on oluliselt lühem, see on
## sobilik näiteks automaatseks varundamiseks.
#
## Skripti loodud varukoopiat saab testida näiteks virtuaalmasinas kui
## ei ole huvi restarti teha. Selleks on vaja lahti haakida (kui on haagitud)
## kõik partitsioonid sellel andmekandjal, seejärel käivitada:
# lsusb
## Sealt lugeda õige seadme Bus ja Device numbrid. Need numbrid saab
## siis panna qemu käsureale selliselt:
# qemu-system-x86_64 -enable-kvm -cpu host -netdev user,id=vmnic,hostname=Estoo-VM \
	-device virtio-net,netdev=vmnic -m 2G -smp 2 -vga std -name Estoo-VM -device \
	usb-ehci,id=usb,bus=pci.0,addr=0x4 -device usb-host,hostbus=001,hostaddr=001
########################################################################

LUKSDEVICEUUID="" # LUKS seadme UUID
LUKSDEVICEKEY="" # LUKS seadme võtmefail (valikuline)
BACKUPNAME="backup" # varukoopianimi
MOUNTPOINT="/mnt/backup" # haakepunkt

# Vaikimisi lipukesed rsync käsule:
RSYNCBASEOPTIONS='--relative --recursive --links --perms
 --executability --acls --owner --group --times --delete-during --ignore-errors'

# Siia võiks lisada kõik kataloogid, mis jäävad varundamisest välja. On
# oluline jälgida, et kõik potensiaalselt haagitud failisüsteemid, mis
# ei peaks varukoopiasse jõudma, oleksid nende kataloogide alla haagitud:
RSYNCEXTRAOPTIONS='--exclude=/proc/* --exclude=/sys/* --exclude=/dev/*
 --exclude=/run/* --exclude=/tmp/* --exclude=/var/log/* --exclude=/var/spool/*
 --exclude=/mnt/* --exclude=/media/*'

# Siia panna kirja kõik kataloogid mis tuleks enne varukoopiate tegemist
# külge haakida:
# Näide: EXTRAMOUNT=("/boot" "/home/andmed")
EXTRAMOUNT=()

# Seadistuste lõpp.
EXTRAUMOUNT=()

if [ ! "${1}" == "auto" ]; then
	RSYNCBASEOPTIONS="--verbose ${RSYNCBASEOPTIONS}"
fi

# Kontrolloperatsioonid:
if [ -e "/dev/mapper/${BACKUPNAME}" ]; then
	echo "/dev/mapper/${BACKUPNAME} on juba kasutuses!"
	exit
fi

if [ ! "`mount | grep "${MOUNTPOINT}"`"  == "" ]; then
	echo "${MOUNTPOINT} on juba haakepunktina kasutuses."
	exit
fi

BACKUPDEVICE="`findfs UUID="${LUKSDEVICEUUID}"`"
if [ ! -e "${BACKUPDEVICE}" ]; then
	echo "Ei leidnud seadet varukoopiate jaoks!"
	exit
fi

mkdir -p "${MOUNTPOINT}"
if [ ! -e "${MOUNTPOINT}" ]; then
	echo "${MOUNTPOINT} ei eksisteeri ja loomine ebaõnnestus!"
	exit
fi

# Krüpto avamine
if [ "${LUKSDEVICEKEY}" == "" ]; then
	cryptsetup open --type luks --allow-discards "${BACKUPDEVICE}" "${BACKUPNAME}"
else
	if [ -e "${LUKSDEVICEKEY}" ]; then
		cryptsetup open --type luks --allow-discards --key-file "${LUKSDEVICEKEY}" "${BACKUPDEVICE}" "${BACKUPNAME}"
	else
		echo "Võtmefaili ${LUKSDEVICEKEY} ei eksisteeri!"
		exit
	fi
fi

if [ ! -e "/dev/mapper/${BACKUPNAME}" ]; then
	echo "Luks krüpteeringu avamine ebaõnnestus!"
	exit
fi

# Haakimine
mount "/dev/mapper/${BACKUPNAME}" "${MOUNTPOINT}"
if [ ${?} -ne 0 ]; then
	echo "/dev/mapper/${BACKUPNAME} haakimine asukohta ${MOUNTPOINT} ebaõnnestus!"
	if [ ! "${1}" == "auto" ]; then
		echo "Vajuta ENTER, krüptoseadme sulgemiseks."
		read -n 1 ANS
	fi
	cryptsetup close "${BACKUPNAME}"
	exit
fi

# Lisa failisüsteemide haakimine
for i in ${!EXTRAMOUNT[*]}; do
	if [ ! "${EXTRAMOUNT[$i]}" == "" ]; then
		if [ "`mount | grep " on ${EXTRAMOUNT[$i]} type "`" == "" ]; then
			mount -v "${EXTRAMOUNT[$i]}"
			EXTRAUMOUNT+=("${EXTRAMOUNT[$i]}")
		else
			echo "${EXTRAMOUNT[$i]} on juba haagitud."
		fi
	fi
done

if [ ! "${1}" == "auto" ]; then
	echo "Varukoopiate seade on ühendatud, teha varukoopiad? [Y/n]"
	read -n 1 ANS
fi
if [ "${ANS}" == "n" ]; then
	umount -Rf "${MOUNTPOINT}"
	cryptsetup close "${BACKUPNAME}"
	# Lisa failisüsteemide lahti haakimine
	for i in ${!EXTRAUMOUNT[*]}; do
		if [ ! "${EXTRAUMOUNT[$i]}" == "" ]; then
			umount -v "${EXTRAUMOUNT[$i]}"
		fi
	done
	sync
	exit
fi

# Varundamine
cd /
rsync ${RSYNCBASEOPTIONS} ${RSYNCEXTRAOPTIONS} \
"." "${MOUNTPOINT}"

# Et varukoopiat oleks võimalik käivitada, on oluline teha ta käivitatavaks:
cd "${MOUNTPOINT}"
if [ -e root/.bash_profile ]; then
	cp -p root/.bash_profile /tmp/${BACKUPNAME}.root.bash.profile
fi
BACKUPBOOTDEVICE="`echo ${BACKUPDEVICE} | sed 's;\(/dev/sd[a-z]\)[0-9]*;\1;'`"
REPLACEFILESYSTEMUUID="`tune2fs -l /dev/mapper/${BACKUPNAME} | grep 'Filesystem UUID' | awk '{print $NF}'`"
cat<<EOF> root/.bash_profile
#!/bin/bash

mkdir -p /backupboot/grub
grub-mkconfig | sed "s; root=UUID=${REPLACEFILESYSTEMUUID} ; root=UUID=${LUKSDEVICEUUID} backuponly ;g" > /backupboot/grub/grub.cfg
grub-install --boot-directory=/backupboot ${BACKUPBOOTDEVICE}
exit
EOF
chmod +x root/.bash_profile
mount -o bind /dev dev
mount -o bind /sys sys
mount -o bind /proc proc
chroot . /bin/bash -l
umount dev sys proc
if [ -e /tmp/${BACKUPNAME}.root.bash.profile ]; then
	cp -p /tmp/${BACKUPNAME}.root.bash.profile root/.bash_profile 
fi

# Lõpetamine
echo "Valmis!"
df -h "/dev/mapper/${BACKUPNAME}"

cd
if [ ! "${1}" == "auto" ]; then
	echo -e "\nHaakida lahti? [Y]"
	read -n 1 ANS
fi
sync
umount -R "${MOUNTPOINT}"
cryptsetup close "${BACKUPNAME}"
sync

# Lisa failisüsteemide lahti haakimine
for i in ${!EXTRAUMOUNT[*]}; do
	if [ ! "${EXTRAUMOUNT[$i]}" == "" ]; then
		umount -v "${EXTRAUMOUNT[$i]}"
	fi
done

sync
