[PYTHON] Ich habe versucht, automatisch eine Portverwaltungstabelle aus L2SW Config zu generieren

Einführung

Im vorherigen Artikel habe ich ein Beispiel für die automatische Generierung von Config aus der Portverwaltungstabelle vorgestellt. Ich habe versucht, die L2SW-Konfiguration automatisch aus der Portverwaltungstabelle + Parametertabelle + Jinja2-Vorlage zu generieren

In einigen Fällen möchten Sie möglicherweise eine Portverwaltungstabelle aus der erstellten Konfiguration erstellen. Dieses Mal habe ich versucht, mithilfe einer Python-Parser-Bibliothek namens TTP (Template Text Parser) automatisch eine Portverwaltungstabelle im CSV-Format aus der L2SW-Konfigurationsdatei zu generieren.

TTP-Übersicht

Um ein einfaches Beispiel für Schnellstart in das Dokument einzuführen, wird "(1) Config" in "(2) Template" geändert. Das Bild wird mit analysiert und der in {{~}} eingeschlossene Teil ist das durch "(3) Ausgabeergebnis (JSON- oder CSV-Format)" erzeugte Bild.

(1) Config

interface Loopback0
 description Router-id-loopback
 ip address 192.168.0.113/24
!
interface Vlan778
 description CPE_Acces_Vlan
 ip address 2002::fd37/124
 ip vrf CPE1
!

(2) Vorlage

interface {{ interface }}
 ip address {{ ip }}/{{ mask }}
 description {{ description }}
 ip vrf {{ vrf }}

(3) Ausgabeergebnis (JSON-Format)

python


[
    [
        {
            "description": "Router-id-loopback",
            "interface": "Loopback0",
            "ip": "192.168.0.113",
            "mask": "24"
        },
        {
            "description": "CPE_Acces_Vlan",
            "interface": "Vlan778",
            "ip": "2002::fd37",
            "mask": "124",
            "vrf": "CPE1"
        }
    ]
]

Konfiguration verwendet

Dieses Mal habe ich fast dieselbe Konfigurationsdatei verwendet wie der am Anfang erwähnte Artikel. Weitere Informationen finden Sie im GitHub-Repository unten. Konfigurationsdatei --config_hqaccess1.txt

Python-Code

Der allgemeine Fluss ist wie folgt.

  1. Perth Verwenden Sie parse_config (), um Analyseergebnisse im JSON-Format von Config und Template auszugeben.

  2. Generieren Sie eine Portverwaltungstabelle Konvertieren Sie JSON in das Wörterbuchformat und konvertieren Sie das Parsergebnis der L2-Schnittstelle in die Portverwaltungstabelle im CSV-Format mit "write_dict_to_csv ()".

Wir werden jedes Ergebnis in den folgenden Punkten vorstellen.

portlist_generation.py


# -*- coding: utf-8 -*-
from ttp import ttp
import json
import csv

#Definieren Sie Pfade für verschiedene Dateien
TEMPLATE = './catalyst2960_template_ttp.txt'
PORT_LIST = './port_list_hqaccess1_ttp.csv'
CONFIG_FILENAME = './config_hqaccess1.txt'
CSV_COLUMNS = ['port_no', 'speed', 'duplex', 'mode', 'vlan', 'portfast', 'status', 'description']


def parse_config(template_file, config_filename):
    with open(config_filename, 'rt') as fc:
        data_to_parse = fc.read()

    with open(template_file, 'rt') as ft:
        ttp_template = ft.read()

    # create parser object and parse data using template:
    parser = ttp(data=data_to_parse, template=ttp_template)
    parser.parse()

    # print result in JSON format
    results = parser.result(format='json')[0]
    return results


def write_dict_to_csv(port_list, csv_columns, results):
    with open(port_list, 'w', newline='') as csvfile:   #Für Windows Newline=''Ist notwendig
        writer = csv.DictWriter(csvfile, fieldnames=csv_columns)
        writer.writeheader()
        for data in results:
            writer.writerow(data)
    return            


