clay584.parse_genie
Parse Genie
¡ATENCIÓN! - Si te enfrentas a un problema con un comando que no puede ser analizado, puede haber un error en la biblioteca de análisis mantenida por Cisco. Para esos problemas, puedes abrir un problema aquí.
El filtro de network genie toma la salida de comandos CLI de red no estructurada de todos los sistemas operativos de red de Cisco, y produce datos estructurados. Aunque es similar a otros analizadores de CLI de red disponibles (parse_cli, parse_cli_textfsm), este analizador está potenciado por una biblioteca muy madura y robusta llamada Genie (y el marco subyacente pyATS). Esto proporciona más de 1200 analizadores que transforman la configuración y la salida de CLI a datos estructurados que están normalizados y se conforman a modelos de datos estándar y agnósticos al sistema operativo.
La biblioteca de Genie también puede servir como motor para analizar texto libre en formato tabular y no tabular utilizando mucho menos código que el que se necesita para el análisis tradicional. Por lo tanto, puede usarse para analizar cualquier salida de proveedor; no solo la de dispositivos Cisco. Sin embargo, eso implicaría escribir analizadores personalizados. Esta versión no incluye la funcionalidad para utilizar analizadores personalizados. Los analizadores compatibles son los que están incluidos en la versión de Genie que el usuario ha instalado en la máquina de control de Ansible.
La lista de sistemas operativos y comandos soportados, así como las definiciones del esquema de datos (modelos de datos) que describen exactamente qué campos y tipos de datos se devolverán para cualquier comando dado, están disponibles en Cisco en el siguiente enlace.
https://pubhub.devnetcloud.com/media/genie-feature-browser/docs/#/parsers
Requisitos Previos
Este plugin requiere lo siguiente:
- Python 3.4+
- Paquetes pyATS y Genie
- Ansible 2.7+ (Debería funcionar en versiones anteriores siempre que se cumplan los otros requisitos)
Instalación
Sigue estas instrucciones para asegurarte de que el plugin de filtro funcione con tus playbooks:
- Crea un directorio para tu playbook y entra en él.
mkdir network_ops && cd network_ops
- Crea un entorno virtual.
python3 -m venv .venv
- Activa el entorno virtual.
source .venv/bin/activate
- Instala Ansible.
pip install ansible
- Instala Genie y pyATS.
pip install genie
- Instala el rol parse_genie desde Ansible Galaxy.
ansible-galaxy install clay584.parse_genie
Mapeos de Ansible a Genie OS
A continuación se presentan los mapeos de ansible_network_os
de Ansible a os
de Genie:
OS de Red Ansible | OS de Genie |
---|---|
ios | ios, iosxe |
nxos | nxos |
iosxr | iosxr |
junos | junos |
Si trabajas con IOS o IOS-XE hay ambigüedad ya que Ansible considera IOS e IOS-XE lo mismo y, por lo tanto, utiliza ansible_network_os = ios
, pero Genie necesita saber específicamente si se trata de IOS o IOS-XE para analizar correctamente la salida de CLI. Si pasas ansible_network_os
a este plugin de filtro y es igual a ios
, parse_genie intentará analizarlo con Genie utilizando os=ios
primero, y si falla, intentará analizarlo con os=iosxe
.
Así que ten eso en cuenta al crear tus playbooks. Puede ser mejor pasar el verdadero sistema operativo a parse_genie. Puedes hacer esto manteniendo otra variable de inventario o host_var para especificar el OS de Genie para cada dispositivo de red y usando esa variable como el OS para parse_genie.
Uso
Asegúrate de incluir el rol parse_genie antes de intentar usarlo más adelante en tu playbook.
...truncado...
tasks:
- name: Leer rol parse_genie
include_role:
name: clay584.parse_genie
...truncado...
Ejemplo Corto
Para convertir la salida de un comando CLI de un dispositivo de red, utiliza el filtro parse_genie
como se muestra en este ejemplo (no utilices comandos CLI abreviados).
Convirtiendo la salida de CLI del comando show version
de un dispositivo Cisco IOS-XE a datos estructurados::
{{ cli_output | parse_genie(command='show version', os='iosxe') }}
Para una abstracción más profunda, podrías querer añadir platform
a parse_genie
.
{{ cli_output | parse_genie(command='show version', os='iosxe', platform='asr1k') }}
El ejemplo anterior produciría lo siguiente:
{
"version": {
"chassis": "CSR1000V",
"chassis_sn": "9TKUWGKX5MO",
"curr_config_register": "0x2102",
"disks": {
"bootflash:.": {
"disk_size": "7774207",
"type_of_disk": "disco duro virtual"
},
"webui:.": {
"disk_size": "0",
"type_of_disk": "Archivos WebUI ODM"
}
},
"hostname": "host-172-16-1-96",
"image_id": "X86_64_LINUX_IOSD-UNIVERSALK9-M",
"image_type": "imagen de producción",
"last_reload_reason": "Comando de recarga",
"license_level": "ax",
"license_type": "Predeterminado. No se encontró una licencia válida.",
"main_mem": "1126522",
"mem_size": {
"configuración no volátil": "32768",
"físico": "3018840"
},
"next_reload_license_level": "ax",
"number_of_intfs": {
"Gigabit Ethernet": "2"
},
"os": "IOS-XE",
"platform": "Virtual XE",
"processor_type": "VXE",
"rom": "IOS-XE ROMMON",
"rtr_type": "CSR1000V",
"system_image": "bootflash:packages.conf",
"uptime": "2 minutos",
"uptime_this_cp": "3 minutos",
"version": "16.5.1b,",
"version_short": "16.5"
}
}
Ejemplo Completo #1
Playbook:
---
- hosts: localhost
connection: local
vars:
show_version_output: |
Software Cisco IOS XE, Versión 16.05.01b
Software Cisco IOS [Everest], Software Virtual XE (X86_64_LINUX_IOSD-UNIVERSALK9-M), Versión 16.5.1b, SOFTWARE DE LIBERACIÓN (fc1)
Soporte Técnico: http://www.cisco.com/techsupport
Copyright (c) 1986-2017 por Cisco Systems, Inc.
Compilado el Tue 11-Apr-17 16:41 por mcpre
Software Cisco IOS-XE, Copyright (c) 2005-2017 por Cisco Systems, Inc.
Todos los derechos reservados. Ciertos componentes de software de Cisco IOS-XE están
licenciados bajo la Licencia Pública General de GNU ("GPL") Versión 2.0. El
código de software licenciado bajo GPL Versión 2.0 es software libre que viene
CON ABSOLUTAMENTE NINGUNA GARANTÍA. Puedes redistribuir y/o modificar dicho
código GPL bajo los términos de GPL Versión 2.0. Para más detalles, consulta la
documentación o el archivo "Aviso de Licencia" que acompaña el software IOS-XE,
o la URL aplicable proporcionada en el folleto que acompaña el software IOS-XE.
ROM: IOS-XE ROMMON
host-172-16-1-96 tiene un tiempo de actividad de 2 minutos
El tiempo de actividad para este procesador de control es de 3 minutos
El sistema volvió a ROM por una recarga
El archivo de imagen del sistema es "bootflash:packages.conf"
Última razón de recarga: Comando de recarga
Este producto contiene características criptográficas y está sujeto a las leyes de Estados Unidos y del país local que rigen la importación, exportación, transferencia y
uso. La entrega de productos criptográficos de Cisco no implica
autoridad de terceros para importar, exportar, distribuir o usar cifrado.
Los importadores, exportadores, distribuidores y usuarios son responsables de
cumplir con las leyes de EE.UU. y del país local. Al usar este producto, aceptas cumplir
con las leyes y regulaciones aplicables. Si no puedes
cumplir con las leyes de EE.UU. y locales, devuelve este producto inmediatamente.
Un resumen de las leyes de EE.UU. que rigen los productos criptográficos de Cisco se puede encontrar en:
http://www.cisco.com/wwl/export/crypto/tool/stqrg.html
Si necesitas más ayuda, contáctanos enviando un correo electrónico a
[email protected].
Nivel de Licencia: ax
Tipo de Licencia: Predeterminado. No se encontró una licencia válida.
Nivel de Licencia para la siguiente recarga: ax
cisco CSR1000V (VXE) procesador (revisión VXE) con 1126522K/3075K bytes de memoria.
ID de placa del procesador 9TKUWGKX5MO
2 interfaces de Gigabit Ethernet
32768K bytes de memoria de configuración no volátil.
3018840K bytes de memoria física.
7774207K bytes de disco duro virtual en bootflash:.
0K bytes de Archivos WebUI ODM en webui:.
El registro de configuración es 0x2102
tasks:
- name: Leer rol parse_genie
include_role:
name: clay584.parse_genie
- name: Depurar Filtro Genie
debug:
msg: "{{ show_version_output | parse_genie(command='show version', os='iosxe') }}"
delegate_to: localhost
Salida:
$ ansible-playbook -i inventory debug.yml
PLAY [localhost] *************************************************************************
TASK [Recolección de Datos] *******************************************************************
ok: [localhost]
TASK [Leer rol parse_genie] **********************************************************
TASK [Depurar Filtro Genie] ****************************************************************
ok: [localhost -> localhost] => {
"msg": {
"version": {
"chassis": "CSR1000V",
"chassis_sn": "9TKUWGKX5MO",
"curr_config_register": "0x2102",
"disks": {
"bootflash:.": {
"disk_size": "7774207",
"type_of_disk": "disco duro virtual"
},
"webui:.": {
"disk_size": "0",
"type_of_disk": "Archivos WebUI ODM"
}
},
"hostname": "host-172-16-1-96",
"image_id": "X86_64_LINUX_IOSD-UNIVERSALK9-M",
"image_type": "imagen de producción",
"last_reload_reason": "Comando de recarga",
"license_level": "ax",
"license_type": "Predeterminado. No se encontró una licencia válida.",
"main_mem": "1126522",
"mem_size": {
"non-volatile configuration": "32768",
"physical": "3018840"
},
"next_reload_license_level": "ax",
"number_of_intfs": {
"Gigabit Ethernet": "2"
},
"os": "IOS-XE",
"platform": "Virtual XE",
"processor_type": "VXE",
"rom": "IOS-XE ROMMON",
"rtr_type": "CSR1000V",
"system_image": "bootflash:packages.conf",
"uptime": "2 minutos",
"uptime_this_cp": "3 minutos",
"version": "16.5.1b,",
"version_short": "16.5"
}
}
}
Ejemplo Completo #2
Playbook:
---
- hosts: csr1000v
gather_facts: False
tasks:
- name: Leer rol parse_genie
include_role:
name: clay584.parse_genie
- name: Obtener Datos Desde el Dispositivo
ios_command:
commands: show arp vrf Mgmt-intf
register: arp_output
- name: Imprimir Datos Estructurados
debug:
msg: "{{ arp_output['stdout'][0] | parse_genie(command='show arp vrf Mgmt-intf', os='iosxe') }}"
delegate_to: localhost
Salida:
$ ansible-playbook -i inventory playbook.yml
PLAY [csr1000v] **************************************************************************
TASK [Leer rol parse_genie] **********************************************************
TASK [Obtener Datos Desde el Dispositivo] **************************************************************
ok: [csr1000v]
TASK [Imprimir Datos Estructurados] *************************************************************
ok: [csr1000v -> localhost] => {
"msg": {
"interfaces": {
"GigabitEthernet1": {
"ipv4": {
"neighbors": {
"172.16.1.111": {
"age": "0",
"ip": "172.16.1.111",
"link_layer_address": "5e00.4004.0000",
"origin": "dinámico",
"protocol": "Internet",
"type": "ARPA"
},
"172.16.1.114": {
"age": "-",
"ip": "172.16.1.114",
"link_layer_address": "5e00.4001.0000",
"origin": "estático",
"protocol": "Internet",
"type": "ARPA"
}
}
}
}
}
}
}
Análisis Tabular Genérico
Cisco Genie tiene soporte para 1200 comandos y contando, pero para esos comandos de mostrar donde no hay un analizador que ha sido construido por Cisco, existe la funcionalidad de análisis tabular genérico. Para más información sobre la funcionalidad de análisis tabular de Genie, consulta su documentación oper_fill_tabular.
Cómo Funciona el Análisis Tabular
Para analizar la salida de un comando cuando hay un analizador que ha sido construido, todo lo que se requiere es el comando
, salida de comando
y os
.
Pero si no hay un analizador construido, debes especificar información adicional para ayudar al analizador a determinar cómo
analizar la salida del comando. Estos datos adicionales son dos:
- Encabezados - Los encabezados de columna como se muestran en la salida del comando.
- Índice - La clave de los elementos del diccionario que el analizador devolverá.
Considera el siguiente ejemplo:
- Comando:
show ip sla summary
- Salida del Comando:
Resumen de la Última Operación de IPSLA
Códigos: * activo, ^ inactivo, ~ pendiente
Todas las estadísticas están en milisegundos. Las estadísticas con u están en microsegundos
ID Tipo Destino Estadísticas Retorno Última
Código Ejecución
------------------------------------------------------------------------------------------------
*1 udp-jitter 10.0.0.2 RTT=900u OK hace 20 segundos
*2 icmp-echo 10.0.0.2 RTT=1 OK hace 3 segundos
- Encabezados -
ID
,Tipo
,Destino
,Estadísticas
,Código de Retorno
, yÚltima Ejecución
. - Índice - Queremos usar la columna
ID
como índice para estos datos cuando los obtengamos de regreso del analizador. - Salida del Analizador:
{'*1': {'Destino ': '10.0.0.2',
'ID ': '*1',
'Última Ejecución': 'hace 20 segundos',
'Código de Retorno': 'OK',
'Estadísticas ': 'RTT=900u',
'Tipo ': 'udp-jitter'},
'*2': {'Destino ': '10.0.0.2',
'ID ': '*2',
'Última Ejecución': 'hace 3 segundos',
'Código de Retorno': 'OK',
'Estadísticas ': 'RTT=1',
'Tipo ': 'icmp-echo'}}
Preparación para Usar el Analizador Tabular
Para usar este analizador tabular, primero debemos construir los encabezados
y índice
para un comando dado en
un OS dado en un formato que pueda ser leído en un playbook de Ansible, y posteriormente alimentado al plugin de filtro parse_genie.
Para hacer esto, debes crear un archivo vars en tu playbook que tenga el siguiente formato. Está organizado por OS, luego por comando. Luego, bajo cada comando, se definen los encabezados y el índice. Puedes definir tantos comandos como desees para cada OS de red siempre que esté dentro de esta estructura de datos.
parse_genie:
ios:
"show ip sla summary":
headers:
- - ID
- Tipo
- Destino
- Estadísticas
- Retorno
- Última
- - ''
- ''
- ''
- ''
- Código
- Ejecución
index:
- 0
iosxe:
"show ip sla summary":
headers:
- - ID
- Tipo
- Destino
- Estadísticas
- Retorno
- Última
- - ''
- ''
- ''
- ''
- Código
- Ejecución
index:
- 1
La equivalente en python del formato yaml anterior es:
python_dict = {
"parse_genie": {
"ios": {
"show ip sla summary": {
"headers": [
[
"ID",
"Tipo",
"Destino",
"Estadísticas",
"Retorno",
"Última"
],
[
"",
"",
"",
"",
"Código",
"Ejecución"
]
],
"index": [
0
]
}
},
"iosxe": {
"show ip sla summary": {
"headers": [
[
"ID",
"Tipo",
"Destino",
"Estadísticas",
"Retorno",
"Última"
],
[
"",
"",
"",
"",
"Código",
"Ejecución"
]
],
"index": [
1
]
}
}
}
}
Llamando al Analizador Tabular en un Playbook
Ahora que hemos definido un comando tabular genérico y sus encabezados e índice, podemos llamarlo desde un playbook.
Primero, leemos el archivo vars que contiene los metadatos del comando tabular genérico.
- name: Incluir archivo vars con metadatos de comandos genéricos
include_vars:
file: parse_genie_generic_commands.yml
name: parse_genie
A continuación, pasamos la salida del comando a parse_genie
pero con un par de parámetros adicionales.
- name: Analizar salida de comando tabular genérico
debug:
msg: "{{ command_output | parse_genie(command='show ip sla summary', os='ios', generic_tabular=True, generic_tabular_metadata=parse_genie) }}"
delegate_to: localhost
La salida analizada resultante se mostrará como sigue:
ok: [localhost -> localhost] => {
"msg": {
"*1": {
"Destino ": "10.0.0.2",
"ID ": "*1",
"Última Ejecución": "hace 20 segundos",
"Código de Retorno": "OK",
"Estadísticas ": "RTT=900u",
"Tipo ": "udp-jitter"
},
"*2": {
"Destino ": "10.0.0.2",
"ID ": "*2",
"Última Ejecución": "hace 3 segundos",
"Código de Retorno": "OK",
"Estadísticas ": "RTT=1",
"Tipo ": "icmp-echo"
}
}
}
Ejemplo Completo #1
Playbook:
---
- hosts: localhost
connection: local
vars:
out_ios_sla: |
Resumen de la Última Operación de IPSLA
Códigos: * activo, ^ inactivo, ~ pendiente
Todas las estadísticas están en milisegundos. Las estadísticas con u están en microsegundos
ID Tipo Destino Estadísticas Retorno Última
Código Ejecución
------------------------------------------------------------------------------------------------
*1 udp-jitter 10.0.0.2 RTT=900u OK hace 20 segundos
*2 icmp-echo 10.0.0.2 RTT=1 OK hace 3 segundos
tasks:
- name: Incluir Rol Parse Genie
include_role:
name: clay584.parse_genie
- name: Incluir archivo vars que tiene metadatos de comando tabular genérico
include_vars:
file: parse_genie_generic_commands.yml
name: parse_genie
- name: Probar Filtro Genie para datos tabulares genéricos
debug:
msg: "{{ out_ios_sla | parse_genie(command='test show ip sla summary', os='ios', generic_tabular=True, generic_tabular_metadata=parse_genie) }}"
delegate_to: localhost
Contenido de parse_genie_generic_commands.yml
:
---
parse_genie:
ios:
"test show ip sla summary":
headers:
- - ID
- Tipo
- Destino
- Estadísticas
- Retorno
- Última
- - ''
- ''
- ''
- ''
- Código
- Ejecución
index:
- 0
iosxe:
"test show ip sla summary":
headers:
- - ID
- Tipo
- Destino
- Estadísticas
- Retorno
- Última
- - ''
- ''
- ''
- ''
- Código
- Ejecución
index:
- 1
Salida del Playbook:
PLAY [localhost] ******************************************************************************************************************************************************************************************************************************************************************
TASK [Recolección de Datos] ************************************************************************************************************************************************************************************************************************************************************
ok: [localhost]
TASK [Incluir Rol Parse Genie] ***************************************************************************************************************************************************************************************************************************************************
TASK [Incluir vars] ***************************************************************************************************************************************************************************************************************************************************************
ok: [localhost]
TASK [Probar Filtro Genie para datos tabulares genéricos] *********************************************************************************************************************************************************************************************************************************
ok: [localhost -> localhost] => {
"msg": {
"*1": {
"Destino ": "10.0.0.2",
"ID ": "*1",
"Última Ejecución": "hace 20 segundos",
"Código de Retorno": "OK",
"Estadísticas ": "RTT=900u",
"Tipo ": "udp-jitter"
},
"*2": {
"Destino ": "10.0.0.2",
"ID ": "*2",
"Última Ejecución": "hace 3 segundos",
"Código de Retorno": "OK",
"Estadísticas ": "RTT=1",
"Tipo ": "icmp-echo"
}
}
}
PLAY RECAP ************************************************************************************************************************************************************************************************************************************************************************
localhost : ok=3 changed=0 unreachable=0 failed=0
Desarrollo
Configura tu entorno de desarrollo:
- Clona el repositorio y entra en él.
git clone https://github.com/clay584/parse_genie.git && cd parse_genie
- Crea un entorno virtual.
python3 -m venv .venv
- Activa el entorno virtual.
source .venv/bin/activate
- Instala Ansible.
pip install ansible
- Instala Genie y pyATS.
pip install genie
- Instala yamllint.
pip install yamllint
Pruebas
Ejecuta estos comandos para probar localmente:
- Verifica todos los archivos YAML.
yamllint -c yamllint_config.yml *
- Ejecuta el playbook de prueba.
ansible-playbook tests/test.yml --connection=local -i tests/inventory
Publicación
Ansible Galaxy funciona con etiquetas.
git commit -m"lo que sea'
git tag -a X.X.X
- donde X.X.X es un número de versión semántica.git push origin master
git push X.X.X
Filter plugin for network CLI parsing using Cisco's Genie/pyATS
ansible-galaxy install clay584.parse_genie