#!/bin/bash
#
# Univention LDAP
#  test script
#
# Copyright 2004-2014 Univention GmbH
#
# http://www.univention.de/
#
# All rights reserved.
#
# The source code of this program is made available
# under the terms of the GNU Affero General Public License version 3
# (GNU AGPL V3) as published by the Free Software Foundation.
#
# Binary versions of this program provided by Univention to you as
# well as other copyrighted, protected or trademarked materials like
# Logos, graphics, fonts, specific documentations and configurations,
# cryptographic keys etc. are subject to a license agreement between
# you and Univention and not subject to the GNU AGPL V3.
#
# In the case you use this program under the terms of the GNU AGPL V3,
# the program is provided in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public
# License with the Debian GNU/Linux or Univention distribution in file
# /usr/share/common-licenses/AGPL-3; if not, see
# <http://www.gnu.org/licenses/>.

. /usr/share/univention-lib/base.sh

cat << End
Possible Tests:

 1  backup listener test
 2  master notifier test
 3  direct ldap modification on backup
 4  listener-kill test
 5  notifier-kill test
 6  slave ldap/backup test
 7  univention-directory-replication-resync test
 8  ldapmodrdn-test
 9  slave listener backup slapd restart test

End

echo -e "Please enter all test you want to run [12345678]"
read choice
if [ -z "$choice" ]
then
	choice="12345678"
fi
n_tests=${#choice}

echo -e "\vHow many objects do you want me to create in each test [1]:"
read LIMIT
if [ -z "$LIMIT" ]
then
	LIMIT=1
fi

echo -e "\vname or ip of domain controller backup:"
read backup

echo -e "\vname or ip of domain controller slave:"
read slave

echo -e "\vroot password:"
stty -echo
read dc_pw
stty echo

let "total = $LIMIT * 6"
let "total = $total * $n_tests"
echo -e "\v##############################################################"
echo "# Note: Each test creates $LIMIT objects of each used module "
echo "#       Total number of objects = $total"
echo "#       The modules are:"
echo "#       users/user groups/group computers/managedclient"
echo "#       networks/network shares/printer shares/share"
echo "##############################################################"

# Last chance to exit
echo -e "\vWanna start now? (Ctrl+C to exit)"
read answer
echo "Starting ..."

# Setting variables and deleting old results
eval "$(univention-config-registry shell)"
echo $dc_pw > pw.tmp
cat /dev/null > result.txt
master=$hostname
pw="pw.tmp"
pre=`date -u +%s`
suf=0
let "sync_time=$LIMIT * 6"
pause=`expr 30 + $sync_time`


#############  Functions ########################################
#
#

random_string ()
{
string1="`makepasswd --minchars=4 --maxchars=12 --string=\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\"`"
string2="`makepasswd --minchars=4 --maxchars=12 --string=\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\"`"
}



random_name () # create objectnames
{
	rand1="Object$pre$suf"
	suf=`expr $suf + 1`
	rand2=$rand1"#sub"
}

user () # create a users/user object
{
	groups_default_domainusers=$(custom_groupname "Domain Users")
	univention-admin "$module" create --set username="$rand1" --set lastname="$rand2" --set password=univention --set unixhome="/home/$rand1" --set primaryGroup="cn=$groups_default_domainusers,cn=groups,$ldap_base" --position="cn=users,$ldap_base"
}

group () # create a groups/group object
{
	univention-admin "$module" create --set name="$rand1" --position="cn=groups,$ldap_base"
}

computer () # create a computers/managedclient object
{
	univention-admin "$module" create --set name="$rand1" --set unixhome=/dev/null --set primaryGroup="cn=Computers,cn=groups,$ldap_base" --position="cn=computers,$ldap_base"
}

network () # create a networks/network object
{
	univention-admin "$module" create --set name="$rand1" --set network=192.168.0.0 --set netmask=255.255.255.0 --position="cn=networks,$ldap_base"
}

printer () # create a shares/printer object
{
	univention-admin "$module" create --set name="$rand1" --set spoolHost="$cups_server" --set uri="lp0://$rand1/" --set model="$rand2" --position="cn=printers,$ldap_base"
}

share () # create a shares/share object
{
	univention-admin "$module" create --set name="$rand1" --set host="$hostname.$domainname" --set path="/home/groups/$rand1/" --position="cn=shares,$ldap_base"
}


modrdn_objects ()
{
for module in "users/user" "groups/group" "computers/managedclient" "networks/network" "shares/printer" "shares/share"
do
	case "$module" in
		users/user) cn="users" ;;
		groups/group) cn="groups" ;;
		computers/managedclient) cn="computers" ;;
		networks/network) cn="networks" ;;
		shares/printer) cn="printers" ;;
		shares/share) cn="shares" ;;
		*);;
	esac
	count=0
	for dn in $(ldapsearch -x -ZZ -D "$ldap_hostdn" -y /etc/machine.secret -b cn="$cn,$ldap_base" -s one | sed -ne '/Object/s/^dn: //p')
	do
		rdn=`echo $dn |awk -F , '{print $1}' |awk -F = '{print $1}'`
		random_string
		echo "Changing $dn to $rdn=Object$string1"
		ldapmodrdn -x -D "cn=admin,$ldap_base" -w "$(cat /etc/ldap.secret)" "$dn" "$rdn=Object$string1"
		echo "Changing $rdn=Object$string1 to $rdn=Objectxxx$string2 (using argument -r )"
		ldapmodrdn -x -D "cn=admin,$ldap_base" -w "$(cat /etc/ldap.secret)" -r "$rdn=Object$string1,cn=$cn,$ldap_base" "$rdn=Objectxxx$string2"
		count=`expr $count + 1`
		if [ "$count" -eq "$LIMIT" ]
		then
			break
		fi
	done
