#!/bin/bash

echo " WARNING: backup your database before performing upgrade

 This is an UNSUPPORTED Zabbix upgrade script from 1.6 to 1.8 for MySQL
 It does the following things:
  1. Drops all indexes that might have been created in Zabbix 1.6 database;
  2. Converts all tables to UTF-8;
  3. Patches the database from 1.6 schema to 1.8 schema;
  4. Adds the 'Discovered Hosts' hosts group and sets it to be used for discovered hosts;
  5. Adds 'Disabled' usergroup if it is missing;
  6. Checks for hosts not belonging to any group and adds them to one if any found.

 This script is not intended for distributed monitoring databases.

 Usage: pass required MySQL parameters to this script (like database, user, password etc).
"

read -n 1 -p "Continue ? (y/n) " RESPONSE

[ "$RESPONSE" == "y" ] || {
	echo
	exit
}

# groupname to use for hosts that do not belong to any group, if any. literar string.
# if missing, will be added, if existing, hosts will be added to it
GROUPFORHOSTS="none"

MYSQL="$(which mysql)"
MYSQLPARAMS="$@"
echo

fail() {
	echo "$1"
	exit 1
}

[[ "$MYSQL" ]] || fail "No mysql binary in path."

timer() {
	TIMER=$(echo "$@" | cut -d" " -f 2- | tr " " _)
	case "$1" in
	start)
		let START_$TIMER=$(date +%s)
		;;
	stop)
		let TOTALTIME=$(date +%s)-START_$TIMER
		let TOTALHOURS=TOTALTIME/3600
		let TOTALMINUTES=(TOTALTIME-TOTALHOURS*3600)/60
		let TOTALSECONDS=TOTALTIME%60
	echo "$(echo $TIMER | tr _ " ") took $TOTALHOURS:$(printf "%02d" $TOTALMINUTES):$(printf "%02d" $TOTALSECONDS)"
	esac
}

increaseid() {
# accepts table name and field as parameters
# increases corresponding id if found, searches the table for max id and inserts one if not
# returns freshly inserted id to be used with new entry
	CURRENTID=$(echo "select nextid from ids where table_name='$1' and field_name='$2';" | $MYSQL $MYSQLPARAMS -N)
	
	[[ "$CURRENTID" ]] && {
		echo "update ids set nextid='$[$CURRENTID+1]' where table_name='$1' and field_name='$2';" | $MYSQL $MYSQLPARAMS
	} || {
		CURRENTID=$(echo "select $2 from $1 order by $2 desc limit 1;" | $MYSQL $MYSQLPARAMS -N)
		echo "insert into ids values (0,'$1','$2',$[$CURRENTID+1]);" | $MYSQL $MYSQLPARAMS
	}
	return $[$CURRENTID+1]
}

drop_index() {
	echo "alter table $1 drop index $2;" | $MYSQL $MYSQLPARAMS 2>&1 | grep -v "check that column/key exists"
}

# ********************   1

echo "Dropping indexes that might need re-creation..."

timer start dropping of indexes

for i in\
 "actions      actions_1"\
 "dhosts       dhosts_1"\
 "dservices    dservices_1"\
 "escalations  escalations_2"\
 "graphs_items graphs_items_1"\
 "graphs_items graphs_items_2"\
 "history_log  history_log_2"\
 "history_text history_text_2"\
 "httptest     httptest_2"\
 "httptest     httptest_3"\
 "services     services_1"; do
	drop_index $i
done
echo -n " ... "
timer stop dropping of indexes

# ********************   2

echo "Converting database to UTF8"

timer start conversion to UTF8
echo "ALTER DATABASE CHARACTER SET utf8;" | $MYSQL $MYSQLPARAMS
for i in $(echo "show tables;" | $MYSQL -N $MYSQLPARAMS); do
	echo "... converting table $i"
	echo "ALTER TABLE $i CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;" | $MYSQL $MYSQLPARAMS
done
echo -n " ... "
timer stop conversion to UTF8

# ********************   3

echo "Patching the database"

timer start patching of the database
$MYSQL $MYSQLPARAMS < patch.sql || fail "Failed to patch Zabbix database. Restore from backup"
echo -n " ... "
timer stop patching of the database

# ********************   4

echo "Adding 'Discovered Hosts' host group"

increaseid groups groupid

echo "update config set discovery_groupid=(select nextid from ids where table_name='groups' and field_name='groupid') where configid='1';
insert into groups (groupid,name,internal) select nextid,'Discovered Hosts','1' from ids where table_name='groups' and field_name='groupid';" | $MYSQL $MYSQLPARAMS

# ********************   5

echo -n "Checking for 'Disabled' user group... "

[[ "$(echo "select name from usrgrp where name='Disabled';" | $MYSQL $MYSQLPARAMS -N)" ]] && {
	echo "found, not doing anything."
} || {
	echo "not found, adding."
	increaseid usrgrp usrgrpid
	echo "insert into usrgrp (usrgrpid,name,gui_access,users_status,api_access,debug_mode) select nextid,'Disabled','0','1','0','0' from ids where table_name='usrgrp' and field_name='usrgrpid';" | $MYSQL $MYSQLPARAMS
}

# ********************   6

echo -n "Checking for hosts not belonging to any group... "

timer start checking for hosts not belonging to any group
HOSTSWOGROUP=$(echo "select hosts.hostid from hosts left join hosts_groups on hosts.hostid=hosts_groups.hostid where hosts_groups.hostid is null;" | $MYSQL $MYSQLPARAMS -N)

[[ "$HOSTSWOGROUP" ]] && {
	echo "found."
	GROUPFORHOSTSID=$(echo "select groupid from groups where name='$GROUPFORHOSTS'" | $MYSQL $MYSQLPARAMS -N)
	[[ "$GROUPFORHOSTSID" ]] && {
		echo "Group '$GROUPFORHOSTS' already exists, adding all orphaned hosts to it."
	} || {
		echo "Group '$GROUPFORHOSTS' does not exist, creating it and adding all orphaned hosts to it."
		GROUPFORHOSTSID=$(increaseid groups groupid)
		echo "insert into groups (groupid,name,internal) select nextid,'$GROUPFORHOSTS','0' from ids where table_name='groups' and field_name='groupid';" | $MYSQL $MYSQLPARAMS
	}
	for ORPHANHOST in $HOSTSWOGROUP; do
		MAPPINGID=$(increaseid hosts_groups hostgroupid)
		echo "insert into hosts_groups (hostgroupid,hostid,groupid) select nextid,'$ORPHANHOST','$GROUPFORHOSTSID' from ids where table_name='hosts_groups' and field_name='hostgroupid';" | $MYSQL $MYSQLPARAMS
		((HOSTSADDED++))
	done
} || {
	echo "not found any"
}
echo "Added $HOSTSADDED hosts to group '$GROUPFORHOSTS'. Move them to correct groups manually."
echo -n " ... "
timer stop checking for hosts not belonging to any group