def main():
    results = parse_config(TEMPLATE, CONFIG_FILENAME)
    print(results)
    results_dict = json.loads(results)
    write_dict_to_csv(PORT_LIST, CSV_COLUMNS, results_dict[0]['l2_interfaces'])


if __name__ == "__main__":
    main()

Vorlagen und perspektivische Ergebnisse

Ich habe tatsächlich eine Datei erstellt (catalog2960_template_ttp.txt), aber zur Erklärung habe ich drei für jedes Einstellungselement erstellt. Es ist geteilt.

(1) Globale Einstellungen

Da die schnittstellenbezogene Vorlage in (2) und (3) erstellt wurde, werden hier andere globale Einstellungen definiert.

part1_template


<group name="global_settings">
hostname {{ hostname }}
enable secret {{ secret }}
username {{ username }} privilege 15 password {{ password }}
ip domain-name {{ hostname }}
ip default-gateway {{ default_gw }}
ntp server {{ ntp_server }}
</group>

Die Einstellungselemente sind durch " </ Gruppe>" in Gruppen unterteilt. Der Gruppenname lautet "global_settings". Wenn das analysierte Ergebnis im JSON-Format ausgegeben wird, wird das Ergebnis daher in "global_settings" angezeigt: {~} ". Ich denke, es ist praktisch, wenn Sie es einfacher machen möchten, die Verarbeitung für jedes Einstellungselement zu sehen und zu trennen.

In der Gruppe wird der Teil, den Sie analysieren möchten, durch "{{~}}" in einer Form angegeben, die der Jinja2-Vorlage ähnelt. Das Ausgabeergebnis ist wie folgt.

part1_output_json


[
    {
        "global_settings": {
            "default_gw": "192.168.100.150",
            "hostname": "hqaccess1",
            "ntp_server": "192.168.100.44",
            "password": "cisco",
            "secret": "test",
            "username": "test"
        }
    }
]

(2) Einstellung der VLAN-Schnittstelle

Ich habe die folgende Vorlage mit dem Gruppennamen "vlan_interfaces" erstellt.

part2_template


<macro>
def check_port_status(data):
    if "down" in data["port_status"]:
        data["status"] = "x"
    else:
        data["status"] = "o"
    return data
</macro>

<group name="vlan_interfaces" macro="check_port_status" del="port_status">
interface Vlan{{ vlan_num }}
 description {{ vlan_desc | ORPHRASE }}
 ip address {{ ip_address }} {{ subnet }}
 shut{{ port_status | default("up") }}
!{{ _end_ }}
</group>

Zusätzlich zu (1) verwenden wir vier zusätzliche Funktionen.

  1. Muster für reguläre Ausdrücke ORPHRASE Wenn die Beschreibung ein Wort enthält, geben Sie das Muster für reguläre Ausdrücke "WORD" an. Wenn mehrere Wörter durch Leerzeichen getrennt sind, z. B. "<< To hqdist1 Gi0 / 1 >>", können Sie "PHRASE" angeben, um zum Zeilenende zu gelangen. Wenn Sie beide von Fall zu Fall nehmen können, geben Sie wie in diesem Fall "ORPHRASE" an.

  2. Geben Sie den Standardwert default () an Da der Befehl nach dem Herunterfahren zum Parsen bestimmt ist, ist der Wert von "port_status" bei einem Befehl zum Herunterfahren "down" (blockierter Zustand). Wenn kein Befehl vorhanden ist, wird standardmäßig "up" (offener Zustand) verwendet.

  3. Gruppenfunktion Makro Mit TTP können Sie Makros mithilfe von Python-Code festlegen. Erstellen Sie hier das Makro "check_port_status". Wenn der Wert von "port_status" "down" ist, geben Sie den Wert des neu erstellten Schlüssels "status" in "x" an. Verwenden Sie für "up" "o".

  4. Gruppenfunktionen del Da für die Statusinformationen zum Öffnen / Blockieren nur "Status" erforderlich ist, wird "Portstatus" aus dem Ausgabeergebnis gelöscht.

