#!/bin/bash
#
# linuxmuster-opsi configuration script
#
# thomas@linuxmuster.net
# 20170719
# GPL v3
#

# read linuxmuster.net settings
. /usr/share/linuxmuster/config/dist.conf || exit 1
. $HELPERFUNCTIONS || exit 1

# parsing parameters
getopt $*

header(){
 [ -n "$quiet" ] && return 0
 local opt="$1"
 local msg="# linuxmuster-opsi $opt # $(date)"
 local chars="$(echo "$msg" | wc -m)"
 echo
 seq -s"#" $chars | tr -d '[:digit:]'
 echo "$msg"
 seq -s"#" $chars | tr -d '[:digit:]'
 echo
}

usage() {
  header "usage"
  echo "linuxmuster-opsi --setup [--password=<password>]"
  echo "                         [--opsiip=<opsiip>]"
  echo "                         [--first]"
  echo "                         [--reboot]"
  echo "                 --disable"
  echo "                 --wsimport"
  echo "                 --quiet"
  echo "                 --help"
  echo
  echo "  setup:      Starts linuxmuster.net specific OPSI support setup."
  echo "              It does an initial setup of passwordless ssh"
  echo "              connection to OPSI server first."
  echo "              If password is not given it will be asked."
  echo "  opsiip:     Set ip address of opsi machine. If not set it will be"
  echo "              derived from setup values or serverip (e.g. 10.16.1.2)."
  echo "  first:      Force creation of certificates on opsi server."
  echo "              To be used for initial setup."
  echo "  reboot:     Reboots opsi server."
  echo "  disable:    Disables OPSI support."
  echo "  wsimport:   Import workstations on OPSI host."
  echo "  quiet:      Minimal console output."
  echo "  help:       Shows this help"
  echo
  exit 1
}

# test parameters
[ -n "$help" ] && usage
[ -z "$disable" -a -z "$setup" -a -z "$wsimport" ] && usage
[ -n "$disable" -a -n "$wsimport" ] && usage
[ -n "$setup" -a -n "$wsimport" ] && usage
[ -n "$disable" -a -n "$setup" ] && usage

# get action
[ -n "$disable" ] && action="disable"
[ -n "$setup" ] && action="setup"
[ -n "$wsimport" ] && action="wsimport"

# print script header
header "$action"

# check if i am already running
mypid=$$
if [ -n "$wsimport" ]; then
 mypidfile="/var/run/linuxmuster-opsi-$action.pid"
else
 mypidfile="/var/run/linuxmuster-opsi-setup.pid"
fi
if [ -e "$mypidfile" ]; then
 echo "There is already an linuxmuster-opsi process running! Exiting!"
 echo "If this is not correct you have to delete $mypidfile!"
 exit 0
fi
echo "$mypid" > $mypidfile

# if opsiip is not set derive it from serverip
[ -z "$opsiip" ] && opsiip="${serverip/.1.1/.1.2}"
validip "$opsiip" || bailout "Opsi ip $opsiip is not valid!"

# exit if error occurs
bailout(){
 local msg="$1"
 echo "$msg"
 rm -f $mypidfile
 exit 1
}

# update opsi entry in workstations file
update_wimportdata(){
  # get mac address from arp
  local opsimac="$(LANG=C arp -a | grep -w "$opsiip" | awk '{ print $4 }' | tr a-z A-Z)"
  if [ -z "$opsimac" ]; then
    echo "Cannot get mac address of opsi machine. Skipping workstations update!"
    return 1
  fi
  # get opsi entry line
  local opsiline="$(grep -w "$opsiip" "$WIMPORTDATA" | grep ^[a-zA-Z0-9] | grep -i \;opsi\;)"
  if [ -n "$opsiline" ]; then
    # create new line with investigated mac address
    local opsiline_new="$(echo "$opsiline" | sed -e 's|\([0-9a-fA-F][0-9a-fA-F]:\)\{5\}[0-9a-fA-F][0-9a-fA-F]|'"$opsimac"'|')"
    # write new line if differs
    if [ "$opsiline" != "$opsiline_new" ]; then
      cp "$WIMPORTDATA" "$WIMPORTDATA".opsi-bak
      sed -e 's|^'"$opsiline"'|'"$opsiline_new"'|' "$WIMPORTDATA".opsi-bak > "$WIMPORTDATA"
      echo "Modified workstations entry for opsi. Please check it and run import_workstations when convenient!"
    fi
  else
    echo "Creating workstations entry for opsi. Please check it and run import_workstations when convenient!"
    cp "$WIMPORTDATA" "$WIMPORTDATA".opsi-bak
    echo "# line created by linuxmuster-opsi" >> "$WIMPORTDATA"
    echo "servers;opsi;x;$opsimac;$opsiip;;;;1;1;0;0" >> "$WIMPORTDATA"
  fi
}

