Dans l'article précédent, j'ai utilisé TTP (Template Text Parser), une bibliothèque d'analyseurs Python, pour analyser le fichier de configuration L2SW et générer automatiquement une table de gestion des ports. J'ai essayé de générer automatiquement une table de gestion des ports à partir de L2SW Config
Cette fois, j'ai pris cet analyseur comme un filtre personnalisé Ansible afin de pouvoir analyser le résultat de la commande show obtenu par le module xxx_command
.
parse_cli_textfsm
utilisant TextFSM et parse_genie
utilisant pyATS / Genie (l'installation est requise depuis Ansible Galaxy. Pour plus de détails, [GitHub / parse_genie]]( (Https://github.com/clay584/parse_genie)).J'ai utilisé Ansible installé dans l'environnement virtuel de Python 3.6.7. Au départ, je testais avec la version 2.9.0, mais j'utilise 2.8.4 car j'ai plusieurs messages d'erreur de journalisation (KeyError).
Une installation TTP supplémentaire est requise.
(venv) [centos@localhost ansible]$ pip install ttp
J'ai créé le script Python suivant.
custom_filters_ttp.py
from ansible.errors import AnsibleError
#Importez ttp et json. Si l'importation échoue, une erreur peut être générée lors du traitement suivant.
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 {
#Le côté gauche est le nom du filtre utilisé dans le playbook et le côté droit est le nom de la fonction à associer.
'parse_cli_ttp': self.parse_cli_ttp,
}
En suivant les meilleures pratiques, nous avons créé un répertoire filter_plugins sous le répertoire qui stocke le playbook et y avons stocké ce fichier.
En outre, les paramètres dans ansible.cfg ont été réécrits comme suit afin qu'Ansible puisse reconnaître ce filtre personnalisé.
ansible.cfg
[defaults]
filter_plugins = [Chemin complet du répertoire de stockage du playbook]/filter_plugins
Playbook
Obtenez la configuration d'exécution dans le module ʻios_command, et dans le module
debug` suivant, obtenez la configuration obtenue et le [modèle de configuration d'interface L2](https://qiita.com/tech_kitara/items/75ec526ff9a27932c565 # 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) chemin du fichier spécifié. C'est simple!
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') }}"
Il y a des différences dans les résultats car la configuration est différente de la fois précédente, mais l'analyse elle-même se fait sans problème.
$ 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
Le plug-in que j'ai créé cette fois a été téléchargé sur GitHub / ansible-ttp. Non seulement Config, mais aussi les résultats de sortie d'autres commandes show peuvent être analysés relativement facilement, veuillez donc l'utiliser.
Recommended Posts