#!/bin/sh # # # OpenStack Scheduler Service (nova-scheduler) # # Description: Manages an OpenStack Scheduler Service (nova-scheduler) process as an HA resource # # Authors: Sébastien Han # Mainly inspired by the Glance API resource agent written by Martin Gerhard Loschwitz from Hastexo: http://goo.gl/whLpr # # 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_user # OCF_RESKEY_pid # OCF_RESKEY_monitor_binary # OCF_RESKEY_database_server_port # OCF_RESKEY_amqp_server_port # OCF_RESKEY_zeromq # OCF_RESKEY_additional_parameters ####################################################################### # Initialization: : ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat} . ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs ####################################################################### # Fill in some defaults if no values are specified OCF_RESKEY_binary_default="nova-scheduler" OCF_RESKEY_config_default="/etc/nova/nova.conf" OCF_RESKEY_user_default="nova" OCF_RESKEY_pid_default="$HA_RSCTMP/$OCF_RESOURCE_INSTANCE.pid" OCF_RESKEY_database_server_port_default="3306" OCF_RESKEY_amqp_server_port_default="5672" OCF_RESKEY_zeromq_default="false" : ${OCF_RESKEY_binary=${OCF_RESKEY_binary_default}} : ${OCF_RESKEY_config=${OCF_RESKEY_config_default}} : ${OCF_RESKEY_user=${OCF_RESKEY_user_default}} : ${OCF_RESKEY_pid=${OCF_RESKEY_pid_default}} : ${OCF_RESKEY_database_server_port=${OCF_RESKEY_database_server_port_default}} : ${OCF_RESKEY_amqp_server_port=${OCF_RESKEY_amqp_server_port_default}} : ${OCF_RESKEY_zeromq=${OCF_RESKEY_zeromq_default}} ####################################################################### usage() { cat < 1.0 Resource agent for the OpenStack Nova Scheduler Service (nova-scheduler) May manage a nova-scheduler instance or a clone set that creates a distributed nova-scheduler cluster. Manages the OpenStack Scheduler Service (nova-scheduler) Location of the OpenStack Nova Scheduler server binary (nova-scheduler) OpenStack Nova Scheduler server binary (nova-scheduler) Location of the OpenStack Scheduler Service (nova-scheduler) configuration file OpenStack Nova Scheduler (nova-scheduler) config file User running OpenStack Scheduler Service (nova-scheduler) OpenStack Scheduler Service (nova-scheduler) user The pid file to use for this OpenStack Scheduler Service (nova-scheduler) instance OpenStack Scheduler Service (nova-scheduler) pid file The listening port number of the database server. Use for monitoring purposes Database listening port The listening port number of the AMQP server. Use for monitoring purposes AMQP listening port If zeromq is used, this will disable the connection test to the AMQP server. Use for monitoring purposes Zero-MQ usage Additional parameters to pass on to the OpenStack Scheduler Service (nova-scheduler) Additional parameters for nova-scheduler END } ####################################################################### # Functions invoked by resource manager actions nova_scheduler_check_port() { # This function has been taken from the squid RA and improved a bit # The length of the integer must be 4 # Examples of valid port: "1080", "0080" # Examples of invalid port: "1080bad", "0", "0000", "" local int local cnt int="$1" cnt=${#int} echo $int |egrep -qx '[0-9]+(:[0-9]+)?(,[0-9]+(:[0-9]+)?)*' if [ $? -ne 0 ] || [ $cnt -ne 4 ]; then ocf_log err "Invalid port number: $1" exit $OCF_ERR_CONFIGURED fi } nova_scheduler_validate() { local rc check_binary $OCF_RESKEY_binary check_binary netstat nova_scheduler_check_port $OCF_RESKEY_database_server_port nova_scheduler_check_port $OCF_RESKEY_amqp_server_port # 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 } nova_scheduler_status() { local pid local rc if [ ! -f $OCF_RESKEY_pid ]; then ocf_log info "OpenStack Nova Scheduler (nova-scheduler) is not running" return $OCF_NOT_RUNNING else pid=`cat $OCF_RESKEY_pid` fi ocf_run -warn kill -s 0 $pid rc=$? if [ $rc -eq 0 ]; then return $OCF_SUCCESS else ocf_log info "Old PID file found, but OpenStack Nova Scheduler (nova-scheduler) is not running" return $OCF_NOT_RUNNING fi } nova_scheduler_monitor() { local rc local pid local rc_db local rc_amqp local scheduler_db_check local scheduler_amqp_check nova_scheduler_status rc=$? # If status returned anything but success, return that immediately if [ $rc -ne $OCF_SUCCESS ]; then return $rc fi # Check the connections according to the PID. # We are sure to hit the scheduler process and not other nova process with the same connection behavior (for example nova-cert) if ocf_is_true "$OCF_RESKEY_zeromq"; then pid=`cat $OCF_RESKEY_pid` scheduler_db_check=`netstat -punt | grep -s "$OCF_RESKEY_database_server_port" | grep -s "$pid" | grep -qs "ESTABLISHED"` rc_db=$? if [ $rc_db -ne 0 ]; then ocf_log err "Nova Scheduler is not connected to the database server: $rc_db" return $OCF_NOT_RUNNING fi else pid=`cat $OCF_RESKEY_pid` scheduler_db_check=`netstat -punt | grep -s "$OCF_RESKEY_database_server_port" | grep -s "$pid" | grep -qs "ESTABLISHED"` rc_db=$? scheduler_amqp_check=`netstat -punt | grep -s "$OCF_RESKEY_amqp_server_port" | grep -s "$pid" | grep -qs "ESTABLISHED"` rc_amqp=$? if [ $rc_amqp -ne 0 ] || [ $rc_db -ne 0 ]; then ocf_log err "Nova Scheduler is not connected to the AMQP server and/or the database server: AMQP connection test returned $rc_amqp and database connection test returned $rc_db" return $OCF_NOT_RUNNING fi fi ocf_log debug "OpenStack Nova Scheduler (nova-scheduler) monitor succeeded" return $OCF_SUCCESS } nova_scheduler_start() { local rc nova_scheduler_status rc=$? if [ $rc -eq $OCF_SUCCESS ]; then ocf_log info "OpenStack Nova Scheduler (nova-scheduler) already running" return $OCF_SUCCESS fi # run the actual nova-scheduler daemon. Don't use ocf_run as we're sending the tool's output # straight to /dev/null anyway and using ocf_run would break stdout-redirection here. su ${OCF_RESKEY_user} -s /bin/sh -c "${OCF_RESKEY_binary} --config-file=$OCF_RESKEY_config \ $OCF_RESKEY_additional_parameters"' >> /dev/null 2>&1 & echo $!' > $OCF_RESKEY_pid # Spin waiting for the server to come up. while true; do nova_scheduler_monitor rc=$? [ $rc -eq $OCF_SUCCESS ] && break if [ $rc -ne $OCF_NOT_RUNNING ]; then ocf_log err "OpenStack Nova Scheduler (nova-scheduler) start failed" exit $OCF_ERR_GENERIC fi sleep 1 done ocf_log info "OpenStack Nova Scheduler (nova-scheduler) started" return $OCF_SUCCESS } nova_scheduler_stop() { local rc local pid nova_scheduler_status rc=$? if [ $rc -eq $OCF_NOT_RUNNING ]; then ocf_log info "OpenStack Nova Scheduler (nova-scheduler) already stopped" return $OCF_SUCCESS fi # Try SIGTERM pid=`cat $OCF_RESKEY_pid` ocf_run kill -s TERM $pid rc=$? if [ $rc -ne 0 ]; then ocf_log err "OpenStack Nova Scheduler (nova-scheduler) 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 nova_scheduler_status rc=$? if [ $rc -eq $OCF_NOT_RUNNING ]; then break fi count=`expr $count + 1` sleep 1 ocf_log debug "OpenStack Nova Scheduler (nova-scheduler) still hasn't stopped yet. Waiting ..." done nova_scheduler_status rc=$? if [ $rc -ne $OCF_NOT_RUNNING ]; then # SIGTERM didn't help either, try SIGKILL ocf_log info "OpenStack Nova Scheduler (nova-scheduler) failed to stop after ${shutdown_timeout}s \ using SIGTERM. Trying SIGKILL ..." ocf_run kill -s KILL $pid fi ocf_log info "OpenStack Nova Scheduler (nova-scheduler) stopped" 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 nova_scheduler_validate || exit $? # What kind of method was invoked? case "$1" in start) nova_scheduler_start;; stop) nova_scheduler_stop;; status) nova_scheduler_status;; monitor) nova_scheduler_monitor;; validate-all) ;; *) usage exit $OCF_ERR_UNIMPLEMENTED;; esac