done
}


create_objects () # create $LIMIT of every function above
{
echo -e "\v===> create $LIMIT objects of each module"
echo "===> users/user groups/group computers/managedclient networks/network shares/printer shares/share"
for module in "users/user" "groups/group" "computers/managedclient" "networks/network" "shares/printer" "shares/share"
do
	for ((a=1; a <= LIMIT ; a++))
	do
		random_name
		echo -e "\n-->Adding $module ($a of $LIMIT)..."
		case "$module" in
			users/user) user ;;
			groups/group) group ;;
			computers/managedclient) computer ;;
			networks/network) network ;;
			shares/printer) printer ;;
			shares/share) share ;;
			*) echo "Module $module not defined in TestScript..." ;;
		esac
	done
done
}

create_ldif () # creates a ldif-file and the same objects on master
{
touch backup.ldif
touch master.tmp
echo -e "\v===> create ldif-file for backup-manipulation"
for dn in $(ldapsearch -x -ZZ -D "$ldap_hostdn" -y /etc/machine.secret -b "cn=users,$ldap_base" -s one | sed -ne '/Object/s/^dn: //p')
do
	echo -e "dn: $dn\nchangetype: modify\nreplace: homeDirectory\nhomeDirectory: /dev/null\n" >> backup.ldif
	echo -e "$dn" >> master.tmp
done
}

