Tabellen und Ansichten mit Junos Pyez

(Nayan Gadre) (12. September 2020)

Dies sind Notizen, die während der Arbeit erstellt wurden Arbeiten mit der Junos Pyez-Bibliothek für die Netzwerkautomatisierung. Junos bietet Tabellen und Ansichten zum Festlegen und Extrahieren benutzerdefinierter Konfigurationsdaten. Der gesamte Pyez-Code und ncclient ist OpenSource unter Apache 2.0-Lizenz.

Sie definieren eine Tabelle und eine Ansicht in einer Yaml-Datei unter lib / jnpr / junos / Ressourcen
wie „ user.yml “ und die entsprechenden Loader-Datei als „ user.py

user.yml
user.py

Die“ user.py „wird verwendet, um die Tabellen- und Ansichtsdefinitionen der yaml-Datei in die globalen Wörterbuchelemente von Python zu konvertieren. Hier zeigt \_\_file \_\_ auf „ user.py “ Datei, die wird. Anschließend wird in den Dateinamen „ user.yml “ konvertiert. Die loadyaml von junos pyez konvertiert dann die Datei „ user.yml „in ein Wörterbuch, um es an das globals () Wörterbuch anzuhängen.

Sowohl die Tabellen- als auch die Ansichtsdefinition im yaml werden in Python in Klassen konvertiert. Die loadyaml ist eine Factory-Methode und wird mit der \_\_ all \_\_ Python-Deklaration. Es enthält ein Wörterbuch mit Definitionen von Elementnamen und Elementklassen, wie im einzeiligen Snap zu sehen ist.

Die Datei user.yml ist in zwei Schlüssel der obersten Ebene unterteilt: „ UserTable “ und „ UserView “ loadyaml gibt 2 Klassen mit diesen Namen zurück.

Wörterbuch, das aus der Datei user.yml

Dieses Wörterbuch wird an die FactoryLoader.load ( ) Methode zum Generieren von Klassen:

FactoryLoader (). load (yaml.load (offen (Pfad, „r“), Loader = yaml.FullLoader))

Der Zweck der Factory Loader-Klasse

Die Methode r der Wörterbuchelemente () r Gibt ein Ansichtsobjekt zurück, das eine Liste von Tupeln enthält, die Schlüssel-Wert-Paare enthalten.

Die Art und Weise, wie der Factory Loader entscheidet, ob das bereitgestellte Tabellen- und Ansichtsschema für die Konfiguration oder für Operationen vorgesehen ist, erfolgt über die im Schema vorhandenen Schlüssel . Zum Beispiel: „ setze “ und „ get “ würden es zu einer Konfigurationstabelle machen.
rpc „, dann ist es eine Operation Tabelle „ Befehl “ oder „ title “ dann ist es eine Befehlstabelle, es gibt auch eine verwirrende Kombination von „ item “ „ view „und“ * „, die auch bestimmen, ob es sich um eine Befehlstabelle handelt.

Da wir uns konzentrieren Die „ user.yml “ wir können sehen, dass es „eine Konfigurationstabelle ist, da es eine“ setze “ in seine Hierarchie. Daher werden wir die \_item\_cfgtables mit der UserTable Schlüssel.

Dies ist die Klassenerstellungsfunktion zum Generieren der Tabellenklasse für Konfigurationstypentabellen.

Die Table-Klasse enthält daher einen Verweis auf die View-Klasse Wenn im Abschnitt „Tabelle“ eine Ansicht definiert ist, erstellen wir eine Klasse für diese Ansicht mit der Methode \_build\_view () und setzen sie Die Klasse als Wert des Schlüssels „ view „.

Mit der Methode get () können Sie einen Standardwert festlegen, wenn der Schlüssel nicht vorhanden ist , hier fehlt der Schlüssel „ view\_name „, sodass die \_build\_view ( view\_name ) erstellt eine Klasse und ordnet die Klasse als Wert dem view\_name Schlüssel. Außerdem werden die Gruppen, Auswertungen und Felder extrahiert und in internen Feldern für Ansichtsobjekte gespeichert.

Wir überprüfen zunächst, wie der Container CFGTABLE wird erstellt unter \_CFGTBL
\_CFGTBL = FactoryCfgTable

Python ermöglicht es Ihnen zum Erstellen dynamischer Klassen oder Typen mit der Methode „ type „.
If „ type „wird an ein vorhandenes Objekt übergeben, es gibt seinen Typ zurück. Wenn jedoch „ type “ 3 Argumente übergeben wird, „ Klassenname „,“ Basistupel „,“ dict „dann es gibt eine neue Klasse zurück. Es gibt auch eine „ vars “ -Methode, die \_\_dict\_\_ Attribut, in dem beschreibbare Objekte gespeichert werden. Python erstellt andere Klassen mithilfe von Metaklassen.

Wir können den Namen der Klasse, von der unsere neue Klasse erbt, als einzelnes Tupel übergeben: Zum Beispiel: new\_cls = type (table\_name, (CfgTable,), {})