Das Ausgabeergebnis ist wie folgt.

part2_output_json


[
    {
        "vlan_interfaces": [
            {
                "status": "x",
                "vlan_num": "1"
            },
            {
                "ip_address": "192.168.100.47",
                "status": "o",
                "subnet": "255.255.255.0",
                "vlan_desc": "<< Server Segment >>",
                "vlan_num": "100"
            }
        ]
    }
]

(3) L2-Schnittstelleneinstellung

Schließlich habe ich die folgende Vorlage mit dem Gruppennamen "l2_interfaces" erstellt.

part3_template


<macro>
def check_port_status(data):
    if "down" in data["port_status"]:
        data["status"] = "x"
    else:
        data["status"] = "o"
    return data

def check_stp_option(data):
    if "portfast" in data["stp_option"]:
        data["portfast"] = "o"
    else:
        data["portfast"] = "x"
    return data
</macro>

<group name="l2_interfaces" exclude="ip_setting, no_ip_setting" macro="check_port_status, check_stp_option" del="port_status, stp_option">
interface {{ port_no }}
 description {{ description | ORPHRASE }}
 switchport access vlan {{ vlan | default("1") }}
 switchport trunk allowed vlan {{ vlan }}
 switchport mode {{ mode | default("access") }}
 duplex {{ duplex | default("auto") }}
 speed {{ speed | default("auto") }}
 shut{{ port_status | default("up") }}
 spanning-tree {{ stp_option | default("none") }}
 ip {{ ip_setting | ORPHRASE }}
 no ip {{ no_ip_setting | ORPHRASE }}
!{{ _end_ }}
</group>

Grundsätzlich handelt es sich um eine Anwendung von (1) und (2), aber um das Ergebnis nur an die L2-Schnittstelle in die Portverwaltungstabelle auszugeben, werden die Vorlagen "ip {{ip_setting}}" und "no ip {{no_ip_setting}}" verwendet. Wenn es eine IP-Einstellung (= L3-Schnittstelleneinstellung) gibt, die dieser entspricht, verwenden Sie die Gruppenfunktion ausschließen. , Das Ergebnis der entsprechenden Schnittstelle wird ausgeschlossen.

Das Ausgabeergebnis ist wie folgt.

part3_output_json


[
    {
        "l2_interfaces": [
            {
                "description": "<< To PC1 >>",
                "duplex": "auto",
                "mode": "access",
                "port_no": "FastEthernet0/1",
                "portfast": "o",
                "speed": "auto",
                "status": "o",
                "vlan": "100"
            },
            {
                "description": "<< To PC2 >>",
                "duplex": "auto",
                "mode": "access",
                "port_no": "FastEthernet0/2",
                "portfast": "o",
                "speed": "auto",
                "status": "o",
                "vlan": "100"
            },
            {
                "duplex": "auto",
                "mode": "access",
                "port_no": "FastEthernet0/3",
                "portfast": "o",
                "speed": "auto",
                "status": "x",
                "vlan": "100"
            },
            {
                "duplex": "auto",
                "mode": "access",
                "port_no": "FastEthernet0/4",
                "portfast": "o",
                "speed": "auto",
                "status": "x",
                "vlan": "100"
            },
            {
                "description": "<< To PC3 >>",
                "duplex": "auto",
                "mode": "access",
                "port_no": "FastEthernet0/5",
                "portfast": "o",
                "speed": "auto",
                "status": "o",
                "vlan": "101"
            },
            {
                "description": "<< To PC4 >>",
                "duplex": "auto",
                "mode": "access",
                "port_no": "FastEthernet0/6",
                "portfast": "o",
                "speed": "auto",
                "status": "o",
                "vlan": "101"
            },
            {
                "duplex": "auto",
                "mode": "access",
                "port_no": "FastEthernet0/7",
                "portfast": "o",
                "speed": "auto",
                "status": "x",
                "vlan": "101"
            },
            {
                "duplex": "auto",
                "mode": "access",
                "port_no": "FastEthernet0/8",
                "portfast": "o",
                "speed": "auto",
                "status": "x",
                "vlan": "101"
            },
            {
                "description": "<< To hqdist1 Gi0/1 >>",
                "duplex": "full",
                "mode": "trunk",
                "port_no": "GigabitEthernet0/1",
                "portfast": "x",
                "speed": "1000",
                "status": "o",
                "vlan": "100-101"
            },
            {
                "description": "<< To hqdist2 Gi0/1 >>",
                "duplex": "full",
                "mode": "trunk",
                "port_no": "GigabitEthernet0/2",
                "portfast": "x",
                "speed": "1000",
                "status": "o",
                "vlan": "100-101"
            }
        ]
    }
]

