#!/bin/bash # # # OpenStack OVS Service # # Description: Manages an OpenStack OVS Service 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 ... # # OCF instance parameters: # OCF_RESKEY_binary # OCF_RESKEY_config # OCF_RESKEY_plugin_config # OCF_RESKEY_user # OCF_RESKEY_pid # OCF_RESKEY_additional_parameters ####################################################################### # Initialization: : ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat} . ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs : ${OCF_FUEL_FUNCTIONS_DIR=${OCF_ROOT}/resource.d/fuel} . ${OCF_FUEL_FUNCTIONS_DIR}/ocf-fuel-funcs ####################################################################### # Fill in some defaults if no values are specified OCF_RESKEY_binary_default="neutron-openvswitch-agent" OCF_RESKEY_config_default="/etc/neutron/neutron.conf" OCF_RESKEY_plugin_config_default="/etc/neutron/plugin.ini" OCF_RESKEY_user_default="neutron" OCF_RESKEY_pid_default="${HA_RSCTMP}/${__SCRIPT_NAME}/${__SCRIPT_NAME}.pid" OCF_RESKEY_segmentation_bridge_default="br-tun" OCF_RESKEY_log_file_default="/var/log/neutron/openvswitch-agent.log" OCF_RESKEY_debug_default='false' : ${HA_LOGTAG="ocf-neutron-ovs-agent"} : ${HA_LOGFACILITY="daemon"} : ${OCF_RESKEY_binary=${OCF_RESKEY_binary_default}} : ${OCF_RESKEY_config=${OCF_RESKEY_config_default}} : ${OCF_RESKEY_plugin_config=${OCF_RESKEY_plugin_config_default}} : ${OCF_RESKEY_user=${OCF_RESKEY_user_default}} : ${OCF_RESKEY_pid=${OCF_RESKEY_pid_default}} : ${OCF_RESKEY_segmentation_bridge=${OCF_RESKEY_segmentation_bridge_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 OVS Service (${OCF_RESKEY_binary}) May manage a neutron-ovs-agent instance or a clone set that creates a distributed neutron-ovs-agent cluster. Manages the OpenStack OVS Service (${OCF_RESKEY_binary}) Location of the OpenStack OVS agent binary (${OCF_RESKEY_binary}) OpenStack OVS agent binary (${OCF_RESKEY_binary}) Location of the OpenStack Neutron Service (neutron-server) configuration file OpenStack Neutron Server (neutron-server) config file Location of the OpenStack OVS agent (${OCF_RESKEY_binary}) configuration file OpenStack OVS agent (${OCF_RESKEY_binary}) config file User running OpenStack OVS Service (${OCF_RESKEY_binary}) OpenStack OVS Service (${OCF_RESKEY_binary}) user The pid file to use for this OpenStack OVS Service (${OCF_RESKEY_binary}) instance OpenStack OVS Service (${OCF_RESKEY_binary}) pid file Additional parameters to pass on to the OpenStack OVS Service (${OCF_RESKEY_binary}) Additional parameters for neutron-ovs-agent OVS integration bridge name OpenStack OVS Service (${OCF_RESKEY_binary}) Segmentation bridge name for neutron-ovs-agent The log file to use for this OpenStack OVS Service (${OCF_RESKEY_binary}) instance OpenStack OVS Service (${OCF_RESKEY_binary}) log file The debug flag for OpenStack OVS 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 '{print $1}'` echo $pid } ####################################################################### # Functions invoked by resource manager actions neutron_ovs_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 return ${OCF_SUCCESS} } neutron_ovs_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 #ocf_log debug "PID='$pid'" # 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_ovs_agent_monitor() { neutron_ovs_agent_status rc=$? return $rc } cleanup_agents_ovs_bridges() { # todo: remove ports, created by agent rc=0 } neutron_ovs_agent_start() { local rc neutron_ovs_agent_status rc=$? if [ $rc -eq $OCF_SUCCESS ]; then ocf_log info "OpenStack OVS agent (${OCF_RESKEY_binary}) already running" return $OCF_SUCCESS fi cleanup_agents_ovs_bridges # run and detach to background Neutron-ovs-agent as daemon. # Don't use ocf_run as we're sending the tool's output su ${OCF_RESKEY_user} -s /bin/sh -c "${OCF_RESKEY_binary} --config-file=$OCF_RESKEY_config \ --config-file=$OCF_RESKEY_plugin_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 sleep 3 neutron_ovs_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 done ocf_log info "OpenStack OVS agent (${OCF_RESKEY_binary}) started" return $OCF_SUCCESS } neutron_ovs_agent_stop() { local rc local pid local shutdown_timeout=15 if [ -n "$OCF_RESKEY_CRM_meta_timeout" ]; then shutdown_timeout=$(( ($OCF_RESKEY_CRM_meta_timeout/1000) )) fi neutron_ovs_agent_status rc=$? if [ $rc -eq $OCF_NOT_RUNNING ]; then cleanup_agents_ovs_bridges ocf_log info "OpenStack OVS agent (${OCF_RESKEY_binary}) already stopped" return $OCF_SUCCESS fi # Try SIGTERM pid=`get_worker_pid` proc_stop "${pid}" "${OCF_RESKEY_binary}" $shutdown_timeout rc=$? if [ "${rc}" -eq "${OCF_ERR_GENERIC}" ]; then ocf_log err "OpenStack OVS agent (${OCF_RESKEY_binary}) couldn't be stopped" exit $OCF_ERR_GENERIC fi cleanup_agents_ovs_bridges 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_ovs_agent_validate || exit $? umask 0022 # What kind of method was invoked? case "$1" in start) neutron_ovs_agent_start;; stop) neutron_ovs_agent_stop;; status) neutron_ovs_agent_status;; monitor) neutron_ovs_agent_monitor;; validate-all) ;; *) usage exit $OCF_ERR_UNIMPLEMENTED;; esac