compare () # compares two ldap_dump-files using diff
{
echo -e "\v===> comparing $rmhost and $rmhost2"
if [ "$rmhost" == "$slave" ]
then
	univention-scp -timeout 60 "$pw" /etc/ldap.secret "root@$rmhost:/etc/"
elif [ "$rmhost2" == "$slave" ]
then
	univention-scp -timeout 60 "$pw" /etc/ldap.secret "root@$rmhost2:/etc/"
fi

cmd="for module in users/user groups/group computers/managedclient networks/network shares/printer shares/share; do univention-admin "$module" list >> /tmp/ldap_dump_$rmhost.tmp; done"
#cmd="ldapsearch -x -b $ldap_base > /tmp/ldap_dump_$rmhost.tmp"
univention-ssh -timeout 60 "$pw" "root@$rmhost" $cmd
univention-scp -timeout 60 "$pw" "root@$rmhost:/tmp/ldap_dump_$rmhost.tmp" /tmp/

cmd="for module in users/user groups/group computers/managedclient networks/network shares/printer shares/share; do univention-admin "$module" list >> /tmp/ldap_dump_$rmhost2.tmp; done"
#cmd="ldapsearch -x -b $ldap_base > /tmp/ldap_dump_$rmhost2.tmp"
univention-ssh -timeout 60 "$pw" "root@$rmhost2" $cmd
univention-scp -timeout 60 "$pw" "root@$rmhost2:/tmp/ldap_dump_$rmhost2.tmp" /tmp/
echo -e "\v ###### $test " >> result.txt
echo -e "diff /tmp/ldap_dump_$rmhost.tmp /tmp/ldap_dump_$rmhost2.tmp :\v" >> result.txt
diff "/tmp/ldap_dump_$rmhost.tmp" "/tmp/ldap_dump_$rmhost2.tmp" >> result.txt
cmd="rm /tmp/ldap_dump*"
echo -e "\v===> deleting temp-files"
univention-ssh -timeout 60 "$pw" "root@$rmhost" $cmd &> /dev/null
univention-ssh -timeout 60 "$pw" "root@$rmhost2" $cmd &> /dev/null

if [ "$rmhost" == "$slave" ]
then
	univention-ssh -timeout 60 "$pw" "root@$rmhost" "rm /etc/ldap.secret"
elif [ "$rmhost2" == "$slave" ]
then
	univention-ssh -timeout 60 "$pw" "root@$rmhost2" "rm /etc/ldap.secret"
fi

}

wait_for () # beautiful sleep-output-function ;o)
{
echo -e "\v===> waiting for $pause seconds"
for ((a=1; a <= pause; a++))
do
printf "\b\b\b\b\b\b\b $a"
sleep 1
done
printf "\b\b\b\b\b\b\b       \n"

}

stop () # stopping daemon on remote host using init-script
{
echo -e "\v===> stopping $what on $where"
cmd="/etc/init.d/$what stop"
univention-ssh -timeout 60 "$pw" "root@$where" $cmd
}

start () # starting daemon on remote host using init-script
{
echo -e "\v===> starting $what on $where"
cmd="/etc/init.d/$what start"
univention-ssh -timeout 60 "$pw" "root@$where" $cmd
}

reset ()
{
echo -e "\v ------ resetting all needed daemon  ------"

cmd="/etc/init.d/univention-directory-listener start"
echo -e "\v===>master:"
univention-ssh -timeout 60 "$pw" "root@$master" $cmd
echo -e "\v===>backup:"
univention-ssh -timeout 60 "$pw" "root@$backup" $cmd
echo -e "\v===>slave:"
univention-ssh -timeout 60 "$pw" "root@$slave" $cmd

cmd="/etc/init.d/univention-directory-notifier start"
echo -e "\v===>master:"
univention-ssh -timeout 60 "$pw" "root@$master" $cmd
echo -e "\v===>backup:"
univention-ssh -timeout 60 "$pw" "root@$backup" $cmd

cmd="/etc/init.d/slapd start"
echo -e "\v===>master"
univention-ssh -timeout 60 "$pw" "root@$master" $cmd
echo -e "\v===>backup"
univention-ssh -timeout 60 "$pw" "root@$backup" $cmd
echo -e "\v===>slave"
univention-ssh -timeout 60 "$pw" "root@$slave" $cmd
}

