#!/bin/sh

set -e

echo "===> Fetching cluster infos"
CLUSTER_NAME=$(ocicli -csv cluster-list | q -H -d, "SELECT name FROM -" | head -n 1)
DOMAIN_NAME=$(ocicli -csv cluster-list | q -H -d, "SELECT domain FROM -" | head -n 1)
SELF_SIGNED_API_CERT=$(ocicli -csv cluster-show ${CLUSTER_NAME} | grep "Self signed API cert:" | cut -d, -f2)
API_HOSTNAME=$(ocicli -csv cluster-show ${CLUSTER_NAME}  | grep "VIP Hostname:" | cut -d, -f2)
if echo "${API_HOSTNAME}" | grep -q -E "^default " ; then
        API_HOSTNAME=${CLUSTER_NAME}-api.${DOMAIN_NAME}
fi

TMP=$(mktemp)
ocicli -csv machine-list -a >${TMP}
ALL_HOSTS=$(cat ${TMP} | q -H -d, "SELECT hostname,Cur_ip FROM - WHERE hostname!='-' AND status='installed'")
CTRL_HOSTS=$(cat ${TMP} | q -H -d, "SELECT hostname,Cur_ip FROM - WHERE hostname!='-' AND role='controller' AND status='installed'")
MSG_HOSTS=$(cat ${TMP} | q -H -d, "SELECT hostname,Cur_ip FROM - WHERE hostname!='-' AND role='messaging' AND status='installed'")
PRX_HOSTS=$(cat ${TMP} | q -H -d, "SELECT hostname,Cur_ip FROM - WHERE hostname!='-' AND role='swiftproxy' AND status='installed'")
COMP_HOSTS=$(cat ${TMP} | q -H -d, "SELECT hostname,Cur_ip FROM - WHERE hostname!='-' AND role='compute' AND status='installed'")
VOL_HOSTS=$(cat ${TMP} | q -H -d, "SELECT hostname,Cur_ip FROM - WHERE hostname!='-' AND role='volume' AND status='installed'")
NET_HOSTS=$(cat ${TMP} | q -H -d, "SELECT hostname,Cur_ip FROM - WHERE hostname!='-' AND role='network' AND status='installed'")
rm -f ${TMP}


CTRL_HOSTS_REV=
for i in $CTRL_HOSTS; do
        CTRL_HOSTS_REV="$i $CTRL_HOSTS_REV"
done

update_oci_utils_on_all_hosts () {
        echo "===> Update oci-utils everywhere"
        for HOST in ${ALL_HOSTS} ; do
                HOSTNAME=$(echo $HOST | cut -d, -f1)
                IP=$(echo $HOST | cut -d, -f2)
                echo "-> Re-installing openstack-cluster-installer-utils on ${HOSTNAME}"
                SSH_AUTH_SOCK= ssh -i /etc/openstack-cluster-installer/id_rsa root@${IP} "apt-get update && apt-get install openstack-cluster-installer-utils openstack-cluster-installer-common --reinstall -y"
        done
}

delete_intermediary_ca_on_oci_host () {
        echo "===> Deleting oci-ca"
        rm -f /var/lib/oci/ssl/ca/oci-pki-oci-ca-chain.pem
        rm -f /var/lib/oci/ssl/ca/oci-pki-oci-ca.pem

        rm -rf /etc/openstack-cluster-installer/pki/ca/oci-ca
        rm -f /etc/openstack-cluster-installer/pki/ca/oci-ca-chain.pem
        rm -f /etc/openstack-cluster-installer/pki/ca/oci-ca.crt
        rm -f /etc/openstack-cluster-installer/pki/ca/oci-ca.csr
}

