#!/bin/bash
#
#	ManageLXC OCF RA. Manages LXC Containers (CT)
#
#   (c) 2011 Christoph Mitasch
#       based on MangeVE RA 1.00.4 
#	2006-2010 Matthias Dahl, Florian Haas
#                 and Linux-HA contributors
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of version 2 of the GNU General Public License as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it would be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
#
# Further, this software is distributed without any warranty that it is
# free of the rightful claim of any third person regarding infringement
# or the like.  Any license provided herein, whether implied or
# otherwise, applies only to this software file.  Patent licenses, if
# any, provided herein do not apply to combinations of this program with
# other software, or any other product whatsoever.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write the Free Software Foundation,
# Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
#
#
# This OCF compliant resource agent manages LXC CT and thus requires
# a proper LXC system including lxc userspace tools.
#
# rev. 1.00.0
#
# Changelog
#
# 24/May/11 1.00.0 first version, tested with lxc 0.7.4
# 

###
: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
###

# required utilities
LXCPATH=/usr/bin

#
# usage()
#
usage()
{
	cat <<-EOF
	usage: $0 {start|stop|status|monitor|validate-all|usage|meta-data}
	EOF
}

#
# meta_data()
#
meta_data()
{
	cat <<END
<?xml version="1.0"?>
<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
<resource-agent name="ManageLXC">
  <version>1.00.0</version>

  <longdesc lang="en">
    This OCF compliant resource agent manages LXC System Containers and thus requires
    an Linux kernel with LXC support and the LXC userspace tools.
  </longdesc>

  <shortdesc lang="en">Manages LXC Containers</shortdesc>

  <parameters>
    <parameter name="lxcconf" unique="0" required="1">
      <longdesc lang="en">
        LXC configuration file with full path
      </longdesc>
      <shortdesc lang="en">LXC configuration file</shortdesc>
      <content type="string" default="" />
    </parameter>
    <parameter name="ctname" unique="0" required="1">
      <longdesc lang="en">
        LXC container name
      </longdesc>
      <shortdesc lang="en">LXC container name</shortdesc>
      <content type="string" default="" />
    </parameter>
  </parameters>

  <actions>
    <action name="start" timeout="75" />
    <action name="stop" timeout="75" />
    <action name="status" depth="0" timeout="10" interval="10" />
    <action name="monitor" depth="0" timeout="10" interval="10" />
    <action name="validate-all" timeout="5" />
    <action name="meta-data" timeout="5" />
  </actions>
</resource-agent>
END
}

#
# start_ct()
#
# Starts a CT, or simply logs a message if the CT is already running.
#
start_ct()
{
  if status_ct; then
	ocf_log info "CT $CTNAME already running."
	return $OCF_SUCCESS
  fi

  ocf_run $LXCPATH/lxc-start -n $CTNAME -f $LXCCONF -d || exit $OCF_ERR_GENERIC

  return $OCF_SUCCESS
}

#
# stop_ct()
#
stop_ct()
{
  status_ct
  if [ $? -eq $OCF_NOT_RUNNING ]; then
	ocf_log info "CT $CTNAME already stopped."
	return $OCF_SUCCESS
  fi

  if [ -x $LXCPATH/lxc-ctrlaltdel ]
  then 
     ocf_run $LXCPATH/lxc-ctrlaltdel -n $CTNAME -w 30
  fi

  ocf_run $LXCPATH/lxc-stop -n $CTNAME -q || exit $OCF_ERR_GENERIC

  return $OCF_SUCCESS
}


#
# status_ct()
#
# This function relies on the output of lxc-info command
#
status_ct()
{ 
  declare -i retcode

  ctstatus=`$LXCPATH/lxc-info -n $CTNAME | grep -q RUNNING 2>/dev/null`
  running=$?
  `$LXCPATH/lxc-info -n $CTNAME >/dev/null 2>&1`
  retcode=$?

  if [[ $retcode != 0 ]]; then
    ocf_log err "lxc-info -n $CTNAME returned: $retcode"
    exit $OCF_ERR_GENERIC
  fi

  case "$running" in
    0)
	return $OCF_SUCCESS
        ;;
    *)
	return $OCF_NOT_RUNNING
        ;;
  esac
}    

#
# validate_all_ct()
#
validate_all_ct()
{
  declare -i retcode

  `status_ct`
  retcode=$?

  if [[ $retcode != $OCF_SUCCESS && $retcode != $OCF_NOT_RUNNING ]]; then
    return $retcode
  fi

  return $OCF_SUCCESS
}
	

if [[ $# != 1 ]]; then
  usage
  exit $OCF_ERR_ARGS
fi

case "$1" in
  meta-data)
	meta_data
	exit $OCF_SUCCESS
	;;
  usage) 
	usage
	exit $OCF_SUCCESS
	;;
  *)
	;;
esac

#
# check relevant environment variables for sanity and security
#

# empty string?
`test -z "$OCF_RESKEY_ctname"`
`test -z "$OCF_RESKEY_lxcconf"`

declare CTNAME=$OCF_RESKEY_ctname
declare LXCCONF=$OCF_RESKEY_lxcconf

#
# check that all relevant utilities are available
# 
check_binary $LXCPATH/lxc-start
check_binary $LXCPATH/lxc-stop
check_binary $LXCPATH/lxc-info

#
# finally... let's see what we are ordered to do :-)
#
case "$1" in
  start)
	start_ct
	;;
  stop)
	stop_ct
	;;
  status|monitor) 
	status_ct
	;;
  validate-all)
	validate_all_ct
	;;
  *)
	usage
	exit $OCF_ERR_UNIMPLEMENTED 
	;;
esac

exit $?
