#! /usr/bin/env bash
#
#############################################################################
# This program is part of Zenoss Core, an open source monitoring platform.
# Copyright (C) 2007, Zenoss Inc.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 as published by
# the Free Software Foundation.
#
# For complete information please visit: http://www.zenoss.com/oss/
#############################################################################
#
# chkconfig: 2345 80 30
#
# zenctl        This init.d script starts and stops Zenoss
#               
# description: Zenoss is a monitoring program written by Zenoss, Inc.
#
# Most of the time this script simply delegates to
# ${ZENHOME}/bin/zenoss to actually execute the requested command
# (start/stop).  But, in some situations it behaves differently.  
#
# This script also checks for the fresh_install or upgraded flags.  If
# they are present the script will delegate to the pre/post-install or
# upgrade scripts as appropriate.  A normal chain of events is
# documented below:
#
# <fresh install>
# zenoss_init_pre
# zenoss start
# zenoss_init_post
# ... time goes by ...
# zenoss stop
# <upgrade occurs>
# zenoss_upgrade_pre
# zenoss start
# zenoss_upgrade_pos
#

# environment variables
# NB: Please keep the ZENHOME='**ZENHOME**' idiom alive in the src.  Tags
#     of this nature are sed substituted at build time based upon the package type.
export ZENHOME="**ZENHOME**"
export RUNUSER="**OS_USERNAME**"
export SNMPD_CONF="**SNMPD_CONF**"
export MY_CNF="**MY_CNF**"
export ZOPE_USERNAME="admin"
export ZOPE_PASSWORD="**ZOPE_PASSWD**"
export ZOPE_LISTEN_PORT="8080"
export PYTHON="**PYTHON**"
export PYTHONPATH="**ZENHOME**/lib/python"
export INSTALL_LOG="$ZENHOME/log/install.log"
# NB: This crude hack is to add output while preserving return codes
# Uses the concepts from http://www.travishartwell.net/blog/2006/08/19_2220
export INSTALL_PIPE="$ZENHOME/log/logging.fifo"
export DELIM="-------------------------" # delimiter in log file

# signature of zenoss having been installed for the first time (but
# not configured yet)
export FRESH_INSTALL=${ZENHOME}/.fresh_install

# signature of zenoss having been upgraded from a previous install
export UPGRADED=${ZENHOME}/.upgraded


# changes the owners and permissions for the zenoss files
set_perms() {
    for dir in \
        ${ZENHOME}/log \
        ${ZENHOME}/etc \
        ${ZENHOME}/var
    do
        if [ ! -d ${dir} ]; then
            continue
        fi

        chown -R ${RUNUSER}:${RUNUSER} ${dir}
        chmod -R 775 ${dir}
    done
}

init_install_log() {
    stage=$1

    if [ ! -z "$ZENOSS_NO_INSTALL_LOGGING" ] ; then
        # If run through ssh the logging hangs for the 'wait'
        return
    fi

    echo $DELIM >> $INSTALL_LOG
    echo $stage
    echo $stage >> $INSTALL_LOG
    date >> $INSTALL_LOG
    uname -a >> $INSTALL_LOG
    echo $DELIM >> $INSTALL_LOG

    # Setup for logging output into FIFO
    if [ ! -e $INSTALL_PIPE ]; then
         mkfifo $INSTALL_PIPE
         if [ $? -gt 0 ] ; then
             echo "Unable to allow simultaneous logging and visible output."
             echo "Defaulting to visible output only."
             echo "To get a log, hit ctl+c within the next 10 seconds and resolve the above issue"
             sleep 10
             echo "Continuing with install process..."
             return
         fi
    fi

    # Spawn an instance of 'tee' to capture the output to a file
    # as well as displaying output to the user
    exec 3>&1 4>&2
    tee -a $INSTALL_LOG < $INSTALL_PIPE >&3 &
    tee_pid=$!
    exec > $INSTALL_PIPE 2>&1
}



