fuel-library/files/fuel-ha-utils/ocf/ocf-fuel-funcs

238 lines
7.2 KiB
Bash

#!/bin/bash
#
# Copyright 2015 Mirantis, Inc.
#
# 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.
#
# Shared resource script for common functions (ocf-fuel-funcs)
#
# Authors: Alex Schultz <aschultz@mirantis.com>
#
###########################################################
# Attempts to kill a process with retries and checks procfs
# to make sure the process is stopped.
#
# Globals:
# LL
# Arguments:
# $1 - pid of the process to try and kill
# $2 - service name used for logging and match-based kill, if the pid is "none"
# $3 - signal to use, defaults to SIGTERM
# $4 - number of retries, defaults to 5
# $5 - time to sleep between retries, defaults to 2
# Returns:
# 0 - if successful
# 1 - if process is still running according to procfs
# 2 - if invalid parameters passed in
###########################################################
proc_kill()
{
local pid="${1}"
local service_name="${2}"
local signal="${3:-SIGTERM}"
local count="${4:-5}"
local process_sleep="${5:-2}"
local LH="${LL} proc_kill():"
local pgrp="$(ps -o pgid= ${pid} 2>/dev/null | tr -d '[[:space:]]')"
if [ "${pid}" -a "${pgrp}" = "1" ] ; then
ocf_log err "${LH} shall not kill by the bad pid 1 (init)!"
return 2
fi
if [ "${pid}" = "none" ]; then
local matched
matched="$(pgrep -fla ${service_name})"
if [ -z "${matched}" ] ; then
ocf_log err "${LH} cannot find any processes matching the ${service_name}!"
return 2
fi
ocf_log debug "${LH} no pid provided, will try the ${service_name}, matched list: ${matched}"
while [ $count -gt 0 ]; do
if [ -z "${matched}" ]; then
break
else
matched="$(pgrep -fla ${service_name})"
ocf_log debug "${LH} Stopping ${service_name} with ${signal}..."
ocf_run pkill -f -"${signal}" "${service_name}"
fi
sleep $process_sleep
count=$(( count-1 ))
done
pgrep -f "${service_name}" > /dev/null
if [ $? -ne 0 ] ; then
ocf_log debug "${LH} Stopped ${service_name} with ${signal}"
return 0
else
ocf_log warn "${LH} Failed to stop ${service_name} with ${signal}"
return 1
fi
else
# pid is not none
while [ $count -gt 0 ]; do
if [ ! -d "/proc/${pid}" ]; then
break
else
ocf_log debug "${LH} Stopping ${service_name} with ${signal}..."
ocf_run pkill -"${signal}" -g "${pgrp}"
fi
sleep $process_sleep
count=$(( count-1 ))
done
# Check if the process ended after the last sleep
if [ ! -d "/proc/${pid}" ] ; then
ocf_log debug "${LH} Stopped ${service_name} with ${signal}"
return 0
fi
ocf_log warn "${LH} Failed to stop ${service_name} with ${signal}"
return 1
fi
}
###########################################################
# Attempts to kill a process with the given pid or pid file
# using proc_kill and will retry with sigkill if sigterm is
# unsuccessful.
#
# Globals:
# OCF_ERR_GENERIC
# OCF_SUCCESS
# LL
# Arguments:
# $1 - pidfile or pid
# $2 - service name used for logging
# $3 - stop process timeout (in sec), used to determine how many times we try
# SIGTERM and an upper limit on how long this function should try and
# stop the process. Defaults to 15.
# Returns:
# OCF_SUCCESS - if successful
# OCF_ERR_GENERIC - if process is still running according to procfs
###########################################################
proc_stop()
{
local pid_param="${1}"
local service_name="${2}"
local timeout="${3:-15}"
local LH="${LL} proc_stop():"
local i
local pid
local pidfile
# check if provide just a number
echo "${pid_param}" | egrep -q '^[0-9]+$'
if [ $? -eq 0 ]; then
pid="${pid_param}"
elif [ -e "${pid_param}" ]; then # check if passed in a pid file
pidfile="${pid_param}"
pid=$(cat "${pidfile}" 2>/dev/null | tr -s " " "\n" | sort -u)
else
ocf_log warn "${LH} pid param ${pid_param} is not a file or a number, try match by ${service_name}"
pid="none"
fi
# number of times to try a SIGTEM is (timeout - 5 seconds) / 2 seconds
local stop_count=$(( ($timeout-5)/2 ))
# make sure we stop at least once
if [ $stop_count -le 0 ]; then
stop_count=1
fi
if [ -z "${pid}" ] ; then
ocf_log warn "${LH} unable to get PID from ${pidfile}, try match by ${service_name}"
pid="none"
fi
if [ -n "${pid}" ]; then
for i in ${pid} ; do
[ "${i}" ] || break
ocf_log info "${LH} Stopping ${service_name} by PID ${i}"
proc_kill "${i}" "${service_name}" SIGTERM $stop_count
if [ $? -ne 0 ]; then
# SIGTERM failed, send a single SIGKILL
proc_kill "${i}" "${service_name}" SIGKILL 1 2
if [ $? -ne 0 ]; then
ocf_log err "${LH} ERROR: could not stop ${service_name}"
return "${OCF_ERR_GENERIC}"
fi
fi
done
fi
# Remove the pid file here which will remove empty pid files as well
if [ -n "${pidfile}" ]; then
rm -f "${pidfile}"
fi
ocf_log info "${LH} Stopped ${service_name}"
return "${OCF_SUCCESS}"
}
###########################################################
# Runs a process as root via su to get the whole PAM stack
# executed.
#
# Globals:
# none
# Arguments:
# $* - ocf_run arguments
# Returns:
# Return code of the ocf_run invocation.
###########################################################
ocf_run_as_root()
{
ocf_run su - root -c "$(printf '%q ' "$@")"
}
###########################################################
# Validate a port according to RFC 793
#
# Globals:
# LL
# Arguments:
# $1 - port for validation
# Returns:
# 0 - if port valid
# 1 - if port invalid
# 2 - if invalid parameters passed in
###########################################################
validate_port()
{
local port=$1
local LH="${LL} validate_port():"
if [ -z "${port}" ]; then
ocf_log info "${LH} Port provided is empty"
return 2
fi
case ${port} in
*[^0-9]*)
ocf_log info "${LH}: invalid port specified: $port"
return 1
;;
esac
# $port contains only digits, check if it's in the correct range
if [ $port -gt 65535 ] || [ $port -lt 1 ]; then
ocf_log err "${LH}: invalid port specified: $port"
return 1
else
ocf_log debug "${LH} got a valid port: $port"
return 0
fi
}
# vim: set ts=4 sw=4 tw=0 et :