#!/bin/bash
#
# Creates a Full Backup of Nagios XI
# Copyright (c) 2011-2020 Nagios Enterprises, LLC. All rights reserved.
#

PATH=/home/nagios/bin:/usr/bin:/bin
. /home/nagios/bin/colors.sh

BASEDIR="/usr/local/nagiosxi/scripts"

timeStamp=`date +%s`
hostname="`/bin/hostname`"
pName=""
sName=""
noping=/bin/false
noFile=/bin/false
execute="-n"
syncfile=""
isP=/bin/false
isS=/bin/false

# Import Nagios XI and xi-sys.cfg config vars
. $BASEDIR/../var/xi-sys.cfg
eval $(php $BASEDIR/import_xiconfig.php)

###############################
# USAGE / HELP
###############################
usage () {
    echo ""
    echo "Use this script to synchronize primary XI to secondary, or to expand primary information on secondary"
    echo ""
	echo " -P | --primary		Set the FQDN of the primary (what is returned by /bin/hostname)"
	echo " -S | --secondary		Set the FQDN of the secondary (what is returned by /bin/hostname)"
	echo " -F | --file		Set the name of the file that we will be restoring from on the secondary"
	echo " -E | --execute		Perform the sync (otherwise, it just does a dry-run)"
        echo " -n | --name              Set the name of the backup minus the .tar.gz"
        echo " -p | --prepend           Prepend a string to the .tar.gz name"
        echo " -a | --append            Append a string to the .tar.gz name"
        echo " -d | --directory         Change the directory to store the compressed backup"
	echo " --nofile			Ignore the missing sync file but continue the process"
    echo ""
}

###############################
# ADDING LOGIC FOR NEW BACKUPS
###############################
while [ -n "$1" ]; do
    case "$1" in
	-P | --primary)
	    pName="$2"
	    ;;
	-S | --secondary)
	    sName="$2"
	    ;;
	-E | --execute)
	    execute=""
	    ;;
	-F | --file)
	    syncfile="$2"
	    ;;
	--noping)
	    noping=/bin/true
	    ;;
	--nofile)
	    noFile=/bin/true
	    ;;
        -h | --help)
            usage
            exit 0
            ;;
        -n | --name)
            fullname=$2
            ;;
        -p | --prepend)
            prepend=$2"."
            ;;
        -a | --append)
            append="."$2
            ;;
        -d | --directory)
            rootdir=$2
            ;;
    esac
    shift
done

