Sync-cacti

From Initech Technical Wiki
Jump to: navigation, search

This script hauls a bunch of info out of your cacti database and updates your /etc/hosts file, your rancid router.db and .cloginrc files.

It has the following requirements and features:

  • Your hosts in cacti must be formatted with the IP address of the device in the hostname field and the name/description in the description field
  • Anything before the first space in the description will be considered to be the hostname and outputted to the /etc/hosts file with the IP address, anything after the first space will be included in the description for the purposes of the .cloginrc comment line which gets picked up by the con script.
    • It is a requirement to have a file called /etc/hosts.orig which contains your original hosts file. This file is used as the basis of your new /etc/hosts file every time this script runs.
  • The base graph tree that the device is a member of will be added to the start of the description, this is useful for designating separation between customers.
  • The host template name (exact match) is matched against hard coded cases in the code below and the .cloginrc output for that device crafted based on this setting alone. It assumes that your access methodology and passwords will be the same for all devices of each type. It is highly recommended to review the device types in the code below!
  • As part of the cleanup process it will remove any devices that you delete from Cacti, also in order to avoid clobbering manual changes to the .cloginrc file it is not recreated every time this sync script runs, instead the device is removed from the file line by line and the original file otherwise preserved. You can therefore define default parameters like usernames and passwords in the bottom of the .cloginrc file and they will not be clobbered.
  • The script will attempt to rename devices that you change the description of in Cacti. It doesn't handle special characters well so its recommended to avoid them. I know its something to do with the escaping of the sed commands in the script but i've been unable to fix it and any help that anyone might have to offer would be appreciated!

The Code

# cat /usr/local/bin/sync_cacti 
#!/bin/bash

SAVEIFS=$IFS
IFS=$(/bin/echo -en "\n\b")

unlink /etc/hosts.cacti