# test connection to opsi vm
test_connection(){
  ping -c2 -q "$opsiip" &> /dev/null || bailout "Connection to opsi not available!"
}

# setup
do_setup(){
  # test if opsi appliance is online
  test_connection
  # test & update opsi entry in workstations file
  update_wimportdata
  # update opsi debconf value
  local status="$(debconf-show linuxmuster-base | grep /opsi | awk -F\: '{ print $2 }' | awk '{ print $1 }')"
  if [ "$status" != "true" ]; then
    echo "Updating debconf variable."
    status="true"
    echo "set linuxmuster-base/opsi $status" | debconf-communicate || bailout "Debconf update failed!"
  else
    echo "Debconf variable already set."
  fi
  # save opsi ip
  if grep -q ^opsiip "$NETWORKSETTINGS"; then
    sed -i "s|^opsiip=.*|opsiip=\"$opsiip\"|" "$NETWORKSETTINGS"
  else
    echo "opsiip=\"$opsiip\"" >> "$NETWORKSETTINGS"
  fi

  # setup ssh connection
  ssh-keygen -f "/root/.ssh/known_hosts" -R "$opsiip"
  if ! test_pwless_opsi; then
    echo "Setting up passwordless ssh connection."
    if [ -z "$password" -a -z "$unattended" ]; then
      echo
      stty -echo
      read -p "Please enter OPSI's root password: " password; echo
      stty echo
    fi
    [ -z "$password" -a -z "$unattended" ] && bailout "No password given!"
    mykey="$(cat /root/.ssh/id_ecdsa.pub)"
    [ -z "$mykey" ] && bailout "No ssh key available!"
    if [ -s /root/.ssh/known_hosts ]; then
      ssh-keygen -f /root/.ssh/known_hosts -R "$opsiip" &> /dev/null
      ssh-keygen -f /root/.ssh/known_hosts -R opsi &> /dev/null
    fi
    # upload root's public key
    echo "$password" | "$SCRIPTSDIR/sshaskpass.sh" ssh -oStrictHostKeyChecking=no "$opsiip" "mkdir -p /root/.ssh && echo "$mykey" >> /root/.ssh/authorized_keys"
    # test passwordless ssh connection again
    test_pwless_opsi || bailout "Aborting!"
    echo
  fi

  # upload settings file
  rsync "$NETWORKSETTINGS" "$opsiip":"$OPSILMNSETTINGS" || bailout "Upload of settings failed!"

  # do setup on opsi server
  OPSISETUP="$OPSISETUP --quiet"
  [ -n "$first" ] && OPSISETUP="$OPSISETUP --first"
  [ -n "$reboot" ] && OPSISETUP="$OPSISETUP --reboot"
  ssh "$opsiip" $OPSISETUP || bailout "Setup on opsi server failed!"
  ssh-keygen -f "/root/.ssh/known_hosts" -R "$opsiip"
  test_pwless_opsi
}

# disable
do_disable(){
 # debconf
 echo "Unsetting debconf variable."
 echo "set linuxmuster-base/opsi false" | debconf-communicate || bailout "Debconf update failed!"
 echo "Removing ip address."
 ssh-keygen -f "/root/.ssh/known_hosts" -R "$opsiip"
 ssh-keygen -f "/root/.ssh/known_hosts" -R opsi
 if grep -q ^opsiip "$NETWORKSETTINGS"; then
  sed -e "s|^opsiip=.*|opsiip=\"\"|" -i "$NETWORKSETTINGS" || bailout "Debconf update failed!"
 else
  echo "opsiip=\"\"" >> "$NETWORKSETTINGS" || bailout "Debconf update failed!"
 fi
}

# wsimport
do_wsimport(){
 test_connection
 echo "Processing opsi workstations:"
 # upload workstations file
 rsync "$WIMPORTDATA" "$opsiip:$OPSIWSDATA"
 # execute script
 ssh "$opsiip" $OPSIWSIMPORT --quiet
 # download opsi host keys
 rsync "$opsiip:$OPSIPCKEYS" "$LINBOOPSIKEYS"
 chmod 600 "$LINBOOPSIKEYS"
}

case "$action" in

 setup) do_setup ;;
 disable) do_disable ;;
 wsimport) do_wsimport ;;
 *) ;;

esac

header "$action"
echo


# delete pid file
rm -f $mypidfile

exit 0
