#!/bin/bash

# This test checks if the systemd service for openipmi can properly start and
# stop openimpi in the same fashion the sysV init file does. For that, we rely
# on a LXD VM with an emulated BMC attached to it. Then, we infers which
# Ubuntu series is being tested by checking the host's series and launches a
# LXD VM using that same series.
# Then, we ensure that the same openipmi binaries available for the host are
# installed in the VM (the VM will be configured with the default pockets, but
# the test environment may enable proposed or inject binary packages.
# Since the VM must install packages, it needs networking capabilities to be up
# before we start processing our setup.

set -euo pipefail

VM_NAME=openipmi-systemd-test
SERIES=$(lsb_release  -cs)
LXD_BIN=lxc

cleanup() {
  $LXD_BIN delete -f $VM_NAME
  rm -rf tmp_debs
}

backoff() {
  BACKOFF_ATTEMPT=$1
  ERROR_MSG=$2
  BACKOFF_FACTOR=2
  MAX_ATTEMPTS=7
  if [ "$BACKOFF_ATTEMPT" -ge "$MAX_ATTEMPTS" ]; then
    echo "$ERROR_MSG"
    exit 1
  fi
  sleep $((BACKOFF_ATTEMPT ** BACKOFF_FACTOR))
}

trap cleanup EXIT

snap install lxd 2>&1
lxd init --auto
$LXD_BIN init --vm ubuntu-daily:"$SERIES" "$VM_NAME"
$LXD_BIN config set $VM_NAME raw.qemu -- "-device ipmi-bmc-sim,id=bmc0 -device isa-ipmi-kcs,bmc=bmc0,ioport=0xca2"
$LXD_BIN start $VM_NAME

# We are skipping this for now since it is somehow redundant with the next  check.
# To drop this, we bumped the backoff MAX_ATTEMPTS from 6 to 7.
# We are leaving the snippet as a comment in case it can aid future enhancements/debugging.
#echo "Waiting for LXD VM to be ready..."
#ATTEMPT=0
#while $LXD_BIN info $VM_NAME | grep -q 'Processes: -1'; do
  #backoff "$ATTEMPT" "TIMEOUT ERROR: Could not set LXD VM up"
  #ATTEMPT=$((ATTEMPT + 1))
#done

echo "Waiting for LXD vm network to be up..."
ATTEMPT=0
while ! $LXD_BIN exec $VM_NAME -- apt-get update -o 'APT::Update::Error-Mode=any' -qq 2>&1; do
  backoff "$ATTEMPT" "TIMEOUT ERROR: Networking not available"
  ATTEMPT=$((ATTEMPT + 1))
done

# The openipmi package installed in the VM must be the same one available in the test environment
mkdir tmp_debs
pushd tmp_debs
apt-get download openipmi 2>&1
# Also get the relevant libopenipmi package
LIB_OPENIPMI=$(dpkg-deb -W --showformat='${Depends}\n' ./openipmi_*.deb | grep -Eo 'libopenipmi[^ ]+')
apt-get download "$LIB_OPENIPMI" 2>&1
$LXD_BIN exec $VM_NAME -- mkdir -p /tmp/tmp_debs
$LXD_BIN file push ./*.deb $VM_NAME/tmp/tmp_debs/
popd

$LXD_BIN exec $VM_NAME -- bash -c "apt-get install -y ipmitool /tmp/tmp_debs/*.deb" 2>&1
$LXD_BIN exec $VM_NAME -- modprobe ipmi_devintf
$LXD_BIN exec $VM_NAME -- modprobe ipmi_si

ATTEMPT=0
while ! $LXD_BIN exec $VM_NAME -- test -e /dev/ipmi0; do
  backoff "$ATTEMPT" "TIMEOUT ERROR: /dev/ipmi0 not available after modprobe calls"
  ATTEMPT=$((ATTEMPT + 1))
done

printf "TEST systemd service started: "
$LXD_BIN exec $VM_NAME -- systemctl start openipmi.service
$LXD_BIN exec $VM_NAME -- ipmitool -I open mc info | grep -q 'Device Available'
echo OK
printf "TEST systemd service stopped: "
$LXD_BIN exec $VM_NAME -- systemctl stop openipmi.service
$LXD_BIN exec $VM_NAME -- ipmitool -I open mc info > /dev/null 2>&1 && echo FAIL && exit 1 || echo OK