Wenn „ set „befindet sich im Abschnitt“ Tabelle „:
für zB: set: system / login / user
Daher sollten wir auch die Konfigurationsbasisklasse übergeben, um unsere UserTable-Klasse zu erstellen:
Zum Beispiel: new\_cls = type (tabellenname, (CfgTable, Config), {})

Felder, die automatisch in der Klasse

ausgefüllt werden erstellt wird, fügen wir es dem Katalog der factoryLoader-Klassen hinzu: self.catalog [tabellenname] = cls

Fahren Sie nun mit der Erstellung der Ansichtsklasse fort:

Ansichtsname = tbl\_dict [“ Ansicht „]
tbl\_dict [“ Ansicht „] = self.catalog.get (view\_name, self.\_build\_view (view\_name))

Der view\_name in der Datei „ user.yml “ ist „ userView „.

Schließlich lädt“ ”Gibt einen Katalog von Klassen zurück, die von der Klasse FactoryLoader

erstellt wurden

Fassen Sie also den Pfad zusammen:

Damit ist nur ein Teil abgeschlossen, in dem die yml in Klassen konvertiert wird, mit denen dann gearbeitet werden kann. Als Nächstes erstellen wir zunächst ein Objekt unserer UserTable-Klasse.

user\_table = UserTable (dev)

Seit dem neu erstellten UserTable erbt von CfgTable und Config Basisklassen, wir erben den Konstruktor und alle in diesen Basisklassen definierten Methoden. Sobald wir ein neues UserTable -Objekt erstellen, ruft es das \_\_init\_\_ der übergeordneten Klassen. Da in der yml-Datei „ set “ erwähnt wird, rufen wir auch den Konstruktor von config auf Basisklasse.

Rufen Sie anschließend auf die Methode get () zum Abrufen der Konfigurationsdaten für system / login / user Hierarchie.
Wir werden zuerst die Option namesonly = false aktivieren.

Denken Sie daran, dass die Hierarchie für den xpath-Ausdruck bereits über die set: system / login / user “ user.yml „-Anweisung. Eine Funktion \_build\_xml übersetzt das in a. XML wie folgt:

Wenn der Benutzer einen bestimmten Benutzernamen angegeben hat, der als „ namekey “ bezeichnet wird, benötigen wir um das in die oben generierte XML einzufügen. Zum Beispiel: get (user = ”regress”) würde das name-Element mit dem Wert regress einfügen:

regress

alles wird in get\_cmd gepackt und an self.RPC.get\_config (get\_cmd) gesendet
Ein typisches XML- RPC sieht unten wie folgt aus:

Format des XML-RPC-Methodenaufrufs XML

Unser XML zum Abrufen von Benutzerinformationen sieht folgendermaßen aus:

Dieser XML-RPC wird in eine HTTP-POST-Anforderung konvertiert und an den Server gesendet: Führt einen XML-RPC aus und gibt die Ergebnisse entweder als XML oder als natives Python zurück

Der eigentliche RPC-Aufruf erfolgt über die RPC-Methode von ncclient über ssh, damit Daten verschlüsselt werden.

Die RPC-Behandlung von Die rpc\_cmd\_e ist. Dies wird von ncclient durchgeführt, das die Implementierung von netconf over ssh bereitstellt. Es wird schwierig zu verstehen, wo die rpc-Methode im Manager () -Objekt aus dem ncclient-Paket tatsächlich definiert ist. Nach dem Studium der ncclient-Bibliothek stellte ich fest, dass sie als Methodenwörterbuch mit „rpc“ = ExecuteRpc , und dieses Wörterbuch ist herstellerspezifisch. Klicken Sie hier, um mehr zu erfahren .

Dieser gesamte Vorgang zum Benennen des Wörterbuchs wird für jede Verbindungsanforderung basierend auf dem Anbieter erstellt und zurückgegeben.

Der endgültige XML-RPC, der auf dem Junos-Gerät über ssh too netconf server gesendet wurde

Ein kurzer Überblick Zusammenfassung der Initiierung und des Austauschs der netconf-Sitzung:

Der Client muss eine netconf-Verbindung zu Port 830 über ssh. Der Server sollte seine HALLO -Nachricht sofort senden, und der Client sollte dies auch tun. Die gesamte Nachricht hallo > gibt die Funktionen des Clients und des Servers an. Der Server sollte dann warten, um alle rpc > -Anfragen zu verarbeiten, und eine rpc-reply >. Der Client kann dem rpc > -Element beliebig viele XML-Attribute hinzufügen Der Server gibt alle diese Attribute im rpc-reply > -Element zurück.

Die Antwort wird für ok > und rpc-error > Tags, die keine / keine Fehler anzeigen. Anschließend wird es in ein geräte- / herstellerabhängiges Format umgewandelt, Namespace-Tags usw. entfernt.

Die Antwort wird schließlich wie folgt empfangen:

[(regress, [(user, regress), (uid, 928), (class\_name, superuser), (password, abc123 @ # $ # $ ^)])]