Blame contrib/bmc-snmp-proxy

Packit Service ed0f68
#!/bin/sh
Packit Service ed0f68
#############################################################################
Packit Service ed0f68
#
Packit Service ed0f68
# bmc-snmp-proxy:	Set SNMP proxy to BMC (Baseboard Management Controller)
Packit Service ed0f68
#
Packit Service ed0f68
# version:	0.62
Packit Service ed0f68
#
Packit Service ed0f68
# Authors:	Charles Rose <charles_rose@dell.com>
Packit Service ed0f68
#		Jordan Hargrave <jordan_hargrave@dell.com>
Packit Service ed0f68
#
Packit Service ed0f68
# Description:  Script to set snmp proxy to the BMC for certain OID
Packit Service ed0f68
#		See here for details:
Packit Service ed0f68
#		https://fedoraproject.org/wiki/Features/AgentFreeManagement
Packit Service ed0f68
#
Packit Service ed0f68
# Assumptions:  This script will work only when /etc/snmp/ is writable.
Packit Service ed0f68
#
Packit Service ed0f68
#############################################################################
Packit Service ed0f68
# GLOBALS
Packit Service ed0f68
#############################################################################
Packit Service ed0f68
SYSCONF_DIR="/etc/sysconfig"
Packit Service ed0f68
CONFIG="${SYSCONF_DIR}/bmc-snmp-proxy"
Packit Service ed0f68
Packit Service ed0f68
SNMPD_BMC_CONF_DIR="/etc/snmp/bmc"
Packit Service ed0f68
SNMPD_BMC_CONF="${SNMPD_BMC_CONF_DIR}/snmpd.local.conf"
Packit Service ed0f68
TRAPD_BMC_CONF="${SNMPD_BMC_CONF_DIR}/snmptrapd.local.conf"
Packit Service ed0f68
Packit Service ed0f68
TRAPD_CONF="/etc/snmp/snmptrapd.conf"
Packit Service ed0f68
Packit Service ed0f68
LOCKFILE="/var/lock/subsys/bmc-snmp-proxy"
Packit Service ed0f68
BMC_INFO="/var/run/bmc-info"
Packit Service ed0f68
Packit Service ed0f68
IPMITOOL=`which ipmitool`
Packit Service ed0f68
Packit Service ed0f68
#Default config
Packit Service ed0f68
BMC_COMMUNITY="public"
Packit Service ed0f68
BMC_OID=".1.3.6.1.4.1.674.10892.2"  # Dell iDRAC
Packit Service ed0f68
TRAP_FORWARD="no"
Packit Service ed0f68
RELOAD_SERVICES="yes"
Packit Service ed0f68
Packit Service ed0f68
#############################################################################
Packit Service ed0f68
Packit Service ed0f68
#TODO: Use inotify and daemonize when $BMC_INFO changes
Packit Service ed0f68
Packit Service ed0f68
# source config
Packit Service ed0f68
[ -r ${CONFIG} ] && . ${CONFIG}
Packit Service ed0f68
Packit Service ed0f68
. gettext.sh
Packit Service ed0f68
Packit Service ed0f68
SCRIPT_NAME=$(basename $0)
Packit Service ed0f68
RETVAL=0
Packit Service ed0f68
Packit Service ed0f68
# Check if bmc-info created by exchange-bmc-os-info
Packit Service ed0f68
bmc_info_exists()
Packit Service ed0f68
{
Packit Service ed0f68
	if [ -r "${BMC_INFO}" ]; then
Packit Service ed0f68
		. ${BMC_INFO}
Packit Service ed0f68
	else
Packit Service ed0f68
		RETVAL=2
Packit Service ed0f68
	fi
Packit Service ed0f68
Packit Service ed0f68
	return $RETVAL
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
check_snmp()
Packit Service ed0f68
{
Packit Service ed0f68
	if [ ! -d /etc/snmp ] || [ ! -x /usr/sbin/snmpd ]; then
Packit Service ed0f68
		RETVAL=12
Packit Service ed0f68
	fi
Packit Service ed0f68
Packit Service ed0f68
	return $RETVAL
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
#############################################################################
Packit Service ed0f68
# configure SNMP proxy
Packit Service ed0f68
#############################################################################
Packit Service ed0f68
write_snmp_conf()
Packit Service ed0f68
{
Packit Service ed0f68
	# SNMPv3 security: bmcview, bmc_ctx, bmc_sec, bmc_grp, bmc_cmty
Packit Service ed0f68
	printf "###############################################\n"
Packit Service ed0f68
	printf "# Automatically created by %s #\n" "${SCRIPT_NAME}"
Packit Service ed0f68
	printf "###############################################\n"
Packit Service ed0f68
	printf "#view bmcview included %s 80\n" "${BMC_OID}"
Packit Service ed0f68
	printf "#com2sec -Cn bmc_ctx bmc_sec default bmc_cmty\n"
Packit Service ed0f68
	printf "#group bmc_grp v1 bmc_sec\n"
Packit Service ed0f68
	printf "#access bmc_grp bmc_ctx any noauth exact bmcview none none\n"
Packit Service ed0f68
	printf "#proxy -Cn bmc_ctx -v 1 %s\n" "${PROXY_TOKEN}"
Packit Service ed0f68
	printf "proxy -v 1 %s\n" "${PROXY_TOKEN}"
Packit Service ed0f68
	printf "###############################################\n"
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
valid_ip()
Packit Service ed0f68
{
Packit Service ed0f68
        #Thanks to mkyong.com
Packit Service ed0f68
        octet="([01]?[[:digit:]][[:digit:]]?|2[0-4][[:digit:]]|25[0-5])"
Packit Service ed0f68
Packit Service ed0f68
        printf -- "%s" "${1}"| grep -Eq \
Packit Service ed0f68
		"^${octet}\\.${octet}\\.${octet}\\.${octet}$"
Packit Service ed0f68
Packit Service ed0f68
        return $?
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
check_vars()
Packit Service ed0f68
{
Packit Service ed0f68
	[ -z ${BMC_COMMUNITY} ] && BMC_COMMUNITY="public"
Packit Service ed0f68
	[ -z ${BMC_OID} ] && return 1
Packit Service ed0f68
Packit Service ed0f68
	if [ -n "${BMC_IPv4}" ] && valid_ip ${BMC_IPv4}; then
Packit Service ed0f68
		return 0
Packit Service ed0f68
	else
Packit Service ed0f68
		return 1
Packit Service ed0f68
	fi
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
set_snmp_proxy()
Packit Service ed0f68
{
Packit Service ed0f68
	if check_vars; then
Packit Service ed0f68
		PROXY_TOKEN="-c ${BMC_COMMUNITY} ${BMC_IPv4} ${BMC_OID}"
Packit Service ed0f68
Packit Service ed0f68
		if [ -d ${SNMPD_BMC_CONF_DIR} ]; then
Packit Service ed0f68
			write_snmp_conf > ${SNMPD_BMC_CONF} || RETVAL=4
Packit Service ed0f68
		fi
Packit Service ed0f68
	else
Packit Service ed0f68
		RETVAL=3
Packit Service ed0f68
	fi
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
set_snmpd_conf_path()
Packit Service ed0f68
{
Packit Service ed0f68
	if [ ! -d ${SNMPD_BMC_CONF_DIR} ]; then
Packit Service ed0f68
		mkdir ${SNMPD_BMC_CONF_DIR} || RETVAL=7
Packit Service ed0f68
	fi
Packit Service ed0f68
Packit Service ed0f68
	# We need SNMPCONFPATH set for both snmpd and snmptrapd
Packit Service ed0f68
	for sysconf in ${SYSCONF_DIR}/snmp*d;
Packit Service ed0f68
	do
Packit Service ed0f68
		if ! grep -q "^SNMPCONFPATH.*${SNMPD_BMC_CONF_DIR}" \
Packit Service ed0f68
			"${sysconf}" > /dev/null 2>&1; then
Packit Service ed0f68
			printf "SNMPCONFPATH=/etc/snmp:%s\n" \
Packit Service ed0f68
				"${SNMPD_BMC_CONF_DIR}" >> ${sysconf} || \
Packit Service ed0f68
				RETVAL=7
Packit Service ed0f68
		fi
Packit Service ed0f68
	done
Packit Service ed0f68
Packit Service ed0f68
	return $RETVAL
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
disable_snmp_proxy()
Packit Service ed0f68
{
Packit Service ed0f68
	if [ -f ${SNMPD_BMC_CONF} ]; then
Packit Service ed0f68
		rm -f ${SNMPD_BMC_CONF} || RETVAL=5
Packit Service ed0f68
	fi
Packit Service ed0f68
}
Packit Service ed0f68
#############################################################################
Packit Service ed0f68
# Trap Forwarding
Packit Service ed0f68
#############################################################################
Packit Service ed0f68
Packit Service ed0f68
pick_alert_dest()
Packit Service ed0f68
{
Packit Service ed0f68
	test_ip="$1"
Packit Service ed0f68
	# We have 4 IPv4 and 4 IPv6 alert dest. We will set IPv4 for now.
Packit Service ed0f68
	for ALERT_DEST in `seq 1 4`
Packit Service ed0f68
	do
Packit Service ed0f68
		temp_ip=$(${IPMITOOL} lan alert print ${CHANNEL} ${ALERT_DEST}\
Packit Service ed0f68
			2>/dev/null| sed -n "s#^Alert IP Address.*: ##p")
Packit Service ed0f68
Packit Service ed0f68
		[ "${temp_ip}" = "${test_ip}" ] && return 0
Packit Service ed0f68
	done
Packit Service ed0f68
	return 1
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
set_alert_dest_ip()
Packit Service ed0f68
{
Packit Service ed0f68
	${IPMITOOL} lan alert set ${CHANNEL} ${ALERT_DEST} ipaddr ${1} \
Packit Service ed0f68
		retry 4 type pet >/dev/null 2>&1 || RETVAL=8
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
config_bmc_alert_dest()
Packit Service ed0f68
{
Packit Service ed0f68
	# call with enable|disable
Packit Service ed0f68
	# Pick the first active LAN channel
Packit Service ed0f68
        for CHANNEL in `seq 1 14`
Packit Service ed0f68
        do
Packit Service ed0f68
                [ $(${IPMITOOL} -I open channel info ${CHANNEL} 2>/dev/null \
Packit Service ed0f68
                        | grep -q "802\.3") ] || break
Packit Service ed0f68
        done
Packit Service ed0f68
Packit Service ed0f68
	# If TRAPD_IP is already set as an alert dest,
Packit Service ed0f68
	if pick_alert_dest "${TRAPD_IP}"; then
Packit Service ed0f68
		# disable: reset it if we are called with disable
Packit Service ed0f68
		[ "${1}" = "disable" ] && \
Packit Service ed0f68
			set_alert_dest_ip "0.0.0.0"
Packit Service ed0f68
	# else, find the next free alert dest,
Packit Service ed0f68
	elif pick_alert_dest "0.0.0.0"; then
Packit Service ed0f68
		[ "${1}" = "disable" ] && \
Packit Service ed0f68
			return $RETVAL
Packit Service ed0f68
		# set: the TRAPD_IP
Packit Service ed0f68
		set_alert_dest_ip "${TRAPD_IP}"
Packit Service ed0f68
	else
Packit Service ed0f68
		# No free alert destinations
Packit Service ed0f68
		RETVAL=9
Packit Service ed0f68
	fi
Packit Service ed0f68
Packit Service ed0f68
	return $RETVAL
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
set_ipmi_pef()
Packit Service ed0f68
{
Packit Service ed0f68
	# Needs ipmitool-1.8.13 + patches
Packit Service ed0f68
	${IPMITOOL} pef policy set ${ALERT_DEST} "${1}" >/dev/null 2>&1 || \
Packit Service ed0f68
		RETVAL=10
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
get_host_ip()
Packit Service ed0f68
{
Packit Service ed0f68
	# Get host's IP that the BMC can reach. This is at best a hack.
Packit Service ed0f68
	IFACE=$(/usr/sbin/ip -o -f inet address |awk '!/: lo/ {print $2}')
Packit Service ed0f68
Packit Service ed0f68
	for dev in ${IFACE}
Packit Service ed0f68
	do
Packit Service ed0f68
		temp_ping=$(ping -c 1 -I ${dev} ${BMC_IPv4})
Packit Service ed0f68
		[ $? -ne 0 ] && continue
Packit Service ed0f68
Packit Service ed0f68
		printf -- "%s" "$temp_ping"| awk 'NR==1{print $5}' && break
Packit Service ed0f68
	done
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
config_bmc_alert()
Packit Service ed0f68
{
Packit Service ed0f68
	# Do two things
Packit Service ed0f68
	# Set/Reset TRAP IP in BMC
Packit Service ed0f68
	# Enable/Disable PEF alerting in BMC for TRAP
Packit Service ed0f68
Packit Service ed0f68
	# Get Host's IP that the BMC can send traps to
Packit Service ed0f68
	TRAPD_IP=$(get_host_ip)
Packit Service ed0f68
Packit Service ed0f68
	# Set Host's IP as the alert destination in the BMC
Packit Service ed0f68
	valid_ip ${TRAPD_IP} && config_bmc_alert_dest "${ACTION}"
Packit Service ed0f68
Packit Service ed0f68
	# Enable/Disable alerting on the LAN channel
Packit Service ed0f68
	[ $RETVAL -eq 0 ] && set_ipmi_pef "${ACTION}"
Packit Service ed0f68
Packit Service ed0f68
	return $RETVAL
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
write_trapd_conf()
Packit Service ed0f68
{
Packit Service ed0f68
	printf "###############################################\n"
Packit Service ed0f68
	printf "# Automatically created by %s #\n" "${SCRIPT_NAME}"
Packit Service ed0f68
	printf "forward default %s\n" "${FORWARD_HOST}"
Packit Service ed0f68
	printf "###############################################\n"
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
config_trapd()
Packit Service ed0f68
{
Packit Service ed0f68
	# Proceed only if snmptrapd is available on the system
Packit Service ed0f68
	if [ -f ${TRAPD_CONF} ]; then
Packit Service ed0f68
		write_trapd_conf > ${TRAPD_BMC_CONF} || RETVAL=11
Packit Service ed0f68
	else
Packit Service ed0f68
		RETVAL=11
Packit Service ed0f68
	fi
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
trap_sink_exists()
Packit Service ed0f68
{
Packit Service ed0f68
	# TODO: We only set the first match. We should be able to set
Packit Service ed0f68
	# multiple
Packit Service ed0f68
	FORWARD_HOST=$(awk '/^trap.*sink/{print $2}; /^informsink/{print $2}' \
Packit Service ed0f68
			/etc/snmp/snmpd*conf | head -1)
Packit Service ed0f68
Packit Service ed0f68
	if [ -z "${FORWARD_HOST}" ]; then
Packit Service ed0f68
		# there is no trapsink setup.
Packit Service ed0f68
		return 1
Packit Service ed0f68
	else
Packit Service ed0f68
		return 0
Packit Service ed0f68
	fi
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
# Forward SNMP traps from the BMC to trapsink.
Packit Service ed0f68
trap_forward()
Packit Service ed0f68
{
Packit Service ed0f68
	NO_TRAP=0
Packit Service ed0f68
	ACTION=${1} # enable or disable
Packit Service ed0f68
Packit Service ed0f68
	if [ "${ACTION}" = "enable" ]; then
Packit Service ed0f68
		# Get trapd config,
Packit Service ed0f68
		if trap_sink_exists; then
Packit Service ed0f68
			config_bmc_alert && config_trapd
Packit Service ed0f68
		else
Packit Service ed0f68
			# exit silently if there is no sink
Packit Service ed0f68
			NO_TRAP=1
Packit Service ed0f68
		fi
Packit Service ed0f68
	else
Packit Service ed0f68
		if [ -f ${TRAPD_BMC_CONF} ]; then
Packit Service ed0f68
			rm -f ${TRAPD_BMC_CONF} >/dev/null 2>&1
Packit Service ed0f68
			config_bmc_alert
Packit Service ed0f68
		else
Packit Service ed0f68
			NO_TRAP=1
Packit Service ed0f68
		fi
Packit Service ed0f68
	fi
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
#############################################################################
Packit Service ed0f68
service_reload()
Packit Service ed0f68
{
Packit Service ed0f68
	#TODO: do this in systemd
Packit Service ed0f68
	if [ ${RETVAL} -eq 0 ] && [ "${RELOAD_SERVICES}" = "yes" ]; then
Packit Service ed0f68
		service $1 reload
Packit Service ed0f68
		[ $? -ne 0 ] && RETVAL=6
Packit Service ed0f68
	fi
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
#############################################################################
Packit Service ed0f68
start()
Packit Service ed0f68
{
Packit Service ed0f68
	if bmc_info_exists && check_snmp; then
Packit Service ed0f68
		touch ${LOCKFILE}
Packit Service ed0f68
Packit Service ed0f68
		set_snmpd_conf_path && set_snmp_proxy
Packit Service ed0f68
		[ $RETVAL -eq 0 ] && service_reload snmpd
Packit Service ed0f68
Packit Service ed0f68
		if [ "${TRAP_FORWARD}" = "yes" ]; then
Packit Service ed0f68
			trap_forward "enable"
Packit Service ed0f68
			[ $RETVAL -eq 0 ] && [ $NO_TRAP -eq 0 ] && \
Packit Service ed0f68
				service_reload snmptrapd
Packit Service ed0f68
		fi
Packit Service ed0f68
	fi
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
#############################################################################
Packit Service ed0f68
stop()
Packit Service ed0f68
{
Packit Service ed0f68
	[ ! -f ${LOCKFILE} ] && return
Packit Service ed0f68
	if bmc_info_exists && check_snmp; then
Packit Service ed0f68
		disable_snmp_proxy
Packit Service ed0f68
		[ $RETVAL -eq 0 ] && service_reload snmpd
Packit Service ed0f68
Packit Service ed0f68
		if [ "${TRAP_FORWARD}" = "yes" ]; then
Packit Service ed0f68
			trap_forward "disable"
Packit Service ed0f68
			[ $RETVAL -eq 0 ] && [ $NO_TRAP -eq 0 ] && \
Packit Service ed0f68
				service_reload snmptrapd
Packit Service ed0f68
		fi
Packit Service ed0f68
Packit Service ed0f68
		rm -f ${LOCKFILE}
Packit Service ed0f68
	fi
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
#############################################################################
Packit Service ed0f68
status()
Packit Service ed0f68
{
Packit Service ed0f68
	eval_gettext "${SCRIPT_NAME}: snmp proxy to BMC is "
Packit Service ed0f68
	# Checking for lockfile is better.
Packit Service ed0f68
	#if grep -q "^proxy" "${SNMPD_BMC_CONF}" > /dev/null 2>&1 ; then
Packit Service ed0f68
	if [ -f ${LOCKFILE} ]; then
Packit Service ed0f68
		eval_gettext "set"
Packit Service ed0f68
	else
Packit Service ed0f68
		eval_gettext "not set"
Packit Service ed0f68
	fi
Packit Service ed0f68
Packit Service ed0f68
	echo
Packit Service ed0f68
	RETVAL=0
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
#############################################################################
Packit Service ed0f68
usage()
Packit Service ed0f68
{
Packit Service ed0f68
	eval_gettext "Usage: $0 {start|stop|status}"; echo 1>&2
Packit Service ed0f68
	RETVAL=1
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
#############################################################################
Packit Service ed0f68
# MAIN
Packit Service ed0f68
#############################################################################
Packit Service ed0f68
case "$1" in
Packit Service ed0f68
	start) start ;;
Packit Service ed0f68
	stop)  stop ;;
Packit Service ed0f68
	status)	status ;;
Packit Service ed0f68
	*) usage ;;
Packit Service ed0f68
esac
Packit Service ed0f68
Packit Service ed0f68
case "$RETVAL" in
Packit Service ed0f68
	0|1) ;;
Packit Service ed0f68
	2) eval_gettext "${SCRIPT_NAME}: failed to read ${BMC_INFO} " 1>&2 ;;
Packit Service ed0f68
	3) eval_gettext "${SCRIPT_NAME}: failed to get proxy config." 1>&2 ;;
Packit Service ed0f68
	4) eval_gettext "${SCRIPT_NAME}: failed to set ${SNMPD_BMC_CONF}." 1>&2 ;;
Packit Service ed0f68
	5) eval_gettext "${SCRIPT_NAME}: failed to disable snmp proxy." 1>&2 ;;
Packit Service ed0f68
	6) eval_gettext "${SCRIPT_NAME}: failed to reload snmpd." 1>&2 ;;
Packit Service ed0f68
	7) eval_gettext "${SCRIPT_NAME}: failed to set snmpd config." 1>&2 ;;
Packit Service ed0f68
	8) eval_gettext "${SCRIPT_NAME}: failed to set IPMI alert dest." 1>&2 ;;
Packit Service ed0f68
	9) eval_gettext "${SCRIPT_NAME}: no free IPMI alert dest." 1>&2 ;;
Packit Service ed0f68
	10) eval_gettext "${SCRIPT_NAME}: failed to set IPMI PEF." 1>&2 ;;
Packit Service ed0f68
	11) eval_gettext "${SCRIPT_NAME}: failed to write snmptrapd.conf." 1>&2 ;;
Packit Service ed0f68
	12) eval_gettext "${SCRIPT_NAME}: snmpd not found." 1>&2 ;;
Packit Service ed0f68
	*) eval_gettext "${SCRIPT_NAME}: unknown error." 1>&2 ;;
Packit Service ed0f68
esac
Packit Service ed0f68
Packit Service ed0f68
if [ ${RETVAL} -gt 1 ]; then
Packit Service ed0f68
        eval_gettext " Return code: ${RETVAL}"; echo
Packit Service ed0f68
fi
Packit Service ed0f68
Packit Service ed0f68
exit ${RETVAL}
Packit Service ed0f68
#############################################################################
Packit Service ed0f68
# end of file
Packit Service ed0f68
#############################################################################