delete_all_server_certs () {
        echo "===> Deleting self-signed API certs"
        if [ "${SELF_SIGNED_API_CERT}" = "yes" ] ; then
                for KEYMATERIAL in .crt .csr .key .pem ; do
                        rm -f /var/lib/oci/ssl/slave-nodes/${API_HOSTNAME}/${API_HOSTNAME}${KEYMATERIAL}
                done
        fi
        echo "===> Deleting all server certs"
        for HOST in ${ALL_HOSTS} ${DEL_API} ; do
                HOSTNAME=$(echo $HOST | cut -d, -f1)
                echo "-> $HOSTNAME"
                for KEYMATERIAL in .crt .csr .key .pem _client.crt _client.csr _client.key _client.pem ; do
                        rm -f /var/lib/oci/ssl/slave-nodes/${HOSTNAME}/${HOSTNAME}${KEYMATERIAL}
                done
        done
}

gen_api_cert () {
        ISTHERE=yes
        for KEYMATERIAL in .crt .csr .key .pem ; do
                if [ ! -e /var/lib/oci/ssl/slave-nodes/${API_HOSTNAME}/${API_HOSTNAME}${KEYMATERIAL} ] ; then
                        ISTHERE=no
                fi
        done
        if [ "${ISTHERE}" = "no" ] ; then
                oci-gen-slave-node-cert ${API_HOSTNAME}
        fi
}

run_puppet_on_ctrls () {
        echo "===> Running puppet on all controllers"
        for HOST in ${CTRL_HOSTS} ; do
                HOSTNAME=$(echo $HOST | cut -d, -f1)
                IP=$(echo $HOST | cut -d, -f2)
                echo "-> Running puppet on ${HOSTNAME}"
                SSH_AUTH_SOCK= ssh -i /etc/openstack-cluster-installer/id_rsa root@${IP} "puppet agent --enable && oci-puppet || true"
                SSH_AUTH_SOCK= ssh -i /etc/openstack-cluster-installer/id_rsa root@${IP} "oci-restart-all-services"
                SSH_AUTH_SOCK= ssh -i /etc/openstack-cluster-installer/id_rsa root@${IP} "/etc/init.d/haproxy restart"
        done
}

run_puppet_on_msgs () {
        echo "===> Running puppet on all messagings"
        for HOST in ${MSG_HOSTS} ; do
                HOSTNAME=$(echo $HOST | cut -d, -f1)
                IP=$(echo $HOST | cut -d, -f2)
                echo "-> Running puppet on ${HOSTNAME}"
                SSH_AUTH_SOCK= ssh -i /etc/openstack-cluster-installer/id_rsa root@${IP} "puppet agent --enable && oci-puppet || true"
        done
}

run_puppet_on_swiftproxies () {
        echo "===> Running puppet on all swift proxies"
        for HOST in ${PRX_HOSTS} ; do
                HOSTNAME=$(echo $HOST | cut -d, -f1)
                IP=$(echo $HOST | cut -d, -f2)
                echo "-> Running puppet on ${HOSTNAME}"
                SSH_AUTH_SOCK= ssh -i /etc/openstack-cluster-installer/id_rsa root@${IP} "puppet agent --enable && oci-puppet || true"
        done
}

