Bulk-update
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.
- 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.
#!/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"