#!{{ shell_binary }} LC_ALL=C export LC_ALL umask 077 # Exit on any error, to prevent inconsistent backup # Error on unset variable expansion set -eu # Redirect output to log exec > >(tee -ai '{{ output_log_file }}') exec 2>&1 echo -e "\n\n$0 run at : $(date)" srv_directory='{{ directory["srv"] }}' backup_directory='{{ directory["backup"] }}' etc_directory='{{ directory["etc"] }}' tmp_directory='{{ directory["tmp"] }}' rsync () { # Workaround for bug https://bugzilla.samba.org/show_bug.cgi?id=3653 IGNOREEXIT=24 IGNOREOUT='^(file has vanished: |rsync warning: some files vanished before they could be transferred)' set -o pipefail set -x '{{ rsync_binary }}' -rlptgov --stats --safe-links --ignore-missing-args --delete --delete-excluded "$@" 2>1 | (egrep -v "$IGNOREOUT" || true) set +x ret=$? if [[ $ret == $IGNOREEXIT ]]; then ret=0 fi exit $ret } ( # XXX: code duplication with runner-import.sh.jinja2 path=$srv_directory/runner backup_path=$backup_directory/runner/ cd "$path" if [ -d instance ]; then # Concatenate the exclude file of each partition of webrunner # to create a global exclude file. # Also, ignore all buildout-managed files. exclude=$({{ sys.executable }} - "$path" <<EOF if 1: import glob, errno, os, sys sys.path[:0] = {{ repr(easy_install.buildout_and_setuptools_path) }} from zc.buildout.configparser import parse path = sys.argv[1] def print_relative(path_list): for p in path_list: p = p.strip() if p: print(os.path.relpath(p, path)) print("*.sock") print("*.socket") print("*.pid") print(".installed*.cfg") for partition in glob.glob(path + "/instance/slappart*"): os.chdir(partition) try: with open("srv/exporter.exclude") as f: exclude = f.readlines() except IOError as e: if e.errno != errno.ENOENT: raise else: print_relative(exclude) for installed in glob.glob(".installed*.cfg"): try: with open(installed) as f: installed = parse(f, installed) except IOError as e: if e.errno != errno.ENOENT: raise else: for section in installed.itervalues(): print_relative(section.get( '__buildout_installed__', '').splitlines()) EOF ) echo "$exclude" |rsync --exclude-from=- instance "$backup_path" fi test -d project && rsync project "$backup_path" test -d public && rsync public "$backup_path" test -f proxy.db && rsync proxy.db "$backup_path" ) # We sync .* appart ( cd "$etc_directory" date +%s -u > .resilient-timestamp rsync config.json "$backup_directory"/etc/ # Hidden files are related to the webrunner's internals cp -r .??* "$backup_directory/etc/" ) if [ -d "$backup_directory"/runner/software ]; then rm "$backup_directory"/runner/software/* fi ( cd "$backup_directory" find -type f ! -name backup.signature -print0 | xargs -0 sha256sum | sort -k 66 > backup.signature ) # Check that export didn't happen during backup of instances tmp_backup_sum=$(mktemp -p "$tmp_directory") tmp_filtered_signature=$(mktemp -p "$tmp_directory") remove_tmp_files () { rm "$tmp_backup_sum" "$tmp_filtered_signature" } trap remove_tmp_files EXIT # Getting files from runner backup directory, as instance backup files may be # explicitely excluded from the backup, using the srv/exporter.exclude cd {{ directory['backup'] }} backup_directory_path=$(find . -path "./runner/instance/slappart*/srv/backup/*" -type f) # If no backup found, it's over if [ -z "$backup_directory_path" ]; then exit 0 fi sleep 5 sha256sum $backup_directory_path | sort -k 66 > "$tmp_backup_sum" egrep "instance/slappart.*/srv/backup/" "$backup_directory/backup.signature" > "$tmp_filtered_signature" # If the diff fails, then the notifier will restart this script if diff "$tmp_backup_sum" "$tmp_filtered_signature"; then exit 0 fi echo "ERROR: Some backups are not consistent, exporter should be re-run." echo "Let's sleep {{ backup_wait_time }} minutes, to let the backup end..." sleep {{ backup_wait_time }}m exit 1