restart_rabbitmq_on_controllers (){
        echo "===> Restarting rabbitmq on all controllers"
        for HOST in ${CTRL_HOSTS} ; do
                HOSTNAME=$(echo $HOST | cut -d, -f1)
                IP=$(echo $HOST | cut -d, -f2)
                echo "-> Running rabbitmqctl stop_app on ${HOSTNAME}"
                SSH_AUTH_SOCK= ssh -i /etc/openstack-cluster-installer/id_rsa root@${IP} "rabbitmqctl stop_app"
        done
        for HOST in ${CTRL_HOSTS} ; do
                HOSTNAME=$(echo $HOST | cut -d, -f1)
                IP=$(echo $HOST | cut -d, -f2)
                echo "-> Stopping rabbitmq-server service on ${HOSTNAME}"
                SSH_AUTH_SOCK= ssh -i /etc/openstack-cluster-installer/id_rsa root@${IP} "/etc/init.d/rabbitmq-server stop"
        done
        for HOST in ${CTRL_HOSTS_REV} ; do
                HOSTNAME=$(echo $HOST | cut -d, -f1)
                IP=$(echo $HOST | cut -d, -f2)
                echo "-> Starting rabbitmq-server service on ${HOSTNAME}"
                SSH_AUTH_SOCK= ssh -i /etc/openstack-cluster-installer/id_rsa root@${IP} "/etc/init.d/rabbitmq-server start"
        done
        for HOST in ${CTRL_HOSTS_REV} ; do
                HOSTNAME=$(echo $HOST | cut -d, -f1)
                IP=$(echo $HOST | cut -d, -f2)
                echo "-> Running rabbitmqctl start_app on ${HOSTNAME}"
                SSH_AUTH_SOCK= ssh -i /etc/openstack-cluster-installer/id_rsa root@${IP} "rabbitmqctl start_app"
        done
}

restart_haproxy_on_all_controllers () {
        echo "===> Restarting haproxy on all controllers"
        for HOST in ${CTRL_HOSTS} ; do
                HOSTNAME=$(echo $HOST | cut -d, -f1)
                IP=$(echo $HOST | cut -d, -f2)
                echo "-> Restarting haproxy service on ${HOSTNAME}"
                SSH_AUTH_SOCK= ssh -i /etc/openstack-cluster-installer/id_rsa root@${IP} "/etc/init.d/haproxy restart"
        done
}

restart_all_service_on_controllers () {
        echo "===> Restarting all openstack services on all controllers"
        for HOST in ${CTRL_HOSTS} ; do
                HOSTNAME=$(echo $HOST | cut -d, -f1)
                IP=$(echo $HOST | cut -d, -f2)
                echo "-> Restarting all OpenStack services on ${HOSTNAME}"
                SSH_AUTH_SOCK= ssh -i /etc/openstack-cluster-installer/id_rsa root@${IP} "oci-restart-all-services"
        done
}

restart_all_service_on_messagings () {
        echo "===> Restarting all openstack services on all messagings"
        for HOST in ${MSG_HOSTS} ; do
                HOSTNAME=$(echo $HOST | cut -d, -f1)
                IP=$(echo $HOST | cut -d, -f2)
                echo "-> Restarting all OpenStack services on ${HOSTNAME}"
                SSH_AUTH_SOCK= ssh -i /etc/openstack-cluster-installer/id_rsa root@${IP} "oci-restart-all-services"
        done
}

run_puppet_on_all_computes () {
        echo "===> Run puppet and restart all services on all compute nodes"
        for HOST in ${COMP_HOSTS} ; do
                HOSTNAME=$(echo $HOST | cut -d, -f1)
                IP=$(echo $HOST | cut -d, -f2)
                echo "-> Run puppet on ${HOSTNAME}"
                SSH_AUTH_SOCK= ssh -i /etc/openstack-cluster-installer/id_rsa root@${IP} "puppet agent --enable && oci-puppet || true"
                echo "-> Restart all services on ${HOSTNAME}"
                SSH_AUTH_SOCK= ssh -i /etc/openstack-cluster-installer/id_rsa root@${IP} "oci-restart-all-services"
                echo "-> Start libvirt over TLS on ${HOSTNAME}"
                SSH_AUTH_SOCK= ssh -i /etc/openstack-cluster-installer/id_rsa root@${IP} "systemctl enable libvirtd-tls.socket && systemctl disable libvirtd-tcp.socket && systemctl stop libvirtd.service && systemctl start libvirtd-tls.socket && systemctl start libvirtd.service"
        done
}