do_primary() {
#ping_host $sName
#[ $? -ne 0 ] && echo "Cannot ping $sName.  Use --noping to continue wihout ping." && exit
echo "Starting sync from $pName to $sName"

# Restart nagios to forcibly update retention.dat
verbose "Restarting nagios to forcibly update retention.dat"
sudo $BASEDIR/manage_services.sh stop nagios
sleep 5
sudo $BASEDIR/manage_services.sh start nagios

if [ -z $rootdir ]; then
    rootdir="/store/backups/nagiosxi"
fi

# Move to root dir to store backups
cd $rootdir

#############################
# SET THE NAME & TIME
#############################
name=$fullname
if [ -z $fullname ]; then
    name=$prepend$timeStamp$append
fi
# Get current Unix timestamp as name
if [ -z $name ]; then
    name=timeStampts
fi

# My working directory
workDir=$rootdir/$name
# Make directory for this specific backup
mkdir -p $workDir

do_rsync() {
  verbose "Syncing $*..."
  src="$1"
  [ ! -e "$src" ] && warning "  OK: No such file or directory: $src" && return
  [ -d "$src" ] && sudo rsync -a --delete --delete-after --rsync-path="sudo /bin/rsync" ${execute} ${src}/ nagios@${sName}:${src}/
  [ -f "$src" ] && sudo rsync -a --delete --delete-after --rsync-path="sudo /bin/rsync" ${execute} ${src} nagios@${sName}:${src}
}

do_backup_files() {
##############################
# BACKUP DIRS
##############################

# Only backup NagiosQL if it exists
if [ -d "/var/www/html/nagiosql" ]; then
    do_rsync /var/www/html/nagiosql
    do_rsync /etc/nagiosql
fi

do_rsync /etc/apache2/sites-available/default-ssl.conf
do_rsync /etc/logrotate.d/nagiosxi
do_rsync /etc/mrtg/conf.d
do_rsync /etc/mrtg/mrtg.cfg
do_rsync /etc/snmp
do_rsync /etc/sysconfig/nagios
do_rsync /home/nagios
do_rsync $httpdconfdir/nagios.conf
do_rsync $httpdconfdir/nagiosmobile.conf
do_rsync $httpdconfdir/nagiosxi.conf
do_rsync $httpdconfdir/nagvis.conf
do_rsync $httpdconfdir/nrdp.conf
do_rsync $httpdconfdir/ssl.conf
do_rsync /usr/local/nagios
do_rsync /usr/local/nagiosmobile
do_rsync /usr/local/nagiosxi
do_rsync /usr/local/nagvis
do_rsync /usr/local/nrdp
do_rsync /usr/share/snmp
do_rsync /var/lib/mrtg
do_rsync /var/spool/cron/apache
do_rsync /var/spool/cron/crontabs/$apacheuser


} # End of do_backup_files

do_backup_sql() {
##############################
# BACKUP DATABASES
##############################
echo "Backing up MySQL databases..."
mkdir -p $workDir/mysql
if [[ "$cfg__db_info__ndoutils__dbserver" == *":"* ]]; then
    ndoutils_dbport=`echo "$cfg__db_info__ndoutils__dbserver" | cut -f2 -d":"`
    ndoutils_dbserver=`echo "$cfg__db_info__ndoutils__dbserver" | cut -f1 -d":"`
else
    ndoutils_dbport='3306'
    ndoutils_dbserver="$cfg__db_info__ndoutils__dbserver"
fi
mysqldump -h "$ndoutils_dbserver" --port="$ndoutils_dbport" -u $cfg__db_info__ndoutils__user --password="$cfg__db_info__ndoutils__pwd" --add-drop-database -B $cfg__db_info__ndoutils__db > $workDir/mysql/nagios.sql
res=$?
if [ $res != 0 ]; then
    echo "Error backing up MySQL database 'nagios' - check the password in this script!"
    rm -r $workDir
    exit $res;
fi
if [[ "$cfg__db_info__nagiosql__dbserver" == *":"* ]]; then
    nagiosql_dbport=`echo "$cfg__db_info__nagiosql__dbserver" | cut -f2 -d":"`
    nagiosql_dbserver=`echo "$cfg__db_info__nagiosql__dbserver" | cut -f1 -d":"`
else
    nagiosql_dbport='3306'
    nagiosql_dbserver="$cfg__db_info__nagiosql__dbserver"
fi
mysqldump -h "$nagiosql_dbserver" --port="$nagiosql_dbport" -u $cfg__db_info__nagiosql__user --password="$cfg__db_info__nagiosql__pwd" --add-drop-database -B $cfg__db_info__nagiosql__db > $workDir/mysql/nagiosql.sql
res=$?
if [ $res != 0 ]; then
    echo "Error backing up MySQL database 'nagiosql' - check the password in this script!"
    rm -r $workDir
    exit $res;
fi

# Only backup PostgresQL if we are still using it 
if [ $cfg__db_info__nagiosxi__dbtype == "pgsql" ]; then
    echo "Backing up PostgresQL databases..."
    mkdir -p $workDir/pgsql
    if [ -z $cfg__db_info__nagiosxi__dbserver ]; then
        cfg__db_info__nagiosxi__dbserver="localhost"
    fi
    pg_dump -h $cfg__db_info__nagiosxi__dbserver -c -U $cfg__db_info__nagiosxi__user $cfg__db_info__nagiosxi__db > $workDir/pgsql/nagiosxi.sql
    res=$?
    if [ $res != 0 ]; then
        echo "Error backing up PostgresQL database 'nagiosxi' !"
        rm -r $workDir
        exit $res;
    fi
else
    if [[ "$cfg__db_info__nagiosxi__dbserver" == *":"* ]]; then
        nagiosxi_dbport=`echo "$cfg__db_info__nagiosxi__dbserver" | cut -f2 -d":"`
        nagiosxi_dbserver=`echo "$cfg__db_info__nagiosxi__dbserver" | cut -f1 -d":"`
    else
        nagiosxi_dbport='3306'
        nagiosxi_dbserver="$cfg__db_info__nagiosxi__dbserver"
    fi
    mysqldump -h "$nagiosxi_dbserver" --port="$nagiosxi_dbport" -u $cfg__db_info__nagiosxi__user --password="$cfg__db_info__nagiosxi__pwd" --add-drop-database -B $cfg__db_info__nagiosxi__db > $workDir/mysql/nagiosxi.sql
    res=$?
    if [ $res != 0 ]; then
        echo "Error backing up MySQL database 'nagiosxi' - check the password in this script!"
        rm -r $workDir
        exit $res;
    fi
fi

##############################
# COMPRESS BACKUP
##############################
verbose "Compressing database file..." -n
tar czfp $name.tar.gz $name
rm -rf $name
verbose "Done."

# Change ownership
chown $nagiosuser:$nagiosgroup $name.tar.gz

if [ -s $name.tar.gz ];then
    echo " "
    echo "==============="
    echo "BACKUP COMPLETE"
    echo "==============="
    echo "Backup stored in $rootdir/$name.tar.gz"
else
    echo " "
    echo "==============="
    echo "BACKUP FAILED"
    echo "==============="
    echo "File was not created at $rootdir/$name.tar.gz"
    rm -rf $workDir
    exit 1;
fi
do_rsync $rootdir/$name.tar.gz
rm -Rf $rootdir/$name.tar.gz
} # End of do_backup_sql

do_backup_files
do_backup_sql
} # End of do_primary

