#!/bin/bash

print_Usage() {
	echo -e "\033[1mUsage:\033[0m
   $( basename $0 ) <target> [<target> ...]

\033[1mFunction:\033[0m
   Retrieve asset information from a devices ENTITY-MIB::entPhysicalTable.

"
}

QUIET=1
FORMAT="tabulated"
TARGETS="$@"

if [ -z "$TARGETS" ]; then
	print_Usage "ERROR: Missing target(s)?"
fi

LAST_TARGET=""

get_snmp_creds() {
	local TARGET=$1
	echo "-v2c -cpublic"
}

output_asset_info() {
	local TARGET="$1"
        local CLASS="$2"
        local DESC="$3"
        local SN="$4"
        local FR="$5"
        local SR="$6"
        if [ "$FORMAT" = "standard" ]; then
		APPEND=""
                if [ -n "$SR" ]; then
                        APPEND=${APPEND}", S/W: $SR"
                fi
                if [ -n "$FR" ]; then
                        APPEND=${APPEND}", F/W: $FR"
                fi
		if [ -n "$SN" ]; then
			APPEND=${APPEND}", S/N: $SN"
		fi
		APPEND=${APPEND#, }
		if [ -n "$APPEND" ]; then
			APPEND=" ($APPEND)"
		fi
                if [ -n "$DESC" ]; then
                        echo "$TARGET: $CLASS: $DESC$APPEND"
                fi
        elif [ "$FORMAT" = "tabulated" ]; then
		if [ "$LAST_TARGET" != "$TARGET" ]; then
			LAST_TARGET="$TARGET"
	                echo -e "${TARGET}\t${CLASS}\t${DESC}\t${SR}\t${FR}\t${SN}"
		else
	                echo -e "\t${CLASS}\t${DESC}\t${SR}\t${FR}\t${SN}"
		fi
        fi
}

s_getval() {
	local TARGET=$1
	local OID=$2
	local SNMP_CREDS="$( get_snmp_creds $TARGET 2>/dev/null )"
	# Skip if target doesn't have SNMP credentials defined
	[ -z "$SNMP_CREDS" ] && return 0
	/usr/bin/snmpget $SNMP_CREDS -OQvt -Ir $EXTRA_SNMP_OPTS $TARGET $OID \
		| /bin/sed -e 's/.*No Such Instance currently exists at this OID.*//;s/.*No Such Object available on this agent at this OID.*//;'
}

get_asset_info() {
	local TARGET="$1"
	local SNMPRESULT SNMPRC DEVICE DEVICEIDX DEVICENAME LINE FILENAMES FILENAME PATTERN CHOICE DELETED_COUNTER

	local SNMP_CREDS="$( get_snmp_creds $TARGET 2>/dev/null )"
	# Skip if target doesn't have SNMP credentials defined
	[ -z "$SNMP_CREDS" ] && return 0

	local IPADDR=
	if type dig &>/dev/null ; then
		IPADDR=$( /usr/bin/dig -t A +short $TARGET )
	fi
	if [ -z "$IPADDR" ] && type gethostip &>/dev/null ; then
		IPADDR=$( gethostip "$TARGET" | awk '{print $2;}' )
	fi
	if [ -z "$IPADDR" ] ; then
		IPADDR=$( ping -q -c 1 "$TARGET" 2>&1 | awk '/^PING/ { print gensub("[()]", "", "g", $3); }' )
	fi
	# Skip if we cannot find an IP address
	[ -z "$IPADDR" ] && return 0

	# Start with a "software" line
	SW_VERSION=$( s_getval $TARGET SNMPv2-MIB::sysDescr.0 2>/dev/null )
	if [ -z "$SW_VERSION" ] ; then
		# Target doesn't seem to answer SNMP queries? Skip.
		return 0
	fi
	SW_VERSION=${SW_VERSION%%[$'\r\n']*}
	output_asset_info "$TARGET" "software" "$SW_VERSION" "" "" ""
	output_asset_info "$TARGET" "managementAddress" "$IPADDR" "" "" ""
        TMP=$( mktemp -t asset-info-XXXXXXXXXX )
        /usr/bin/snmptable $SNMP_OPTS $SNMP_CREDS -Ci -CH -Cf \; $TARGET ENTITY-MIB::entPhysicalTable > "$TMP"
	local ASSETS=() ASSET=
        while read ENTRY ; do
                OLD_IFS="$IFS"
                IFS=";"
                set -- $ENTRY
		if [ -n "$1" -a -z "${1//[0-9]/}" ] ; then
			ASSETS[$1]="$1;$2;$7;$4;$5;$9;${10};${11};${13};${16}"
		fi
                IFS=$OLD_IFS
        done < "$TMP"
	rm -f "$TMP"
	for ASSET in "${ASSETS[@]}" ; do
                OLD_IFS=$IFS
                IFS=";"
		set -- $ASSET
		AssetIndex=$1
                PhysicalDescr=$2
                PhysicalName=$3
		Parent=$4
                Class=$5
                FirmwareRev=$6
                SoftwareRev=$7
                SerialNum=$8
                ModelName=$9
                IsFRU=${10}
                IFS=$OLD_IFS
                # Trim
                PhysicalDescr=$( echo $PhysicalDescr | sed -e 's/\xff//g;s/[^a-zA-Z0-9 _\/-]//g;' )
                ModelName=$( echo $ModelName | sed -e 's/\xff//g;s/[^a-zA-Z0-9 _\/-]//g;' )
                SerialNum=$( echo $SerialNum )
		PhysicalDescr=${PhysicalDescr#Transceiver }
		PhysicalName=${PhysicalName#Transceiver }
		PhysicalName=${PhysicalName/TenGigabitEthernet/Te}
		PhysicalName=${PhysicalName/GigabitEthernet/Gi}
		PhysicalName=${PhysicalName/FastEthernet/Fa}
		if [ -n "$ModelName" -o -n "$SerialNum" ]; then
			if [ -z "$ModelName" -a -n "$PhysicalDescr" ] ; then
				ModelName="$PhysicalDescr"
			fi
			if [ "${PhysicalName#$ModelName}" = "$PhysicalName" -a "$PhysicalName" != "$PhysicalDescr" -a -n "${PhysicalName//[0-9]}" ] ; then
				ModelName="$ModelName ($PhysicalName)"
			else
				# Traverse upwards to second container and display this (typically the slot)
                		OLD_IFS=$IFS
		                IFS=";"
				while [ -n "$Parent" -a "$Parent" -ne 0 ] ; do
					Second=$1
					set -- ${ASSETS[$Parent]}
					Parent=$4
				done
				set -- ${ASSETS[$Second]}
				ModelName="$ModelName ($3)"
				IFS=$OLD_IFS
			fi
	                output_asset_info "$TARGET" "$Class" "$ModelName" "$SerialNum" "$FirmwareRev" "$SoftwareRev"
		fi
	done
}

for TARGET in $TARGETS ; do
	get_asset_info "$TARGET"
done