run_puppet_on_all_network_nodes () {
        echo "===> Run puppet and restart all services on all network nodes"
        for HOST in ${NET_HOSTS} ; do
                HOSTNAME=$(echo $HOST | cut -d, -f1)
                IP=$(echo $HOST | cut -d, -f2)
                echo "-> Run puppet on ${HOSTNAME}"
                SSH_AUTH_SOCK= ssh -i /etc/openstack-cluster-installer/id_rsa root@${IP} "puppet agent --enable && oci-puppet || true"
                echo "-> Restart all services on ${HOSTNAME}"
                SSH_AUTH_SOCK= ssh -i /etc/openstack-cluster-installer/id_rsa root@${IP} "oci-restart-all-services"
        done
}

run_puppet_on_all_volumes () {
        echo "===> Run puppet and restart all services on all volume nodes"
        for HOST in ${VOL_HOSTS} ; do
                HOSTNAME=$(echo $HOST | cut -d, -f1)
                IP=$(echo $HOST | cut -d, -f2)
                echo "-> Run puppet on ${HOSTNAME}"
                SSH_AUTH_SOCK= ssh -i /etc/openstack-cluster-installer/id_rsa root@${IP} "puppet agent --enable && oci-puppet || true"
                echo "-> Restart all services on ${HOSTNAME}"
                SSH_AUTH_SOCK= ssh -i /etc/openstack-cluster-installer/id_rsa root@${IP} "oci-restart-all-services"
        done
}

enable_puppet_on_all_hosts () {
        echo "===> Enabling puppet on all hosts"
        for HOST in ${ALL_HOSTS} ; do
                HOSTNAME=$(echo $HOST | cut -d, -f1)
                IP=$(echo $HOST | cut -d, -f2)
                echo "-> $HOSTNAME"
                SSH_AUTH_SOCK= ssh -i /etc/openstack-cluster-installer/id_rsa root@${IP} "puppet agent --enable"
                echo "-> Restart all services on ${HOSTNAME}"
                SSH_AUTH_SOCK= ssh -i /etc/openstack-cluster-installer/id_rsa root@${IP} "oci-restart-all-services"
        done
}

upgrade_oci_host () {
        apt-get update
        apt-get dist-upgrade -y
        MYCURDIR=$(pwd)
        cd /usr/share/openstack-cluster-installer
        php db_sync.php
        cd ${MYCURDIR}
        /etc/init.d/puppet-master restart
        ocicli cluster-set ${CLUSTER_NAME} --install-designate no --install-octavia yes --initial-cluster-setup yes
}

switch_to_bullseye_victoria () {
        if [ -e /etc/apt/sources.list.d/openstack.list ] ; then
                sed -i s/pub1-repo.infomaniak.ch/bullseye-victoria.debian.net/ /etc/apt/sources.list.d/openstack.list
                apt-get update
        fi
}

install_old_root_ca_on_all_hosts () {
        echo "===> Copying old root CA to /usr/share/ca-certificates/oci-old in all hosts"
        for HOST in ${ALL_HOSTS} ; do
                HOSTNAME=$(echo $HOST | cut -d, -f1)
                IP=$(echo $HOST | cut -d, -f2)
                echo "-> $HOSTNAME"
                SSH_AUTH_SOCK= ssh -i /etc/openstack-cluster-installer/id_rsa root@${IP} "mkdir -p /usr/share/ca-certificates/oci-old"
                SSH_AUTH_SOCK= scp -i /etc/openstack-cluster-installer/id_rsa /var/lib/oci/ssl/ca/oci-pki-root-ca.pem root@${IP}:/usr/share/ca-certificates/oci-old/OCI_old_1_selfsigned-root-ca.crt
                SSH_AUTH_SOCK= scp -i /etc/openstack-cluster-installer/id_rsa /var/lib/oci/ssl/ca/oci-pki-oci-ca.pem root@${IP}:/usr/share/ca-certificates/oci-old/OCI_old_2_oci-ca.crt
                SSH_AUTH_SOCK= ssh -i /etc/openstack-cluster-installer/id_rsa root@${IP} "if ! grep -q -E ^oci-old/OCI_old_1_selfsigned-root-ca.crt /etc/ca-certificates.conf; then echo oci-old/OCI_old_1_selfsigned-root-ca.crt >> /etc/ca-certificates.conf ; fi"
                SSH_AUTH_SOCK= ssh -i /etc/openstack-cluster-installer/id_rsa root@${IP} "if ! grep -q -E ^oci-old/OCI_old_2_oci-ca.crt /etc/ca-certificates.conf; then echo oci-old/OCI_old_2_oci-ca.crt >> /etc/ca-certificates.conf ; fi"
                SSH_AUTH_SOCK= ssh -i /etc/openstack-cluster-installer/id_rsa root@${IP} "update-ca-certificates"
        done 
}