check_failed () # check for replication failed.ldif
{
echo -e "------ checking for failed.ldiff ------"
cmd="/usr/bin/test -e /var/lib/univention-directory-replication/failed.ldif"
univention-scp -timeout 60 "$pw" "root@$where:/var/lib/univention-directory-replication/failed.ldif" . >/dev/null 2>&1

if [ -e failed.ldif ] ; then
	echo "failed.ldif exists on $where"
	echo "failed.ldif exists on $where" >> result.txt
	rm failed.ldif
fi

}

get_id () # get notifier id
{
echo -e "------ getting notifier id from $where ------"
cmd="cat /var/lib/univention-directory-listener/notifier_id"
notifier_id=$(univention-ssh -timeout 60 "$pw" "root@where" $cmd)
echo "notifier_id: $notifier_id"
}

compare_ids ()
{
	if [ $last_id != $notifier_id ] ; then
		check_failed
	 else
		get_id
		pause=5
		wait_for
		compare_ids
	fi
}

config_slavelistener () # config listener to connect first on $con_to
{
	eval "$(univention-config-registry shell)"

	slave="$where"
	slave_hostdn=$(univention-admin computers/domaincontroller_slave list --filter cn="$slave" | sed -ne 's/^DN: //p')

	backup="$con_to.$domainname"
	echo '#!/bin/sh -e' > /tmp/listener-run0
	echo "" >> /tmp/listener-run0
	echo "exec /usr/sbin/univention-directory-listener -h '$backup' -F -b '$ldap_base' -m '/usr/lib/univention-directory-listener/system' -c '/var/lib/univention-directory-listener' -o -x -ZZ -D '$slave_hostdn' -y /etc/machine.secret >>/var/log/univention/listener.log 2>&1" >> /tmp/listener-run0

	univention-scp -timeout 60 "$pw" /tmp/listener-run0 "root@$where:/etc/runit/univention-directory-listener/run"
	rm /tmp/listener-run0
}

defconfig_slavelistener ()
{
	cmd="univention-config-registry commit /etc/runit/univention-directory-listener/run"
	univention-ssh -timeout 60 "$pw" "root@$where" $cmd
}

#####################  Tests ###############################
#
#

reset

#test="compare master and backup before starting test "
#rmhost=$backup
#rmhost2=$master
#compare

#test="compare master and backup before starting test "
#rmhost=$slave
#rmhost2=$master
#compare

run=`echo $choice |grep 1`
if [ -n "$run" ]
then
test="**********  backup listener test **********"
echo -e "\v$test"
###################################################################
#
# stop backup-listener / create objects / start backup-listener /
# compare ldap_dump
#
###################################################################
	rmhost=$backup
	rmhost2=$master

	what="univention-directory-listener"
	where=$backup
	stop

	create_objects

	start

	wait_for

	compare


	# reset
fi

run=`echo $choice |grep 2`
if [ -n "$run" ]
then
test="**********  master notifier test **********"
	echo -e "\v$test"
###################################################################
#
# stop master-notifier / create objects / start master-notifier /
# compare ldap_dump
#
###################################################################
	rmhost=$backup
	rmhost2=$master

	what="univention-directory-notifier"
	where=$master
	stop

	create_objects

	start

	wait_for

	compare

	# reset
fi

run=`echo $choice |grep 3`
if [ -n "$run" ]
then
test="**********  direct ldap modification on backup **********"
echo -e "\v$test"
###################################################################
#
# stop backup-listener / change objects using ldapadd on backup /
# change same on master / start backup-listener / compare ldap_dump
#
###################################################################
	rmhost=$backup
	rmhost2=$master

	create_objects

	what="univention-directory-listener"
	where=$rmhost
	stop

	create_ldif

	echo -e "\v===> copy ldif to $rmhost"
	univention-scp -timeout 60 "$pw" backup.ldif "root@$rmhost:~/"

	echo -e "\v===> get ldap-rootpw from $rmhost"
	univention-scp -timeout 60 "$pw" "root@$rmhost:/etc/ldap/rootpw.conf" .
	rootpw=`cat rootpw.conf |awk '{print $2}' |perl -pi -e 's/\"/ /g'`
	echo -e "===> sounds like: $rootpw"
	rm rootpw.conf

	echo -e "\v===> using ldif on $rmhost"
	cmd="ldapmodify -x -D 'cn=update,$ldap_base' -w '$rootpw' -f backup.ldif"
	univention-ssh -timeout 60 "$pw" "root@$rmhost" $cmd

	echo -e "\v===> using ldif on master"
	for dn in `cat master.tmp`
	do
		univention-admin users/user modify --dn "$dn" --set unixhome=/home/groups
	done

	start

	wait_for

	compare

	# reset
