#!/bin/bash # # # OpenStack Neutron Metadata Agent service # # Description: Manages an OpenStack Neutron Metadata Agent process as an HA resource # # Authors: Emilien Macchi # Mainly inspired by the Nova Network resource agent written by Emilien Macchi & Sebastien Han # # Support: openstack@lists.launchpad.net # License: Apache Software License (ASL) 2.0 # # # See usage() function below for more details ... # ####################################################################### # Initialization: : ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat} . ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs ####################################################################### # Fill in some defaults if no values are specified PATH=/sbin:/usr/sbin:/bin:/usr/bin OCF_RESKEY_binary_default="neutron-metadata-agent" OCF_RESKEY_config_default="/etc/neutron/neutron.conf" OCF_RESKEY_agent_config_default="/etc/neutron/metadata_agent.ini" OCF_RESKEY_log_file_default="/var/log/neutron/metadata-agent.log" OCF_RESKEY_user_default="neutron" OCF_RESKEY_pid_default="${HA_RSCTMP}/${__SCRIPT_NAME}/${__SCRIPT_NAME}.pid" OCF_RESKEY_debug_default="false" : ${OCF_RESKEY_binary=${OCF_RESKEY_binary_default}} : ${OCF_RESKEY_config=${OCF_RESKEY_config_default}} : ${OCF_RESKEY_agent_config=${OCF_RESKEY_agent_config_default}} : ${OCF_RESKEY_user=${OCF_RESKEY_user_default}} : ${OCF_RESKEY_pid=${OCF_RESKEY_pid_default}} : ${OCF_RESKEY_log_file=${OCF_RESKEY_log_file_default}} : ${OCF_RESKEY_debug=${OCF_RESKEY_debug_default}} ####################################################################### usage() { cat < 1.0 Resource agent for the OpenStack Neutron Metadata Agent May manage a neutron-metadata-agent instance or a clone set that creates a distributed neutron-metadata-agent cluster. Manages the OpenStack OVS Service (${OCF_RESKEY_binary}) Location of the Neutron Metadata Agent binary Neutron Metadata Agent binary Location of the OpenStack Neutron Service (neutron-server) configuration file OpenStack OVS Server (neutron-server) config file Location of the OpenStack Neutron Metadata Agent configuration file OpenStack Neutron Metadata Agent config file User running Neutron Metadata Agent service (${OCF_RESKEY_binary}) OpenStack Neutron Metadata Agent service (${OCF_RESKEY_binary}) user The pid file to use for this Neutron Metadata Agent service (${OCF_RESKEY_binary}) instance OpenStack Neutron Metadata Agent service (${OCF_RESKEY_binary}) pid file The log file to use for this OpenStack Metadata Service (${OCF_RESKEY_binary}) instance OpenStack Metadata Service (${OCF_RESKEY_binary}) log file The debug flag for OpenStack Metadata Service (${OCF_RESKEY_binary}) instance OpenStack Metadata Service (${OCF_RESKEY_binary}) debug flag END } get_worker_pid() { local options local pid # FIXME: Remove if condition and set 'falo' statically once Fuel # discontinue support of Ubuntu 12.04 and CentOs 6.x where -a was not defined. if pgrep -V | awk 'match($0, /[0-9]\.[0-9].*/) {if (substr($0, RSTART, RLENGTH) < 3.3) {exit 1}}'; then options='falo' else options='flo' fi pid=`pgrep -u ${OCF_RESKEY_user} -${options} ${OCF_RESKEY_binary} | awk '/python \/usr\/bin/ {print $1}'` echo $pid } ####################################################################### # Functions invoked by resource manager actions neutron_metadata_agent_validate() { local rc check_binary $OCF_RESKEY_binary check_binary netstat # A config file on shared storage that is not available # during probes is OK. if [ ! -f $OCF_RESKEY_config ]; then if ! ocf_is_probe; then ocf_log err "Config $OCF_RESKEY_config doesn't exist" return $OCF_ERR_INSTALLED fi ocf_log_warn "Config $OCF_RESKEY_config not available during a probe" fi getent passwd $OCF_RESKEY_user >/dev/null 2>&1 rc=$? if [ $rc -ne 0 ]; then ocf_log err "User $OCF_RESKEY_user doesn't exist" return $OCF_ERR_INSTALLED fi true } neutron_metadata_agent_status() { local pid local f_pid local rc # check and make PID file dir local PID_DIR="$( dirname ${OCF_RESKEY_pid} )" if [ ! -d "${PID_DIR}" ] ; then ocf_log debug "Create pid file dir: ${PID_DIR} and chown to ${OCF_RESKEY_user}" mkdir -p "${PID_DIR}" chown -R ${OCF_RESKEY_user} "${PID_DIR}" chmod 755 "${PID_DIR}" fi pid=`get_worker_pid` if [ "xxx$pid" == "xxx" ] ; then ocf_log warn "OpenStack Neutron agent '$OCF_RESKEY_binary' not running." return $OCF_NOT_RUNNING fi # Check PID file and create if need if [ ! -f $OCF_RESKEY_pid ] ; then ocf_log warn "OpenStack Neutron agent (${OCF_RESKEY_binary}) was run, but no PID file found." ocf_log warn "Writing PID='$pid' to '$OCF_RESKEY_pid' for '${OCF_RESKEY_binary}' worker..." echo $pid > $OCF_RESKEY_pid return $OCF_SUCCESS fi # compare PID from file with PID from `pgrep...` f_pid=`cat $OCF_RESKEY_pid | tr '\n' ' ' | awk '{print $1}'` if [ "xxx$pid" == "xxx$f_pid" ]; then return $OCF_SUCCESS fi # at this point we have PID file and PID from it # defferents with PID from `pgrep...` if [ ! -d "/proc/$f_pid" ] || [ "xxx$f_pid" == "xxx" ] ; then # process with PID from PID-file not found ocf_log warn "Old PID file $OCF_RESKEY_pid found, but no running processes with PID=$f_pid found." ocf_log warn "PID-file will be re-created (with PID=$pid)." echo $pid > $OCF_RESKEY_pid return $OCF_SUCCESS fi # at this point we have alien PID-file and running prosess with this PID. ocf_log warn "Another daemon (with PID=$f_pid) running with PID file '$OCF_RESKEY_pid'. My PID=$pid" return $OCF_ERR_GENERIC } neutron_metadata_agent_monitor() { neutron_metadata_agent_status rc=$? return $rc } neutron_metadata_agent_start() { local rc neutron_metadata_agent_status rc=$? if [ $rc -eq $OCF_SUCCESS ]; then ocf_log info "OpenStack Neutron Metadata Agent (${OCF_RESKEY_binary}) already running" return $OCF_SUCCESS fi # run and detach to background Neutron-metadata-agent as daemon. # Don't use ocf_run as we're sending the tool's output to /dev/null su ${OCF_RESKEY_user} -s /bin/sh -c "${OCF_RESKEY_binary} --config-file=$OCF_RESKEY_config \ --config-file=$OCF_RESKEY_agent_config --log-file=$OCF_RESKEY_log_file $OCF_RESKEY_additional_parameters \ >> /dev/null"' 2>&1 & echo \$! > $OCF_RESKEY_pid' ocf_log debug "Create pid file: ${OCF_RESKEY_pid} with content $(cat ${OCF_RESKEY_pid})" # Spin waiting for the server to come up. # Let the CRM/LRM time us out if required while true; do neutron_metadata_agent_monitor rc=$? [ $rc -eq $OCF_SUCCESS ] && break if [ $rc -ne $OCF_NOT_RUNNING ] ; then ocf_log err "OpenStack (${OCF_RESKEY_binary}) start failed" exit $OCF_ERR_GENERIC fi sleep 3 done ocf_log info "OpenStack Neutron Metadata Agent (${OCF_RESKEY_binary}) started" return $OCF_SUCCESS } neutron_metadata_agent_stop() { local rc local pid neutron_metadata_agent_status rc=$? if [ $rc -eq $OCF_NOT_RUNNING ]; then ocf_log info "OpenStack Neutron Metadata Agent (${OCF_RESKEY_binary}) already stopped" return $OCF_SUCCESS fi # Try SIGTERM pid=`get_worker_pid` if [ "xxx$pid" == "xxx" ] ; then ocf_log warn "OpenStack Neutron Metadata Agent (${OCF_RESKEY_binary}) not running." #return $OCF_NOT_RUNNING return $OCF_SUCCESS fi ocf_run kill -s TERM $pid rc=$? if [ $rc -ne 0 ]; then ocf_log err "OpenStack Neutron Metadata Agent (${OCF_RESKEY_binary}) couldn't be stopped" exit $OCF_ERR_GENERIC fi # stop waiting shutdown_timeout=15 if [ -n "$OCF_RESKEY_CRM_meta_timeout" ]; then shutdown_timeout=$((($OCF_RESKEY_CRM_meta_timeout/1000)-5)) fi count=0 while [ $count -lt $shutdown_timeout ]; do neutron_metadata_agent_status rc=$? if [ $rc -eq $OCF_NOT_RUNNING ]; then break fi count=`expr $count + 1` sleep 1 ocf_log debug "OpenStack Neutron Metadata Agent (${OCF_RESKEY_binary}) still hasn't stopped yet. Waiting ..." done neutron_metadata_agent_status rc=$? if [ $rc -ne $OCF_NOT_RUNNING ]; then # SIGTERM didn't help either, try SIGKILL ocf_log info "OpenStack Neutron Metadata Agent (${OCF_RESKEY_binary}) failed to stop after ${shutdown_timeout}s \ using SIGTERM. Trying SIGKILL ..." ocf_run kill -s KILL $pid fi ocf_log info "OpenStack Neutron Metadata Agent (${OCF_RESKEY_binary}) stopped" ocf_log debug "Delete pid file: ${OCF_RESKEY_pid} with content $(cat ${OCF_RESKEY_pid})" rm -f $OCF_RESKEY_pid return $OCF_SUCCESS } ####################################################################### case "$1" in meta-data) meta_data exit $OCF_SUCCESS;; usage|help) usage exit $OCF_SUCCESS;; esac # Anything except meta-data and help must pass validation neutron_metadata_agent_validate || exit $? umask 0022 # What kind of method was invoked? case "$1" in start) neutron_metadata_agent_start;; stop) neutron_metadata_agent_stop;; status) neutron_metadata_agent_status;; monitor) neutron_metadata_agent_monitor;; validate) neutron_metadata_agent_validate;; validate-all) neutron_metadata_agent_validate;; *) usage exit $OCF_ERR_UNIMPLEMENTED;; esac