#!/bin/bash usage() { echo "Usage: $0 [ -z UUID ] [ -h hostname ] [ -p port ] [ -k KEY ] [ -n name ] [ -d dir ]" >&2 exit 1 } while getopts "z:h:p:k:n:d:" opt; do case "$opt" in z) UUID=$OPTARG ;; h) HOSTNAME=$OPTARG ;; n) NAME=$OPTARG ;; p) PORT=$OPTARG ;; k) KEY=$OPTARG ;; d) DIR=$OPTARG ;; \?) echo "Error: Invalid Option: -${OPTARG}" >&2 usage ;; :) echo "Error: -${OPTARG} requires an argument." usage ;; *) usage ;; esac done shift $((OPTIND-1)) if [ -z "${UUID}" ] || [ -z "${HOSTNAME}" ] || [ -z ${PORT} ] || [ -z ${KEY} ] || [ -z "${NAME}" ] || [ -z "${DIR}" ]; then usage fi SSH="ssh -i $KEY -p ${PORT} -o StrictHostKeyChecking=no" DSTDIR="${DIR}/${NAME}" ################# # functions ################# create_snap() { DATASET=$1 echo "Creating snapshot of ${DATASET}..." /usr/sbin/zfs snapshot zones/${DATASET}@`date +%Y%m%d` check_err echo "...done." } send_snap() { DATASET=$1 echo "Sending snapshot of ${DATASET}..." # taking care for additional datasets SLASH=`echo ${DATASET} | grep -c '/'` if [ ${SLASH} -ne 0 ]; then RENAME=`echo ${DATASET} | sed 's/\//-/'` /usr/sbin/zfs send zones/${DATASET}@`date +%Y%m%d` | ${SSH} ${HOSTNAME} "dd of=${DSTDIR}/${UUID}/${RENAME}.zfs bs=4M" else /usr/sbin/zfs send zones/${DATASET}@`date +%Y%m%d` | ${SSH} ${HOSTNAME} "dd of=${DSTDIR}/${DATASET}/${DATASET}.zfs bs=4M" fi check_err echo "...done." } check_snap() { ZONE=$1 echo "Checking for snapshot of ${ZONE}..." zfs list -t snapshot zones/${ZONE}@`date +%Y%m%d` 2>/dev/null 1>&2 } check_err() { STATUS=$? if [ ${STATUS} -ne 0 ]; then echo "Unexpected error: ${STATUS}" exit ${STATUS} fi } send_config() { echo "Sending config to ${HOSTNAME}..." zonecfg -z ${UUID} export | ${SSH} ${HOSTNAME} "dd of=${DSTDIR}/${UUID}/${UUID}.cfg" check_err echo "...done." } create_dir() { echo "Creating directory at ${HOSTNAME}..." ${SSH} ${HOSTNAME} mkdir -p ${DSTDIR}/${UUID} check_err echo "...done." } check_multidataset() { echo "Looking for addtional children datasets in ${UUID}..." DATASET=`vmadm get ${UUID} | json datasets.0 | sed 's/zones\///' | tr -d '\n'` echo "...done." if [ ! -z "${DATASET}" ]; then echo "Finded children dataset: ${DATASET}" check_snap ${DATASET} if [ $? -ne 0 ]; then create_snap ${DATASET} else echo "Snapshot of ${DATASET} already available" echo "Skipping create snapshot..." fi send_snap ${DATASET} else echo "No children datasets finded." fi } ################# # main ################# echo "--- BACKUP_SERVER: ${HOSTNAME} UUID to backup: ${UUID} ---" create_dir ${UUID} check_snap ${UUID} if [ $? -ne 0 ]; then create_snap ${UUID} else echo "Snapshot of ${UUID} already available" echo "...done." fi send_snap ${UUID} check_multidataset send_config