Cisco CLI + TextFSM
W poprzednich wpisach pokazałem jak można wykorzystać Pythona i biblioteki Netmiko, Paramiko do wydawania komend w Cisco IOS. Tradycyjnie SSH jest używany do łączenia się z urządzeniem sieciowym, wydawania polecenia i zrzutu wyników zwykłego tekstu z powrotem do użytkownika.
W celu automatyzacji niektórych czynności musimy często wyniki z komend sformatować w sposób umożliwiający wydobywanie tylko niektórych informacji. W tym celu możemy posłużyć się biblioteką Pythona textFSM.
Zobaczmy jak korzystając z textFSM przetwarzać wyniki komend CISCO IOS. Do pracy z textFSM przyda się podstawowa wiedza z wyrażeń regularnych, jednak nie jest ona niezbędna. Pokaże jak szybko nauczyć się podstawowych wyrażeń regularnych. Budując wyrażenia regularne będziemy posługiwać się stroną regex101.com.
Przed przystąpieniem do pracy z textFSM musimy go zainstalować:
pip install textfsm Collecting textfsm Downloading textfsm-0.3.2.tar.gz Installing collected packages: textfsm Running setup.py install for textfsm ... done Successfully installed textfsm-0.3.2
a następnie w skrypcie Pythona musimy go zaimportować:
Python 2.7.14 (v2.7.14:84471935ed, Sep 16 2017, 20:25:58) [MSC v.1500 64 bit (AMD64)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> import textfsm
Załóżmy, że chcemy z routera Cisco wyciągnąć takie informacje jak:
- hostname,
- model,
- uptime,
- serial number,
- ios,
- software version.
Skrzystajmy więc z biblioteki netmiko i podłączmy się przez ssh do routera R1 o adresie IP 192.168.174.200 korzystając z użytkownika admin o haśle cisco i wydajmy polecenie show version.
>>> from netmiko import ConnectHandler >>> cisco = {'device_type':'cisco_ios','ip':'192.168.174.200','username':'admin','password':'cisco'} >>> net_connect = ConnectHandler(**cisco) >>> output = net_connect.send_command('show version') >>> ssh_connection.disconnect() >>> print output
Wynik komendy show version najlepiej zapisać w notatniku, bo przyda nam się do zbudowania wyrażeń regularnych:
Cisco IOS Software, 7200 Software (C7200-JK9S-M), Version 12.4(13b), RELEASE SOFTWARE (fc3) Technical Support: http://www.cisco.com/techsupport Copyright (c) 1986-2007 by Cisco Systems, Inc. Compiled Wed 25-Apr-07 03:18 by prod_rel_team ROM: ROMMON Emulation Microcode BOOTLDR: 7200 Software (C7200-JK9S-M), Version 12.4(13b), RELEASE SOFTWARE (fc3) R1 uptime is 1 minute System returned to ROM by unknown reload cause - suspect boot_data[BOOT_COUNT] 0x0, BOOT_COUNT 0, BOOTDATA 19 System image file is "tftp://255.255.255.255/unknown" This product contains cryptographic features and is subject to United States and local country laws governing import, export, transfer and use. Delivery of Cisco cryptographic products does not imply third-party authority to import, export, distribute or use encryption. Importers, exporters, distributors and users are responsible for compliance with U.S. and local country laws. By using this product you agree to comply with applicable laws and regulations. If you are unable to comply with U.S. and local laws, return this product immediately. A summary of U.S. laws governing Cisco cryptographic products may be found at: http://www.cisco.com/wwl/export/crypto/tool/stqrg.html If you require further assistance please contact us by sending email to export@cisco.com. Cisco 7206VXR (NPE400) processor (revision A) with 491520K/32768K bytes of memory. Processor board ID 4279256517 R7000 CPU at 150MHz, Implementation 39, Rev 2.1, 256KB L2 Cache 6 slot VXR midplane, Version 2.1 Last reset from power-on PCI bus mb0_mb1 (Slots 0, 1, 3 and 5) has a capacity of 600 bandwidth points. Current configuration on bus mb0_mb1 has a total of 600 bandwidth points. This configuration is within the PCI bus capacity and is supported. PCI bus mb2 (Slots 2, 4, 6) has a capacity of 600 bandwidth points. Current configuration on bus mb2 has a total of 0 bandwidth points This configuration is within the PCI bus capacity and is supported. Please refer to the following document "Cisco 7200 Series Port Adaptor Hardware Configuration Guidelines" on Cisco.com <http://www.cisco.com> for c7200 bandwidth points oversubscription and usage guidelines. 3 FastEthernet interfaces 509K bytes of NVRAM. 8192K bytes of Flash internal SIMM (Sector size 256K). Configuration register is 0x2102
Przykładowe użycie biblioteki wygląda następująco:
>>> re_table = textfsm.TextFSM(open("template.textfsm")) >>> fsm_results = re_table1.ParseText(output)
gdzie output to surowy tekst wyniku naszej komendy show version, a template.textfsm to plik zawierający szablon z wyrażeniami regularnymi dla naszej komendy show version i informacji które chcemy z niej wyciągnąć.
template.textfsm
Value hostname (\S+) Value model (\S+) Value uptime (.+) Value serial ([^ ,]+) Value ios (\S+) Value version ([^ ,]+) Start ^.*Software.*Version\s+${version} ^${hostname}\s+uptime\s+is\s+${uptime} ^Cisco\s+${model}.+ ^System\s+image\s+file\s+is\s+.${ios}. ^Processor\s+board\s+ID\s+${serial}
Sprawdźmy co zawiera zmienna fsm_results:
>>> print fsm_results [[u'R1', u'7206VXR', u'4 weeks, 1 day, 8 hours, 19 minutes', u'4279256517', u'tftp://255.255.255.255/unknown', u'12.4(13b)']]
Jest to tablica, z której w łatwy sposób możemy wyciągnać interesującą nas rzecz. Np. jeśli chcemy wyświetlić sam numer seryjny routera, wystarczy że wpiszemy:
>> fsm_results[0][3] u'4279256517'
Pokażę teraz jak stworzyć zawartość pliku template.textfsm. Otwórzmy stronę regex101.com i wklejmy w polu TEST STRING wynik komendy show version:
Strona powyższa pozwoli nam przetestować regex, który wyciąga odpowiednią informację. Najważniejsze regexy które należy znać to:
\s+ spacja występująca raz lub więcej razy
\S+ dowolny znak bez spacji występujących raz lub więcej razy
.+ dowolny znak występujący od 1 do nieskończoności razy
Jeśli nie znamy wyrażeń regularnych możemy skorzystać z pomocy na stronie regex101.com. Weźmy wyrażenie regularne którego nie znamy, np. [^ ,]+ i wklejmy w pole REGULAR EXPRESSION, otrzymamy taki wynik:
Po prawej stronie mamy wyjaśnienie (EXPLANATION) co robi dane wyrażenie regularne. W tym przypadku jest to dowolna znak, oprócz spacji i przecinka które występujący raz lub więcej razy.
Wróćmy teraz do textFSM. Zawartość pliku template.textfsm wygląda następująco:
Value wartosc1 regex Value wartosc2 regex Start ^regex ${wartosc1} ^regex ${wartosc2}
Domyślnie textFSM działa następująco. Parser textFSM tworzy tablice wartości [wartosc1,wartosc2,..] na podstawie szablonu template.textfsm. Najpierw sprawdzana jest pierwsza linijka tekstu – w moim przypadku jest to tekst ze zmiennej output (re_table1.ParseText(output)) i sprawdzane są wyrażenia regularne po kolei (Start ^regex -> ^regex …). Jeśli któreś wyrażenie regularne dla danej wartości pasuje, to zapisywana jest wartość wyrażenia regularnego do buforu. Następnie sprawdzana jest druga linijka i również dla drugiej linijki sprawdzane są wyrażenia regularne po kolei tak jak dla pierwszej linijki, jak któreś z nich pasuje, to zapisywana jest wartość tego wyrażenia do buforu. Na końcu bufor zawiera wartości dla pól Value, które są w takiej kolejności jak zadeklarowane wartości w pliku template.textfsm.
Najlepiej pokazać tworzenie zawartości pliku textfsm na przykladzie. Weźmy teraz dla przykładu ios. Do wyciągnięcia informacji o pliku z systemem IOS musimy stworzyć regex o postaci:
Jak widać z powyższego zrzutu ekranu, dokładnie taki regex wyciągnie nam informacje o IOS.
Value ios (\S+) ^System\s+image\s+file\s+is\s+.${ios}.
Więcej gotowych szablonów dla różnych komend dla różnych urządzeń znajduje się pod poniższym linkiem.
Polecam naukę wyrażeń regularnych, bo przydają się one bardzo często, chociażby do takich czynności jak praca z textfsm, które jest bardzo pomocnym narzędziem do automatyzacji pracy z urządzeniami sieciowymi.