#!/bin/bash
#
# Author: Mark Lamourine <markllama@gmail.com>
# Copyright 2012
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# This script checks the status of a host that is running an Openshift Origins
# Broker service.
#
# Check that the broker components are installed and communicating properly
#
OSO_CONF_DIR=${OSO_CONF_DIR:=/etc/openshift}

OSO_BROKER_ROOT=${OSO_BROKER_ROOT:=/var/www/openshift/broker}

OSO_CFG_DIR=${OSO_BROKER_ROOT}/config
OSO_HTTPD_DIR=${OSO_BROKER_ROOT}/httpd
OSO_HTTPD_CONF_DIR=${OSO_HTTPD_DIR}/conf.d
OSO_ENV_DIR=${OSO_CFG_DIR}/environments
OSO_INI_DIR=${OSO_CFG_DIR}/initializers

if [ -e '/etc/openshift/development' ] ; then
  OSO_ENVIRONMENT=${OSO_ENVIRONMENT:=development}
else
  OSO_ENVIRONMENT=${OSO_ENVIRONMENT:=production}
fi

AUTH_PLUGINS="mongo"
NAME_PLUGINS="bind"
MESG_PLUGINS="mcollective"

DEFAULT_PACKAGES="
  ruby
  rubygems
  rubygem-rails
  rubygem-passenger
  rubygem-openshift-origin-common
  rubygem-openshift-origin-controller
  openshift-origin-broker 
"

DEFAULT_SERVICES="openshift-broker"

# Depends on OSO_BROKER_ROOT in ruby lib search list
OSO_RUBY_LIBS="openshift-origin-controller config/application"

if [ -z "$PACKAGES" ]
then
    PACKAGES="$DEFAULT_PACKAGES"
else
    echo WARNING: ENV overrides PACKAGES >&2
fi

if [ -z "$SERVICES" ]
then
    SERVICES="$DEFAULT_SERVICES"
else
    echo WARNING: ENV overrides SERVICES >&2
fi

BROKER_REST_API_BASE="https://localhost/broker/rest/"

# we will fill APP_VALUES with output from ruby commands corresponding to the map
declare -A APP_VALUES
declare -A APP_VALUE_MAP=(
		["oo_ds_provider"]="OpenShift::DataStore.instance_variable_get('@oo_ds_provider')"
		["oo_auth_provider"]="OpenShift::AuthService.instance_variable_get('@oo_auth_provider')"
		["oo_dns_provider"]="OpenShift::DnsService.instance_variable_get('@oo_dns_provider')"
		["proxy_provider"]="OpenShift::ApplicationContainerProxy.instance_variable_get('@proxy_provider')"
	)

# ============================================================================
#
# Utility Functions
#
# ============================================================================

function verbose() {
    # MESSAGE=$*

    if [ -n "$VERBOSE" ]
    then
	echo "INFO: $*"
    fi
}

function notice() {
    # MESSAGE=$*
    echo "NOTICE: $*"
}

function fail() {
    # MESSAGE=$*
    echo "FAIL: $*" >&2
    STATUS=$(($STATUS + 1))
}


# ==========================================================================
#
# ==========================================================================
function probe_version() {
    # Find out who owns /var/www/openshift/broker

    BROKER_RPM=$(rpm -qf $OSO_BROKER_ROOT --qf '%{NAME}\n' 2>/dev/null)
    if [ -z "$BROKER_RPM" ]
    then
      fail "broker Rails app root ${OSO_BROKER_ROOT} does not exist: no broker package"
    else
      verbose "Broker package is: $BROKER_RPM"
    fi
}

