#!/bin/sh

set -e
#set -x

usage () {
	echo "Usage: $0 <CLUSTER_NAME>"
	exit 1
}

ALL_SERVICES_CTRL="aodh-api aodh-evaluator aodh-expirer aodh-listener aodh-notifier barbican-api barbican-keystone-listener barbican-worker ceilometer-agent-central ceilometer-agent-notification ceilometer-polling cinder-api cinder-backup cinder-scheduler cinder-volume cloudkitty-api cloudkitty-processor glance-api gnocchi-api gnocchi-metricd gnocchi-statsd heat-api-cfn heat-api heat-engine keystone magnum-api magnum-conductor neutron-api neutron-dhcp-agent neutron-l3-agent neutron-metadata-agent neutron-metering-agent neutron-openvswitch-agent neutron-rpc-server nova-api nova-api-metadata nova-compute nova-conductor nova-novncproxy nova-scheduler octavia-api octavia-health-manager octavia-housekeeping octavia-worker panko-api placement-api neutron-api neutron-rpc-server"
ALL_SERVICES_VOL="cinder-backup cinder-volume"
ALL_SERVICES_NET="neutron-dhcp-agent neutron-l3-agent neutron-metadata-agent neutron-metering-agent neutron-openvswitch-agent"
ALL_SERVICES_COMP="ceilometer-agent-compute cinder-backup cinder-volume neutron-dhcp-agent neutron-l3-agent neutron-metadata-agent neutron-metering-agent neutron-openvswitch-agent nova-compute"

CLUSTER_NAME=${1}

DOMAIN_NAME=$(ocicli -csv cluster-show ${CLUSTER_NAME} | grep Domain: | cut -d, -f2)

# Make a survey of all the hosts we have in the cluster
ALL_CTRL=$(ocicli -csv machine-list | q -H -d, "SELECT Cur_ip,hostname FROM - WHERE hostname LIKE '${CLUSTER_NAME}-controller-%.${DOMAIN_NAME}' AND status='installed' ORDER BY hostname" | tr '\n' ' ')
ALL_CTRL_REVERT=$(ocicli -csv machine-list | q -H -d, "SELECT Cur_ip,hostname FROM - WHERE hostname LIKE '${CLUSTER_NAME}-controller-%.${DOMAIN_NAME}' AND status='installed' ORDER BY hostname DESC" | tr '\n' ' ')
ONE_CTRL=$(ocicli -csv machine-list | q -H -d, "SELECT Cur_ip,hostname FROM - WHERE hostname LIKE '${CLUSTER_NAME}-controller-%' AND status='installed' ORDER BY hostname LIMIT 1" | tr '\n' ' ')
ONE_CTRL_IP=$(echo ${ONE_CTRL} | cut -d, -f1)
ONE_CTRL_HOSTNAME=$(echo ${ONE_CTRL} | cut -d, -f2)
ALL_NODES=$(ocicli -csv machine-list | q -H -d, "SELECT Cur_ip,hostname FROM - WHERE hostname LIKE '${CLUSTER_NAME}-%-${DOMAIN_NAME}' AND status='installed' ORDER BY hostname" | tr '\n' ' ')

#########################
### GENERIC FUNCTIONS ###
#########################

RED="\033[1;31m"
NO_COL="\033[0m"
GREEN="\033[1;32m"
green_echo () {
	echo ${GREEN}${1}${NO_COL}
}
red_echo () {
	echo ${RED}${1}${NO_COL}
}

sshi () {
	ssh -i /etc/openstack-cluster-installer/id_rsa $@
}

scpi () {
	scp -i /etc/openstack-cluster-installer/id_rsa $@
}

disable_puppet () {
	local HOST HOST_IP HOST_NAME
	HOST=${1}
	HOST_IP=$(echo ${HOST} | cut -d, -f1)
	HOST_NAME=$(echo ${HOST} | cut -d, -f2)

	green_echo "-> ${HOST_NAME}"
	sshi root@${HOST_IP} "systemctl stop puppet"
	sshi root@${HOST_IP} "systemctl disable puppet"
	sshi root@${HOST_IP} "systemctl mask puppet"
	sshi root@${HOST_IP} "rm -f /usr/sbin/policy-rc.d"
}

