#!/bin/bash # To create a new host in the database ZFSCMD=/sbin/zfs ZPOOLCMD=/sbin/zpool if [ -z $1 ] ; then echo Use: $0 hostname [flag [flag [...]]] echo Known flags: postgres, mysql exit 1 fi HN=$1 shift set -e # Find FQDN for $HN FQDN=`getent hosts $HN | awk ' { print $2 } '` if [ -z "$FQDN" ]; then echo "Hostname \"$HN\" didn't resolve into a FQDN." >&2 echo "Please check your spelling and try again." >&2 exit 1 fi echo Searching for existing ZFS ... # Find an existing ZFS for this host: # Never use zroot ZPS=`$ZPOOLCMD list -H -o name | grep -v zroot` TGT='' for ZPOOL in $ZPS ; do if [ -z $TGT ] ; then if $ZFSCMD list -H -o name $ZPOOL/$FQDN >/dev/null 2>&1 ; then TGT=$ZPOOL/$FQDN fi fi done # Load some settings . /etc/default/zfs-backup if [ -z $TGT ] ; then echo No existing ZFS found # Find emptiest zpool ZPOOL=`$ZFSCMD list -H -oname -S avail -d0 | grep -v zroot | head -n1` TGT=$ZPOOL/$FQDN echo Using $ZPOOL fi function ensurezfs() { ZFS=$1 if ! $ZFSCMD list $ZFS >/dev/null 2>&1; then $ZFSCMD create $ZFS fi } function dosql() { psql -q -t -c "$1" } # Some SQL to create the host #select host_id from host where hostname='database.ch.private.cam.ac.uk'; function ensurehost() { FQDN=$1 HOSTID=`dosql "select host_id from host where hostname='$FQDN';"` if [ -z $HOSTID ] ; then HOSTID=`dosql " insert into host (hostname, offline, disabled) values ('$FQDN',false,false); select host_id from host where hostname='$FQDN';"` fi echo $HOSTID } function backuptask() { FQDN=$1 TARGET=$2 DIR=$3 SOFT=$4 HARD=$5 if [ -z "$SOFT" ]; then SOFT=14400 fi if [ -z "$HARD" ]; then HARD=86400 fi BTID=`dosql " select backup_task_id from backup_task natural join host natural join zfs_rsync_detail where hostname='$FQDN' and directory_source='$DIR' and backup_type_id=3;"` SN=`echo $FQDN | sed s/\\\\..*//` if [ -z $BTID ] ; then BTID=`dosql " insert into backup_task(host_id,backup_task_name,timeout_soft,timeout_hard,zfs_target,backup_type_id) values ($HOSTID,'Rsync $DIR on $SN',$SOFT,$HARD,'$TARGET',3); insert into zfs_rsync_detail (backup_task_id,directory_source) values ((select backup_task_id from backup_task where backup_task_name='Rsync $DIR on $SN' and host_id=$HOSTID),'$DIR'); select backup_task_id from backup_task natural join host natural join zfs_rsync_detail where hostname='$FQDN' and directory_source='$DIR' and backup_type_id=3;"` fi echo $BTID } # Does that backup task have pruning? function dopruning() { BTID=$1 PRUNID=`dosql " select count(*) from zfs_pruning where backup_task_id=$BTID;"` if [ $PRUNID = 0 ] ; then # Add the pruning dosql " insert into zfs_pruning (backup_task_id,zfs_pruning_age,zfs_pruning_count,flagname) values ($BTID,86400,6,'hourly'), ($BTID,604800,7,'daily'), ($BTID,2419200,4,'weekly'), ($BTID,14515200,6,'monthly');" fi } function backupdir() { FQDN=$1 TARGET=$2 DIR=$3 # Create settings file if ! [ -f /etc/chem-zfs-backup-server/zfs-rsync.d/${FQDN}_${DIR//\//.} ] && [ -f /usr/lib/chem-zfs-backup-server/templates/zfs-rsync/template_${DIR//\//.} ] ; then cp /usr/lib/chem-zfs-backup-server/templates/zfs-rsync/template_${DIR//\//.} /etc/chem-zfs-backup-server/zfs-rsync.d/${FQDN}_${DIR//\//.} fi # Root backup ensurezfs $TARGET BTID=`backuptask $FQDN $TARGET "$DIR"` dopruning $BTID echo Backup Task for $FQDN:$DIR is $BTID } function getsshkey() { # don't be concerned if ssh-keyscan returns non-zero. This will happen # if the host is offline - for most servers, we deploy signed ssh host keys # anyway. set +e FQDN=$1 ssh-keyscan $FQDN 2>/dev/null >> /root/.ssh/known_hosts set -e } HOSTID=`ensurehost $FQDN` echo Host ID is $HOSTID ensurezfs $TGT $ZFSCMD set sharenfs=ro=${FQDN},no_root_squash,crossmnt $TGT # Do root backup backupdir $FQDN $TGT/zfs-rsnap / # set ssh key in known_hosts getsshkey $FQDN # Parse flags while ! [ -z $1 ] ; do case $1 in postgres) backupdir $FQDN $TGT/pgdumps /var/empty 43200 60480 echo "Now set up /etc/chem-zfs-backup-server/zfs-rsync.d/${FQDN}_.var.empty to" echo "run your postgres backup task via e.g.:" echo echo " PRE=/usr/lib/chem-zfs-backup-server/pg-dump-script" echo " PGDUMP_DATABASE=name_of_database" echo echo "You should check/etc/chem-zfs-backup-server/zfs-rsync.d/${FQDN}_. too , e.g." echo echo " RSYNCARGS=\"... --exclude=/var/lib/postgresql" echo " PRE=/etc/chem-zfs-backup-server/zfs-rsync.d/prepare-ignore-mysql-and-postgres" echo ;; mysql) backupdir $FQDN $TGT/mysql-files /var/lib/mysql-files echo Note: You almost certainly want to edit /etc/chem-zfs-backup-server/zfs-rsync.d/${FQDN}_. echo by adding --exclude=/var/lib/mysql --exclude=/var/lib/mysql-files to the rsync args ;; *) echo Unknown flag $1 ;; esac shift done ZFSs=$(zfs list -r -H -oname $TGT | grep -v ${TGT}$) echo "Please check/set quotas on child ZFSs:" for ZFS in $ZFSs; do echo " zfs set quota=\$QUOTA $ZFS" done