Im vorherigen Artikel habe ich TTP (Template Text Parser), eine Python-Parser-Bibliothek, verwendet, um die L2SW-Konfigurationsdatei zu analysieren und automatisch eine Portverwaltungstabelle zu generieren. Ich habe versucht, automatisch eine Portverwaltungstabelle aus L2SW Config zu generieren
Dieses Mal habe ich diesen Parser als benutzerdefinierten Ansible-Filter verwendet, damit ich das Ergebnis des Befehls show analysieren kann, das vom Modul xxx_command
erhalten wurde.
parse_cli_textfsm
mit TextFSM und parse_genie
mit pyATS / Genie (Installation von Ansible Galaxy erforderlich. Für Details [GitHub / parse_genie]]( (Https://github.com/clay584/parse_genie)).Ich habe Ansible verwendet, das in der virtuellen Umgebung von Python 3.6.7 installiert ist. Anfangs habe ich mit Version 2.9.0 getestet, aber ich verwende 2.8.4, weil ich mehrere KeyError-Meldungen (Logging Error) erhalten habe.
Eine zusätzliche TTP-Installation ist erforderlich.
(venv) [centos@localhost ansible]$ pip install ttp
Ich habe das folgende Python-Skript erstellt.
custom_filters_ttp.py
from ansible.errors import AnsibleError
#Importieren Sie ttp und json. Wenn der Import fehlschlägt, kann bei der nachfolgenden Verarbeitung ein Fehler ausgegeben werden.
try:
from ttp import ttp
HAS_TTP = True
except ImportError:
HAS_TTP = False
try:
import json
HAS_JSON = True
except ImportError:
HAS_JSON = False
class FilterModule(object):
def parse_cli_ttp(self, cli_output, template_file):
if not HAS_TTP:
raise AnsibleError('parse_cli_ttp filter requires TTP library to be installed')
if not HAS_JSON:
raise AnsibleError('parse_cli_ttp filter requires JSON library to be installed')
with open(template_file, 'rt') as ft:
ttp_template = ft.read()
# create parser object and parse data using template
parser = ttp(data=cli_output, template=ttp_template)
parser.parse()
# return result in JSON format
results = parser.result(format='json')[0]
return results
def filters(self):
return {
#Die linke Seite ist der im Playbook verwendete Filtername und die rechte Seite ist der zuzuordnende Funktionsname.
'parse_cli_ttp': self.parse_cli_ttp,
}
Nach der Best Practice haben wir ein filter_plugins-Verzeichnis unter dem Verzeichnis erstellt, in dem das Playbook gespeichert ist, und diese Datei darin gespeichert.
Außerdem wurden die Einstellungen in ansible.cfg wie folgt umgeschrieben, damit Ansible diesen benutzerdefinierten Filter erkennen kann.
ansible.cfg
[defaults]
filter_plugins = [Vollständiger Pfad des Playbook-Speicherverzeichnisses]/filter_plugins
Playbook Rufen Sie die laufende Konfiguration im Modul "ios_command" und im folgenden Modul "debug" die erhaltene Konfiguration und die im vorherigen Artikel (https://qiita.com/tech_kitara/items/75ec526ff9a27932c565) erstellte Konfiguration und die [Vorlage für die Einstellung der L2-Schnittstelle] ab # 3-l2% E3% 82% A4% E3% 83% B3% E3% 82% BF% E3% 83% BC% E3% 83% 95% E3% 82% A7% E3% 83% BC% E3% 82 % B9% E8% A8% AD% E5% AE% 9A) Dateipfad angegeben. Es ist einfach!
playbook_ttp.yml
---
- hosts: cisco
gather_facts: no
connection: network_cli
tasks:
- name: run show command on remote devices
ios_command:
commands: show running-config
register: result
- name: display parsed output
debug:
msg: "{{ result.stdout[0] | parse_cli_ttp('catalyst2960_template_ttp2.txt') }}"
Es gibt Unterschiede in den Ergebnissen, da sich die Konfiguration von der vorherigen unterscheidet, die Analyse selbst jedoch ohne Probleme durchgeführt wird.
$ ansible-playbook -i inventory_2960.ini playbook_ttp.yml
PLAY [cisco] *************************************************************************************************
TASK [run show command on remote devices] ********************************************************************
ok: [hqdist1A]
TASK [display parsed output] *********************************************************************************
ok: [hqdist1A] => {
"msg": [
{
"l2_interfaces": [
{
"description": "<< Connect hqdist1 and hqdist2 >>",
"duplex": "auto",
"mode": "trunk",
"port_no": "Port-channel1",
"portfast": "x",
"speed": "auto",
"status": "o",
"vlan": "1,101"
},
{
"description": "<< To hqborder1 Fa1 >>",
"duplex": "full",
"mode": "access",
"port_no": "FastEthernet0/1",
"portfast": "x",
"speed": "100",
"status": "o",
"vlan": "200"
},
{
"description": "<< To hqborder2 Fa1 >>",
"duplex": "full",
"mode": "access",
"port_no": "FastEthernet0/2",
"portfast": "x",
"speed": "100",
"status": "o",
"vlan": "202"
},
{
"description": "<< To hqaccess1 Fa0/23 >>",
"duplex": "full",
"mode": "access",
"port_no": "FastEthernet0/3",
"portfast": "x",
"speed": "100",
"status": "o",
"vlan": "100"
},
{
"duplex": "auto",
"mode": "trunk",
"port_no": "FastEthernet0/4",
"portfast": "x",
"speed": "auto",
"status": "o",
"vlan": "1"
},
{
"duplex": "auto",
"mode": "access",
"port_no": "FastEthernet0/5",
"portfast": "x",
"speed": "auto",
"status": "x",
"vlan": "1"
},
{
"duplex": "auto",
"mode": "access",
"port_no": "FastEthernet0/6",
"portfast": "x",
"speed": "auto",
"status": "x",
"vlan": "1"
},
{
"duplex": "auto",
"mode": "access",
"port_no": "FastEthernet0/7",
"portfast": "x",
"speed": "auto",
"status": "x",
"vlan": "1"
},
{
"duplex": "auto",
"mode": "access",
"port_no": "FastEthernet0/8",
"portfast": "x",
"speed": "auto",
"status": "x",
"vlan": "1"
},
{
"duplex": "auto",
"mode": "access",
"port_no": "FastEthernet0/9",
"portfast": "x",
"speed": "auto",
"status": "x",
"vlan": "1"
},
{
"duplex": "auto",
"mode": "access",
"port_no": "FastEthernet0/10",
"portfast": "x",
"speed": "auto",
"status": "x",
"vlan": "1"
},
{
"duplex": "auto",
"mode": "access",
"port_no": "FastEthernet0/11",
"portfast": "x",
"speed": "auto",
"status": "x",
"vlan": "1"
},
{
"duplex": "auto",
"mode": "access",
"port_no": "FastEthernet0/12",
"portfast": "x",
"speed": "auto",
"status": "o",
"vlan": "203"
},
{
"duplex": "auto",
"mode": "access",
"port_no": "FastEthernet0/13",
"portfast": "x",
"speed": "auto",
"status": "o",
"vlan": "100"
},
{
"duplex": "auto",
"mode": "access",
"port_no": "FastEthernet0/14",
"portfast": "x",
"speed": "auto",
"status": "x",
"vlan": "1"
},
{
"duplex": "auto",
"mode": "access",
"port_no": "FastEthernet0/15",
"portfast": "x",
"speed": "auto",
"status": "x",
"vlan": "1"
},
{
"duplex": "auto",
"mode": "access",
"port_no": "FastEthernet0/16",
"portfast": "x",
"speed": "auto",
"status": "x",
"vlan": "1"
},
{
"duplex": "auto",
"mode": "access",
"port_no": "FastEthernet0/17",
"portfast": "x",
"speed": "auto",
"status": "x",
"vlan": "1"
},
{
"duplex": "auto",
"mode": "access",
"port_no": "FastEthernet0/18",
"portfast": "x",
"speed": "auto",
"status": "x",
"vlan": "1"
},
{
"duplex": "auto",
"mode": "access",
"port_no": "FastEthernet0/19",
"portfast": "x",
"speed": "auto",
"status": "x",
"vlan": "1"
},
{
"duplex": "auto",
"mode": "access",
"port_no": "FastEthernet0/20",
"portfast": "x",
"speed": "auto",
"status": "x",
"vlan": "1"
},
{
"duplex": "auto",
"mode": "access",
"port_no": "FastEthernet0/21",
"portfast": "x",
"speed": "auto",
"status": "x",
"vlan": "1"
},
{
"duplex": "auto",
"mode": "access",
"port_no": "FastEthernet0/22",
"portfast": "x",
"speed": "auto",
"status": "x",
"vlan": "1"
},
{
"description": "<< To hqdist2 Fa0/23 >>",
"duplex": "auto",
"mode": "trunk",
"port_no": "FastEthernet0/23",
"portfast": "x",
"speed": "auto",
"status": "o",
"vlan": "1,101"
},
{
"description": "<< To hqdist2 Fa0/24 >>",
"duplex": "auto",
"mode": "trunk",
"port_no": "FastEthernet0/24",
"portfast": "x",
"speed": "auto",
"status": "o",
"vlan": "1,101"
},
{
"duplex": "auto",
"mode": "access",
"port_no": "GigabitEthernet0/1",
"portfast": "x",
"speed": "auto",
"status": "o",
"vlan": "1"
},
{
"duplex": "auto",
"mode": "access",
"port_no": "GigabitEthernet0/2",
"portfast": "x",
"speed": "auto",
"status": "o",
"vlan": "1"
}
]
}
]
}
PLAY RECAP ***************************************************************************************************
hqdist1A : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Das Plug-In, das ich dieses Mal erstellt habe, wurde auf GitHub / ansible-ttp hochgeladen. Nicht nur Config, sondern auch die Ausgabeergebnisse anderer show-Befehle können relativ einfach analysiert werden. Verwenden Sie sie daher bitte.
Recommended Posts