#!/bin/bash

set -e

LIBDIR="@LOCALSTATEDIR@/lib"
DATADIR="${LIBDIR}/ganeti"
RUNDIR="@LOCALSTATEDIR@/run"
GNTRUNDIR="${RUNDIR}/ganeti"
LOGDIR="@LOCALSTATEDIR@/log"
GNTLOGDIR="${LOGDIR}/ganeti"
LOCKDIR="@LOCALSTATEDIR@/lock"

_fileset_owner() {
  case "$1" in
    masterd)
      echo "@GNTMASTERUSER@:@GNTMASTERDGROUP@"
      ;;
    confd)
      echo "@GNTCONFDUSER@:@GNTCONFDGROUP@"
      ;;
    rapi)
      echo "@GNTRAPIUSER@:@GNTRAPIGROUP@"
      ;;
    noded)
      echo "root:@GNTMASTERDGROUP@"
      ;;
    daemons)
      echo "@GNTMASTERUSER@:@GNTDAEMONSGROUP@"
      ;;
    masterd-confd)
      echo "@GNTMASTERUSER@:@GNTCONFDGROUP@"
      ;;
    *)
      echo "root:root"
      ;;
  esac
}

_ensure_file() {
  local file="$1"
  local perm="$2"
  local owner="$3"

  [[ -e "${file}" ]] || return 1
  chmod ${perm} "${file}"

  if ! [[ -z "${owner}" ]]; then
    chown ${owner} "${file}"
  fi

  return 0
}

_ensure_dir() {
  local dir="$1"
  local perm="$2"
  local owner="$3"

  [[ -d "${dir}" ]] || mkdir "${dir}"

  _ensure_file "${dir}" "${perm}" "${owner}"
}

_gather_files() {
  local path="$1"
  local perm="$2"
  local user="$3"
  local group="$4"

  shift 4

  find "${path}" -type f "(" "!" -perm ${perm} -or "(" "!" -user ${user} -or \
       "!" -group ${group} ")" ")" "$@"
}

_ensure_datadir() {
  local full_run="$1"

  _ensure_dir ${DATADIR} 0755 "$(_fileset_owner masterd)"
  _ensure_dir ${DATADIR}/queue 0700 "$(_fileset_owner masterd)"
  _ensure_dir ${DATADIR}/queue/archive 0700 "$(_fileset_owner masterd)"
  _ensure_dir ${DATADIR}/uidpool 0750 "$(_fileset_owner noded)"
  _ensure_dir ${DATADIR}/rapi 0750 "$(_fileset_owner rapi)"

  # We ignore these files if they don't exists (incomplete setup)
  _ensure_file ${DATADIR}/cluster-domain-secret 0640 \
               "$(_fileset_owner masterd)" || :
  _ensure_file ${DATADIR}/config.data 0640 "$(_fileset_owner masterd-confd)" || :
  _ensure_file ${DATADIR}/hmac.key 0440 "$(_fileset_owner confd)" || :
  _ensure_file ${DATADIR}/known_hosts 0644 "$(_fileset_owner masterd)" || :
  _ensure_file ${DATADIR}/rapi.pem 0440 "$(_fileset_owner rapi)" || :
  _ensure_file ${DATADIR}/rapi/users 0640 "$(_fileset_owner rapi)" || :
  _ensure_file ${DATADIR}/server.pem 0440 "$(_fileset_owner masterd)" || :
  _ensure_file ${DATADIR}/queue/serial 0600 "$(_fileset_owner masterd)" || :

  # To not change the utils.LockFile object
  touch ${DATADIR}/queue/lock
  _ensure_file ${DATADIR}/queue/lock 0600 "$(_fileset_owner masterd)"

  if ! [[ -z "${full_run}" ]]; then
    local queue_owner="$(_fileset_owner masterd)"
    local ssconf_owner="$(_fileset_owner noded)"

    _gather_files ${DATADIR}/queue 0600 @GNTMASTERUSER@ @GNTMASTERDGROUP@ | \
    while read path; do
      _ensure_file "$path" 0600 "$queue_owner"
    done

    _gather_files ${DATADIR} 0600 root @GNTMASTERDGROUP@ -name 'ssconf_*' | \
    while read path; do
      _ensure_file "$path" 0444 "$ssconf_owner"
    done
  fi
}

_ensure_rundir() {
  _ensure_dir ${GNTRUNDIR} 0775 "$(_fileset_owner daemons)"
  _ensure_dir ${GNTRUNDIR}/socket 0750 "$(_fileset_owner daemons)"
  _ensure_dir ${GNTRUNDIR}/bdev-cache 0755 "$(_fileset_owner noded)"
  _ensure_dir ${GNTRUNDIR}/instance-disks 0755 "$(_fileset_owner noded)"
  _ensure_dir ${GNTRUNDIR}/crypto 0700 "$(_fileset_owner noded)"
  _ensure_dir ${GNTRUNDIR}/import-export 0755 "$(_fileset_owner noded)"

  # We ignore this file if it don't exists (not yet start up)
  _ensure_file ${GNTRUNDIR}/socket/ganeti-master 0770 \
               "$(_fileset_owner daemons)" || :
}

_ensure_logdir() {
  _ensure_dir ${GNTLOGDIR} 0770 "$(_fileset_owner daemons)"
  _ensure_dir ${GNTLOGDIR}/os 0750 "$(_fileset_owner daemons)"

  # We ignore these files if they don't exists (incomplete setup)
  _ensure_file ${GNTLOGDIR}/master-daemon.log 0600 "$(_fileset_owner masterd)" || :
  _ensure_file ${GNTLOGDIR}/conf-daemon.log 0600 "$(_fileset_owner confd)" || :
  _ensure_file ${GNTLOGDIR}/node-daemon.log 0600 "$(_fileset_owner noded)" || :
  _ensure_file ${GNTLOGDIR}/rapi-daemon.log 0600 "$(_fileset_owner rapi)" || :
}

_ensure_lockdir() {
  _ensure_dir ${LOCKDIR} 1777 ""
}

_operate_while_hold() {
  local fn=$1
  local path=$2
  shift 2

  (cd ${path};
   ${fn} "$@")
}

main() {
  local full_run

  while getopts "f" OPTION; do
    case ${OPTION} in
      f) full_run=1 ;;
    esac
  done

  _operate_while_hold "_ensure_datadir" ${DATADIR} ${full_run}
  _operate_while_hold "_ensure_rundir" ${RUNDIR}
  _operate_while_hold "_ensure_logdir" ${LOGDIR}
  _operate_while_hold "_ensure_lockdir" @LOCALSTATEDIR@
}

main "$@"