install_new_root_ca_on_all_hosts () {
        echo "===> Copying new root CA to /usr/share/ca-certificates/oci in all hosts"
        for HOST in ${ALL_HOSTS} ; do
                HOSTNAME=$(echo $HOST | cut -d, -f1)
                IP=$(echo $HOST | cut -d, -f2)
                echo "-> $HOSTNAME"
                SSH_AUTH_SOCK= ssh -i /etc/openstack-cluster-installer/id_rsa root@${IP} "mkdir -p /usr/share/ca-certificates/oci"
                SSH_AUTH_SOCK= scp -i /etc/openstack-cluster-installer/id_rsa /var/lib/oci/ssl/ca/oci-pki-root-ca.pem root@${IP}:/usr/share/ca-certificates/oci/OCI_1_selfsigned-root-ca.crt
                SSH_AUTH_SOCK= scp -i /etc/openstack-cluster-installer/id_rsa /var/lib/oci/ssl/ca/oci-pki-oci-ca.pem root@${IP}:/usr/share/ca-certificates/oci/OCI_2_oci-ca.crt
                SSH_AUTH_SOCK= ssh -i /etc/openstack-cluster-installer/id_rsa root@${IP} "if ! grep -q -E ^oci/OCI_1_selfsigned-root-ca.crt /etc/ca-certificates.conf; then echo oci/OCI_1_selfsigned-root-ca.crt >> /etc/ca-certificates.conf ; fi"
                SSH_AUTH_SOCK= ssh -i /etc/openstack-cluster-installer/id_rsa root@${IP} "if ! grep -q -E ^oci/OCI_2_oci-ca.crt /etc/ca-certificates.conf; then echo oci/OCI_2_oci-ca.crt >> /etc/ca-certificates.conf ; fi"
                SSH_AUTH_SOCK= ssh -i /etc/openstack-cluster-installer/id_rsa root@${IP} "update-ca-certificates"
        done
}

remove_old_root_ca_on_all_hosts () {
        echo "===> Remove old root CA in /usr/share/ca-certificates/oci-old in all hosts"
        for HOST in ${ALL_HOSTS} ; do
                HOSTNAME=$(echo $HOST | cut -d, -f1)
                IP=$(echo $HOST | cut -d, -f2)
                echo "-> $HOSTNAME"
                SSH_AUTH_SOCK= ssh -i /etc/openstack-cluster-installer/id_rsa root@${IP} "rm -rf /usr/share/ca-certificates/oci-old"
                SSH_AUTH_SOCK= ssh -i /etc/openstack-cluster-installer/id_rsa root@${IP} "set -x ; sed -i '/^oci-old\\/OCI_old_1_selfsigned-root-ca.crt/d' /etc/ca-certificates.conf"
                SSH_AUTH_SOCK= ssh -i /etc/openstack-cluster-installer/id_rsa root@${IP} "set -x ; sed -i '/^oci-old\\/OCI_old_2_oci-ca.crt/d' /etc/ca-certificates.conf"
                SSH_AUTH_SOCK= ssh -i /etc/openstack-cluster-installer/id_rsa root@${IP} "update-ca-certificates"
        done
}

