#!/bin/bash

set -eEu -o pipefail

die() {
  local message="$*"

  echo "ERROR: ${message}" >&2
  exit 1
}

usage() {
  echo "
Tool to update the transport value for Corosync from 'udpu' to 'knet'

Usage: $0 [<option>...]

Options:
  -h|--help         This help.
  -a|--applied      Apply the change without committing anything new.
                    It is intented to be executed only after the management
                    node has been already updated.
"
}

APPLY=false
NGCP_TYPE="$(ngcpcfg get general.ngcp_type)"

for arg in "$@"; do
  case "$arg" in
    -h|--help)
      usage
      exit 0
      ;;
    -a|--applied)
      APPLY=true
      ;;
    *)
      echo "Invalid option."
      usage >&2
      exit 1
  esac
done

if ngcp-check-active -q; then
  die "This is the active node, please run this script on the standby one."
fi

if ! "${APPLY}"; then
  echo "INFO: Pulling pending configuration (if any)..."
  ngcpcfg pull

  if grep -q 'transport: udpu' /etc/ngcp-config/templates/etc/corosync/corosync.conf.tt2 ; then
    echo "INFO: 'transport: udpu' found in corosync.conf.tt2, updating transport to 'knet'."
    sed -i 's/transport: udpu/transport: knet/g' /etc/ngcp-config/templates/etc/corosync/corosync.conf.tt2
  else
    echo "INFO: 'transport: udpu' not found, nothing to do here. Exiting..."
    if [[ "${NGCP_TYPE}" == 'carrier' ]]; then
      echo "NOTE: If you already applied the change on the management node."
      echo "      Run 'ngcp-corosync-transport -a' on the other nodes."
    fi
    exit 1
  fi

  echo "INFO: Committing changes and pushing to shared storage..."
  ngcpcfg build
  ngcpcfg commit 'Update Corosync Transport from udpu to knet'
  ngcpcfg push --noapply
else
  echo "INFO: Pulling and building configuration from shared storage..."
  ngcp-parallel-ssh pair 'ngcpcfg pull && ngcpcfg build'
  if ! grep -q 'transport: knet' /etc/ngcp-config/templates/etc/corosync/corosync.conf.tt2 ; then
    echo "INFO: It seems that the transport is not yet updated to 'knet'."
    echo "      Please first run 'ngcp-corosync-transport' before adding '-a'."
    exit 1
  fi
  echo "INFO: Corosync Transport updated on cluster, continuing with service restart..."
fi

echo "Restarting Corosync on this cluster..."
ngcp-parallel-ssh pair 'ngcp-service restart corosync' >/dev/null

loops=1
max_loops=30
while true ; do
  if ngcp-parallel-ssh peer "ngcp-check-active -v" >/dev/null ; then
    echo  "INFO: Corosync is now stable."
    if [[ "${NGCP_TYPE}" == 'carrier' ]]; then
      echo  "INFO: You can proceed with the remaining nodes, if applicable."
    fi
    break
  else
    echo "INFO: Corosync is not yet stable, please wait..."
    loops=$((loops+1))
    if [ "$loops" -ge "$max_loops" ] ; then
      die "WARNING: Please fix Corosync service on this cluster before continuing with the other nodes."
    fi
  fi

  sleep 3
done

