Use o Junos PyEZ para executar RPCs em dispositivos Junos
RESUMO Use a Device
rpc
propriedade para executar RPCs operacionais em dispositivos Junos.
Você pode usar o Junos PyEZ para executar chamadas de procedimento remoto (RPCs) sob demanda em dispositivos Junos. Depois de criar uma instância da Device
classe, você pode executar RPCs como uma propriedade da Device
instância. Você pode executar a maioria dos mesmos comandos operacionais usando o Junos PyEZ que você pode executar na CLI.
A API Junos XML é uma representação XML de declarações de configuração do Junos OS e comandos de modo operacional. Ele define um equivalente XML para todas as declarações na hierarquia de configuração do Junos OS e muitos dos comandos que você emite no modo operacional CLI. Cada comando de modo operacional com uma contraparte do Junos XML mapeia um elemento de tag de solicitação e, se necessário, um elemento de tag de resposta. As tags de solicitação são usadas em RPCs dentro de sessões de protocolo NETCONF ou Junos XML para solicitar informações de um dispositivo Junos. O servidor retorna a resposta usando elementos Junos XML incluídos no elemento tag de resposta.
Quando você usa o Junos PyEZ para executar RPCs, você mapeia o nome da tag de solicitação para um nome de método. Este tópico descreve como mapear comandos CLI para RPCs Junos PyEZ, como executar RPCs usando Junos PyEZ e como personalizar os dados devolvidos na resposta do RPC.
Mapeie os comandos do Junos OS para os RPCs Junos PyEZ
Todos os comandos operacionais que têm contrapartes Junos XML estão listados no Junos XML API Explorer. Você também pode exibir o elemento de tag de solicitação Junos XML para qualquer comando de modo operacional que tenha uma contraparte Junos XML no CLI ou usando Junos PyEZ. Após obter a tag de solicitação, você pode mapeá-la para o nome do método Junos PyEZ RPC.
Para exibir a tag de solicitação Do Junos XML para um comando na CLI, inclua a opção | display xml rpc
após o comando. O exemplo a seguir exibe a tag de solicitação para o 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>
Você também pode exibir a tag de solicitação Junos XML para um comando usando o Junos PyEZ. Para exibir a tag de solicitação, ligue para o Device
método de instância display_xml_rpc()
e inclua a string de comando e format='text'
como argumentos. Por exemplo:
from jnpr.junos import Device with Device(host='router.example.com') as dev: print (dev.display_xml_rpc('show route', format='text'))
A execução do programa devolve a tag de solicitação para o show route
comando.
<get-route-information> </get-route-information>
Você pode mapear as tags de solicitação para obter um comando operacional para um nome de método Junos PyEZ RPC. Para obter o nome do método RPC, substitua quaisquer hífens na tag de solicitação por sublinhados (_) e remova os parênteses de ângulo fechados. Por exemplo, a tag de solicitação <get-route-information>
mapeia o nome do get_route_information()
método.
Execute RPCs como propriedade da instância do dispositivo
Cada instância Device
tem uma rpc
propriedade que permite que você execute qualquer RPC disponível através da API Junos XML. Em um aplicativo Junos PyEZ, após estabelecer uma conexão com o dispositivo, você pode executar o RPC anexando o nome da propriedade e do rpc
método RPC à instância do dispositivo, conforme mostrado no exemplo a seguir:
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'))
O valor de devolução é um objeto XML que começa no primeiro elemento sob a <rpc-reply>
tag. Neste caso, o get_software_information()
RPC devolve o <software-information>
elemento.
<software-information> <host-name>dc1a</host-name> ... </software-information>
Os comandos do Junos OS podem ter opções de forma fixa que não têm valor. Por exemplo, o equivalente ao Junos XML para o show interfaces terse
comando indica que terse
é um elemento vazio.
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 executar um RPC e incluir uma opção de comando que não tenha um valor, adicione a opção à lista de argumentos do método RPC, altere quaisquer traços no nome da opção para sublinhar e configure-o igual ao True. O código a seguir executa o Junos PyEZ RPC equivalente ao show interfaces terse
comando:
rsp = dev.rpc.get_interface_information(terse=True)
Os comandos do Junos OS também podem ter opções que exigem um valor. Por exemplo, na saída a seguir, o interface-name
elemento requer um valor, que é o nome da interface para a qual você deseja devolver informações:
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 executar um RPC e incluir uma opção de comando que requer um valor, adicionar a opção à lista de argumentos do método RPC, alterar quaisquer traços no nome da opção para sublinhar e, em seguida, configurá-lo igual ao valor apropriado. O exemplo a seguir executa o Junos PyEZ RPC equivalente ao show interfaces ge-0/0/0
comando:
rsp = dev.rpc.get_interface_information(interface_name='ge-0/0/0')
Especifique o formato da saída de RPC
Por padrão, o valor de retorno do RPC é um objeto XML que começa no primeiro elemento sob a <rpc-reply>
tag. Você também pode devolver a saída RPC em texto ou formato De notação de objetos JavaScript (JSON), incluindo o ou o {'format':'text'}
{'format':'json'}
níquete como o primeiro argumento do método RPC.
A saída de RPC no formato JSON é suportada a partir do Junos OS Release 14.2R1.
O exemplo a seguir retorna a saída do get_software_information()
RPC no formato de texto, que é idêntico à saída emitida para o show version
comando no CLI, exceto que a saída RPC está fechada dentro de um <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>
O exemplo a seguir devolve a saída do get_software_information()
RPC no 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'}]}, ...
Especifique o escopo dos dados para retornar
Você pode usar o Junos PyEZ para executar um RPC para recuperar informações operacionais dos dispositivos Junos. A partir do Junos PyEZ Release 2.3.0, quando você solicita a saída XML, você pode filtrar a resposta para devolver apenas elementos específicos. Filtrar a saída é benéfico quando você tem uma saída operacional extensa, mas você só precisa trabalhar com um subconjunto dos dados.
Para filtrar a resposta do RPC para devolver apenas tags específicas, inclua o argumento do filter_xml
método RPC. O filter_xml
parâmetro leva uma corda contendo o filtro de sub-árvore que seleciona os elementos para retornar. O filtro subtree devolve os dados que correspondem aos critérios de seleção.
O exemplo do Junos PyEZ a seguir executa o <get-interface-information>
RPC e filtra a saída para recuperar apenas o <name>
elemento para cada <physical-interface>
elemento na resposta:
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'))
Quando você executa o script, ele exibe o elemento de nome de cada interface 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 o tempo limite do RPC
O tempo de execução do RPC pode variar consideravelmente dependendo do RPC e do dispositivo. Por padrão, os RPCs NETCONF saem após 30 segundos. Você pode estender o valor de tempo limite, incluindo o dev_timeout=seconds
argumento quando executa o RPC para garantir que o RPC não desempregue durante a execução. dev_timeout
Ajuste o tempo limite do dispositivo apenas para essa única operação RPC.
dev.rpc.get_route_information(table='inet.0', dev_timeout=55)
Normalize a resposta de RPC do XML
Quando você executa um RPC, a resposta de RPC pode incluir dados que estão envolvidos em novas linhas ou contêm outro whitespace supérfluo. O whitespace desnecessário pode dificultar a análise do XML e encontrar informações usando pesquisas baseadas em texto. Você pode normalizar uma resposta RPC, que elimina todos os whitespaces líderes e trailing e substitui sequências de caracteres whitespace internos por um único espaço.
A Tabela 1 compara uma resposta RPC padrão com a versão normalizada. A resposta RPC padrão inclui muitas linhas novas que não estão presentes na resposta normalizada.
Resposta padrão do RPC |
Resposta 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> |
Você pode habilitar a normalização durante a sessão com um dispositivo ou normalizar uma resposta RPC individual ao executar o RPC. Para permitir a normalização de toda a sessão do dispositivo, inclua normalize=True
na lista de argumentos quando você cria a instância do dispositivo ou quando se conecta ao dispositivo usando o open()
método.
dev = Device(host='router1.example.com', user='root', normalize=True) # or dev.open(normalize=True)
Para normalizar uma resposta RPC individual, inclua normalize=True
na lista de argumentos para esse método RPC.
dev.rpc.rpc_method(normalize=True)
Por exemplo:
rsp = dev.rpc.get_interface_information(interface_name='ge-0/0/0.0', terse=True, normalize=True)
Se você não normalizar a resposta do RPC, você deve responder por qualquer whitespace ao usar expressões XPath que façam referência a um nó ou valor específicos. O exemplo a seguir seleciona o endereço IPv4 para uma interface lógica. Na expressão XPath, o predicado que especifica a inet
família deve responder pelo whitespace adicional para que a busca tenha sucesso. O valor resultante inclui novas linhas líderes e trailing.
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'
Quando você normaliza a resposta rpc, qualquer whitespace líder e trailing é removido, o que torna as pesquisas baseadas em texto muito mais simples.
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'