Verwenden von Junos PyEZ zum Ausführen von RPCs auf Junos-Geräten
ZUSAMMENFASSUNG Verwenden Sie die Device
rpc
Eigenschaft, um operative RPCs auf Junos-Geräten auszuführen.
Sie können Junos PyEZ verwenden, um Remote Procedure Calls (RPCs) bei Bedarf auf Junos-Geräten auszuführen. Nachdem Sie eine Instanz der Device
Klasse erstellt haben, können Sie RPCs als Eigenschaft der Device
Instanz ausführen. Mit Junos PyEZ können Sie die meisten der gleichen Betriebsbefehle ausführen, die Sie auch in der CLI ausführen können.
Die Junos XML-API ist eine XML-Darstellung von Junos OS-Konfigurationsanweisungen und Befehlen für den Betriebsmodus. Er definiert eine XML-Entsprechung für alle Anweisungen in der Junos OS-Konfigurationshierarchie und viele der Befehle, die Sie im CLI-Betriebsmodus ausgeben. Jeder Betriebsmodusbefehl mit einem Junos XML-Gegenstück ist einem Anforderungs-Tag-Element und, falls erforderlich, einem Antwort-Tag-Element zugeordnet. Anforderungstags werden in RPCs innerhalb von NETCONF- oder Junos XML-Protokollsitzungen verwendet, um Informationen von einem Junos-Gerät anzufordern. Der Server gibt die Antwort mithilfe von Junos XML-Elementen zurück, die in das Antwort-Tag-Element eingeschlossen sind.
Wenn Sie Junos PyEZ zum Ausführen von RPCs verwenden, ordnen Sie den Namen des Anforderungs-Tags einem Methodennamen zu. In diesem Thema wird beschrieben, wie CLI-Befehle Junos PyEZ-RPCs zugeordnet werden, wie RPCs mit Junos PyEZ ausgeführt werden und wie die in der RPC-Antwort zurückgegebenen Daten angepasst werden.
Zuordnen von Junos OS-Befehlen zu Junos PyEZ-RPCs
Alle Betriebsbefehle, für die es Junos XML-Entsprechungen gibt, werden im Junos XML-API-Explorer aufgelistet. Sie können auch das Junos XML-Anforderungstag-Element für jeden Betriebsmodusbefehl anzeigen, für den es eine Junos XML-Entsprechung gibt, entweder in der CLI oder mithilfe von Junos PyEZ. Nachdem Sie das Anforderungs-Tag erhalten haben, können Sie es dem RPC-Methodennamen von Junos PyEZ zuordnen.
Um das Junos XML-Anforderungs-Tag für einen Befehl in der CLI anzuzeigen, fügen Sie die | display xml rpc
Option nach dem Befehl ein. Im folgenden Beispiel wird das Anforderungstag für den show route
Befehl angezeigt:
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>
Sie können das Junos XML-Anforderungs-Tag für einen Befehl auch mit Junos PyEZ anzeigen. Um das Anforderungstag anzuzeigen, rufen Sie die Device
instance-Methode display_xml_rpc()
auf, und fügen Sie die Befehlszeichenfolge und format='text'
als Argumente ein. Zum Beispiel:
from jnpr.junos import Device with Device(host='router.example.com') as dev: print (dev.display_xml_rpc('show route', format='text'))
Beim Ausführen des Programms wird das Anforderungs-Tag für den show route
Befehl zurückgegeben.
<get-route-information> </get-route-information>
Sie können die Anforderungs-Tags für einen Betriebsbefehl einem Junos PyEZ-RPC-Methodennamen zuordnen. Um den RPC-Methodennamen abzuleiten, ersetzen Sie alle Bindestriche im Anforderungstag durch Unterstriche (_), und entfernen Sie die einschließenden spitzen Klammern. Das <get-route-information>
Anforderungstag wird z. B. dem get_route_information()
Methodennamen zugeordnet.
RPCs als Eigenschaft der Geräteinstanz ausführen
Jede Instanz von Device
verfügt über eine rpc
Eigenschaft, mit der Sie jeden RPC ausführen können, der über die Junos XML-API verfügbar ist. In einer Junos PyEZ-Anwendung können Sie nach dem Herstellen einer Verbindung mit dem Gerät den RPC ausführen, indem Sie die Eigenschaft und den rpc
RPC-Methodennamen an die Geräteinstanz anhängen, wie im folgenden Beispiel gezeigt:
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'))
Der Rückgabewert ist ein XML-Objekt, das mit dem ersten Element unter dem <rpc-reply>
Tag beginnt. In diesem Fall gibt der get_software_information()
RPC das <software-information>
Element zurück.
<software-information> <host-name>dc1a</host-name> ... </software-information>
Junos OS-Befehle können Optionen in fester Form haben, die keinen Wert haben. Die Junos-XML-Entsprechung für den show interfaces terse
Befehl gibt beispielsweise an, dass es terse
sich um ein leeres Element handelt.
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>
Um einen RPC auszuführen und eine Befehlsoption einzuschließen, die keinen Wert akzeptiert, fügen Sie die Option der Argumentliste der RPC-Methode hinzu, ändern Sie alle Bindestriche im Optionsnamen in Unterstriche, und legen Sie sie auf True fest. Mit dem folgenden Code wird das Junos PyEZ RPC-Äquivalent des show interfaces terse
Befehls ausgeführt:
rsp = dev.rpc.get_interface_information(terse=True)
Junos OS-Befehle können auch Optionen enthalten, für die ein Wert erforderlich ist. In der folgenden Ausgabe benötigt das interface-name
Element z. B. einen Wert, bei dem es sich um den Namen der Schnittstelle handelt, für die Sie Informationen zurückgeben möchten:
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>
Um einen RPC auszuführen und eine Befehlsoption einzuschließen, für die ein Wert erforderlich ist, fügen Sie die Option der Argumentliste der RPC-Methode hinzu, ändern Sie alle Bindestriche im Optionsnamen in Unterstriche, und legen Sie sie dann auf den entsprechenden Wert fest. Im folgenden Beispiel wird das Junos PyEZ RPC-Äquivalent des show interfaces ge-0/0/0
Befehls ausgeführt:
rsp = dev.rpc.get_interface_information(interface_name='ge-0/0/0')
Angeben des Formats der RPC-Ausgabe
Standardmäßig ist der RPC-Rückgabewert ein XML-Objekt, das mit dem ersten Element unter dem <rpc-reply>
Tag beginnt. Sie können die RPC-Ausgabe auch im Text- oder JSON-Format (JavaScript Object Notation) zurückgeben, indem Sie entweder das oder {'format':'json'}
das {'format':'text'}
Wörterbuch als erstes Argument der RPC-Methode einschließen.
Die RPC-Ausgabe im JSON-Format wird ab Junos OS Version 14.2R1 unterstützt.
Im folgenden Beispiel wird die Ausgabe des get_software_information()
RPC im Textformat zurückgegeben, das mit der Ausgabe identisch ist, die für den show version
Befehl in der CLI ausgegeben wird, mit der Ausnahme, dass die RPC-Ausgabe in ein <output>
Element eingeschlossen ist.
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>
Im folgenden Beispiel wird die Ausgabe des get_software_information()
RPC im JSON-Format zurückgegeben.
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'}]}, ...
Geben Sie den Umfang der zurückzugebenden Daten an
Sie können Junos PyEZ verwenden, um einen RPC auszuführen, um Betriebsinformationen von Junos-Geräten abzurufen. Ab Junos PyEZ, Version 2.3.0, können Sie beim Anfordern einer XML-Ausgabe die Antwort so filtern, dass nur bestimmte Elemente zurückgegeben werden. Das Filtern der Ausgabe ist von Vorteil, wenn Sie über umfangreiche Betriebsausgaben verfügen, aber nur mit einer Teilmenge der Daten arbeiten müssen.
Um die RPC-Antwort so zu filtern, dass nur bestimmte Tags zurückgegeben werden, schließen Sie das filter_xml
Argument der RPC-Methode ein. Der filter_xml
Parameter akzeptiert eine Zeichenfolge, die den Unterstrukturfilter enthält, der die zurückzugebenden Elemente auswählt. Der Teilbaumfilter gibt die Daten zurück, die den Selektionskriterien entsprechen.
Im folgenden Junos PyEZ-Beispiel wird der <get-interface-information>
RPC ausgeführt und die Ausgabe gefiltert, um nur das <name>
Element für jedes <physical-interface>
Element in der Antwort abzurufen:
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'))
Wenn Sie das Skript ausführen, wird das Namenselement jeder physischen Schnittstelle angezeigt.
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>
Angeben des RPC-Timeouts
Die RPC-Ausführungszeit kann je nach RPC und Gerät erheblich variieren. Standardmäßig tritt bei NETCONF-RPCs nach 30 Sekunden ein Timeout auf. Sie können den Timeoutwert erweitern, indem Sie das dev_timeout=seconds
Argument beim Ausführen des RPC einschließen, um sicherzustellen, dass der RPC während der Ausführung kein Timeout auftritt. dev_timeout
passt das Gerätetimeout nur für diesen einzelnen RPC-Vorgang an.
dev.rpc.get_route_information(table='inet.0', dev_timeout=55)
Normalisieren der XML-RPC-Antwort
Wenn Sie einen RPC ausführen, kann die RPC-Antwort Daten enthalten, die in Zeilenumbrüche eingeschlossen sind oder andere überflüssige Leerzeichen enthalten. Unnötige Leerzeichen können das Parsen des XML-Codes und das Auffinden von Informationen mithilfe textbasierter Suchen erschweren. Sie können eine RPC-Antwort normalisieren, bei der alle führenden und nachfolgenden Leerzeichen entfernt und Sequenzen interner Leerzeichen durch ein einzelnes Leerzeichen ersetzt werden.
In Tabelle 1 wird eine standardmäßige RPC-Antwort mit der normalisierten Version verglichen. Die standardmäßige RPC-Antwort enthält viele Zeilenumbrüche, die in der normalisierten Antwort nicht vorhanden sind.
Standardmäßige RPC-Antwort |
Normalisierte RPC-Antwort |
---|---|
<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> |
Sie können die Normalisierung für die Dauer einer Sitzung mit einem Gerät aktivieren, oder Sie können eine einzelne RPC-Antwort normalisieren, wenn Sie den RPC ausführen. Um die Normalisierung für die gesamte Gerätesitzung zu aktivieren, fügen Sie es entweder beim Erstellen der Geräteinstanz oder beim Herstellen einer Verbindung mit dem Gerät mithilfe der open()
Methode in die Argumentliste einnormalize=True
.
dev = Device(host='router1.example.com', user='root', normalize=True) # or dev.open(normalize=True)
Um eine einzelne RPC-Antwort zu normalisieren, schließen Sie sie in die Argumentliste für diese RPC-Methode ein.normalize=True
dev.rpc.rpc_method(normalize=True)
Zum Beispiel:
rsp = dev.rpc.get_interface_information(interface_name='ge-0/0/0.0', terse=True, normalize=True)
Wenn Sie die RPC-Antwort nicht normalisieren, müssen Sie bei der Verwendung von XPath-Ausdrücken, die auf einen bestimmten Node oder Wert verweisen, Leerzeichen berücksichtigen. Im folgenden Beispiel wird die IPv4-Adresse für eine logische Schnittstelle ausgewählt. Im XPath-Ausdruck muss das Prädikat, das die inet
Familie angibt, die zusätzlichen Leerzeichen berücksichtigen, damit die Suche erfolgreich ist. Der resultierende Wert enthält führende und nachfolgende Zeilenumbrüche.
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'
Wenn Sie die RPC-Antwort normalisieren, werden alle führenden und nachfolgenden Leerzeichen entfernt, wodurch die textbasierte Suche viel einfacher wird.
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'