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