enable_puppet () {
	local HOST HOST_IP HOST_NAME
	HOST=${1}
	HOST_IP=$(echo ${HOST} | cut -d, -f1)
	HOST_NAME=$(echo ${HOST} | cut -d, -f2)

	green_echo "-> ${HOST_NAME}"
	sshi root@${HOST_IP} "systemctl unmask puppet"
	sshi root@${HOST_IP} "systemctl enable puppet"
	sshi root@${HOST_IP} "systemctl start puppet"
}

# Example call:
# iterate_on_hosts "192.168.101.2,z-controller-1 192.168.101.3,z-controller-2" switch_to_release buster rocky buster stein
# Example transformation for the first host:
# switch_to_release 192.168.101.2,z-controller-1 buster rocky buster stein
iterate_on_hosts () {
	local HOST_LIST
	HOST_LIST=${1}
	FUNCTION=${2}
	shift
	shift
	for i in ${HOST_LIST} ; do
		${FUNCTION} ${i} $@
	done
}

install_openstack_pkg_tools () {
	local HOST HOST_IP HOST_NAME
	HOST=${1}
	HOST_IP=$(echo ${HOST} | cut -d, -f1)
	HOST_NAME=$(echo ${HOST} | cut -d, -f2)
	echo "---> Installing openstack-pkg-tools on ${HOST_NAME}"
	sshi root@${HOST_IP} "apt-get install -y openstack-pkg-tools"
}

grant_sql_access () {
	local SERVICE_NAME
	SERVICE_NAME=${1}
	green_echo "---> Granting SQL access for ${SERVICE_NAME}"
	SERVICE_PASS=$(oci-puppet-external-node-classifier ${ONE_CTRL_HOSTNAME} | grep pass_${SERVICE_NAME}_db | awk '{print $2}')
	sshi root@${ONE_CTRL_IP} "mysql -e \"GRANT ALL PRIVILEGES ON ${SERVICE_NAME}db.* TO '${SERVICE_NAME}'@'%' IDENTIFIED BY '${SERVICE_PASS}';\""
}

fix_keystone_connection () {
	local HOST HOST_IP HOST_NAME
	HOST=${1}
	HOST_IP=$(echo ${HOST} | cut -d, -f1)
	HOST_NAME=$(echo ${HOST} | cut -d, -f2)
	green_echo "-> Fixing keystone db connection on ${HOST_NAME}"
	LINE_NUM=$(sshi root@${HOST_IP} "grep -n 'connection = mysql+pymysql' /etc/keystone/keystone.conf | cut -d: -f1")
	sshi root@${HOST_IP} "sed -i '${LINE_NUM} s/127.0.0.1/${HOST_IP}/' /etc/keystone/keystone.conf"
}

fix_barbican_connection () {
	local HOST HOST_IP HOST_NAME
	HOST=${1}
	HOST_IP=$(echo ${HOST} | cut -d, -f1)
	HOST_NAME=$(echo ${HOST} | cut -d, -f2)
	green_echo "-> Fixing barbican db connection on ${HOST_NAME}"
	LINE_NUM=$(sshi root@${HOST_IP} "grep -n 'connection = mysql+pymysql' /etc/barbican/barbican.conf | cut -d: -f1")
	sshi root@${HOST_IP} "sed -i '${LINE_NUM} s/127.0.0.1/${HOST_IP}/' /etc/barbican/barbican.conf"
}

fix_heat_connection () {
	local HOST HOST_IP HOST_NAME
	HOST=${1}
	HOST_IP=$(echo ${HOST} | cut -d, -f1)
	HOST_NAME=$(echo ${HOST} | cut -d, -f2)
	green_echo "-> Fixing heat db connection on ${HOST_NAME}"
	LINE_NUM=$(sshi root@${HOST_IP} "grep -n 'connection = mysql+pymysql' /etc/heat/heat.conf | cut -d: -f1")
	sshi root@${HOST_IP} "sed -i '${LINE_NUM} s/127.0.0.1/${HOST_IP}/' /etc/heat/heat.conf"
	sshi root@${HOST_IP} "systemctl restart heat-engine"
}