function check_ruby_requirements() {
    verbose checking ruby requirements
    if [ ! -x /usr/bin/ruby ]
    then
	fail ruby is not installed or not executable
	return
    fi
    for OSO_RUBY_LIB in $*
    do
	verbose checking ruby requirements for $OSO_RUBY_LIB
        GEM_ERROR=`ruby -I ${OSO_BROKER_ROOT} -r rubygems -- <<EOF
            require 'bundler'
            begin
              require '$OSO_RUBY_LIB'
            rescue Bundler::GemNotFound => gem_error
              puts "Gem Not Found for $OSO_RUBY_LIB: #{gem_error}"
              exit 1
            end
EOF`
	if [ $? -ne 0 ]
        then
	    fail module $OSO_RUBY_LIB -- "$GEM_ERROR"
        fi 
    done
}

#
# Get a set of values from the Rails application.
# Yes, this is inefficient, but the point is to not depend on the system
# you're examining (Ruby/Rails) to confirm itself.
#

function load_application_values() {
	# Build ruby program statements from APP_VALUE_MAP and
	# read the output values into the APP_VALUES hash.
	# This is all predicated on each value landing on one line;
	# if there are any multiline values, we're in trouble.
	# Also if there are any errors this won't work. Which is why we
	# can't get all the values in one go - some exist conditionally.

	ruby_program=""
	declare -a keys=( ${!APP_VALUE_MAP[@]} )
	for key in ${keys[@]}
	do
		ruby_program+="
			puts ${APP_VALUE_MAP[$key]}"
	done

	# run those statements after initializing the Rails env
	OLD_IFS=$IFS; IFS=$'\n' # read into array one line per element
	declare -a new_app_values=( `run_ruby_rails_command "$ruby_program"` )
	IFS=$OLD_IFS # back to normal
	if [ $? -ne 0 ]
	then
		fail "Error while running ruby code.
#####
$ruby_program
#####
${new_app_values[@]}
#####"
	elif (( ${#new_app_values[@]} != ${#keys[@]} ))
	then
		fail "wrong number of values returned from ruby code
keys: ${#keys[@]}; values: ${#new_app_values[@]}
#####
$ruby_program
#####
${new_app_values[@]}
#####"
	fi

	# now read the array of output ruby values into the values hash
	for (( i=0 ; $i < ${#keys[@]} ; i++ ))
	do
		APP_VALUES["${keys[$i]}"]=${new_app_values[$i]}
	done
}

function run_ruby_rails_command() {
  # $1 = ruby statements to run after initialization
  if [ -z "$OSO_BROKER_ROOT" ]
  then
      fail OSO_BROKER_ROOT is unset.  Cannot load app configuration
      exit $STATUS
  fi
  if [ -z "$OSO_ENVIRONMENT" ]
  then
      fail OSO_ENVIRONMENT is unset.  Cannot load app configuration
      exit $STATUS
  fi
  if which ruby 2>/dev/null >/dev/null
  then
      ruby -I ${OSO_BROKER_ROOT} -r rubygems -- <<EOF 2>&1
        require 'bundler'
        require 'rails'
        begin
          require 'openshift-origin-controller'
          require 'config/application'
          #require 'config/initializers/broker'
          require 'config/environments/$OSO_ENVIRONMENT'
        rescue Bundler::GemNotFound => gem_error
          puts "Error loading libs or gems: #{gem_error}"
          exit 1
        end
	Broker::Application.initialize!
        $1
EOF
      return $?
  else
      fail ruby is not installed or not executable
      exit $STATUS
  fi
}


# ============================================================================
#
# Base Packages and Components
#
# ============================================================================

# Network Manager (disabled or not present)

# network "service" enabled

# SSH max connections

# Kernel Settings
#  - Ephemeral Port Range
#  - Kernel Semaphores (httpd communications)
#  - netfilter conntrack buffer size

# IPTables

# ============================================================================
#
# Configuration and Variables
# 
# ============================================================================

#
# Check packages
#
function check_packages() {
    # $* = $PACKAGES
    verbose checking packages
    for PKGNAME in $*
    do
	verbose checking package $PKGNAME
	PKGSTATUS=`rpm -q $PKGNAME`
	if echo $PKGSTATUS | grep "not installed" >/dev/null
	then
	    fail "package $PKGNAME is not installed"
	fi 
    done
}


#
# There are two different service monitors:  RHEL6 still uses service and chkconfig
# Fedora 16+ use systemctl (as part of systemd)
#
function service_enabled() {
  # $1 = SERVICE_NAME

  if [ -x /bin/systemctl -a ! -x /etc/init.d/$1 ]
  then
      systemctl is-enabled $1.service 2>&1 >/dev/null
  else
      chkconfig $1
  fi

  if [ $? != 0 ]
  then
      fail "service $1 not enabled;"
  fi
}

function service_running() {
  # $1 = SERVICE_NAME

  if [ -x /bin/systemctl ]
  then
      systemctl status $1.service 2>&1 | grep -e "^\s*Active: active" >/dev/null
  else
      service $1 status 2>&1 > /dev/null
  fi

  if [ $? != 0 ]
  then
      fail "service $1 not running"
  fi
}


#
# Check services
#
function check_services() {
    verbose checking services
    for SVCNAME in $SERVICES
    do
	service_enabled $SVCNAME
        service_running $SVCNAME
    done
}

function check_selinux_modules() {
  verbose "checking that selinux modules are loaded"
  # if not enforcing, just say so
  notice "SELinux is " `getenforce`
  if [ `getenforce 2>/dev/null` != "Enforcing" ]
  then
    return
  fi

  SEMODULE=$(which semodule 2>/dev/null)
  if [ $? != 0 ]
  then
    fail "semodule binary not present (from policycoreutils RPM)"
    return
  fi

  SELINUX_MODULES='rubygem_passenger openshift-origin-broker'
  for MODNAME in $SELINUX_MODULES
  do
    MODSPEC=$($SEMODULE -l | grep $MODNAME)
    if [ -n "$MODSPEC" ]
    then
      MODVERS=$(echo $MODSPEC | awk '{print $2;}')
      verbose "SELinux module $MODNAME is version $MODVERS"
    else
      fail "SELinux module $MODNAME is not loaded"
    fi
  done
}


function check_kernel_settings() {
  verbose "checking kernel settings"

  KERNEL_SETTINGS="kernel.sem net.ipv4.ip_local_port_range net.netfilter.nf_conntrack_max"

  for KERNEL_KEY in $KERNEL_SETTINGS
  do
      notice current - $(sysctl $KERNEL_KEY)
      notice config - $(grep -e "^$KERNEL_KEY " /etc/sysctl.conf)
  done
}

function check_firewall() {
  verbose "checking firewall settings"

  
  # check for 'enabled'
  service_enabled iptables
  service_running iptables
  # Need to check for ports TCP/22, TCP/53, TCP/80, TCP/443 and UDP/53 allowed
}

#
# Check SELinux
#
function check_selinux_booleans() {
  # if not enforcing, just say so
  notice "SELinux is " `getenforce`
  if [ `getenforce 2>/dev/null` != "Enforcing" ]
  then
    return
  fi

  # check httpd_unified
  if getsebool httpd_unified | grep -e '--> on' >/dev/null
  then
    verbose SELinux boolean httpd_unified is enabled
  else
    fail "SELinux boolean httpd_unified is disabled -- run setsebool -P httpd_unified=on"
  fi


  # Only needed with BIND DDNS plugin
  # check allow_ypbind
  # check httpd_unified
  if getsebool allow_ypbind | grep -e '--> on' >/dev/null
  then
    verbose SELinux boolean allow_ypbind is enabled
  else
    notice "SELinux boolean allow_ypbind is disabled -- run setsebool -P allow_ypbind=on"
  fi
  
}

# ============================================================================
#
# DataStore
#
# ============================================================================

function check_datastore() {
    verbose checking datastore
    DATA_PLUGIN=${APP_VALUES["oo_ds_provider"]}
    case $DATA_PLUGIN in
        'OpenShift::DataStore')

	    fail "configured datastore class is the abstract one: $DATA_PLUGIN"
	    ;;
	'OpenShift::MongoDataStore')
	    verbose "datastore plugin: $DATA_PLUGIN"
	    check_datastore_mongo
            ;;

	*)
	    fail unknown datastore class: $DATA_PLUGIN
	;;
    esac
    unset DATA_PLUGIN
}

function check_mongo_login() {
    # $HOST_PORT=$1
    # $DB=$2
    # $USER=$3
    # $PASS=$4
    verbose checking mongo db login access
    ssl_opt=""
    if [ "${APP_VALUES[DS_SSL]}" == "true" ]
    then
        ssl_opt="--ssl"
    fi
    mongo $1/$2 --username $3 --password $ssl_opt<<EOF 2>&1 >/dev/null 
$4
exit
EOF

    if [ $? -eq 0 ]
    then
	verbose "mongo db login successful: $1/$2 --username $3"
    else
        fail "error logging into mongo db: $1/$2 --username $3, exit code: $?"
    fi
}

function check_datastore_mongo() {
    verbose checking mongo datastore configuration

    # get the service hostname, port, username, password
	APP_VALUE_MAP=(
		["DS_HOST"]="Rails.application.config.datastore[:host_port].flatten[0]"
		["DS_PORT"]="Rails.application.config.datastore[:host_port].flatten[1]"
		["DS_USER"]="Rails.application.config.datastore[:user]"
		["DS_PASS"]="Rails.application.config.datastore[:password]"
		["DS_NAME"]="Rails.application.config.datastore[:db]"
                ["DS_SSL"]="Rails.application.config.datastore[:ssl]"
		)
	load_application_values
    verbose "Datastore Host: ${APP_VALUES[DS_HOST]}"
    verbose "Datastore Port: ${APP_VALUES[DS_PORT]}"
    verbose "Datastore User: ${APP_VALUES[DS_USER]}"
    verbose "Datastore SSL: ${APP_VALUES[DS_SSL]}"

    
    if [ "${APP_VALUES[DS_PASS]}" == "mooo" ]
    then
	fail "Datastore Password has been left configured as the default 'mooo'
	-- please reconfigure and ensure the DB user's password matches."
    else
        verbose "Datastore Password has been set to non-default"
    fi
    verbose "Datastore DB Name: ${APP_VALUES[DS_NAME]}"

    # Only check local values if DS_HOST is localhost
    if [ "${APP_VALUES[DS_HOST]}" == "localhost" ]
    then
	verbose "Datastore configuration is on localhost"

	# check presence of mongodb package
	check_packages mongodb

        # check auth enabled
        if grep -e '^auth = true' /etc/mongodb.conf >/dev/null
        then
            verbose "LOCAL: mongod auth is enabled"
        else
	    fail "LOCAL: mongod auth is not enabled in /etc/mongodb.conf;
	    -- please add a line with 'auth = true' and restart mongod."
        fi

        # check service enabled
	if (service mongod status 2>/dev/null | grep enabled 2>&1 >/dev/null \
            || chkconfig --list 2>/dev/null | grep '^mongod.*2:on.*3:on.*4:on.*5:on' 2>&1 >/dev/null)
        then
	    verbose "LOCAL: mongod service enabled"
        else
	    fail "LOCAL: mongod service not enabled"
        fi

        # check service started
	if (service mongod status 2>/dev/null | grep 'running' 2>&1 >/dev/null)
        then
	    verbose "LOCAL: mongod service running"
        else
	    fail "LOCAL: mongod service not running"
        fi

        # check OpenShift mongo ssl configuration
        if [ "${APP_VALUES[DS_SSL]}" == "true" ]
        then
            if grep -e '^sslOnNormalPorts = true' /etc/mongodb.conf >/dev/null
            then
                verbose "LOCAL: mongodb ssl connections are enabled"
            else
                fail "LOCAL: OpenShift broker SSL connections to mongo is enabled;
                -- please update /etc/mongodb.conf with sslOnNormalPorts = true"
            fi
        else
            if grep -e '^sslOnNormalPorts = true' /etc/mongodb.conf >/dev/null
            then
                fail "LOCAL: Although the broker.conf has mongo SSL connections turned off,
                mongodb is configured to only accept SSL connection;
                -- please update /etc/mongodb.conf with sslOnNormalPorts = false"
            fi
        fi

    else
        verbose "Datastore: mongo db service is remote"
    fi
 
    # check OpenShift Origin user (username/password)
    check_mongo_login "${APP_VALUES[DS_HOST]}:${APP_VALUES[DS_PORT]}" ${APP_VALUES[DS_NAME]} ${APP_VALUES[DS_USER]} ${APP_VALUES[DS_PASS]}
}

function check_auth_mongo() {
    verbose checking mongo auth configuration

    # get the service hostname, port, username, password
	APP_VALUE_MAP=(
		["DS_HOST"]="Rails.application.config.auth[:mongo_host_port].flatten[0]"
		["DS_PORT"]="Rails.application.config.auth[:mongo_host_port].flatten[1]"
		["DS_USER"]="Rails.application.config.auth[:mongo_user]"
		["DS_PASS"]="Rails.application.config.auth[:mongo_password]"
		["DS_NAME"]="Rails.application.config.auth[:mongo_db]"
		["DS_SSL"]="Rails.application.config.auth[:mongo_ssl]"
		)
	load_application_values
    verbose "Auth Host: ${APP_VALUES[DS_HOST]}"
    verbose "Auth Port: ${APP_VALUES[DS_PORT]}"
    verbose "Auth User: ${APP_VALUES[DS_USER]}"
    verbose "Auth SSL: ${APP_VALUES[DS_SSL]}"
    if [ "${APP_VALUES[DS_PASS]}" == "mooo" ]
    then
	fail "Datastore Password has been left configured as the default 'mooo'
	-- please reconfigure and ensure the DB user's password matches."
    else
        verbose "Datastore Password has been set to non-default"
    fi
    verbose "Auth DB Name: ${APP_VALUES[DS_NAME]}"

    # Only check local values if DS_HOST is localhost
    if [ "${APP_VALUES[DS_HOST]}" = "localhost" ]
    then
	verbose "Auth configuration is on localhost"

	# check presence of mongodb package
	check_packages mongodb

        # check auth enabled
        if grep -e '^auth = true' /etc/mongodb.conf >/dev/null
        then
            verbose "LOCAL: mongod auth is enabled"
        else
	    fail "LOCAL: mongod auth is not enabled in /etc/mongodb.conf"
        fi

        # check service enabled
	if (service mongod status 2>/dev/null | grep enabled 2>&1 >/dev/null \
            || chkconfig --list 2>/dev/null | grep '^mongod.*2:on.*3:on.*4:on.*5:on' 2>&1 >/dev/null)
        then
	    verbose "LOCAL: mongod service enabled"
        else
	    fail "LOCAL: mongod service not enabled"
        fi

        # check service started
	if (service mongod status 2>/dev/null | grep 'running' 2>&1 >/dev/null)
        then
	    verbose "LOCAL: mongod service running"
        else
	    fail "LOCAL: mongod service not running"
        fi
    else
        verbose "Auth: mongo db service is remote"
    fi

    # check OpenShift Origin user (username/password)
    check_mongo_login "${APP_VALUES[DS_HOST]}:${APP_VALUES[DS_PORT]}" ${APP_VALUES[DS_NAME]} ${APP_VALUES[DS_USER]} ${APP_VALUES[DS_PASS]}
}

function get_http_response_code() {
    curl -k -s -o /dev/null -w '%{http_code}'  "$1"
}

assert_rest_api_returns() {
    if [ "$1" = "$(get_http_response_code "$2")" ]
    then
        verbose "Got HTTP $1 response from $2"
    else
        fail "Did not get expected HTTP $1 response from $2"
    fi
}

function check_auth_remote_user() {
    verbose checking remote-user auth configuration

	APP_VALUE_MAP=(
		["RU_TRUSTED_HEADER"]="Rails.application.config.auth[:trusted_header]"
		)
	load_application_values
    verbose "Auth trusted header: ${APP_VALUES[RU_TRUSTED_HEADER]}"

    if grep -q 'BrowserMatchNoCase\s\+\^OpenShift\s\+passthrough' ${OSO_HTTPD_CONF_DIR}/*.conf \
       && grep -q 'Allow\s\+from\s\+env=passthrough' ${OSO_HTTPD_CONF_DIR}/*.conf
    then
        verbose 'Auth passthrough is enabled for OpenShift services'
    else
        fail 'Auth passthrough appears not to be enabled, which will break JBossTools and node-to-broker authentication'
    fi

    UNAUTHENTICATED_APIS="api application_templates cartridges"
    AUTHENTICATED_APIS="user domains"

    for api in $UNAUTHENTICATED_APIS
    do
        assert_rest_api_returns 200 "${BROKER_REST_API_BASE}${api}"
    done

    for api in $AUTHENTICATED_APIS
    do
        assert_rest_api_returns 401 "${BROKER_REST_API_BASE}${api}"
    done
}
# ============================================================================
#
# Cloud User Authentication
#
# ============================================================================

function check_authentication() {
    verbose checking cloud user authentication
    AUTH_PLUGIN=${APP_VALUES[oo_auth_provider]}
    verbose auth plugin = $AUTH_PLUGIN
    case $AUTH_PLUGIN in
        'OpenShift::AuthService')

	    fail "configured auth class is the abstract one: $AUTH_PLUGIN"
	    ;;
	'OpenShift::MongoAuthService')
	    verbose "auth plugin: $AUTH_PLUGIN"
	    check_auth_mongo
            ;;

	'OpenShift::RemoteUserAuthService')
	    verbose "auth plugin: $AUTH_PLUGIN"
	    check_auth_remote_user
            ;;

	*)
	    fail unknown auth class: $AUTH_PLUGIN
	    ;;
    esac
    unset AUTH_PLUGIN
}

# ============================================================================
#
# Dynamic DNS Updates
#
# ============================================================================

function dns_bind_update_record() {
    # $1 = server
    # $2 = key name
    # $3 = key value
    # $4 = function (add|delete)
    # $5 = type (A, TXT, CNAME)
    # $6 = name 
    # $7 = value

    # check $1: should be an IP address
    # check $3: should be a key string
    # check $4: should be add|delete
    # check $5 should be A, TXT, CNAME

    verbose "${4}ing $5 record named $6 to server $1: $7"

    nsupdate <<EOF
server $1
key $2 $3
update $4 $6 1 $5 $7
send
EOF

    if [ $? != 0 ]
    then
	fail "error ${4}ing $5 record name $6 to server $1: $7
	-- is the nameserver running, reachable, and key auth working?"
    fi

}

function check_dns_bind() {
    verbose checking bind dns plugin configuration

	APP_VALUE_MAP=(
		["DNS_SERVER"]="Rails.application.config.dns[:server]"
		["DNS_PORT"]="Rails.application.config.dns[:port].to_s"
		["DNS_KEYNAME"]="Rails.application.config.dns[:keyname]"
		["DNS_KEYVAL"]="Rails.application.config.dns[:keyvalue]"
		["DNS_ZONE"]="Rails.application.config.dns[:zone]"
		["DNS_SUFFIX"]="Rails.application.config.openshift[:domain_suffix]"
		)
	load_application_values

    verbose "DNS Server: ${APP_VALUES[DNS_SERVER]}"
    verbose "DNS Port: ${APP_VALUES[DNS_PORT]}"
    verbose "DNS Key Name: ${APP_VALUES[DNS_KEYNAME]}"
    verbose "DNS Key Value: *****"
    verbose "DNS Zone: ${APP_VALUES[DNS_ZONE]}"
    verbose "DNS Domain Suffix: ${APP_VALUES[DNS_SUFFIX]}"

    # check that zone suffix ends exactly with dns_zone (zone contains suffix)

    # try to add a dummy TXT record to the zone
    dns_bind_update_record ${APP_VALUES[DNS_SERVER]} ${APP_VALUES[DNS_KEYNAME]} ${APP_VALUES[DNS_KEYVAL]} add txt testrecord.${APP_VALUES[DNS_SUFFIX]} this_is_a_test

    # verify that the record is there
    if host -t txt testrecord.${APP_VALUES[DNS_SUFFIX]} ${APP_VALUES[DNS_SERVER]} >/dev/null
    then
	verbose "txt record successfully added"
    else
        fail "txt record testrecord.${APP_VALUES[DNS_SUFFIX]} does not resolve on server ${APP_VALUES[DNS_SERVER]}"
    fi

    # remove it.
    dns_bind_update_record ${APP_VALUES[DNS_SERVER]} ${APP_VALUES[DNS_KEYNAME]} ${APP_VALUES[DNS_KEYVAL]} delete txt testrecord.${APP_VALUES[DNS_SUFFIX]}

    # verify that the record is removed
    if host -t txt testrecord.${APP_VALUES[DNS_SUFFIX]} ${APP_VALUES[DNS_SERVER]} >/dev/null
    then
        fail "txt record testrecord.${APP_VALUES[DNS_SUFFIX]} still resolves on server ${APP_VALUES[DNS_SERVER]}"
    else
	verbose "txt record successfully deleted"
    fi
}

function check_dynamic_dns() {
    verbose checking dynamic dns plugin
    NAME_PLUGIN=${APP_VALUES[oo_dns_provider]}
    case $NAME_PLUGIN in
        'OpenShift::DnsService')
	    fail "configured dns class is the abstract one: $NAME_PLUGIN"
	    ;;

	'OpenShift::BindPlugin')
	    verbose dynamic dns plugin = $NAME_PLUGIN
	    check_dns_bind
	    ;;

	*)
	    fail unknown dns class: $NAME_PLUGIN
	    ;;
    esac
    unset NAME_PLUGIN
}

# ============================================================================
#
# Broker -> Node messaging
#
# ============================================================================

function check_messaging() {
    verbose checking messaging configuration

    MSG_PLUGIN=${APP_VALUES[proxy_provider]}
    case $MSG_PLUGIN in
        'OpenShift::ApplicationContainerProxy')
	    fail "configured messaging class is the abstract one: $MSG_PLUGIN"
	    ;;

	'OpenShift::MCollectiveApplicationContainerProxy')
	    verbose messaging plugin = $MSG_PLUGIN
	    ;;

	*)
	    fail unknown messaging class: $MSG_PLUGIN
	    ;;
    esac
    unset MSG_PLUGIN
}

# ==========================================================================
# Process CLI arguments
# ==========================================================================

function print_help() {
    echo "usage: $0 [-h] [-v] [-d]

  -h) Display this simple usage message and exit.
  -v) Enable verbose (INFO) output during the run of the script
  -d) Enable debugging mode (display every command executed)
"
    exit 0
}


OPT_FORMAT="dhv"

while getopts $OPT_FORMAT OPTION
do
    case $OPTION in
        d) 
	    set -x
            ;;

	h) 
	    print_help
	    ;;

	v)
	    VERBOSE="true"
	    ;;

        ?) print_help
        ;;
    esac
done

# =============================================================================
#
# MAIN
#
# =============================================================================

# Initial status is PASS (0)
# each fail adds one
STATUS=0

probe_version

check_packages $PACKAGES
check_ruby_requirements $OSO_RUBY_LIBS
load_application_values
#check_selinux_modules
#check_selinux_booleans
#check_kernel_settings
check_firewall
check_services

check_datastore
check_authentication
check_dynamic_dns
check_messaging
exit

if [ "$STATUS" -eq 0 ]
then
    echo PASS
else
    echo $STATUS ERRORS
fi
exit $STATUS
