#!/bin/bash
#
# OpenLDAP backup script
#
# - setup
# @code
# yum install s3cmd --enablerepo=epel
# s3cmd --configure
# chmod 755 ldap-backup.sh
# @endcode
#
# - You should just change LDAP suffix from "dc=my-domain,dc=com" to your actual one.
# - To restore you should perform the following steps.
# 1. stop slapd daemon:
#    debian:~# /etc/init.d/slapd stop
# 2. delete old database (make sure you are in right directory to use rm):
#    debian:~# cd /var/lib/ldap
#    rm -rf *
# 3. Restore database from LDIF file:
#    debian:~# /usr/sbin/slapadd -l backup.ldif
# 4. run slapd daemon:
#    debian:~# /etc/init.d/slapd start
#
# $Revision:$
# $Date:$

# define
OPT_LDAP_DIR="/etc/openldap"
OPT_BASE_DN= # dc=my-domain,dc=com
OPT_BACKUP_DIR= # /path/to/backup
OPT_S3CMD_CONFIG= # /path/to/.s3cfg
OPT_S3_BUCKET= # s3://BUCKET/path/to
OPT_LOG_DIR= # /tmp

PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
readonly DEBUG=0
export LANG=C
readonly CUR_DIR=$(cd $(dirname $0);pwd) # current directory
readonly PID=$$
readonly CMDNAME=`basename $0`
readonly CMDBASENAME=`basename $0 .sh`
LOG_FILE= # "$CUR_DIR/${CMDBASENAME}.log"

# ESC  http://ascii-table.com/ansi-escape-sequences.php
# BASH http://archive.linux.or.jp/JF/JFdocs/Bash-Prompt-HOWTO-5.html
readonly ESC="\e["
readonly ESCEND=m
readonly ESC_CLEAR=${ESC}${ESCEND}
# ESC Foreground colors
readonly ESC_BLACK="30"
readonly ESC_RED="31"
readonly ESC_GREEN="32"
readonly ESC_YELLOW="33"
readonly ESC_BLUE="34"
readonly ESC_MAGENTA="35"
readonly ESC_CYAN="36"
readonly ESC_WHITE="37"
readonly ESC_DARK_GRAY="30;1"
readonly ESC_LIGHT_RED="31;1"
readonly ESC_LIGHT_GREEN="32;1"
readonly ESC_LIGHT_YELLOW="33;1"
readonly ESC_LIGHT_BLUE="34;1"
readonly ESC_LIGHT_MAGENTA="35;1"
readonly ESC_LIGHT_CYAN="36;1"

# /define

# function
echo_prestr() {
	echo -e `date '+%Y-%m-%d %H:%M:%S'`"\t${PID}"
}

echo_blank() {
	echo "" | tee -a ${LOG_FILE}
}

echo_info() {
	local prestr=`echo_prestr`"\tINFO"
	echo -en "${ESC}${ESC_LIGHT_GREEN}${ESCEND}"
	echo -e "${prestr}\t${1}" | tee -a ${LOG_FILE}
	echo -en "${ESC_CLEAR}"
	return 0
}

echo_warn() {
	local prestr=`echo_prestr`"\tWARN"
	{
		echo -en "${ESC}${ESC_YELLOW}${ESCEND}"
		echo -e "${prestr}\t${1}" | tee -a ${LOG_FILE}
		echo -en "${ESC_CLEAR}"
	} 1>&2
}

echo_error() {
	local prestr=`echo_prestr`"\tERROR"
	{
		echo -en "${ESC}${ESC_MAGENTA}${ESCEND}"
		echo -e "${prestr}\t${1}" | tee -a ${LOG_FILE}
		echo -en "${ESC_CLEAR}"
	} 1>&2

	return 1
}

function ldap_backup() {
	local ymd=$(date '+%Y%m%d')
	local tmp_dir=$(mktemp -d $OPT_BACKUP_DIR/${ymd}-XXXXXX)
	local backup_file=$OPT_BACKUP_DIR/$(hostname -s).${OPT_BASE_DN}.$ymd.tar.gz

	# export ldap
	slapcat -b "${OPT_BASE_DN}" -l $tmp_dir/ldap.${OPT_BASE_DN}.$ymd.ldif 2>&1 | tee -a ${LOG_FILE}
        # config file
        cp -f $OPT_LDAP_DIR/*.{conf,sysconfig} $tmp_dir/ > /dev/null 2>&1
	# archive
	cd "${tmp_dir}"
	tar cfz "${backup_file}" ./* 2>&1 | tee -a ${LOG_FILE}
	cd "${CUR_DIR}"

	# copy local to S3
	if [ "$OPT_S3_BUCKET" != "" -a -f "${backup_file}" ]; then
		s3cmd -c "$OPT_S3CMD_CONFIG" --no-progress put "${backup_file}" "$OPT_S3_BUCKET/" 2>&1 | tee -a ${LOG_FILE}
		if [ $? -eq 0 ]; then
			rm -f ${backup_file}
		fi
	fi

	# cleanup
	if [ "$DEBUG" == "0" -a -d "$tmp_dir" ]; then
		rm -rf $tmp_dir
	fi
}

function main() {
	if [ -z "$OPT_BASE_DN" ]; then
		echo_error "--base-dn is required"
		exit 1
	fi

	if [ ! -d "$OPT_BACKUP_DIR" ]; then
		echo_error "--backup-dir is not found. [$OPT_BACKUP_DIR]"
		exit 1
	fi

	if [ ! -z "$OPT_S3CMD_CONFIG" -a ! -f "$OPT_S3CMD_CONFIG" ]; then
		echo_error "--s3cmd-config is not found. [$OPT_S3CMD_CONFIG]"
		exit 1
	fi
	
	ldap_backup
}

usage_exit() {
	cat 1>&2 << EOS
Usage: $CMDNAME [options]

Common options:
  --base-dn                  base dn for search
                             ex: dc=my-domain,dc=com
  --backup-dir               ex: /path/to/backup
  --ldap-dir                 default: ${OPT_LDAP_DIR}
  --s3-bucket                ex: s3://BUCKET/path/to
  --s3cmd-config             ex: /path/to/.s3cfg
  --log-dir                  ex: /tmp
  --help                     help
EOS
	exit 1
}

# /function

# check command args.
if [ $# -lt 1 ]; then
    usage_exit
fi

OPT=`getopt -q -o "" -l "help,log-dir:,ldap-dir:,base-dn:,s3cmd-config:,s3-bucket:,backup-dir:" -- "$@"`
if [ $? != 0 ]; then
	usage_exit
fi
 
eval set -- "$OPT"
while [ -n "$1" ]; do
	case $1 in
		--backup-dir) OPT_BACKUP_DIR=$2; shift 2;;
		--s3-bucket) OPT_S3_BUCKET=$2; shift 2;;
		--s3cmd-config) OPT_S3CMD_CONFIG=$2; shift 2;;
		--base-dn) OPT_BASE_DN=$2; shift 2;;
		--ldap-dir) OPT_LDAP_DIR=$2; shift 2;;
		--log-dir) 
			OPT_LOG_DIR=$2
			shift 2
			if [ -d "$OPT_LOG_DIR" ]; then
				LOG_FILE=$OPT_LOG_DIR/${CMDBASENAME}.log
			else
				echo_error "directory not found. [$OPT_LOG_DIR]"
				exit 1
			fi
			;;
		--help) usage_exit;;
		--) shift; break;;
		*) echo_error "Unknown option($1) used."; exit 1;;
	esac
done

main

# vim: ts=4:sw=4