restore_secondary() {
# Change this password if your root password is different than "nagiosxi"
# MySQL root password
themysqlpass="nagiosxi"

# Tests mysql connection by opening a connection and selecting the DB we want to use
test_mysql_connection() {
    local db_host="$1"
    local db_port="$2"
    local db_username="$3"
    local db_password="$4"
    db_error=$(mysql -h "$db_host" --port="$db_port" -u $db_username --password=$db_password -e "show databases;" 2>&1)
    return $?
}

rootdir=/store/backups/nagiosxi
backupfile=$1
# This is a poor way to write this, but it's the easiest.  Skip doing all the restore operations if there's no file to restore from.
if [ ! $noFile ]; then
if [ ! -f $backupfile ]; then
    error "Unable to find backup file $backupfile!"
    exit 1
fi

ts=`date +%s`
mydir=${rootdir}/${ts}-restore
mkdir -p $mydir
if [ ! -d $mydir ]; then
    error "Unable to create restore directory $mydir!"
    exit 1
fi

# Extract backup
verbose "Extracting backup to $mydir..."
cd $mydir
tar xzfps $backupfile
# Change to subdirectory
cd `ls | head -1`
backupdir=`pwd`

verbose "Backup files look okay.  Preparing to restore..."

# Shutdown services
verbose "Shutting down services..."
[ -r "/usr/local/nagios/var/retention.dat" ] && cp /usr/local/nagios/var/retention.dat $backupdir
sudo $BASEDIR/manage_services.sh stop nagios
sudo $BASEDIR/manage_services.sh stop ndo2db
sudo $BASEDIR/manage_services.sh stop npcd
[ -r "$backupdir/retention.dat" ] && cp $backupdir/retention.dat /usr/local/nagios/var/retention.dat


rootdir=/
# Overwrite the mysqlpass with the hardcoded one at the top
mysqlpass="$themysqlpass"

# Restore databases
verbose "Restoring MySQL databases..."
if [[ "$cfg__db_info__ndoutils__dbserver" == *":"* ]]; then
    ndoutils_dbport=`echo "$cfg__db_info__ndoutils__dbserver" | cut -f2 -d":"`
    ndoutils_dbserver=`echo "$cfg__db_info__ndoutils__dbserver" | cut -f1 -d":"`
else
    ndoutils_dbport='3306'
    ndoutils_dbserver="$cfg__db_info__ndoutils__dbserver"
fi

# Test mysql and see if we can connect before continuing
x=1
while [ $x -le 5 ];
do
    test_mysql_connection $ndoutils_dbserver $ndoutils_dbport "root" $mysqlpass
    if [ $? == 1 ]; then
        error "ERROR: Could not connect to $ndoutils_dbserver:$ndoutils_dbport with root password supplied."
        read -s -r -p "Please enter the MySQL root password: " mysqlpass
        echo ""
    else
        break
    fi
    if [ $x -eq 5 ]; then
        error "ERROR: Aborting restore: Could not connect to MySQL."
        error "$db_error"
        exit 1
    fi
    x=$(($x+1))
done

# Save old Program URL
old_url=$(echo "select value from xi_options where name='url'" | mysql -h "$ndoutils_dbserver" --port="$ndoutils_dbport" -u root --password=$mysqlpass -N nagiosxi)
mysql -h "$ndoutils_dbserver" --port="$ndoutils_dbport" -u root --password=$mysqlpass < $backupdir/mysql/nagios.sql
res=$?
if [ $res != 0 ]; then
    error "Error restoring MySQL database 'nagios'"
    exit 1
fi
# Restore old Program URL
echo "update xi_options set value='$old_url' where name='url'" | mysql -h "$ndoutils_dbserver" --port="$ndoutils_dbport" -u root --password=$mysqlpass -N nagiosxi

if [[ "$cfg__db_info__nagiosql__dbserver" == *":"* ]]; then
    nagiosql_dbport=`echo "$cfg__db_info__nagiosql__dbserver" | cut -f2 -d":"`
    nagiosql_dbserver=`echo "$cfg__db_info__nagiosql__dbserver" | cut -f1 -d":"`
else
    nagiosql_dbport='3306'
    nagiosql_dbserver="$cfg__db_info__nagiosql__dbserver"
fi

# Test mysql again and see if we can connect before continuing
x=1
while [ $x -le 5 ];
do
    test_mysql_connection $nagiosql_dbserver $nagiosql_dbport "root" $mysqlpass
    if [ $? == 1 ]; then
        error "ERROR: Could not connect to $nagiosql_dbserver:$nagiosql_dbport with root password supplied."
        read -s -r -p "Please enter the MySQL root password: " mysqlpass
        echo ""
    else
        break
    fi
    if [ $x -eq 5 ]; then
        error "ERROR: Aborting restore: Could not connect to MySQL."
        error "$db_error"
        exit 1
    fi
    x=$(($x+1))
done

mysql -h "$nagiosql_dbserver" --port="$nagiosql_dbport" -u root --password=$mysqlpass < $backupdir/mysql/nagiosql.sql
res=$?
if [ $res != 0 ]; then
    error "Error restoring MySQL database 'nagiosql'"
    exit 1
fi

# Only restore PostgresQL if we are still using it 
if [ "$cfg__db_info__nagiosxi__dbtype" == "pgsql" ]; then
    service postgresql initdb &>/dev/null || true
    verbose "Restoring Nagios XI PostgresQL database..."
    if [ -f /var/lib/pgsql/data/pg_hba.conf ]; then
        pghba="/var/lib/pgsql/data/pg_hba.conf"
        cp -pr $pghba $pghba.old
    else
        #Ubuntu/Debian
        pghba=$(find /etc/postgresql -name "*pg_hba.conf")
        cp -pr $pghba $pghba.old
    fi
    echo "local  all         all                   trust
host    all         all         127.0.0.1/32          trust
host    all         all         ::1/128               trust" > $pghba
    $BASEDIR/manage_services.sh start postgresql
    sudo -u postgres psql -c "create user nagiosxi with password 'n@gweb';"
    sudo -u postgres psql -c "create database nagiosxi owner nagiosxi;"
    $BASEDIR/manage_services.sh restart postgresql
    # Sleep a bit (required so Postgres finishes startup before we connect again)
    verbose "Sleeping for a few seconds (please wait)..."
    sleep 7
    psql -U nagiosxi nagiosxi < $backupdir/pgsql/nagiosxi.sql
    res=$?
    if [ $res != 0 ]; then
        error "Error restoring PostgresQL database 'nagiosxi' !"
        exit 1
    fi
    $BASEDIR/manage_services.sh restart postgresql
    if [ "$dist" == "el7" ] || [ "$dist" == "el8" ]; then
        systemctl enable postgresql.service
    elif [[ "$distro" == "Ubuntu" ]] || [[ "$distro" == "Debian" ]]; then
        update-rc.d postgresql enable
    else
        chkconfig postgresql on
    fi
    # Remove nagiosxi db from mysql if postgres is used instead
    if [[ "$cfg__db_info__nagiosql__dbserver" == *":"* ]]; then
        nagiosql_dbport=`echo "$cfg__db_info__nagiosql__dbserver" | cut -f2 -d":"`
        nagiosql_dbserver=`echo "$cfg__db_info__nagiosql__dbserver" | cut -f1 -d":"`
    else
        nagiosql_dbport='3306'
        nagiosql_dbserver="$cfg__db_info__nagiosql__dbserver"
    fi
    mysql -h "$nagiosql_dbserver" --port="$nagiosql_dbport" -u root --password=$mysqlpass < "DROP TABLE IF EXISTS nagiosxi;"
else
    verbose "Restoring Nagios XI MySQL database..."
    if [[ "$cfg__db_info__nagiosxi__dbserver" == *":"* ]]; then
        nagiosxi_dbport=`echo "$cfg__db_info__nagiosxi__dbserver" | cut -f2 -d":"`
        nagiosxi_dbserver=`echo "$cfg__db_info__nagiosxi__dbserver" | cut -f1 -d":"`
    else
        nagiosxi_dbport='3306'
        if [ "x$cfg__db_info__nagiosxi__dbserver" == "x" ]; then
            nagiosxi_dbserver="localhost"
        else
            nagiosxi_dbserver="$cfg__db_info__nagiosxi__dbserver"
        fi
    fi

    # Test mysql again and see if we can connect before continuing
    x=1
    while [ $x -le 5 ];
    do
        test_mysql_connection $nagiosxi_dbserver $nagiosxi_dbport "root" $mysqlpass
        if [ $? == 1 ]; then
            error "ERROR: Could not connect to $nagiosxi_dbserver:$nagiosxi_dbport with root password supplied."
            read -s -r -p "Please enter the MySQL root password: " mysqlpass
            echo ""
        else
            break
        fi
        if [ $x -eq 5 ]; then
            error "ERROR: Aborting restore: Could not connect to MySQL."
            error "$db_error"
            exit 1
        fi
        x=$(($x+1))
    done

    mysql -h "$nagiosxi_dbserver" --port="$nagiosxi_dbport" -u root --password=$mysqlpass < $backupdir/mysql/nagiosxi.sql
    res=$?
    if [ $res != 0 ]; then
        error "Error restoring MySQL database 'nagiosxi' !"
        exit 1
    fi
fi
fi		# This is from the "noFile" check previously
##############################
# RESTART SERVICES
##############################
verbose "Restarting services..."
sudo $BASEDIR/manage_services.sh restart mysqld
sudo $BASEDIR/manage_services.sh restart httpd
sudo $BASEDIR/manage_services.sh start npcd
sudo $BASEDIR/manage_services.sh start ndo2db
sudo $BASEDIR/manage_services.sh start nagios
verbose "Restarting Nagios XI"
cd /usr/local/nagiosxi/scripts
./reconfigure_nagios.sh
rm -rf $mydir
echo " "
echo "==============="
echo "RESTORE COMPLETE"
echo "==============="
}

do_secondary() {
  [ ! $noFile -a ! -r "$syncfile" ] && error "No sync file ($syncfile) found." && exit 2
  restore_secondary "$syncfile"
  if [ $? -eq 0 ]; then
    rm -f ${syncfile}
  fi
} # End of do_secondary

ping_host() {
  $noping && return 0
  /usr/local/nagios/libexec/check_icmp -H $1 >/dev/null 2>&1
}
  
[ -z "$pName" -o -z "$sName" ] && echo "Must specify primary name and secondary name" && exit 0
[ "$hostname" = "$pName" ] && isP=/bin/true
[ "$hostname" = "$sName" ] && isS=/bin/true
$isP && do_primary
$isS && do_secondary
