Python und SNMP

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Kickstart
User
Beiträge: 4
Registriert: Donnerstag 9. September 2010, 07:41

Ich versuche gerade ein Python Script zu schreiben, welches mir alle wichtigen Daten über mein Netzwerk sammelt und in eine SQL Datenbank schreibt. Dazu ist auch nötig zu erfahren um welche Art von Gerät es sich handelt (Windows oder Linux Client, Drucker, USV, usw... ) damit Nagios die entsprechenden von mir geschriebenen Plugins auf die Hosts anwenden kann. Dazu starte ich einzelne SNMP Abfragen über das Python Modul pysnmp, um den Typ des Gerätes zu bestimmen und direkt in die DB eintragen zu können, wie zum Beispiel für die Gerätebeschreibung:

Code: Alles auswählen

errorIndication, errorStatus, errorIndex, varbindtablesysdesc = cmdgen.CommandGenerator().bulkCmd(cmdgen.CommunityData('my-agent', 'public', 1),cmdgen.UdpTransportTarget((ip, 161)),0,20,(1,3,6,1,2,1,1,1))
Das Problem ist nur, dass der SNMP Dienst noch nicht auf allen Windows Maschinen im Netzwerk aktiviert ist, sodass die Ausführung der Abfrage bei entsprechenden Geräten extrem lange dauern kann, bevor ein timeout auftritt und das Script weiterläuft.

Gibt es eine Möglichkeit, dies zu umgehen bzw. eine andere Methode der Abfrage ?
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Du kannst mehrere Threads verwenden und die Anfragen über einen Threadpool verwalten.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Kickstart
User
Beiträge: 4
Registriert: Donnerstag 9. September 2010, 07:41

Genau das habe ich mittlerweile auch schon versucht, indem ich über das importieren des "threading" Moduls eine Klasse dafür anlegen wollte:

Code: Alles auswählen

class snmpthread(threading.Thread):
	def __init__(self,ip):
		threading.Thread.__init__(self,ip)
		self.ip = ip

	def run(self):
		desc = ""
		errorIndication, errorStatus, errorIndex, varbindtablesysdesc = cmdgen.CommandGenerator().bulkCmd(cmdgen.CommunityData('my-agent', 'public', 1),cmdgen.UdpTransportTarget((self.ip, 161)),0,20,(1,3,6,1,2,1,1,1))
		for value in varbindtablesysdesc:
			if value[0][0][6] == 1 and value[0][0][7] == 1:
				desc = str(value[0][1])
		return desc
ausgeführt wird die Klasse bei mir über den Befehl:

Code: Alles auswählen

thread = thread.snmpthread(ip)
		thread.start()
was dann eigentlich die Klasse benutzen sollte um die Description auszugeben. Nur leider bekomme ich immer die Fehlermeldung:

Code: Alles auswählen

NameError: name 'thread' is not defined
und bin mit meinem Latein am Ende, da ich mich bisher nicht groß mit dem Erstellen eigener Klassen beschäftigt habe.
Wo liegt der Fehler in meiner Syntax ?
BlackJack

@Kickstart: Die Fehlermeldung ist doch ziemlich eindeutig. Wo sollte denn Deiner Meinung nach der Name `thread` herkommen? Bevor er das erste mal benutzt wird, muss er ja irgendwie definiert/gebunden werden.

Des weiteren erwartet die `__init__()` von `threading.Thread` sicher die `ip` nicht als Argument.

Und in der `run()`-Methode macht es keinen Sinn etwas zurück zu geben. Das läuft ja asynchron; es würde auf ein Ergebnis ja gar nicht gewartet. Da müsstest Du schon irgendwie für eine Kommunikation zwischen den Threads sorgen. Zum Beispiel mit einer `Queue.Queue` die übergeben wird, und in die der Thread am Ende das Ergebnis schreibt, damit Du da im Hauptthread am Ende auch irgendwie heran kommst.

Für so einfache Sachen, die keinen Zustand über mehrere Methoden hinweg benötigten, würde ich auch keine eigene Klasse schreiben. Man kann mit `threading.Thread()` auch Funktionen asynchron starten ohne eine eigene Klasse schreiben zu müssen, die am Ende nur eine `run()`-Methode besitzen.
Kickstart
User
Beiträge: 4
Registriert: Donnerstag 9. September 2010, 07:41

Ok, ich sehe schon, dass ich ich erst noch eine Weile mit Klassen beschäftigen sollte ...

Trotzdem erstmal Danke für die schnelle Antwort.
BlackJack

@Kickstart: Der `NameError` hat hier nichts mit Klassen zu tun. Wenn Du so etwas wie ``x = x + 1`` schreibst, müssen alle Namen die rechts vom Gleichheitszeichen stehen halt irgendwo vorher mal an einen Wert gebunden werden, in diesem Fall das `x`.

Und Du hast da ``thread = thread.snmpthread(ip)`` stehen. Das `thread` rechts vom Gleichheitszeichen ist offenbar unbekannt. Wobei es, wenn es bekannt *wäre* auch keine gute Idee ist das Ergebnis von dem Aufruf an den Namen `thread` zu binden, weil dass ja die alte Bindung überschreiben würde.
Kickstart
User
Beiträge: 4
Registriert: Donnerstag 9. September 2010, 07:41

Ich dachte mir nur, dass ich mit der Einführung von Klassen besser komme, da ich noch diverse andere informationen über SNMP auslesen will. In der Endversion des Scriptes sollte die Ausgabe auch noch in html Form erfolgen, um anschließed weiterverwendet werden zu können (Nagios). So kommen schnell einige hundert Zeilen Code zusammen, die ich gerne etwas übersichtlicher gestalten würde.

Leider habe ich vorher noch nie in Python Klassen erstellt und würde mich auch noch als "Python - Neuling" bezeichnen, tue mich deshalb mit der korrekten Formulierung der Codezeilen noch etwas schwer.

Über ein paar genauere Vorschläge zur verbesserung würde ich mich daher sehr freuen. :D
Antworten