for LINE in `/bin/echo "select host.hostname as IP, SUBSTRING_INDEX( SUBSTRING_INDEX( description, ' ', 1 ) , ' ', -1 ) AS HOSTNAME, host.snmp_community as SNMP_COMMUNITY, host.snmp_version as SNMP_VERSION, host_template.name as TEMPLATE, CASE WHEN CONCAT(graph_tree.name,' - ', host.description) IS NULL OR CONCAT(graph_tree.name,' - ', host.description) = '' THEN host.description ELSE CONCAT(graph_tree.name,' - ', host.description) END as DESCRIPTION from host inner join host_template on host.host_template_id = host_template.id left join graph_tree_items on host.id = graph_tree_items.host_id left join graph_tree on graph_tree_items.graph_tree_id = graph_tree.id where host.hostname <> '127.0.0.1' and host.disabled <> 'on' order by host.hostname;" | /usr/bin/mysql -N -D cacti | /bin/sed -e 's/\t/,/g'`; do
	IP=`/bin/echo $LINE |/bin/awk -F, '{print $1}'`
	HOSTNAME=`/bin/echo $LINE |/bin/awk -F, '{print $2}'`
	SNMP_COMMUNITY=`/bin/echo $LINE |/bin/awk -F, '{print $3}'`
	SNMP_VERSION=`/bin/echo $LINE |/bin/awk -F, '{print $4}'`
	TEMPLATE=`/bin/echo $LINE |/bin/awk -F, '{print $5}'`
	DESCRIPTION=`/bin/echo $LINE |/bin/awk -F, '{print $6}'`
	FILENAME=$(/bin/echo $DESCRIPTION| /bin/sed -e 's/[]\/$*^|[]/\./g')
	unset USER
	unset PASSWORD
	unset CYPHER
        /bin/echo "${IP} ${HOSTNAME}" >> /etc/hosts.cacti
        case $SNMP_VERSION in
        "1")
                SNMP_VERSION="v1"
        ;;
        "2")
                SNMP_VERSION="v2c"
        ;;
        "3")
                SNMP_VERSION="v3"
        ;;
        esac
	case $TEMPLATE in
		"AT Switch (Alliedware)")
				TYPE="aw"
				METHOD="ssh"
				;;
		"AT Switch (AT8000 Series)")
				TYPE="at"
				METHOD="telnet"
				;;
		"AT Switch (X Series)")
				TYPE="cisco"
				METHOD="ssh"
				;;
		"Cisco Router")
				TYPE="cisco"
				METHOD="ssh"
				;;
        "Juniper EX")
                TYPE="juniper"
                METHOD="ssh"
                ;;
        "Juniper MX")
                TYPE="juniper"
                METHOD="ssh"
                ;;
        "Juniper SRX")
                TYPE="juniper"
                METHOD="ssh"
                ;;
        "Patton")
                TYPE="patton"
                METHOD="telnet"
                ;;
        "Audiocodes")
                TYPE="ac"
                METHOD="ssh"
				CYPHER="aes128-cbc"
				USER="Admin"
				PASSWORD="Admin Admin"
                ;;
        "FortiGate")
                TYPE="fortigate"
                METHOD="ssh"
                USER="admin"
                PASSWORD="1H@teTax"
                ;;
	*)
		continue
		;;
	esac
	/bin/echo "${HOSTNAME}:${TYPE}:up" >> ~rancid/managed_devices/router.db.new
	if ! /bin/egrep -q "\s$HOSTNAME\s" ~rancid/.cloginrc; then
		/bin/echo "Adding $DESCRIPTION to .cloginrc"
		/bin/echo "# $DESCRIPTION" >> ~rancid/.cloginrc.new
		/bin/echo "add method $HOSTNAME $METHOD" >> ~rancid/.cloginrc.new
		if [[ -n $CYPHER ]] ; then
			/bin/echo "add cyphertype $HOSTNAME $CYPHER" >> ~rancid/.cloginrc.new
		fi 
                if [[ -n $USER ]] ; then
                        /bin/echo "add user $HOSTNAME $USER" >> ~rancid/.cloginrc.new
                fi
                if [[ -n $PASSWORD ]] ; then
                        /bin/echo "add password $HOSTNAME $PASSWORD" >> ~rancid/.cloginrc.new
                fi

		/bin/cat ~rancid/.cloginrc >> ~rancid/.cloginrc.new
		/bin/mv ~rancid/.cloginrc.new ~rancid/.cloginrc && /bin/chown rancid:rancid ~rancid/.cloginrc && /bin/chmod 600 ~rancid/.cloginrc
	else
		OLD_COMMENT=`/bin/egrep -B 1 "\s${HOSTNAME}\s" ~rancid/.cloginrc |/bin/egrep "^#\s"`
		if [ "$OLD_COMMENT" != "# $DESCRIPTION" ]; then
			/bin/echo "Renaming: $OLD_COMMENT -> # $DESCRIPTION"
			ESCAPED_OLD_COMMENT=$(/bin/echo $OLD_COMMENT| /bin/sed -e 's/[]\/$*.^|[]/\\&/g')
			ESCAPED_DESCRIPTION=$(/bin/echo $DESCRIPTION| /bin/sed -e 's/[\/&]/\\&/g')
			/bin/sed -i".bak" -r -e "s/^${ESCAPED_OLD_COMMENT}$/# $ESCAPED_DESCRIPTION/" ~rancid/.cloginrc
		fi
	fi
done

/bin/mv ~rancid/managed_devices/router.db.new ~rancid/managed_devices/router.db && /bin/chown rancid:rancid ~rancid/managed_devices/router.db
cat /etc/hosts.orig > /etc/hosts && cat /etc/hosts.cacti >> /etc/hosts
scp -q /etc/hosts mgmt2.telesmart.co.nz:/etc/

# Remove old credentials that are no longer needed
for HOSTNAME in `/bin/grep '^add\s' ~rancid/.cloginrc | /bin/awk '{print $3}' |/bin/grep -v '^\*$' |/bin/sort | /usr/bin/uniq`; do
	if ! /bin/egrep -q "^${HOSTNAME}:" ~rancid/managed_devices/router.db; then
		/bin/echo "Removing $HOSTNAME from .cloginrc"
		/bin/sed -i".bak" -r "/\s${HOSTNAME}\s/d" ~rancid/.cloginrc
	fi
done

# Remove all empty lines
/bin/sed -i".bak" '/^$/d' ~rancid/.cloginrc 
/bin/sed -i".bak" '/./!d' ~rancid/.cloginrc

# Remove orphaned comments
for LINE in `/bin/grep '^#\s' ~rancid/.cloginrc`; do
	ESCAPED_LINE=$(/bin/echo $LINE| /bin/sed -e 's/[]\/$*.^|[]/\\&/g')
	if ! /bin/egrep -A 1 "^${ESCAPED_LINE}$" ~rancid/.cloginrc | /usr/bin/tail -1 | /bin/egrep -q "^add\s" ; then
		/bin/echo "Removing orphaned comment $LINE"
		/bin/sed -i".bak" -r "/^${ESCAPED_LINE}$/d" ~rancid/.cloginrc
	fi
done

IFS=$SAVEIFS