restart_apache_on_host () {
	local HOST HOST_IP HOST_NAME
	HOST=${1}
	HOST_IP=$(echo ${HOST} | cut -d, -f1)
	HOST_NAME=$(echo ${HOST} | cut -d, -f2)
	green_echo "-> Restarting Apache on ${HOST_NAME}"
	sshi root@${HOST_IP} "apache2ctl graceful"
}

fix_mysql_binding () {
	local HOST HOST_IP HOST_NAME
	HOST=${1}
	HOST_IP=$(echo ${HOST} | cut -d, -f1)
	HOST_NAME=$(echo ${HOST} | cut -d, -f2)
	green_echo "-> Fixing MySQL binding on ${HOST_NAME} my.cnf"
	sshi root@${HOST_IP} "sed -i 's/bind_address = .*/bind_address = ${HOST_IP}/' /etc/mysql/my.cnf"
}

fix_galera_cluster_name () {
	local HOST HOST_IP HOST_NAME
	HOST=${1}
	HOST_IP=$(echo ${HOST} | cut -d, -f1)
	HOST_NAME=$(echo ${HOST} | cut -d, -f2)
# Fix something like this:
#wsrep_cluster_name s1
#wsrep_node_address = 10.54.2.2
#wsrep_node_incoming_address = 10.54.2.2
#wsrep_node_name = ver1-controller-1.infomaniak.ch
#wsrep_sst_auth = backup:BLABLA
#wsrep_sst_method = mariabackup
#wsrep_sst_receive_address = 10.54.2.2
	green_echo "-> Fixing Galera cluster parameters on ${HOST_NAME} my.cnf"
	sshi root@${HOST_IP} "if ! grep -q wsrep_cluster_name /etc/mysql/my.cnf ; then . /usr/share/openstack-pkg-tools/pkgos_func ; pkgos_add_directive /etc/mysql/my.cnf mysqld wsrep_cluster_name '# name of cluster' '= '${CLUSTER_NAME} ; fi"
	sshi root@${HOST_IP} "if ! grep -q wsrep_node_address /etc/mysql/my.cnf ; then . /usr/share/openstack-pkg-tools/pkgos_func ; pkgos_add_directive /etc/mysql/my.cnf mysqld wsrep_node_address '# wsrep_node_address' '= '${HOST_IP} ; fi"
	sshi root@${HOST_IP} "if ! grep -q wsrep_node_incoming_address /etc/mysql/my.cnf ; then . /usr/share/openstack-pkg-tools/pkgos_func ; pkgos_add_directive /etc/mysql/my.cnf mysqld wsrep_node_incoming_address '# wsrep_node_incoming_address' '= '${HOST_IP} ; fi"
	sshi root@${HOST_IP} "if ! grep -q wsrep_node_name /etc/mysql/my.cnf ; then . /usr/share/openstack-pkg-tools/pkgos_func ; pkgos_add_directive /etc/mysql/my.cnf mysqld wsrep_node_name '# wsrep_node_name' '= '${HOST_NAME} ; fi"

	sshi root@${HOST_IP} "if ! grep -q wsrep_sst_receive_address /etc/mysql/my.cnf ; then . /usr/share/openstack-pkg-tools/pkgos_func ; pkgos_add_directive /etc/mysql/my.cnf mysqld wsrep_sst_receive_address '# wsrep_sst_receive_address' '= '${HOST_IP} ; fi"

	sshi root@${HOST_IP} ". /usr/share/openstack-pkg-tools/pkgos_func ; pkgos_inifile set /etc/mysql/my.cnf mysqld wsrep_sst_auth backup:BLABLA"
	sshi root@${HOST_IP} ". /usr/share/openstack-pkg-tools/pkgos_func ; pkgos_inifile set /etc/mysql/my.cnf mysqld wsrep_sst_method mariabackup"
}

