1#!/bin/sh 2 3# 4# Analyze equipment configuration files and chain different phases 5# to build the network graph. 6# 7# Syntax: 8# $0 [-v] [-1] [-t] [eq ... eq] 9# 10# History : 11# 2004/06/08 : pda/jean : design 12# 2004/09/29 : pda/jean : remove generated files before new generation 13# 2006/06/01 : pda/jean : test snmp community 14# 2006/06/19 : pda/boggia : send sensors 15# 2007/07/17 : pda : rancid does not detect cisco access point model 16# 2008/10/01 : pda : add -1 mode ("at least once") 17# 2008/11/12 : pda/jean : add special equipment _vlan 18# 2010/11/17 : pda : adapt list-vlans 19# 2010/11/17 : pda/jean : stop sending sensors 20# 2010/11/23 : pda : remove status file 21# 2010/12/18 : pda : rework installation 22# 2012/01/18 : pda : rancidconfdir + ranciddb -> ranciddir 23# 24 25TMP=/tmp/topo.$$ 26TMPERR=/tmp/topoerr.$$ 27 28eval `%CONFPROG% \ 29 ranciddir \ 30 eqvirtdir \ 31 eqgendir \ 32 filterdir \ 33 topograph \ 34 topobindir \ 35 checkrouterif \ 36 ssidsensors \ 37 topocpgraph \ 38 ` 39vlanfile=$eqgendir/_vlan.eq 40 41VERBOSE=0 42 43############################################################################## 44# Utility functions 45############################################################################## 46 47verbose () 48{ 49 if [ $VERBOSE != 0 ] 50 then echo "$*" >&2 51 fi 52} 53 54usage () 55{ 56 echo "usage: anaconf [-v][-1][-t] [eq ...eq]" >&2 57 exit 1 58} 59 60############################################################################## 61# Phases to build the graph 62############################################################################## 63 64# 65# Get equipment list in the rancid configuration file, and extract 66# equipment model from the equipment configuration file. 67# 68 69list_rancid () 70{ 71 verbose "calling 'list-rancid'" 72 $topobindir/list-rancid $ranciddir/router.db $ranciddir/configs > $TMP 73 return $? 74} 75 76# 77# Clean-up the generation directory. This handles the case where 78# old equipments have been removed from rancid. 79# 80 81cleanup_eqgen () 82{ 83 if [ $# = 0 ] 84 then rm -f $eqgendir/* 85 fi 86 return 0 87} 88 89# 90# Get vlans list. 91# 92 93list_vlans () 94{ 95 verbose "calling 'list-vlans'" 96 $topobindir/list-vlans > $vlanfile 97 return $? 98} 99 100# 101# Extract informations from equipment configuration files 102# 103 104analyze_conf () 105{ 106 if [ $# = 0 ] 107 then 108 analyze_eq < $TMP 109 else 110 for eq 111 do 112 if [ "$eq" = "_vlan" ] 113 then : 114 elif [ -f "$eqvirtdir/$eq.eq" ] 115 then : 116 elif grep "^$eq " $TMP | analyze_eq 117 then : 118 else echo "$eq not found in list-rancid result" >&2 119 fi 120 done 121 fi 122 return 0 123} 124 125# 126# Filter to rewrite equipement configuration file. 127# Original configuration is simply "piped" to a program 128# 129 130filter () 131{ 132 eqtype=$1 133 infile=$2 134 135 # The filter program is called only if it exists in "filterdir" directory ; 136 # "filterdir" is a variable defined in the configuration file 137 138 if [ -n "$filterdir" -a -f "$filterdir/$eqtype" ] ; then 139 140 # The name of the program called is be the same as the equipment type 141 # Example: /usr/lib/netmagis/filters/cisco 142 143 $filterdir/$eqtype < $infile 144 else 145 cat $infile 146 fi 147} 148 149analyze_eq () 150{ 151 r=1 # 1 if no equipment found 152 while read name type model 153 do 154 # remove domain name 155 n=`echo $name | sed 's/\..*//'` 156 157 verbose "analyze $name" 158 # for an unknown reason, rancid does not detect model for 159 # some Cisco access points (not for all) 160 if [ x"$model" = x ] 161 then model="UNKNOWN" 162 fi 163 eqconf="/tmp/$name.$$" 164 filter $type $ranciddir/configs/$name > $eqconf 165 $topobindir/analyze $topobindir $type "$model" $eqconf $n \ 166 > $eqgendir/$n.eq 167 rm $eqconf 168 r=0 # at least one equipment found 169 done 170 return $r 171} 172 173# 174# Equipments not managed by rancid, just copy files (virtual files) 175# 176 177copy_eqvirt () 178{ 179 for nameeq in `ls $eqvirtdir | grep '\.eq$'` 180 do 181 cp $eqvirtdir/$nameeq $eqgendir/$nameeq 182 done 183 return 0 184} 185 186# 187# Local policy to get sensors for each ssid 188# 189 190ssidsensors () 191{ 192 if [ "$ssidsensors" = yes ] 193 then $topobindir/ssidsensors 194 else cat 195 fi 196} 197 198# 199# Graph generation 200# 201 202build_graph () 203{ 204 verbose "graph generation" 205 cat $eqgendir/* \ 206 | ssidsensors \ 207 | $topobindir/buildgraph > $topograph.tmp \ 208 && mv $topograph.tmp $topograph 209 return $? 210} 211 212# 213# Check that SNMP community is specified on all equipments 214# 215 216check_snmp () 217{ 218 verbose "SNMP community check" 219 r=0 220 WITHOUTSNMP=`$topobindir/dumpgraph < $topograph \ 221 | sed -n '/^eq .* snmp -$/s/eq \([^ ]*\) .*/\1/p'` 222 if [ "$WITHOUTSNMP" != "" ] 223 then 224 ( 225 echo "Warning : equipements without any SNMP community string" 226 echo "$WITHOUTSNMP" | sed 's/^/ /' 227 ) >&2 228 r=1 229 fi 230 return $r 231} 232 233# 234# Check that router interfaces are declared in the DNS 235# (not activated here) 236# 237 238check_dns () 239{ 240 verbose "checking DNS declaration of router interfaces" 241 if [ "checkrouterif" = "yes" ] 242 then 243 $topobindir/getnetif < $topograph | $topobindir/checkdns 244 fi 245 return 0 246} 247 248# 249# Copy graph to another host if configured 250# 251 252copy_graph () 253{ 254 if [ -n "$topocpgraph" -a -n "$topograph" ] 255 then 256 userhost=`echo "$topocpgraph" | cut -f1 -d:` 257 destfile=`echo "$topocpgraph" | cut -f2 -d:` 258 scp -q $topograph $userhost:$destfile.new && \ 259 ssh -q $userhost \ 260 "mv $destfile $destfile.old;mv $destfile.new $destfile" 261 fi 262 return 0 263} 264 265############################################################################## 266# Phase chaining 267############################################################################## 268 269chain () 270{ 271 list_rancid \ 272 && cleanup_eqgen $* \ 273 && list_vlans \ 274 && analyze_conf $* \ 275 && copy_eqvirt \ 276 && build_graph \ 277 && copy_graph \ 278 && check_snmp \ 279 && check_dns 280 return $? 281} 282 283execute () 284{ 285 if [ "$ONCE" = true -o "$TESTONLY" = true ] 286 then 287 chain $* 288 error=$? 289 else 290 rm -f $TMPERR 291 chain $* 2> $TMPERR 292 293 # 294 # Distinguish true errors (return code != 0) from inconsistencies 295 # detected by various tools (buildgraph for example): the last 296 # do not prevent graph building. 297 # 298 299 error=$? 300 if [ $error != 0 ] 301 then 302 if [ -s $TMPERR ] 303 then NEWERR="`cat $TMPERR`" 304 else NEWERR="Unknown error (no error message)" 305 fi 306 else 307 if [ -s $TMPERR ] 308 then NEWERR="`cat $TMPERR`" 309 fi 310 fi 311 312 # 313 # Display warning or error messages 314 # 315 316 if [ ! -z "$NEWERR" ] 317 then echo "$NEWERR" 318 fi 319 fi 320 321 return $error 322} 323 324############################################################################## 325# Main program 326############################################################################## 327 328# 329# Syntax checking 330# 331 332args=`getopt v1 $*` 333 334if [ $? != 0 ] 335then usage 336fi 337 338set -- $args 339 340TESTONLY=false 341for i in $* 342do 343 case "$i" in 344 -v) VERBOSE=1 345 shift 346 ;; 347 -1) ONCE=true 348 shift 349 ;; 350 --) shift 351 break 352 ;; 353 esac 354done 355 356if [ $? != 0 ] 357then usage 358fi 359 360# 361# Go! 362# 363 364execute $* 365error=$? 366 367# 368# Exit clean-up 369# 370 371rm -f $TMP $TMPERR 372exit $error 373