summaryrefslogtreecommitdiff
path: root/contrib/bmc-snmp-proxy
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/bmc-snmp-proxy')
-rw-r--r--contrib/bmc-snmp-proxy381
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
+#############################################################################