Usar Junos PyEZ para ejecutar RPC en dispositivos Junos
RESUMEN Utilice la Device
rpc
propiedad para ejecutar RPC operativas en dispositivos Junos.
Puede utilizar Junos PyEZ para ejecutar llamadas a procedimiento remoto (RPC) a petición en dispositivos Junos. Después de crear una instancia de la Device
clase, puede ejecutar RPC como una propiedad de la Device
instancia. Puede ejecutar la mayoría de los mismos comandos operativos con Junos PyEZ que puede ejecutar en la CLI.
La API XML de Junos es una representación XML de las instrucciones de configuración y los comandos de modo operativo de Junos OS. Define un equivalente XML para todas las instrucciones de la jerarquía de configuración de Junos OS y muchos de los comandos que se emiten en el modo operativo de la CLI. Cada comando del modo operativo con un homólogo XML de Junos se asigna a un elemento de etiqueta de solicitud y, si es necesario, a un elemento de etiqueta de respuesta. Las etiquetas de solicitud se utilizan en RPC dentro de las sesiones de protocolo XML de NETCONF o Junos para solicitar información de un dispositivo Junos. El servidor devuelve la respuesta utilizando elementos XML de Junos encerrados dentro del elemento de etiqueta de respuesta.
Cuando se utiliza Junos PyEZ para ejecutar RPC, se asigna el nombre de la etiqueta de solicitud a un nombre de método. En este tema se describe cómo asignar comandos de CLI a RPC de Junos PyEZ, cómo ejecutar RPC con Junos PyEZ y cómo personalizar los datos devueltos en la respuesta RPC.
Asigne comandos de Junos OS a RPC de Junos PyEZ
Todos los comandos operativos que tienen homólogos XML de Junos se enumeran en el Explorador de API XML de Junos. También puede mostrar el elemento de etiqueta de solicitud XML de Junos para cualquier comando de modo operativo que tenga un homólogo XML de Junos en la CLI o mediante Junos PyEZ. Una vez que obtenga la etiqueta de solicitud, puede asignarla al nombre del método RPC de Junos PyEZ.
Para mostrar la etiqueta de solicitud XML de Junos para un comando en la CLI, incluya la | display xml rpc
opción después del comando. En el ejemplo siguiente se muestra la etiqueta request para el show route
comando:
user@router> show route | display xml rpc <rpc-reply xmlns:junos="http://xml.juniper.net/junos/15.1R1/junos"> <rpc> <get-route-information> </get-route-information> </rpc> </rpc-reply>
También puede mostrar la etiqueta de solicitud XML de Junos para un comando mediante Junos PyEZ. Para mostrar la etiqueta request, llame al método instance Device
display_xml_rpc()
e incluya la cadena de comandos y format='text'
los argumentos as. Por ejemplo:
from jnpr.junos import Device with Device(host='router.example.com') as dev: print (dev.display_xml_rpc('show route', format='text'))
La ejecución del programa devuelve la etiqueta de solicitud para el show route
comando.
<get-route-information> </get-route-information>
Puede asignar las etiquetas de solicitud de un comando operativo a un nombre de método RPC de Junos PyEZ. Para derivar el nombre del método RPC, reemplace los guiones de la etiqueta de solicitud por guiones bajos (_) y quite los corchetes angulares de cierre. Por ejemplo, la etiqueta request <get-route-information>
se asigna al nombre del get_route_information()
método.
Ejecutar RPC como una propiedad de la instancia de dispositivo
Cada instancia de Device
tiene una rpc
propiedad que le permite ejecutar cualquier RPC disponible a través de la API XML de Junos. En una aplicación Junos PyEZ, después de establecer una conexión con el dispositivo, puede ejecutar el RPC anexando la propiedad y el nombre del rpc
método RPC a la instancia del dispositivo, como se muestra en el ejemplo siguiente:
from jnpr.junos import Device from lxml import etree with Device(host='dc1a.example.com') as dev: #invoke the RPC equivalent to "show version" sw = dev.rpc.get_software_information() print(etree.tostring(sw, encoding='unicode'))
El valor devuelto es un objeto XML que comienza en el primer elemento de la <rpc-reply>
etiqueta. En este caso, el get_software_information()
RPC devuelve el <software-information>
elemento.
<software-information> <host-name>dc1a</host-name> ... </software-information>
Los comandos de Junos OS pueden tener opciones de forma fija que no tienen un valor. Por ejemplo, el equivalente XML de Junos para el show interfaces terse
comando indica que terse
es un elemento vacío.
user@router> show interfaces terse | display xml rpc <rpc-reply xmlns:junos="http://xml.juniper.net/junos/14.1R1/junos"> <rpc> <get-interface-information> <terse/> </get-interface-information> </rpc> </rpc-reply>
Para ejecutar un RPC e incluir una opción de comando que no tome un valor, agregue la opción a la lista de argumentos del método RPC, cambie los guiones del nombre de opción a guiones bajos y establézcalo igual a True. El código siguiente ejecuta el equivalente del show interfaces terse
comando Junos PyEZ RPC:
rsp = dev.rpc.get_interface_information(terse=True)
Los comandos de Junos OS también pueden tener opciones que requieren un valor. Por ejemplo, en el siguiente resultado, el interface-name
elemento requiere un valor, que es el nombre de la interfaz para la que desea devolver información:
user@router> show interfaces ge-0/0/0 | display xml rpc <rpc-reply xmlns:junos="http://xml.juniper.net/junos/14.1R1/junos"> <rpc> <get-interface-information> <interface-name>ge-0/0/0</interface-name> </get-interface-information> </rpc> </rpc-reply>
Para ejecutar un RPC e incluir una opción de comando que requiera un valor, agregue la opción a la lista de argumentos del método RPC, cambie los guiones del nombre de opción a guiones bajos y, a continuación, establézcalo igual al valor adecuado. En el ejemplo siguiente se ejecuta el equivalente RPC show interfaces ge-0/0/0
del comando Junos PyEZ:
rsp = dev.rpc.get_interface_information(interface_name='ge-0/0/0')
Especifique el formato de la salida RPC
De forma predeterminada, el valor devuelto RPC es un objeto XML que comienza en el primer elemento de la <rpc-reply>
etiqueta. También puede devolver la salida RPC en formato de texto o notación de objetos JavaScript (JSON) incluyendo el {'format':'text'}
diccionario o {'format':'json'}
como primer argumento del método RPC.
La salida RPC en formato JSON se admite a partir de Junos OS versión 14.2R1.
En el ejemplo siguiente se devuelve la salida de la get_software_information()
RPC en formato de texto, que es idéntica a la salida emitida para el show version
comando en la CLI, excepto que la salida RPC está encerrada dentro de un <output>
elemento.
from jnpr.junos import Device from lxml import etree with Device(host='router1.example.com') as dev: sw_info_text = dev.rpc.get_software_information({'format':'text'}) print(etree.tostring(sw_info_text))
user@server:~$ python3 junos-pyez-rpc-text-format.py <output> Hostname: router1 Model: mx104 Junos: 18.3R1.9 JUNOS Base OS boot [18.3R1.9] JUNOS Base OS Software Suite [18.3R1.9] JUNOS Crypto Software Suite [18.3R1.9] JUNOS Packet Forwarding Engine Support (TRIO) [18.3R1.9] JUNOS Web Management [18.3R1.9] JUNOS Online Documentation [18.3R1.9] JUNOS SDN Software Suite [18.3R1.9] JUNOS Services Application Level Gateways [18.3R1.9] JUNOS Services COS [18.3R1.9] JUNOS Services Jflow Container package [18.3R1.9] JUNOS Services Stateful Firewall [18.3R1.9] JUNOS Services NAT [18.3R1.9] JUNOS Services RPM [18.3R1.9] JUNOS Services Captive Portal and Content Delivery Container package [18.3R1.9] JUNOS Macsec Software Suite [18.3R1.9] JUNOS Services Crypto [18.3R1.9] JUNOS Services IPSec [18.3R1.9] JUNOS DP Crypto Software Software Suite [18.3R1.9] JUNOS py-base-powerpc [18.3R1.9] JUNOS py-extensions-powerpc [18.3R1.9] JUNOS jsd [powerpc-18.3R1.9-jet-1] JUNOS Kernel Software Suite [18.3R1.9] JUNOS Routing Software Suite [18.3R1.9] <output>
En el ejemplo siguiente se devuelve el resultado del get_software_information()
RPC en formato JSON.
from jnpr.junos import Device from pprint import pprint with Device(host='router1.example.com') as dev: sw_info_json = dev.rpc.get_software_information({'format':'json'}) pprint(sw_info_json)
user@server:~$ python3 junos-pyez-rpc-json-format.py {u'software-information': [{u'host-name': [{u'data': u'router1'}], u'junos-version': [{u'data': u'18.3R1.9'}], u'package-information': [{u'comment': [{u'data': u'JUNOS Base OS boot [18.3R1.9]'}], u'name': [{u'data': u'junos'}]}, {u'comment': [{u'data': u'JUNOS Base OS Software Suite [18.3R1.9]'}], u'name': [{u'data': u'jbase'}]}, ...
Especificar el ámbito de los datos que se van a devolver
Puede usar Junos PyEZ para ejecutar una RPC para recuperar información operativa de dispositivos Junos. A partir de Junos PyEZ versión 2.3.0, cuando solicite una salida XML, puede filtrar la respuesta para devolver solo elementos específicos. Filtrar la salida es beneficioso cuando tiene una salida operativa extensa, pero solo necesita trabajar con un subconjunto de los datos.
Para filtrar la respuesta RPC para devolver solo etiquetas específicas, incluya el argumento del filter_xml
método RPC. El filter_xml
parámetro toma una cadena que contiene el filtro de subárbol que selecciona los elementos que se van a devolver. El filtro de subárbol devuelve los datos que coinciden con los criterios de selección.
En el siguiente ejemplo de Junos PyEZ se ejecuta la <get-interface-information>
RPC y se filtra el resultado para recuperar solo el elemento de <name>
cada <physical-interface>
elemento de la respuesta:
from jnpr.junos import Device from lxml import etree with Device(host='router.example.com', use_filter=True) as dev: filter = '<interface-information><physical-interface><name/></physical-interface></interface-information>' result = dev.rpc.get_interface_information(filter_xml=filter) print (etree.tostring(result, encoding='unicode'))
Cuando se ejecuta el script, se muestra el elemento name de cada interfaz física.
user@server:~$ python3 junos-pyez-get-interface-names.py <interface-information style="normal"><physical-interface><name> lc-0/0/0 </name></physical-interface><physical-interface><name> pfe-0/0/0 </name></physical-interface><physical-interface><name> pfh-0/0/0 </name></physical-interface><physical-interface><name> xe-0/0/0 </name></physical-interface><physical-interface><name> xe-0/1/0 </name></physical-interface><physical-interface><name> ge-1/0/0 </name></physical-interface> ... </interface-information>
Especifique el tiempo de espera de RPC
El tiempo de ejecución de RPC puede variar considerablemente según el RPC y el dispositivo. De forma predeterminada, los RPC de NETCONF agotan el tiempo de espera después de 30 segundos. Puede ampliar el valor de tiempo de espera incluyendo el dev_timeout=seconds
argumento al ejecutar la RPC para asegurarse de que la RPC no agota el tiempo de espera durante la ejecución. dev_timeout
ajusta el tiempo de espera del dispositivo solo para esa única operación RPC.
dev.rpc.get_route_information(table='inet.0', dev_timeout=55)
Normalizar la respuesta RPC XML
Cuando se ejecuta una RPC, la respuesta RPC puede incluir datos envueltos en líneas nuevas o que contienen otros espacios en blanco superfluos. Los espacios en blanco innecesarios pueden dificultar el análisis del XML y la búsqueda de información mediante búsquedas basadas en texto. Puede normalizar una respuesta RPC, que elimina todos los espacios en blanco iniciales y finales y reemplaza las secuencias de caracteres de espacio en blanco internos por un solo espacio.
En la tabla 1 se compara una respuesta RPC predeterminada con la versión normalizada. La respuesta RPC predeterminada incluye muchas líneas nuevas que no están presentes en la respuesta normalizada.
Respuesta RPC predeterminada |
Respuesta RPC normalizada |
---|---|
<interface-information style="terse"> <logical-interface> <name>\nge-0/0/0.0\n</name> <admin-status>\nup\n</admin-status> <oper-status>\nup\n</oper-status> <filter-information>\n</filter-information> <address-family> <address-family-name>\ninet\n</address-family-name> <interface-address> <ifa-local emit="emit">\n198.51.100.1/24\n</ifa-local> </interface-address> </address-family> </logical-interface> </interface-information> |
<interface-information style="terse"> <logical-interface> <name>ge-0/0/0.0</name> <admin-status>up</admin-status> <oper-status>up</oper-status> <filter-information/> <address-family> <address-family-name>inet</address-family-name> <interface-address> <ifa-local emit="emit">198.51.100.1/24</ifa-local> </interface-address> </address-family> </logical-interface> </interface-information> |
Puede habilitar la normalización mientras dure una sesión con un dispositivo o puede normalizar una respuesta RPC individual al ejecutar el RPC. Para habilitar la normalización para toda la sesión del dispositivo, incluya normalize=True
en la lista de argumentos cuando cree la instancia del dispositivo o cuando se conecte al dispositivo mediante el open()
método.
dev = Device(host='router1.example.com', user='root', normalize=True) # or dev.open(normalize=True)
Para normalizar una respuesta RPC individual, inclúyala normalize=True
en la lista de argumentos para ese método RPC.
dev.rpc.rpc_method(normalize=True)
Por ejemplo:
rsp = dev.rpc.get_interface_information(interface_name='ge-0/0/0.0', terse=True, normalize=True)
Si no normaliza la respuesta RPC, debe tener en cuenta cualquier espacio en blanco cuando utilice expresiones XPath que hagan referencia a un nodo o valor específico. En el ejemplo siguiente se selecciona la dirección IPv4 para una interfaz lógica. En la expresión XPath, el predicado que especifica la inet
familia debe tener en cuenta el espacio en blanco adicional para que la búsqueda se realice correctamente. El valor resultante incluye las nuevas líneas iniciales y finales.
rsp = dev.rpc.get_interface_information(interface_name='ge-0/0/0.0', terse=True) print (rsp.xpath('.// \ address-family[normalize-space(address-family-name)="inet"]/ \ interface-address/ifa-local')[0].text)
'\n198.51.100.1/24\n'
Cuando se normaliza la respuesta RPC, se quitan los espacios en blanco iniciales y finales, lo que hace que las búsquedas basadas en texto sean mucho más sencillas.
rsp = dev.rpc.get_interface_information(interface_name='ge-0/0/0.0', terse=True, normalize=True) print (rsp.xpath('.//address-family[address-family-name="inet"]/ \ interface-address/ifa-local')[0].text)
'198.51.100.1/24'