# these commands are run when zenoss was installed for the first time
# and BEFORE the zenoss processes are started
fresh_install_pre() {
    echo "Zenoss not initialized.  Performing first-boot initialization..."

    if [ `id -u` != 0 ]; then
        echo "Must be root when starting this service for the first time after an install."
        exit 1
    fi

    # location of where we copy configuration items to
    ZEN_ETC=${ZENHOME}/etc

    # update the snmpd.conf file
    SNMPD_CONF_DIR=`dirname ${SNMPD_CONF}`
    BACKUP=${SNMPD_CONF_DIR}/`basename ${SNMPD_CONF}`.orig
    if [ -f ${SNMPD_CONF} ]; then
        cp ${SNMPD_CONF} ${BACKUP}
    fi
    if [ ! -d ${SNMPD_CONF_DIR} ]; then
        mkdir -p ${SNMPD_CONF_DIR}
    fi
    cp ${ZEN_ETC}/snmpd.conf ${SNMPD_CONF}
    
    init_install_log "Fresh install pre steps"
 
    # run the first time initialization pre-run script
    set_perms
    ${ZENHOME}/bin/zenoss_init_pre
    if [ $? -gt 0 ] ; then
      exit 1
    fi
    set_perms

    echo "Zenoss initialization complete."
}


# these commands are run when zenoss was installed for the first time
# but AFTER the zenoss processes are started
fresh_install_post() {
    echo
    echo "Fresh install post step"

    # run the first time initialization post-run script
    ${ZENHOME}/bin/zenoss_init_post

    echo "Zenoss installation completed."
}



# and BEFORE the zenoss processes are started
upgrade_pre() {
    echo "Zenoss upgraded.  Running data migration scripts..."

    if [ `id -u` != 0 ]; then
        echo "Must be root when starting this service for the first time after an upgrade."
        exit 1
    fi

    init_install_log "Upgrade pre step"

    # run the upgrade pre-run script
    set_perms
    ${ZENHOME}/bin/zenoss_upgrade_pre
    if [ $? -gt 0 ] ; then
      exit 1
    fi  
    set_perms

    echo "Zenoss upgrade pre-restart commands complete."
}


# these commands are run when zenoss is started after being upgraded
# but AFTER the zenoss processes are started
upgrade_post() {
    echo
    echo "Upgrade install post step"

    # run the upgrade post-run script
    set_perms
    ${ZENHOME}/bin/zenoss_upgrade_post
    if [ $? -gt 0 ] ; then
      exit 1
    fi  
    set_perms

    echo "Zenoss upgrade complete."
}


#
# main script starts here
#
# basically we check if the fresh_install/upgraded flag exists.  if it
# does then we run the pre functions prior to starting up zenoss.
# this allows us to do things like zeneventbuild, or zenmigrate.  then
# we start up zenoss.  lastly we run the post functions after zenoss
# is up and running.  this allows us to do things like "add localhost
# to the zenoss database through the web UI
#

# LSB exit code reference.
#   0       program is running or service is OK
#   1       program is dead and /var/run pid file exists
#   2       program is dead and /var/lock lock file exists
#   3       program is not running
#   4       program or service status is unknown
#   5-99    reserved for future LSB use
#   100-149 reserved for distribution use
#   150-199 reserved for application use
#   200-254 reserved

# When run in an HA configuration with $ZENHOME on shared storage the real
# Zenoss startup script may not exist.
if [ ! -f "${ZENHOME}/bin/zenoss" ]; then
    echo "Startup script not found at ${ZENHOME}/bin/zenoss."
    exit 3
fi

# run the firstboot if this is the first time zenoss was started
if [ "$1" = start -a -f ${FRESH_INSTALL} ]; then
    fresh_install_pre
fi

# run the upgrade if this is the first time zenoss was started since
# an upgrade occurred
if [ "$1" = start -a -f ${UPGRADED} ]; then
    upgrade_pre
fi


# delegate to the main zenoss script for control functions
su - ${RUNUSER} sh -c "${ZENHOME}/bin/zenoss $@"
EXITCODE=$?

# run the post-script for firstboot and remove the firstboot flag
if [ "$1" = start -a -f ${FRESH_INSTALL} ]; then
    fresh_install_post
    rm ${FRESH_INSTALL}
fi

# run the post-script for upgrade and remove the upgradeflag
if [ "$1" = start -a -f ${UPGRADED} ]; then
    upgrade_post
    rm ${UPGRADED}
fi

# Just in case we log, wait for the tee to finish
if [ ! -z "$tee_pid" ] ; then
    # Cleanup -- leave the fifo alone
    exec 1>&3 3>&- 2>&4 4>&-

    # Zombies are bad. Bad zombies
    wait $tee_pid
fi

exit $EXITCODE
