Bulk-update

From Initech Technical Wiki
Revision as of 22:22, 9 May 2016 by Timprice (talk | contribs) (Created page with "<pre> #!/bin/bash # Written by Tim Price, 18/12/2014 # # The purpose of this script is to be able to apply carefully considered bulk updates to any number of rancid # managed...")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search
#!/bin/bash

# Written by Tim Price, 18/12/2014
#
# The purpose of this script is to be able to apply carefully considered bulk updates to any number of rancid
# managed devices easily and automatically.
# 
# This script takes one argument from the command line, a search string.  The search string could be all or part of 
# a device ip address, a device type (as defined in router.db and recognised by rancid) or device description(#1).
# The script will present a checkbox list (all items checked by default) of all the devices that match that search 
# parameter which will allow you to fine-tune your selection of devices to apply the update to.

# This will be followed by a multi-line text editing prompt where commands that would be valid for CLI input to 
# devices are entered.  The commands entered at the second prompt are not validated for syntax or sanity in any way,
# the user is trusted implicitely, therefore you must take extreme care.  It is recommended to lab test all code 
# used for bulk updates and carefully consider the list of hosts that the code will applied to.
#
# Also note that 'conf t' and 'wr mem' for cisco and 'configure' and 'commit' for juniper are not implied, they
# must be part of your script.
#
# (1). Device descriptions are formed by syncing Cacti information into the .cloginrc file for rancid to use.  the 
#      device descriptions are a concatination of the Cacti graph tree name and the device name and are stored as
#      hash (#) prefixed comments before each entry in the .cloginrc file for rancid.  Because the structure
#      of the .cloginrc file is maintained automatically by another script it is expected that the structure
#      will remain consistent to this format.
# 

declare MENU_TEMP=`mktemp`
declare COMMAND_TEMP=`mktemp`
declare COMMAND_TEMP2=`mktemp`
declare -a MENU_OPTIONS

function cleanup {
	unlink $MENU_TEMP
	unlink $COMMAND_TEMP
	unlink $COMMAND_TEMP2
	if [ ! -z $1 ]; then
		echo "#################################################"
		echo ""
		echo $1
		echo ""
		echo "#################################################"
	fi
	exit
}


# Bail out if the current user is not the 'rancid' user.  This is important because rancid basically doesn't
# work unless you're logged in as the rancid user.  `sudo su - rancid` fixes this normally.

if [ `whoami` != "rancid" ]; then
	cleanup "You must be the rancid user to run this, exiting"
fi


# Test to see if a search term was provided to the program at startup.  We don't care either way but the program
# behaviour will differ depending.  If no search term was provided then all the devices in the .cloginrc file
# are presented in the checkbox list for deselection.

if [ -z "$1" ] ; then
	IP_LIST=`cat ~rancid/.cloginrc | egrep "^add\s" |awk '{print $3}' | sort | uniq | grep -v "\*"`
else
	declare IP_LIST
	for GROUP in `grep '^LIST_OF_GROUPS' /etc/rancid/rancid.conf | sed -r -e "s/LIST_OF_GROUPS(\s*)?=(\s*)?\"(.*)\"/\3/"`
	do
		IP_LIST="$IP_LIST"`egrep -i $1 ~rancid/"${GROUP}"/routers.up | awk -F: '{print $1}'`
	done
	if [ -z "$IP_LIST" ]; then
		IP_LIST=`egrep -i -A 1 $1 ~rancid/.cloginrc | egrep "^add\s" |awk '{print $3}' | sort | uniq | grep -v "\*"`
	fi
fi

# If nothing matches the search term or there is nothing in the .cloginrc file then bail out.

if [ -z "$IP_LIST" ]; then
        $0 
	cleanup
fi

# This compiles the list of array of IP addresses, device descriptions and 'on' checkbox statuses for the dialog menu binary.

COUNT=0
for IP in $IP_LIST
do
	DESC=`egrep -B 1 "\s$IP\s" ~rancid/.cloginrc | egrep "^(\s*)?#" | sed -r -e "s/(\s*)?#(\s*)?//g"`
	MENU_OPTIONS=( "${MENU_OPTIONS[@]}" "${IP}" )
	MENU_OPTIONS=( "${MENU_OPTIONS[@]}" "${DESC}" )
        MENU_OPTIONS=( "${MENU_OPTIONS[@]}" "on" )
	COUNT=$((COUNT+1))
done

# Present the dialog checklist menu, save the selected items to the temporary file defined in the script header.  If no
# devices are selected then bail out and cleanup temp files.

if [ "$COUNT" -gt "0" ] ; then
	dialog --separate-output --checklist "The following devices match your search term of $1 please select one to connect" 0 0 0 "${MENU_OPTIONS[@]}" 2>$MENU_TEMP
	if [ "$?" != "0" ]; then
		cleanup
	else
		if [ ! -s $MENU_TEMP ]; then
			cleanup "No devices selected, exiting"
		fi
#		IP=$(<$MENU_TEMP)
	fi
else
	cleanup
fi

# Firstly echo some words of wisdom to the temporary file defined in the header for storing the device commands, then
# present it to the user for editing.  Save the output back to the same file.

echo "# Enter your commands here, hash (#) prepended lines will be ignored." > $COMMAND_TEMP
echo "# Remember to 'conf t' and 'wr mem' for cisco or 'configure' and 'commit' for juniper" >> $COMMAND_TEMP
echo "" >> $COMMAND_TEMP
echo "" >> $COMMAND_TEMP

dialog --editbox $COMMAND_TEMP 0 0 2> $COMMAND_TEMP2
if [ "$?" != "0" ]; then
	cleanup
fi

# Strip all the comments out of the command file

sed -i '/^#\|^\s#\|^\s*#\|^$/d' $COMMAND_TEMP2

# Bail out if there are no commands present in the command file after stripping out blank lines and comments

if [ ! -s $COMMAND_TEMP2 ]; then
	cleanup "No commands entered, exiting"
fi

# Load in IP addresses from first dialog for for each run the command file against it.

IPS=$(<$MENU_TEMP)

clear

for IP in $IPS
do
	for GROUP in `grep '^LIST_OF_GROUPS' /etc/rancid/rancid.conf | sed -r -e "s/LIST_OF_GROUPS(\s*)?=(\s*)?\"(.*)\"/\3/"`
	do
		TYPE=`grep "^${IP}:" ~rancid/${GROUP}"/router.db" | awk -F: '{print $2}'`
		LOGIN_COMMAND=`egrep "\s"\'"${TYPE}"\'"\s" ~rancid/bin/rancid-fe | awk '{print $3}' |sed -r -e s/\'\(,\)\?//g | xargs -I arg1 egrep "\s*open\(INPUT,\".*login " ~rancid/bin/arg1 |awk '{print $1}' |sed -e s/open\(INPUT,\"//`
		$LOGIN_COMMAND -x $COMMAND_TEMP2 $IP
	done
done
cleanup "Bulk update completed"