123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403 |
- #!/bin/sh
- #############################################################################
- #
- # bmc-snmp-proxy: Set SNMP proxy to BMC (Baseboard Management Controller)
- #
- # version: 0.62
- #
- # 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_BMC_CONF_DIR="/etc/snmp/bmc"
- SNMPD_BMC_CONF="${SNMPD_BMC_CONF_DIR}/snmpd.local.conf"
- TRAPD_BMC_CONF="${SNMPD_BMC_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 "proxy -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_BMC_CONF_DIR} ]; then
- write_snmp_conf > ${SNMPD_BMC_CONF} || RETVAL=4
- fi
- else
- RETVAL=3
- fi
- }
- set_snmpd_conf_path()
- {
- if [ ! -d ${SNMPD_BMC_CONF_DIR} ]; then
- mkdir ${SNMPD_BMC_CONF_DIR} || RETVAL=7
- fi
- # We need SNMPCONFPATH set for both snmpd and snmptrapd
- for sysconf in ${SYSCONF_DIR}/snmp*d;
- do
- if ! grep -q "^SNMPCONFPATH.*${SNMPD_BMC_CONF_DIR}" \
- "${sysconf}" > /dev/null 2>&1; then
- printf "SNMPCONFPATH=/etc/snmp:%s\n" \
- "${SNMPD_BMC_CONF_DIR}" >> ${sysconf} || \
- RETVAL=7
- fi
- done
- return $RETVAL
- }
- disable_snmp_proxy()
- {
- if [ -f ${SNMPD_BMC_CONF} ]; then
- rm -f ${SNMPD_BMC_CONF} || RETVAL=5
- fi
- }
- #############################################################################
- # Trap Forwarding
- #############################################################################
- pick_alert_dest()
- {
- test_ip="$1"
- # We have 4 IPv4 and 4 IPv6 alert dest. We will set IPv4 for now.
- 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 || RETVAL=8
- }
- config_bmc_alert_dest()
- {
- # call with enable|disable
- # 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
- # disable: reset it if we are called with disable
- [ "${1}" = "disable" ] && \
- 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}" = "disable" ] && \
- return $RETVAL
- # set: the TRAPD_IP
- set_alert_dest_ip "${TRAPD_IP}"
- else
- # No free alert destinations
- RETVAL=9
- fi
- return $RETVAL
- }
- set_ipmi_pef()
- {
- # Needs ipmitool-1.8.13 + patches
- ${IPMITOOL} pef policy set ${ALERT_DEST} "${1}" >/dev/null 2>&1 || \
- RETVAL=10
- }
- get_host_ip()
- {
- # Get host's IP that the BMC can reach. This is at best a hack.
- IFACE=$(/usr/sbin/ip -o -f inet address |awk '!/: lo/ {print $2}')
- for dev in ${IFACE}
- do
- temp_ping=$(ping -c 1 -I ${dev} ${BMC_IPv4})
- [ $? -ne 0 ] && continue
- printf -- "%s" "$temp_ping"| awk 'NR==1{print $5}' && break
- done
- }
- config_bmc_alert()
- {
- # Do two things
- # Set/Reset TRAP IP in BMC
- # Enable/Disable PEF alerting in BMC for TRAP
- # 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} && config_bmc_alert_dest "${ACTION}"
- # Enable/Disable alerting on the LAN channel
- [ $RETVAL -eq 0 ] && set_ipmi_pef "${ACTION}"
- return $RETVAL
- }
- write_trapd_conf()
- {
- printf "###############################################\n"
- printf "# Automatically created by %s #\n" "${SCRIPT_NAME}"
- printf "forward default %s\n" "${FORWARD_HOST}"
- printf "###############################################\n"
- }
- config_trapd()
- {
- # Proceed only if snmptrapd is available on the system
- if [ -f ${TRAPD_CONF} ]; then
- write_trapd_conf > ${TRAPD_BMC_CONF} || RETVAL=11
- else
- RETVAL=11
- 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} # enable or disable
- if [ "${ACTION}" = "enable" ]; then
- # Get trapd config,
- if trap_sink_exists; then
- config_bmc_alert && config_trapd
- else
- # exit silently if there is no sink
- NO_TRAP=1
- fi
- else
- if [ -f ${TRAPD_BMC_CONF} ]; then
- rm -f ${TRAPD_BMC_CONF} >/dev/null 2>&1
- config_bmc_alert
- 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
- }
- #############################################################################
- 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 "enable"
- [ $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 "disable"
- [ $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_BMC_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_BMC_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 set snmpd config." 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
- #############################################################################
|