Parse Your Cisco Devices To Reconcile Customer Information
Since I work for a datacenter, we have a LOT of ports. Our customers hang off of a handful of pieces of equipment, but we have a lot of density on these devices. Every so often we run the numbers for how much bandwidth is subscribed to each customer as well as how much are they contracted for. We also check to see how much bandwidth we have subscribed in total.
As you can imagine, it takes forever and a day to run all this information…and I just don’t have the patience for that! I wrote two scripts. One goes out to a list of devices, logs in and dumps the configs as well as interface status to a text file. The second script goes through these and parses out the info and comma separates everything. I can then take the files and reconcile in just a couple hours…which is about all the patience I have for paperwork…hehehe.
Here’s the first script. You will need to create a text file for this guy to read devices from. Name the file devices.txt and put it in the program’s root folder. Entries will need to be like below:
If you are using ACS, make your entry like below:
core-router-1,1.1.1.1,ACS
If you are just using passwords, then make your entries like this:
core-router-2,2.2.2.2,password1,password2
You can mix and match passworded devices with ACS devices.
Here are the compiled files if you don’t want to compile it yourself: Cisco-Inventory (3294 downloads)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 | ; this was shamelessly borrowed from the forums...I have no idea who the original poster was! #include <File.au3> #include <Array.au3> #include <GUIConstants.au3> DirCreate(@ScriptDir & "\parse") $MoveNext = 1 ;TCP starten TCPStartup () ;GUI Creation GuiCreate("Telnet Client", 500, 390,-1, -1 ) ;----------> GUI Control Creation Anfang <---------- ;Edit Control für Chat Text $Edit = GuiCtrlCreateEdit("", 10, 10, 480, 330) ;Input Control für Chat Text Eingabe $Input = GuiCtrlCreateInput("", 10, 360, 480, 20) ;-----------> GUI Control Creation Ende <----------- ;GUI sichtbar machen GUISetState () Dim $aSwitches, $Connection, $eingabe If Not _FileReadToArray(@ScriptDir & "\devices.txt",$aSwitches) Then MsgBox(4096,"Error", " Please create the file devices.txt in this folder. It needs to have the format:" & @CRLF & "Description,IPaddress,ACS for acs clients or Description,IPAddress,Password1,Password2") Exit EndIf $UserName = "" for $d = 1 to $aSwitches[0] if StringInStr($aSwitches[$d],",ACS") > 1 and $UserName == "" Then ;this guy is an acs device, ask for username and password $UserName = InputBox("username","Put your friggin username here") $Password = InputBox("Password", "Put your friggin password here") EndIf Next For $x = 1 to $aSwitches[0] ;pull with telnet ToolTip($aSwitches[$x],0,0) $MoveNext = 1 _PullConfs() Next _CleanFiles() Func _PullConfs () $Connection = TCPConnect ( StringMid($aSwitches[$x],StringInStr($aSwitches[$x],",") + 1,StringInStr($aSwitches[$x],",",0,2) - StringInStr($aSwitches[$x],",") - 1), 23 ) ;<<<<<<<<<< change the port If @error Then Exit $Uname = 0 $Pword = 0 $More = 0 $MoresHit = 0 While 1 = $MoveNext $msg = GuiGetMsg() If $msg = $GUI_EVENT_CLOSE Then Exit $recv = TCPRecv ( $Connection,2048 ) If $recv <> "" Then if StringRight($recv,10) == "Username: " Then $Uname = 1 EndIf if StringRight($recv,10) == "Password: " Then $Pword = 1 EndIf if StringRight($recv,10) == " --More-- " Then $More = 1 EndIf $text = GUICtrlRead ( $Edit ) GUICtrlSetData ( $Edit,$text & $recv ) ControlSend ( "Telnet Client","", $Edit, "{ENTER}") EndIf if StringRight($recv,1) == "#" Then if $MoresHit = 0 Then $MoresHit = 1 _IssueCommand() sleep(1800) $eingabe = "show int | inc Ethernet" sleep(1000) _IssueCommand() else $eingabe = "exit" _IssueCommand() _WriteFile () GUICtrlSetData ( $Edit,"") TCPCloseSocket($Connection) $MoveNext = 0 EndIf EndIf if $More == 1 Then sleep(100) $eingabe = Chr ( 32 ) TCPSend ( $Connection, $eingabe) $More = 0 EndIf if $Uname == 1 Then $eingabe = $UserName _IssueCommand() $Uname = 0 EndIf if $Pword == 1 Then if StringInStr($aSwitches[$x],",ACS") == 0 Then $eingabe = StringMid($aSwitches[$x],StringInStr($aSwitches[$x],",",0,2) + 1,StringInStr($aSwitches[$x],",",0,3) - StringInStr($aSwitches[$x],",",0,2) - 1) _IssueCommand() sleep(5000) $eingabe = "en" _IssueCommand() sleep(5000) $eingabe = stringmid($aSwitches[$x],StringInStr($aSwitches[$x],",",0,3) + 1) _IssueCommand() Else $eingabe = $Password sleep(800) _IssueCommand() EndIf $Pword = 0 sleep(2000) $eingabe = @CRLF _IssueCommand() sleep(1000) $eingabe = "show run" _IssueCommand () Sleep(1000) EndIf WEnd EndFunc Func _IssueCommand () TCPSend ( $Connection, $eingabe & Chr ( 10 ) ) If @error Then MsgBox (0,"","Error") Exit EndIf EndFunc Func _WriteFile () $file = FileOpen(FileGetShortName(@ScriptDir) & "\parse\" & StringLeft($aSwitches[$x],StringInStr($aSwitches[$x],",") - 1) & ".txt", 2) ; Check if file opened for writing OK If $file = -1 Then MsgBox(0, "Error", "Unable to open file.") Exit EndIf FileWrite($file, GUICtrlRead ( $Edit )) ;ToolTip(GUICtrlRead ( $Edit ),0,0) FileClose($file) EndFunc Func _CleanFiles () For $x = 1 to $aSwitches[0] Dim $aCleaners ;MsgBox(0,"",@ScriptDir & "\" & $aSwitches[$x] & "\.txt") If Not _FileReadToArray(@ScriptDir & "\parse\" & StringLeft($aSwitches[$x],StringInStr($aSwitches[$x],",") - 1) & ".txt",$aCleaners) Then MsgBox(4096,"Error", " Error reading log to Array error:" & @error) Exit EndIf For $z = 1 to $aCleaners[0] ;Msgbox(0,'Record:' & $z, $aCleaners[$z]) $aCleaners[$z] = StringReplace($aCleaners[$z]," ","") ; --More-- $aCleaners[$z] = StringReplace($aCleaners[$z]," --More-- ","") Next _FileWriteFromArray(@ScriptDir & "\parse\" & StringLeft($aSwitches[$x],StringInStr($aSwitches[$x],",") - 1) & ".txt",$aCleaners,1) Next MsgBox(0,"Done","pulledem all") Exit EndFunc |
Here’s the script that actually parses the config. It creates a CSV file that is listed as thus:
hostname,interface,description,ip address,subnet mask,bandwidth,port status
Bandwidth is whatever the port is configured to with a service policy. If there is no service policy, then it uses the ports physical rate limit. If the port is down or admin down, it sets this value to 0.
Port status is up, down or admin down.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 | ;here we gooooooooooo #include <file.au3> #Include <Array.au3> ;#########parse the pulled file####################### $FileList=_FileListToArray(@ScriptDir & "\parse") If @Error=1 Then MsgBox (0,"","No Files\Folders Found.") Exit EndIf for $y = 1 to $FileList[0] $hostname = "" $interface = "" $ipAddress = "" $subnet = "" $ratelimit = "" $interfaceDesc = "" $intStarted = 0 $exclimationMarks = 0 Local $aCompleted[1] $aCompleted[0] = "0" Dim $aParse If Not _FileReadToArray(@ScriptDir & "\parse\" & $FileList[$y],$aParse) Then MsgBox(4096,"Error", " Error reading log to Array error:" & @error) Exit EndIf For $x = 1 to $aParse[0] ;find hostname if StringInStr("-" & $aParse[$x], "hostname") > 1 and stringInStr("-" & $aParse[$x], "hostname") < 4 Then ;found hostname $hostname = StringMid($aParse[$x],9) EndIf ;look for interfaces if StringInStr("-" & $aParse[$x], "interface") > 1 Then ;mark that we have found the first interface $intStarted = 1 $exclimationMarks = 0 ;set interface name $interface = StringMid($aParse[$x],10) ;set default rate limit based on interface name if StringInStr("-" & $aParse[$x], "Giga") > 1 Then ;gigabit interface, set the RL to 1000 $ratelimit = 1000 Elseif StringInStr("-" & $aParse[$x], "Fast") > 1 Then $ratelimit = 100 Else $ratelimit = 0 EndIf EndIf ;look for description if StringInStr("-" & $aParse[$x], "description") > 1 Then ;found desc $interfaceDesc = StringMid($aParse[$x],13) EndIf ;look for ip address if StringInStr("-" & $aParse[$x], "ip address") > 1 and StringInStr("-" & $aParse[$x], "ip address") < 4 Then ;found address $subnet = StringMid($aParse[$x],StringInStr($aParse[$x],"255")) $ipAddress = StringMid($aParse[$x], 12, StringInStr($aParse[$x]," ",0,4) - 12) EndIf ;look for rate limit if StringInStr("-" & $aParse[$x], "service-policy") > 1 Then ;found SP $ratelimit = StringMid($aParse[$x],StringInStr($aParse[$x]," ",0,3) + 1) $ratelimit = StringLeft($ratelimit,StringLen($ratelimit) - 3) EndIf ;look for switch port with access vlan if StringInStr("-" & $aParse[$x], "switchport access vlan") > 1 Then ;found access port $ipAddress = "vlan" & StringMid($aParse[$x],StringInStr($aParse[$x]," ", 0,4) + 1) EndIf ;look for switch port set as trunk if StringInStr("-" & $aParse[$x], "switchport mode trunk") > 1 Then ;found trunk port $ratelimit = 0 $ipAddress = "trunk port" EndIf ;look for ! that signals the end of interface if StringInStr("-" & $aParse[$x], "!") > 1 Then ;found ! $exclimationMarks = $exclimationMarks + 1 ;write all this good stuff, then clear if $intStarted == 1 and $exclimationMarks == 1 Then $aCompleted[0] = $aCompleted[0] + 1 _ArrayAdd($aCompleted, $hostname & "," & $interface & "," & $interfaceDesc & "," & $ipAddress & "," & $subnet & "," & $ratelimit) EndIf $interface = "" $ipAddress = "" $subnet = "" $ratelimit = "" $interfaceDesc = "" EndIf ;###start the parse of "show int | inc Ethernet" if StringInStr("-" & $aParse[$x], "line protocol") > 1 Then ;found interface info. Search through our existing array to find a match. for $z = 1 to $aCompleted[0] - 1 if StringInStr("-" & $aCompleted[$z], StringLeft($aParse[$x], StringInStr($aParse[$x], " ") - 1) & ",") > 1 Then ;we have our match! Append the status if StringInStr("-" & $aParse[$x], "administratively") > 1 Then $aCompleted[$z] = StringLeft($aCompleted[$z], StringInStr($aCompleted[$z],",",0,5)) & "0,admin down" ;also clear out RL elseif StringInStr("-" & $aParse[$x], "line protocol is down") > 1 Then ;also clear out RL $aCompleted[$z] = StringLeft($aCompleted[$z], StringInStr($aCompleted[$z],",",0,5)) & "0,down" elseif StringInStr("-" & $aParse[$x], "line protocol is up") > 1 Then $aCompleted[$z] = $aCompleted[$z] & ",up" EndIf EndIf Next EndIf Next FileDelete(@ScriptDir & "\" & StringLeft($FileList[$y],StringLen($FileList[$y]) - 4) & ".csv") _FileWriteFromArray(@ScriptDir & "\" & StringLeft($FileList[$y],StringLen($FileList[$y]) - 4) & ".csv",$aCompleted,1) Next |