fi

run=`echo $choice |grep 4`
if [ -n "$run" ]
then
test="**********  listener-kill test **********"
echo -e "\v$test"
###################################################################
#
# kill listener / create objects / start killing/create-loop /
# compare ldap_dump
#
###################################################################
	rmhost=$backup
	rmhost2=$master

	echo -e "\v===> killing backup listener"
	cmd="killall -9 univention-directory-listener"
	univention-ssh -timeout 60 "$pw" "root@$backup" $cmd

	create_objects

	echo -e "\v\v===> starting killing-loop"
	for module in "users/user" "groups/group" "computers/managedclient" "networks/network" "shares/printer" "shares/share"
	do
		for ((a=1; a <= LIMIT; a++))
		do
			random_name
			echo -e "\v\v===> killing master listener"
			cmd="killall -9 univention-directory-listener"
			univention-ssh -timeout 60 "$pw" "root@$backup" $cmd 2> /dev/null
			case "$module" in
				users/user)user;;
				groups/group)group;;
				computers/managedclient)computer;;
				networks/network)network;;
				shares/printer)printer;;
				shares/share)share;;
				*);;
			esac
		done
	done

	wait_for

	compare

	# reset
fi

run=`echo $choice |grep 5`
if [ -n "$run" ]
then
test="**********  notifier-kill test **********"
echo -e "\v$test"
###################################################################
#
# kill master-notifier / create objects / start killing/create-loop /
# compare ldap_dump
#
###################################################################
	rmhost=$backup
	rmhost2=$master

	echo -e "\v===> killing backup listener"
	cmd="killall -9 univention-directory-listener"
	univention-ssh -timeout 60 "$pw" "root@$backup" $cmd

	create_objects

	echo -e "\v\v===> starting killing-loop"
	for module in "users/user" "groups/group" "computers/managedclient" "networks/network" "shares/printer" "shares/share"
	do
		for ((a=1; a <= LIMIT; a++))
		do
			random_name
			echo -e "\v\v===> killing master notifier"
			cmd="killall -9 univention-directory-notifier"
			univention-ssh -timeout 60 "$pw" "root@$master" $cmd 2> /dev/null
			case "$module" in
				users/user)user;;
				groups/group)group;;
				computers/managedclient)computer;;
				networks/network)network;;
				shares/printer)printer;;
				shares/share)share;;
				*);;
			esac
		done
	done
	wait_for
	compare

	# reset
fi

run=`echo $choice |grep 6`
if [ -n "$run" ]
then
test="**********  slave ldap/backup test **********"
echo -e "\v$test"
###################################################################
#
# stop slave-listener / create objects / stop master-notifier /
# start slave-listener / compare ldap_dump / stop slave-listener /
# start master-notifier / create objects / stop backup-notifier /
# start slave-listener / compare ldap_dump / start backup-notifier
#
###################################################################
	what=univention-directory-listener
	where=$slave
	stop

	create_objects

	what=univention-directory-notifier
	where=$master
	stop

	what=univention-directory-listener
	where=$slave
	start

	wait_for

	rmhost=$slave
	rmhost2=$master
	compare

	stop

	what=univention-directory-notifier
	where=$master
	start

	create_objects

	what=univention-directory-notifier
	where=$backup
	stop

	what=univention-directory-listener
	where=$slave
	start

	wait_for

	rmhost=$slave
	rmhost2=$master
	compare

	what=univention-directory-notifier
	where=$backup
	start


	# reset