remove_rabbitmq_ssl_ca_file () {
        echo "===> Remove location of CA in /etc/neutron/neutron.conf"
        for HOST in ${CTRL_HOSTS} ${COMP_HOSTS} ; do
                HOSTNAME=$(echo $HOST | cut -d, -f1)
                IP=$(echo $HOST | cut -d, -f2)
                echo "-> CA location remove on ${HOSTNAME}"
                #SSH_AUTH_SOCK= ssh -i /etc/openstack-cluster-installer/id_rsa root@${IP} "sed -i '/^ssl_ca_file=.*/d' /etc/neutron/neutron.conf"

                SSH_AUTH_SOCK= ssh -i /etc/openstack-cluster-installer/id_rsa root@${IP} "sed -i 's@ssl_ca_file=/etc/ssl/certs/oci-pki-oci-ca-chain.pem@ssl_ca_file=/etc/ssl/certs/ca-certificates.crt@g' /etc/neutron/neutron.conf"
                echo "-> restarting all neutron services on ${HOSTNAME}"
                SSH_AUTH_SOCK= ssh -i /etc/openstack-cluster-installer/id_rsa root@${IP} "systemctl restart 'neutron-*'"
                echo "-> Wait 5 secondes after neutron restart on ${HOSTNAME}"
                sleep 5
        done


        for HOST in ${NET_HOSTS} ; do
                HOSTNAME=$(echo $HOST | cut -d, -f1)
                IP=$(echo $HOST | cut -d, -f2)
                echo "-> CA location remove on ${HOSTNAME}"
                SSH_AUTH_SOCK= ssh -i /etc/openstack-cluster-installer/id_rsa root@${IP} "sed -i 's@ssl_ca_file=/etc/ssl/certs/oci-pki-oci-ca-chain.pem@ssl_ca_file=/etc/ssl/certs/ca-certificates.crt@g' /etc/neutron/neutron.conf"

                #echo "-> restarting all neutron services on ${HOSTNAME}"
                #SSH_AUTH_SOCK= ssh -i /etc/openstack-cluster-installer/id_rsa root@${IP} "systemctl restart neutron-dhcp-agent.service; systemctl restart neutron-metadata-agent.service; systemctl restart neutron-openvswitch-agent.service; systemctl restart neutron-l3-agent.service "
                #SSH_AUTH_SOCK= ssh -i /etc/openstack-cluster-installer/id_rsa root@${IP} "systemctl show --property MainPID --value neutron-bgp-dragent.service | xargs kill -SIGHUP"
                #echo "-> Wait 5 secondes after neutron restart on ${HOSTNAME}"         #sleep 5
        done
}

# Prepare the upgrade
oci-disable-puppet
update_oci_utils_on_all_hosts

# Switch to bullseye-victoria instead of pub1-repo.
# Note: this is only for the PoC, but shouldn't be a problem
# for production.
switch_to_bullseye_victoria

# Upgrade OCI
upgrade_oci_host

# Install the old root ca
install_old_root_ca_on_all_hosts

# Remake the PKI
delete_intermediary_ca_on_oci_host
oci-root-ca-destroy
oci-root-ca-gen

install_new_root_ca_on_all_hosts

remove_rabbitmq_ssl_ca_file

delete_all_server_certs
gen_api_cert


# Apply on controllers & messaging
run_puppet_on_ctrls
run_puppet_on_msgs

# Apply on swift proxies
run_puppet_on_swiftproxies

restart_rabbitmq_on_controllers

restart_haproxy_on_all_controllers
restart_all_service_on_controllers
restart_all_service_on_messagings

#
# Apply on all servers
#run_puppet_on_all_network_nodes
run_puppet_on_all_computes
run_puppet_on_all_volumes

remove_old_root_ca_on_all_hosts

oci-enable-puppet
ocicli cluster-set ${CLUSTER_NAME} --initial-cluster-setup no