Generieren Sie eine Portverwaltungstabelle

Das Ausgabeergebnis (3) im vorherigen Abschnitt wird in das Wörterbuchformat konvertiert, und die Ergebnisausgabe in CSV lautet wie folgt. portlist_output.png

[Letzte Portverwaltungstabelle](https://qiita.com/tech_kitara/items/b6ffd9790483b08b568b#%E3%83%9D%E3%83%BC%E3%83%88%E7%AE%A1%E7%90 Im Vergleich zu% 86% E8% A1% A8) gibt es Unterschiede zwischen den Zellen E10 und E11 aufgrund der Hinzufügung des Befehls "Switchport Trunk erlaubt vlan 100-101" zu Gi0 / 1 und Gi0 / 2, aber ansonsten grundsätzlich Das gleiche wurde erzeugt.

Schließlich

Bisher habe ich TextFSM und Genie Parser als Parser für NW-Geräte verwendet. Wenn Sie jedoch einen eigenen Parser erstellen möchten, der zu Ihrer Umgebung passt, ist TTP meiner Meinung nach auch eine leistungsstarke Option, wenn es um Funktionalität und Anpassbarkeit geht. Die diesmal eingeführten Dateien wurden auf GitHub --portlist_generator hochgeladen. Ich hoffe, Sie finden sie hilfreich.

Recommended Posts

Ich habe versucht, automatisch eine Portverwaltungstabelle aus L2SW Config zu generieren
Ich habe ein Tool erstellt, um automatisch ein einfaches ER-Diagramm aus der Anweisung CREATE TABLE zu generieren
Ich habe versucht, mit PI Fu aus einem Bild ein 3D-Modell einer Person zu erstellen
Ich habe ein Plugin erstellt, um mit Vim eine Markdown-Tabelle aus CSV zu generieren
Ich habe versucht, eine zufällige Zeichenfolge zu generieren
Ich habe versucht, automatisch die Zeichenfolge zu generieren, die mit Python in Mr. Adjustment eingegeben werden soll
[Python] Ich habe versucht, automatisch einen täglichen Bericht über YWT mit Outlook-Mail zu erstellen
Ich möchte viele Prozesse von Python aus starten
Ich möchte automatisch einen modernen Metal-Bandnamen generieren
Ich habe einen Befehl zum Generieren eines Kommentars für eine Tabelle in Django eingegeben
Ich habe versucht, mit Pandas eine Pferderenn-Datenbank zu erstellen
Ein Memorandum beim automatischen Erwerb mit Selen
Ich habe versucht, mit Python einen regulären Ausdruck für "Betrag" zu erstellen
Ich habe versucht, mit Python einen regulären Ausdruck von "Zeit" zu erstellen
Ich habe versucht, mit Python eine Liste von Primzahlen zu erstellen
Ich habe versucht, mit Python einen regulären Ausdruck von "Datum" zu erstellen
Ich habe versucht, mit Boto3 eine Liste der AMI-Namen zu erhalten
Ich habe versucht, ein Standbild aus dem Video auszuschneiden
Ich habe versucht, automatisch Bilder von Kanna Hashimoto mit Python zu sammeln! !!
Ich habe versucht, mit Go einen exklusiven Kontrollmechanismus zu erstellen
Ich habe versucht, einen Linebot zu erstellen (Implementierung)
Ich habe versucht, einen Linebot zu erstellen (Vorbereitung)
Ich habe versucht, die Bewegungen von Wiire-Playern automatisch mit Software zu extrahieren
Ich habe versucht, mit django eine E-Mail zum Abschluss der Registrierung von Google Mail zu senden.
[Outlook] Ich habe versucht, mit Python automatisch eine tägliche Berichtsmail zu erstellen
Ich habe eine Web-API erstellt
Ich habe versucht, das RSS des Top-Songs des iTunes Store automatisch abzurufen
Ich habe versucht, eine Clusteranalyse von Kunden anhand von Kaufdaten durchzuführen
Ich habe versucht, den Höhenwert von DTM in einem Diagramm anzuzeigen
Ich habe versucht, das Ergebnis des A / B-Tests mit dem Chi-Quadrat-Test zu überprüfen
Ich habe versucht, ein Auto in 3D zu erkennen
Ich habe versucht, Trumps Kartenspiel in Python zu implementieren
Ich habe eine einfache Mail-Sendeanwendung mit tkinter von Python erstellt
[Azure] Ich habe versucht, eine virtuelle Linux-Maschine mit Azure von Microsoft Learn zu erstellen
[IBM Cloud] Ich habe versucht, über Cloud Funtions (Python) auf die Tabelle Db2 on Cloud zuzugreifen.
Ich habe versucht, die Strichzeichnung mit Deep Learning aus dem Bild zu extrahieren
Ich habe ein Tool zum Generieren von Markdown aus der exportierten Scrapbox-JSON-Datei erstellt
Ich habe ein Tool zum automatischen Sichern der Metadaten der Salesforce-Organisation erstellt
[Python] Ich habe versucht, den Typnamen als Zeichenfolge aus der Typfunktion abzurufen
Ich habe versucht, ein Modell mit dem Beispiel von Amazon SageMaker Autopilot zu erstellen
Ich habe versucht, die Literatur des neuen Corona-Virus mit Python automatisch an LINE zu senden
Ich habe versucht, eine Super-Resolution-Methode / ESPCN zu erstellen
Ich habe die Pivot-Table-Funktion von Pandas ausprobiert
Ich habe DCGAN implementiert und versucht, Äpfel zu generieren
Ich habe versucht, Slack über das Update von Redmine zu informieren
Ich habe versucht, das Umfangsverhältnis mit 100 Millionen Stellen zu ermitteln
So generieren Sie ein Python-Objekt aus JSON
Ich habe versucht, eine Super-Resolution-Methode / SRCNN build zu erstellen
Ich habe versucht, eine Super-Resolution-Methode / SRCNN build zu erstellen
Ich habe ein ○ ✕ Spiel mit TensorFlow gemacht
Ich habe versucht, die Texte von Hinatazaka 46 zu vektorisieren!
Ich habe eine Funktion zum Abrufen von Daten aus der Datenbank spaltenweise mithilfe von SQL mit SQLite3 von Python [SQLite3, SQL, Pandas] erstellt.
Ich habe versucht, mit dem Seq2Seq-Modell von TensorFlow so etwas wie einen Chatbot zu erstellen
Ich habe versucht, das Update von "Werde ein Romanautor" mit "IFTTT" und "Werde ein Romanautor API" zu benachrichtigen.
Versuchen Sie, mit matplotlib aus den Daten von "Schedule-kun" eine Kampfaufzeichnungstabelle zu erstellen.