mysql_cluster_restart (){
	local HOST_IP HOST_NAME
	green_echo "==> Stopping Galera cluster"
	for i in ${ALL_CTRL} ; do
		HOST_IP=$(echo ${i} | cut -d, -f1)
		HOST_NAME=$(echo ${i} | cut -d, -f2)
		green_echo "-> Stopping MySQL on ${HOST_NAME}"
		sshi root@${HOST_IP} "systemctl stop mysql"

		fix_galera_cluster_name ${i}
	done
	green_echo "==> Starting Galera cluster"
	CNT=0
	for i in ${ALL_CTRL_REVERT} ; do
		HOST_IP=$(echo ${i} | cut -d, -f1)
		HOST_NAME=$(echo ${i} | cut -d, -f2)
		if [ "${CNT}" = 0 ] ; then
			green_echo "-> running galera_new_cluster on ${HOST_NAME}"
			sshi root@${HOST_IP} "galera_new_cluster"
		else
			green_echo "-> starting mysql on ${HOST_NAME}"
			sshi root@${HOST_IP} "systemctl start mysql"
		fi
		CNT=$(( ${CNT} + 1 ))
	done
}

fix_missing_nf_conntrack () {
	local HOST HOST_IP HOST_NAME
	HOST=${1}
	HOST_IP=$(echo ${HOST} | cut -d, -f1)
	HOST_NAME=$(echo ${HOST} | cut -d, -f2)
	green_echo "-> fixing nf_conntrack autoload in /etc/modules-load.d/modules.conf on ${HOST_NAME}"
	if sshi ${HOST_IP} "grep -q nf_conntrack /etc/modules-load.d/modules.conf" ; then echo -n "" ; else sshi ${HOST_IP} "echo nf_conntrack >>/etc/modules-load.d/modules.conf"; fi
	sshi ${HOST_IP} "modprobe nf_conntrack"
}

install_missing_oci_utils () {
	local HOST HOST_IP HOST_NAME
	HOST=${1}
	HOST_IP=$(echo ${HOST} | cut -d, -f1)
	HOST_NAME=$(echo ${HOST} | cut -d, -f2)
	green_echo "-> Making sure /var/lib/oci-first-boot and /etc/rc.local are gone on ${HOST_NAME}"
	sshi ${HOST_IP} "rm -f /var/lib/oci-first-boot /etc/rc.local"
	green_echo "-> Installing openstack-cluster-installer-utils on ${HOST_NAME}"
	sshi ${HOST_IP} "apt-get update ; apt-get install openstack-cluster-installer-utils -y"
}

clean_iptables_input_chain () {
	local HOST HOST_IP HOST_NAME
	HOST=${1}
	HOST_IP=$(echo ${HOST} | cut -d, -f1)
	HOST_NAME=$(echo ${HOST} | cut -d, -f2)
	green_echo "-> Removing all iptables INPUT rules on ${HOST_NAME}"
	sshi ${HOST_IP} "iptables -F INPUT"
}

upgrade_all_controllers () {
	iterate_on_hosts "${ALL_CTRL}" install_openstack_pkg_tools
	grant_sql_access keystone
	grant_sql_access heat
	grant_sql_access barbican

	iterate_on_hosts "${ALL_CTRL}" fix_keystone_connection
	iterate_on_hosts "${ALL_CTRL}" fix_barbican_connection
	iterate_on_hosts "${ALL_CTRL}" fix_heat_connection
	iterate_on_hosts "${ALL_CTRL}" restart_apache_on_host

	iterate_on_hosts "${ALL_CTRL}" fix_mysql_binding
	mysql_cluster_restart

	iterate_on_hosts "${ALL_CTRL}" fix_missing_nf_conntrack
	iterate_on_hosts "${ALL_CTRL}" install_missing_oci_utils
	iterate_on_hosts "${ALL_CTRL}" clean_iptables_input_chain
}


upgrade_all_controllers
echo "Done, please run puppet on all 3 controllers now."