fi

run=`echo $choice |grep 7`
if [ -n "$run" ]
then
test="**********  univention-directory-replication-resync test **********"
echo -e "\v$test"
###################################################################
#
# stop backup-slapd / create objects / start backup-slapd /
# execute univention-directory-replication / compare ldap_dump
#
###################################################################
	what=slapd
	where=$backup
	stop

	wait_for

	create_objects

	what=slapd
	where=$backup
	start

	pause=10
	wait_for

	echo -e "\v===> execute univention-directory-replication-resync on backup"
	cmd="univention-directory-replication-resync /var/lib/univention-directory-replication/failed.ldif"
	univention-ssh -timeout 360 "$pw" "root@$slave" $cmd

	pause=`expr 30 + $sync_time`
	wait_for

	rmhost=$backup
	rmhost2=$master
	compare

	# reset
fi


run=`echo $choice |grep 8`
if [ -n "$run" ]
then
test="**********  ldapmodrdn test **********"
echo -e "\v$test"
###################################################################
#
# stop backup-listener / change objects using ldapmodrdn /
# start backup-listener / compare ldap_dump
#
###################################################################
        what=univention-directory-listener
        where=$backup
        stop

	create_objects

	modrdn_objects

	start

        pause=`expr 30 + $sync_time`
        wait_for

        rmhost=$backup
        rmhost2=$master
        compare

        # reset
fi

run=`echo $choice |grep 9`
if [ -n "$run" ]
then
test="********** slave listener backup slapd restart test  **********"
echo -e "\v$test"
echo -e "\v ###### $test " >> result.txt
###################################################################
#
# stop slave listener / create objects / start slave listener/
# restart backup slapd / check for failed.ldiff
#
###################################################################
		what=univention-directory-listener
		where=$slave
		stop
		con_to=$backup
		config_slavelistener
		create_objects
		start

		what=slapd
		where=$backup
		stop
		start

		where=$slave
		compare_ids
		what=univention-directory-listener
		where=$slave
		stop
		defconfig_slavelistener
		start
fi

echo -e "\v\v**********  The Results **********"
#cat result.txt
echo -e "\v Results saved in result.txt"

echo -e "\v**********  removing temp-files **********"
cmd="if [ -e backup.ldif ] ; then rm backup.ldif ; fi"
univention-ssh -timeout 60 "$pw" "root@$backup" $cmd
if [ -e "backup.ldif" ] ; then rm backup.ldif ; fi
if [ -e "master.tmp" ] ; then rm master.tmp ; fi
if [ -e "pw.tmp" ] ; then rm pw.tmp ; fi
#if [ -e "modrdn.tmp" ] ; then rm modrdn.tmp ; fi

echo -e "\v\v**********  Remove created objects **********"
echo -e "\vDo you want to delete all $total created objects? [Crt-C for \"No\"]"
read answer
echo "Removing all created objects..."
for module in "users/user" "groups/group" "computers/managedclient" "networks/network" "shares/printer" "shares/share"
do
	case "$module" in
		users/user)cn="cn=users";;
		groups/group)cn="cn=groups";;
		computers/managedclient)cn="cn=computers";;
		networks/network)cn="cn=networks";;
		shares/printer)cn="cn=printers";;
		shares/share)cn="cn=shares";;
		*)cn="cn=NotValidCN$pre";;
	esac

	for dn in $(ldapsearch -x -ZZ -D "$ldap_hostdn" -y /etc/machine.secret -b "$cn,$ldap_base" -s one | sed -ne '/Object/s/^dn: //p')
	do
		univention-admin "$module" remove --dn "$dn"
	done
done

echo -e "\v\v********** FINISH **********\v"
exit 0
