Dieser Artikel ist der 14. Tagesartikel von NIFTY Adventskalender 2016. Gestern war @ntoofus Ansible-Konfigurationsinformationen mit Grafik-DB verwalten.
Hallo. In meiner täglichen Arbeit baue, betreibe und pflege ich die Netzwerkinfrastruktur in Nifty Cloud. Dieses Mal möchte ich ein wenig über die Automatisierung des Betriebs physischer Geräte im Netzwerk schreiben, die auf der Serviceseite von Nifty Cloud nicht sichtbar ist.
-Der Neustart des Geräts wurde ausgeführt
-Die Geräteschnittstelle ist abgestürzt
-Modul fehlgeschlagen
-Jedenfalls stimmt etwas nicht
Es kommt oft vor, dass so etwas wie ... auftritt und Sie den Status des Geräts sofort überprüfen möchten. Melden Sie sich in diesen Fällen beim Gerät an (solange es noch verfügbar ist) und Es ist notwendig, sofort show-Befehle zu drücken, um Informationen zu sichern.
Man kann sagen, dass die Befehle zu diesem Zeitpunkt bis zu einem gewissen Grad standardisiert sind. (Im Folgenden finden Sie eine Liste, in der Sie solche Befehle unabhängig vom jeweiligen Gerät / Betriebssystem auflisten können.)
show running-config
show interfaces
show logging
show inventory
show modules
show tech-support
···Eine solche. Bei Netzwerkgeräten und Betriebssystemen wie Cisco IOS können Sie beispielsweise die Einstellungsinformationen und den Status überprüfen, indem Sie den obigen Befehl eingeben.
Besonders in einer sehr dringenden Situation, beispielsweise wenn ein Fehler auftritt Ich möchte Routinearbeiten mit so wenig menschlichem Eingreifen wie möglich durchführen, um Zeit für die Untersuchung aufzuwenden.
In diesem Artikel, um das Ergebnis des obigen Befehls schnell zu erhalten Ich werde die Geschichte der Implementierung eines Skripts in Python vorstellen, das sich automatisch am Gerät anmeldet, Befehle eingibt und Ausgaben abruft.
Im Allgemeinen glauben wir, dass Operationen für Netzwerkgeräte in drei Typen unterteilt werden können.
--Überprüfen Sie die Einstellungen Geben Sie Befehle ein, um den Gerätestatus und die Einstellungen zu überprüfen, z. B. den oben genannten Befehl show.
--Einstellungen ändern Geben Sie Befehle ein, um den Gerätestatus / die Einstellungen wie Konfigurationsmodus, Festschreiben und Schreiben zu ändern
Dieser Artikel befasst sich insbesondere mit der Überprüfung der Einstellungen.
Wie in dem im Referenzabschnitt eingeführten Artikel angegeben, Unter den Betriebsmethoden für Netzwerkgeräte erfolgt der Allzweckbetrieb über die CLI. Verkehrsfluss usw. kann durch SNMP erhalten werden, aber die Arten von Informationen sind begrenzt. APIs können implementiert werden, variieren jedoch von Hersteller zu Hersteller.
Alle Geräte basieren auf dem CLI-Betrieb, dh der Betrieb nach dem Verbinden mit ssh oder Telnet ist die Betriebsmethode für allgemeine Netzwerkgeräte.
Mit anderen Worten bedeutet die Automatisierung dieser Operationen Dies bedeutet, dass die folgenden Vorgänge, die normalerweise von Menschen an der CLI ausgeführt werden, vom Skript ausgeführt werden.
$ telnet 192.168.0.2
Trying 192.168.0.2...
Connected to 192.168.0.2 (192.168.0.2).
Escape character is '^]'.
User Access Verification
Username: root
Password:
(hostname)#show run
...Ausgabe
(hostname)#
Ich werde den Inhalt des Skripts erklären.
Verwenden des pexpect-Moduls in Python3 Implementiert erwartungsgemäß eine Proxy-Operation für die CLI-Schnittstelle.
Verwenden Sie zunächst pexpect.spawn (), um einen untergeordneten Prozess zu starten. Der untergeordnete Prozess wird hier als untergeordnet bezeichnet, und der Prozess wird danach für das untergeordnete Element fortgesetzt. Im Argument von spawn muss der zu startende Prozess in der Befehlsanweisung angegeben werden, und hier handelt es sich um Telnet.
Indem Sie den Dateideskriptor für die Protokolldatei in die Variable child.logfile_read einfügen, Sie können das Ausgabeziel des gestarteten untergeordneten Prozesses für eine Datei angeben. Alternativ können Sie dieser Variablen die Standardausgabe (sys.stdout) zuweisen und die Ausgabe auf der Konsole anzeigen.
def login(ipaddr, passwd):
child = pexpect.spawn("telnet " + ipaddr)
logname = "./log/" + "log_" + ipaddr + \
"_" + datetime.now().strftime("%s") + ".log"
wb = open(logname, 'wb')
child.logfile_read = wb
Verarbeitung mit Expect, nicht beschränkt auf Pexpect,
1. sendline()Befehl senden von
2. expect()Warten auf die Ausgabe der erwarteten Zeichenfolge durch
Wird wiederholt. Im Fall von pexpect kann die zu wartende Zeichenfolge in der Liste angegeben werden, und hier wird sie gemäß der erwarteten Zeichenfolge wie folgt angegeben.
expect_list = [u"#",
u">",
u"\nlogin: ",
u"Username: ",
u"Password: ",
u"Connection closed by foreign host.",
u"Login incorrect"]
Wenn Sie pexpect.spawn (Telnet [IP-Adresse]) ausführen, wird Telnet auf dem Gerät ausgeführt und das Gerät wartet auf die nächste Eingabe. Das heißt, wenn es manuell ausgeführt wird, ist der Status des Bildes wie folgt.
$ telnet 192.168.0.2
Trying 192.168.0.2...
Connected to 192.168.0.2 (192.168.0.2).
Escape character is '^]'.
User Access Verification
Username: [Cursor]
Führen Sie nun erwartungsgemäß wie unten gezeigt aus.
index = child.expect(expect_list)
Zu diesem Zeitpunkt stimmt das im dritten Teil der Liste gespeicherte Element "Benutzername:" mit der letzten Zeile der Ausgabe des Geräts überein. Wenn eine Liste als erwartetes Argument angegeben wird, ist der Rückgabewert die Elementnummer der Liste. Daher wird "3" in der Variablen index gespeichert. Wenn keine übereinstimmende Zeichenfolge vorhanden ist, wartet Expect () weiterhin auf weitere Ausgaben vom Gerät. In diesem Fall endet die Verarbeitung erst nach Ablauf des Zeitlimits. Es ist jedoch auch möglich, die Fehlerverarbeitung zu implementieren, indem zu diesem Zeitpunkt auf das Zeitlimit gewartet wird.
In der aktuellen Implementierung wird die folgende Verarbeitung gemäß dem Indexwert durchgeführt.
Selbst wenn Sie sich erfolgreich anmelden, müssen Sie das Kennwort möglicherweise erneut eingeben, wenn das Gerät die Aktivierung erfordert. Da es eine Grenze gibt, die Verarbeitung für diese Geräte individuell zu beschreiben, ist die Implementierung bis dahin jetzt ruhig. Überprüfen Sie für alle Geräte und Betriebssysteme, die sich anmelden sollen, wie der Anmeldevorgang bei manuellem Betrieb abläuft. Es muss so gestaltet sein, dass Verzweigung und Verarbeitung normal ablaufen.
while True:
if index == 0: # success to login.
return child
elif index == 1: # need to promoted to enable mode.
child.sendline("enable")
index = child.expect(expect_list)
elif index == 2 or index == 3: # need to input "root".
child.sendline("root")
index = child.expect(expect_list)
elif index == 4: # need to input password.
child.sendline(passwd)
index = child.expect(expect_list)
elif index == 5: # Connection is closed.
print("Unmatched password, or connection is closed.")
return -1
elif index == 6: # incorrect password.
print("\nFault: incorrect password.")
return -1
In den bisherigen Beispielen enthält der Index 3 als Wert, sodass er in der dritten if-Anweisung als Zweig enthalten ist. Sendet die von sendline () angeforderte Zeichenfolge als Benutzernamen. (root ist ein Beispiel) Zu diesem Zeitpunkt erfolgt die Ausgabe des Geräts manuell wie folgt.
Username: root
Password: [Cursor]
Dies stimmt mit dem in erwartungsliste gespeicherten "Passwort:" überein, und die while-Schleife geht weiter. Ebenso wird das Kennwort in das Gerät eingegeben, und wenn die Authentifizierung erfolgreich ist, ist die Anmeldung abgeschlossen.
Hier ist die Anmeldung abgeschlossen, wenn "#" empfangen wird. Dies setzt voraus, dass Sie sich wie unten gezeigt im privilegierten Modus anmelden. Es besteht jedoch Verbesserungsbedarf, da dies je nach Betriebssystem zu Fehlfunktionen führen kann.
Username: root
Password:
(hostname)#
Wenn die Anmeldung abgeschlossen ist, wartet das Gerät auf den nächsten Befehl. Dieses Mal habe ich unter der Annahme der Befehlseingabe vom Typ Bestätigung (show) die folgende Funktion erstellt. Befehle ist eine Liste, und es wird angenommen, dass Befehle wie "show interfaces" als Zeichenfolge für jedes Element gespeichert werden. Insbesondere wird hier keine Fehlerbehandlung implementiert.
def exec_command(commands, child):
expect_list = u"#"
for c in commands:
child.sendline(c)
child.expect(expect_list)
Wenn Sie einen Befehl zum Ändern von Einstellungen eingeben möchten, müssen Sie die Einstellungen im Voraus überprüfen und feststellen, ob er sich in einem Zustand befindet, der für die Eingabe des Befehls geeignet ist, den Sie einstellen möchten. Und auch nach der Eingabe muss überprüft werden, ob die Einstellungen sicher wiedergegeben werden und ob andere seltsame Protokolle vorhanden sind. Die bisher beschriebene Implementierung im String-Standby erfordert viel Geduld.
Einige der Aufgaben, die vollständig stilisiert wurden, werden implementiert, da die Ausgabe erwartet werden kann. Auf der anderen Seite möchte ich, da es sich um ein Skript handelt, das den Inhalt festlegt, der der tatsächlichen Arbeit sehr nahe kommt, davon Abstand nehmen, ihn hier einzuführen.
Übrigens, für "child.logfile_read" festgelegt, als der untergeordnete Prozess gestartet wurde, Alle Ausgaben der Befehle, die bisher vom Login ausgeführt wurden, werden geschrieben. Diesmal handelt es sich um eine Demo-Implementierung, aber nachdem Sie das Kennwort in das Skript eingegeben haben, Wenn Sie festlegen, dass dieses Skript angezeigt wird, wenn Sie ein bestimmtes Syslog sehen, Beispielsweise ist es möglich, die Geräteeinstellungen und den Status unmittelbar nach der Ausgabe eines Modulfehlers abzurufen.
Bei einigen Befehlen müssen Wartungsinformationen im Gerät generiert und manuell über FTP usw. erfasst werden. Ich möchte eine weitere Gelegenheit nutzen, um diese Automatisierungen durchzuführen.
Dieses Mal habe ich die Automatisierung des CLI-Betriebs mit pexpect eingeführt. Es ist ein ziemlich schlammiger Weg, aber andererseits gibt es keine Netzwerkgeräte, die nicht mit Telnet (?) Betrieben werden können Es ist auch eine Methode, die bei ordnungsgemäßem Design mit jedem Gerät verwendet werden kann.
Ich möchte über REST-APIs sprechen, die von bestimmten Herstellern wie Junipers PyEz bereitgestellt werden.
Vielen Dank.
Morgen ist ein Beitrag von @hitsumabushi.