Accueil / Blog / Métier / 2016 / Initiation à SNMP avec Python : PySNMP (Partie 2) - Utilisation de la librairie

Initiation à SNMP avec Python : PySNMP (Partie 2) - Utilisation de la librairie

Par Gaël Pegliasco publié 03/03/2016, édité le 25/04/2016
SNMP est un protocole de supervision réseau universellement répandu. C'est le standard utilisé par la quasi totalité des équipements réseaux. Il permet de superviser (interrogation et modification) tous les types de matériels, allant du routeur à l'imprimante, et même certaines machines à café connectées. Cette seconde partie du tutoriel vous présente la librairie PySNMP
Initiation à SNMP avec Python : PySNMP (Partie 2) - Utilisation de la librairie

Introduction

Ce tutoriel vous propose de découvrir la librairie Python PySNMP permettant de dialoguer avec tout matériel compatible avec le protocole du même nom.

Dans cette seconde partie nous allons vous présenter l'utilisation du protocole SNMP au travers de la librairie PySNMP.

Vous pouvez démarrer son apprentissage directement par cette seconde partie si vous connaissez déjà le protocole SNMP.

Toutefois, si vous débutez sur ce protocole nous vous conseillons très vivement de lire auparavant la première partie de ce tutoriel qui vous présentera le protocole SNMP, ses qualités et défauts et vous fournira les outils de base pour commencer à l'utiliser et vous l'approprier. Sans ces connaissances préliminaires, ce second chapitre risque fort de vous sembler bien difficile à appréhender.

A la fin de cette seconde partie vous serez normalement capable :

  • De manipuler les éléments de base OID, communautés, comptes utilisateurs, contextes, ...
  • D'utiliser vos propres MIBs
  • D'exécuter des requêtes GET/GETNEXT/SET et simuler des WALK

  • De créer des sondes pour des outils de supervision comme Nagios, Centreon et consorts.

Plan

  • Présentation du protocole
    • SNMP

    • Les MIB

    • ASN1

    • Les requêtes

  • PySNMP

    • Les requêtes

    • Les tables
    • Utiliser ses MIBs avec un agent

PySNMP

Maintenant que nous avons présenté le protocole SNMP et quelques commandes pour l'utiliser, nous pouvons enfin passer au véritable sujet de ce tutorial : la librairie PySNMP !
PySNMP
est une librairie Python qui implémente toutes les versions du protocole SNMP et ce entièrement en Python.

Ses principales caractéristiques sont :

  • Complète : elle implémente l'intégralité du protocole SNMP (v1 à v3) entièrement en Python

  • Assez légère, environ 15000 lignes de code

  • Assez simple pour les choses simples

  • Très utilisée dans la communauté : 30 000 téléchargements par mois sur Pypi

  • Très pratique pour écrire des sondes nagios/centreon/autre ou récupérer des informations SNMP dans vos programmes Python

  • Elle permet d'écrire vos propres agents

  • Elle est parfois complexe et manque d'une documentation claire sur certains éléments comme les agents

Installation de PySNMP

L'installation de la librairie est simple, c'est du Python :

$ pip install pysnmp

Toutefois, sur les machines Windows la commande « pip » échouera généralement sur l'installation de « pycrypto » que « pip » veut compiler. Or ces dernières sont souvent dépourvues de tels outils.
Dans ce cas installez un binaire « pycrypto » au préalable depuis ce site  ou depuis ce site pour Python 3.5.

Si vraiment vous avez des difficultés, suivez ce tutoriel d'installation de PySNMP sous Windows rédigé spécialement à la demande de nos lecteurs.

Manipuler les données ASN.1

Avec PySNMP il vous arrivera de manipuler des données au format ASN.1 puisque c'est celui qui est utilisé par le protocole SNMP.

La librairie PySNMP s'appuie sur une autre librairie : pyasn1 pour réaliser cela.
La conversion des types ASN.1 vers python est presque naturelle :

from pyasn1.type.univ import *
a = Integer(21) * 2
print(a)
a = Integer(-1) + Integer(1)
print(a)
a = int(Integer(42))
print(a)
a = OctetString('Hello') + ', ' + OctetString(hexValue='5079534e4d5021')
print(a, type(a))

Les commandes de base

PySNMP propose différentes fonctions de « bas niveau » pour utiliser le protocole SNMP, mais il est conseillé d'utiliser le module « hlapi » signifiant « High Level API ».

Ce dernier propose des fonctions de haut niveau, assez faciles à paramétrer pour exécuter les commandes de base que l'on peut lister de cette manière

from pysnmp.hlapi import *
l = [ x for x in dir() if 'Cmd' in x]
print(l)
help('pysnmp.hlapi.getCmd')

ce qui affiche

['bulkCmd', 'getCmd', 'nextCmd', 'setCmd']
Help on function getCmd in pysnmp.hlapi:
pysnmp.hlapi.getCmd = getCmd(snmpEngine, authData, transportTarget, contextData, *varBinds, **options)
Creates a generator to perform one or more SNMP GET queries.

Avant d'utiliser ces commandes nous allons apprendre à manipuler les paramètres dont elles ont besoin :

  • Les OIDs que l'on souhaite consulter/modifier

  • Les éléments de connexion « communauté » pour le protocole v2 ou l'utilisateur pour le protocole v3

Les OIDS

Les OIDs sont les identifiants des informations décrites dans les MIBs.
Un OID indique le chemin à suivre dans l'arbre de la MIB pour trouver l'information ; « .1.2.3.0 » pourrait se comprendre par :

  • « . »
    En partant de la place centrale, plusieurs rues sont faces à vous.

  • « 1 »
    Prenez la première à partir de la gauche
    Vous arrivez sur une nouvelle place.

  • « 2 »
    Plusieurs rues sont de nouveau face à vous.
    Prenez la seconde sur votre gauche.
    Vous arrivez sur une nouvelle place.

  • « 3 »
    Plusieurs rues sont de nouveau face à vous.
    Prenez la troisième sur votre gauche.
    Vous arrivez sur une nouvelle place.
  • « 0 »
    Il y a une plaque sur la place, elle contient votre information.
    Si vous avez envoyé un « GET » vous la lisez, si vous avez envoyé un « SET » vous la modifiez.

 

PySNMP1.png
Cheminement dans la MIB

 

Un OID est représenté soit par une suite de valeurs numériques, soit par une suite de noms désignant chaque branche parcourue dans la MIB.
Si vous souhaitez plus de précisions sur ces OIDs je vous invite à lire la documentation de PySNMP à ce sujet.

Pour créer un OID avec PySNMP il convient d'instancier la classe « ObjectIdentity »

Un OIDs peut être défini :

  • Par une chaîne de caractères

  • Par un tuple

  • Par son libellé

Ces 4 instances ci-dessous définissent le même objet

o = ObjectIdentity('1.3.6.1.2.1.1.3.0')
o = ObjectIdentity((1, 3, 6, 1, 2, 1, 1, 3, 0))
o = ObjectIdentity('SNMPv2-MIB', 'sysUpTime', 0)
o = ObjectIdentity('iso.org.dod.internet.mgmt.mib-2.system.sysUpTime.0')

Cela semble simple, mais à l'utilisation les malheurs commencent :

from pysnmp.hlapi import *
o = ObjectIdentity('1.3.6.1.2.1.1.3.0')
print(o.getLabel())
print(o.getMibNode())
print(o.getMibSymbol())
print(o.getOid())
print(o.prettyPrint())
Traceback (most recent call last):
File "<...>/oid_example.py", line 4, in <module>
print(o.getLabel())
File "<...>/site-packages/pysnmp/smi/rfc1902.py", line 185, in getLabel
raise SmiError('%s object not fully initialized' % self.__class__.__name__)
pysnmp.smi.error.SmiError: ObjectIdentity object not fully initialized

Mais pourquoi cette erreur? Les exemples de la documentation de PySNMP sont plutôt maladroits à cet égard :

>>> from pysnmp.hlapi import *
>>> x = ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysDescr', 0), 'Linux i386 box'))
>>> # ... calling MIB lookup ...
>>> x[0].prettyPrint()

Il faut effectivement rechercher cet OID dans la MIB, ce n'est pas automatique car il y a de nombreuses MIBs. PySNMP est fourni avec tout un arsenal de Mibs, néanmoins il faut lui dire ou les trouver.

Et pour cela la documentation est bien malheureuse car elle n'affiche jamais d'exemple réel !

Vous avez le droit de pester ; une fois vos nerfs calmés, rappelez-vous que c'est un produit OpenSource et que vous disposez fort heureusement de l'accès au code !
La commande « help » de Python montre qu'il existe une méthode « resolveWithMib ».

Cette méthode prend en paramètre un objet « MibViewController ».
Ce contrôleur a pour rôle de résoudre la correspondance « OID »/MIB.

La documentation de la classe « MibViewController » est quasiment inexistante. Cette classe prend un objet « MibBuilder » en argument lors de sa création.
Il faut donc aller voir la classe « MibBuilder »

Mais une petite recherche dans l'arborescence de PySNMP montre qu'apparemment un « MibViewController » s'obtient à partir du moteur SNMP engine.
L'engine est en quelque sorte le coeur de la librairie PySNMP qui vous permet de dialoguer avec les différents éléments du protocole (messages, hôtes, communautés, OIDs, MIBS, etc.)

Vous pouvez avoir plusieurs moteurs pour, par exemple, travailler avec plusieurs MIBs.

Notre code devient alors :

from pysnmp.hlapi import *

se = SnmpEngine()
mvc = se.getUserContext('mibViewController')
o.resolveWithMib(mvc)

o = ObjectIdentity('1.3.6.1.2.1.1.3.0')
print(o.getLabel())
print(o.getMibNode())
print(o.getMibSymbol())
print(o.getOid())
print(o.prettyPrint())

Hélas, nous n'y sommes toujours pas...

 Traceback (most recent call last):
File "<...>/PySNMP/oid_example.py", line 7, in <module>
o.resolveWithMib(mvc)
File "<...>/site-packages/pysnmp/smi/rfc1902.py", line 355, in resolveWithMib
addMibCompiler(mibViewController.mibBuilder,
AttributeError: 'NoneType' object has no attribute 'mibBuilder'

Le mib view controller n'est pas défini car nous n'avons pas créé de « UserContext ».
La solution la plus simple revient, finalement, à créer nous-même le « MibViewController » :

from pysnmp.hlapi import *
from pysnmp.smi.view import MibViewController

se = SnmpEngine()
mvc = se.getUserContext('mibViewController')
if not mvc:
   mvc = MibViewController(se.getMibBuilder())

o = ObjectIdentity('1.3.6.1.2.1.1.3.0')
o.resolveWithMib(mvc)

print(o.getLabel())
print(o.getMibNode())
print(o.getMibSymbol())
print(o.getOid())
print(o.prettyPrint())

Et voilà !

('iso', 'org', 'dod', 'internet', 'mgmt', 'mib-2', 'system', 'sysUpTime')
MibScalar((1, 3, 6, 1, 2, 1, 1, 3), TimeTicks())
('SNMPv2-MIB', 'sysUpTime', (ObjectName('0'),))
1.3.6.1.2.1.1.3.0
SNMPv2-MIB::sysUpTime.

Le contrôleur de MIB utilise le MIB « builder » par défaut de PySNMP qui stocke les versions « pythonisées » des MIBS dans le sous-dossier d'installation de pysnmp : « pysnmp/smi/mibs/ ». N'hésitez pas à y jeter un œil.

Travailler avec sa propre MIB

Pour les MIBs standard, vous savez comment faire. Mais vous allez dire :

« Oui, mais je travaille avec des MIBs propriétaires car je suis un constructeur de matériels ou j'utilise le matériel spécifique d'un constructeur et j'aurais besoin de ma propre MIB ».
Pas de problème, les OIDs peuvent le faire pour vous.

Supposons que vous disposiez de votre propre MIB, comme celle ci-dessous dont l'essentiel à été emprunté à ce tutoriel :

MAKINA_MIB DEFINITIONS ::= BEGIN

IMPORTS
OBJECT-TYPE, Integer32, NOTIFICATION-TYPE, enterprises
FROM SNMPv2-SMI
;

MakinaCorpus OBJECT IDENTIFIER ::= {enterprises 3}

dataValue OBJECT-TYPE
SYNTAX Integer32
MAX-ACCESS read-only
STATUS current
DESCRIPTION "A sample count of something."
::= {MakinaCorpus 1}

dataDescription OBJECT-TYPE
SYNTAX OCTET STRING
MAX-ACCESS read-only
STATUS current
DESCRIPTION "A description of something"
::= {MakinaCorpus 2}

testTrap NOTIFICATION-TYPE
STATUS current
DESCRIPTION "Test notification"
::= {MakinaCorpus 3}
END

En général les MIB des constructeurs sont stockées sous l'OID « enterprises » : iso . org . dod . internet . private . Enterprises (1.3.6.1.4.1)
Le site IP monitor semble montrer que le sous nœud « .3 » est libre, je l'ai donc choisi pour installer la MIB de Makina ci-dessus, mais vous pourriez prendre un sous noeud existant.

 MakinaCorpus OBJECT IDENTIFIER ::= {enterprises 3}

Il convient maintenant de compiler cette MIB avec PySMI. Normalement cette librairie est installée avec PySNMP, sinon exécutez « pip install pysmi ».
PySNMP est livré avec plusieurs scripts, notamment « build-pysnmp-mib » qui va réaliser cette conversion pour nous :

$ build-pysnmp-mib -o MAKINA_MIB.py MAKINA_MIB

Ceci générera un fichier « MAKINA_MIB.py » contenant le code Python implémentant cette MIB.

Toutefois, depuis la version 4.3 de PySNMP le script "build-pysnmp-mib" est devenu obsolète et n'est plus livré.

Pour compiler votre MIB vous devez utiliser le script "mibdump.py" généralement installé dans le dossier "/usr/local/bin"

$ /path/to/mibdump.py /path/to/MAKINA_MIB # use ./MAKINA_MIB if you are in the good repository to avoid mib not found error
Source MIB repositories: file:///path/to/MAKINA_MIB, file:///usr/share/snmp/mibs, http://mibs.snmplabs.com/asn1/@mib@
Borrow missing/failed MIBs from: http://mibs.snmplabs.com/pysnmp/notexts/@mib@
Existing/compiled MIB locations: pysnmp.smi.mibs, pysnmp_mibs
Compiled MIBs destination directory: /home/<user>/.pysnmp/mibs
...
Created/updated MIBs: MAKINA_MIB
Pre-compiled MIBs borrowed:
Up to date MIBs: SNMPv2-CONF, SNMPv2-SMI, SNMPv2-TC
Missing source MIBs:
Ignored MIBs:
Failed MIBs:

Enfin, pour construire un OID utilisant cette dernière vous devez maintenant écrire :

o = ObjectIdentity((1, 3, 6, 1, 4, 1, 3, 1))
o.addMibSource('/path/to/makina_mib/dot/py/folder')
o.loadMibs("MAKINA_MIB")
o.resolveWithMib(mvc)

print(o.getLabel())
print(o.getMibNode())
print(o.getMibSymbol())
print(o.getOid())
print(o.prettyPrint())
('iso', 'org', 'dod', 'internet', 'private', 'enterprises', 'MakinaCorpus', 'dataValue')
MibScalar((1, 3, 6, 1, 4, 1, 3, 1), Integer32())
('MAKINA_MIB', 'dataValue', ())
1.3.6.1.4.1.3.1
MAKINA_MIB::dataValue

Nous verrons en exécutant les commandes de base que l'on peut aussi spécifier directement la source ASN.1 au lieu de compiler la MIB. Depuis la version 4.3, PySNMP peut le faire automatiquement dans certains cas.

Autres éléments avant de commencer

Les commandes « GET », « SET » et « BULK » de la librairie PySNMP requièrent plusieurs paramètres :

  • Le moteur SNMP à utiliser

  • Le paramètre d'authentification, « communauté » ou « utilisateur »

  • Le type de transport utilisé (UDP), IPv4 ou IPv6 et le port (161 par défaut)

  • Le contexte d'exécution

  • Et les variables à manipuler (les OIDs)

Le moteur SNMP

PySNMP permet de dialoguer avec tous les composants du protocole SNMP via un objet « SNMP Engine ». Sa description complète est consultable dans la documentation officielle.
Bien souvent vous avez uniquement besoin de l'instancier.

from pysnmp.hlapi import *
se = SnmpEngine()

Paramètre d'authentification

Ce paramètre est soit :

  • Une communauté pour les protocoles v1 et v2

  • Un utilisateur (avec les 5 paramètres login, mot de passe, algorithme chiffrement mot de passe, salt chiffrement communication, algorithme chiffrement communication) dans le cas du protocole v3

La communauté est fournie par la classe « CommunityData »

from pysnmp.hlapi import *
cv1 = CommunityData('public', mpModel=0) # SNMPv1
cv2 = CommunityData('public', mpModel=1) # SNMPv2c

Les utilisateurs utilisés pour les connexions via le protocole v3 doivent être instanciés via la classe « UsmUserData » qui accepter 5 paramètres :

  • userName : Login de l'utilisateur

  • authKey : mot de passe

  • authProtocol : protocole pour chiffrer le mot de passe
    Un tuple indiquant le chemin dans la MIB définisant le protocole.

    Sous « iso . org . dod . internet . snmpV2 . snmpModules . snmpFrameworkMIB . snmprameworkAdmin . SnmpAuthProtocols »
    Par défaut « usmHMACMD5AuthProtocol »

  • privKey : La clef/le salt pour l'algorithme de chiffrement

  • privProtocol : L'algorithme de chiffrement.
    Un tuple indiquant le chemin dans la MIB définissant cet algorithme
    soit sous « iso . org . dod . internet . snmpV2 . snmpModules . snmpFrameworkMIB . snmpFrameworkAdmin . snmpPrivProtocols », soit ailleurs.
    PySNMP propose 6 algorithmes :

    • usmNoPrivProtocol, par défaut si pas de clef associée

    • usmDESPrivProtocol, par défaut si non précisé et clef associée

    • usm3DESEDEPrivProtocol

    • usmAesCfb128Protocol

    • usmAesCfb192Protocol

    • usmAesCfb256Protocol

Exemple :

u = UsmUserData('userlogin'
                , authKey='authenticationkey'
                , privKey='encryptionkey'
                , privProtocol=usmAesCfb256Protocol)
print(u)
UsmUserData(userName='userlogin', authKey=<AUTHKEY>, 
privKey=<PRIVKEY>, authProtocol=(1, 3, 6, 1, 6, 3, 10, 1, 1, 2),
privProtocol=(1, 3, 6, 1, 4, 1, 9, 12, 6, 1, 2),
securityEngineId='<DEFAULT>', securityName='userlogin')

Les types de transport

UDP en IPv4 ou IPv6 :

Ce sera donc une instance d'une de ces 2 types de transports:

  • UdpTransportTarget

  • Udp6TransportTarget

Ces 2 classes acceptent plusieurs arguments :

  • Le premier étant un couple (adresse ip, port).
    L'adresse est une chaîne de caractères, hostname ou adresse IP. Le port un entier.
    Les adresses IPv6 doivent respecter la RFC 1924#section-3

  • un timeout, exprimé en secondes, par défaut

  • un nombre maximum pour le « retry », par défaut

  • une liste de tags, selon la RFC 3413#section-4.1.4

Exemple :

t1 = UdpTransportTarget(('demo.snmplabs.com', 161))
t2 = Udp6TransportTarget(('google.com', 161))
print(t1)
print(t2)
UdpTransportTarget(('195.218.195.228', 161), timeout=1, retries=5, tagList=b'')
Udp6TransportTarget(('2a00:1450:4007:80e::200e', 161), timeout=1, retries=5, tagList=b'')

Les contextes

Il s'agit des contextes SNMP tels que définis par la RFC 3411.#3.3.1

Avec SNMPv1 un agent ne pouvait gérer qu'une seule MIB.
Or aujourd'hui certains matériels peuvent gérer plusieurs MIB, par exemple un commutateur ATM ayant plusieurs cartes, chacune avec sa propre base.

Le contexte permet donc d'indiquer à quelle sous-ensemble des MIBs de l'agent on s'adresse.

Pour créer un contexte il convient d'instancier la classe « ContextData ».

Elle accepte 2 paramètres :

  • Le contextEngineId

  • Ou le contextName

Les OIDs et ObjectType

Nous avons couvert les OIDs dans un précédent chapitre.
Cependant, lorsque vous envoyez une commande via la librairie SNMP vous le faîtes via la classe « ObjectType ». L'object type permet d'encapsuler l'OID et sa valeur réelle (dans le cas d'une commande « SET ») ou en retour d'un « GET ».
Dans le cadre d'un GET vous ne spécifiez que l'OID lorsque vous construisez l'instance « ObjectType » mais en retour vous aurez un ObjectType avec le même OID et sa valeur.

ot = ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysDescr'), 'Linux i386 box')
ot.resolveWithMib(mvc)
print(ot)
SNMPv2-MIB::sysDescr = Linux i386 box

La commande « GET »

Maintenant que nous avons passé en revue l'ensemble des éléments nécessaires à l'appel de commandes, nous allons ENFIN pouvoir écrire notre première commande GET
Pour envoyer un message « GET » il convient d'utiliser la fonction « getCmd » listée précédemment.

Enfin, lorsque vous exécutez cette commande vous pouvez demander plusieurs OID à la fois.
La syntaxe est la suivante :

pysnmp.hlapi.getCmd(snmpEngine, authData, transportTarget, contextData, *varBinds, **options)

Cette fonction retourne un tuple de 4 éléments :

  • errorIndication : Une valeur considérée comme « True » si une erreur s'est produite dans l'engine

  • errorStatus : Une valeur considérée comme « True » pour une erreur PDU

  • errorIndex : L'index de la variable ayant provoqué l'erreur (commence à 0)

  • varBinds : Une tuple contenant les valeurs retournées par la commande dans des instances de la classe « ObjectType »

Soit la commande suivante :

$ snmpget -v1 -c public demo.snmplabs.com sysLocation.0 sysDescr.0

Elle peut être exécutée via le code Python suivant :

from pysnmp.hlapi import *

data = (
  ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysLocation', 0)),
  ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysDescr', 0))
)

g = getCmd(SnmpEngine()
           , CommunityData('public', mpModel=0)
           , UdpTransportTarget(('demo.snmplabs.com', 161))
           , ContextData()
           , *data)

errorIndication, errorStatus, errorIndex, varBinds = next(g)

if errorIndication:
    print(errorIndication)
elif errorStatus:
    print('%s at %s' % (
                         errorStatus.prettyPrint(),
                         errorIndex and varBinds[int(errorIndex) - 1][0] or '?'
                       )

          )
else:
    for varBind in varBinds:
        print(' = '.join([x.prettyPrint() for x in varBind]))
SNMPv2-MIB::sysLocation.0 = Moscow, Russia
SNMPv2-MIB::sysDescr.0 = SunOS zeus.snmplabs.com 4.1.3_U1 1 sun4m

Pour l'exécuter avec le protocole « v2c » changez simplement la valeur du paramètre « mpModel=1 » dans l'objet community.

Pour l'exécuter avec le protocole « v3 » remplacez l'instance « CommunityData » par une instance « UsmUserData ».

La liste des communautés et utilisateurs disponibles sur le site « demo.snmplabs.com » est accessible à cette URL.
Exemple d'utilisateur (usr-sha-des/SHA/authkey1/DES/privkey1 ) :

UsmUserData("usr-sha-des"
            , authProtocol=usmHMACSHAAuthProtocol
            , authKey="authkey1"
            , privProtocol=usmDESPrivProtocol
            , privKey="privkey1" )

La commande « GetNEXT »

La commande « GetNEXT » s'exécute exactement comme une commande « get », avec les mêmes paramètres.
Elle permet de récupérer l'élément suivant l'OID passé en argument.

from pysnmp.hlapi import *
g = nextCmd(SnmpEngine()
            , CommunityData('public', mpModel=1)
            , UdpTransportTarget(('demo.snmplabs.com', 161))
            , ContextData()
            , ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysObjectID', 0)))

errorIndication, errorStatus, errorIndex, varBinds = next(g)

if errorIndication:
    print(errorIndication)
elif errorStatus:
    print('%s at %s' % (
                        errorStatus.prettyPrint()
                        , errorIndex and varBinds[int(errorIndex) - 1][0] or '?'
                       )
         )
else:
    for varBind in varBinds:
        print(' = '.join([x.prettyPrint() for x in varBind]))
SNMPv2-MIB::sysUpTime.0 = 280102869

Comme vous l'avez peut-être remarqué, la commande retourne un « générateur ».
Vous pouvez donc la rappeler avec la fonction « next » pour avoir l'élément suivant.
Ce qui vous permet de descendre toute une MIB en modifiant quelque peu le code ci-dessus, une fois la variable « g » instanciée.

from pysnmp.hlapi import *


g = nextCmd(SnmpEngine()
            , CommunityData('public', mpModel=1)
            , UdpTransportTarget(('demo.snmplabs.com', 161))
            , ContextData()
            , ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysObjectID', 0)))

for errorIndication, errorStatus, errorIndex, varBinds in g:

    if errorIndication:
        print(errorIndication)
    elif errorStatus:
        print('%s at %s' % (
            errorStatus.prettyPrint(),
            errorIndex and varBinds[int(errorIndex) - 1][0] or '?'
        )
              )
    else:
        for varBind in varBinds:
            print(' = '.join([x.prettyPrint() for x in varBind]))
 SNMPv2-MIB::sysUpTime.0 = 280140241
SNMPv2-MIB::sysContact.0 = SNMP Laboratories, info@snmplabs.com
SNMPv2-MIB::sysName.0 = zeus.snmplabs.com
SNMPv2-MIB::sysLocation.0 = Moscow, Russia
SNMPv2-MIB::sysServices.0 = 72
SNMPv2-MIB::sysORLastChange.0 = 280140343
SNMPv2-MIB::sysORID.1 = PYSNMP-MIB::pysnmpObjects.1
SNMPv2-MIB::sysORDescr.1 = new comment
SNMPv2-MIB::sysORUpTime.1 = 123

La commande « SET »

La commande «SET» s'exécute exactement comme une commande « get », avec les mêmes paramètres.
Excepté que l'ObjectType contient un second argument : la nouvelle valeur.

from pysnmp.hlapi import *

def show_item( ):

    g = getCmd(SnmpEngine()
               , CommunityData('public', mpModel=1)
               , UdpTransportTarget(('demo.snmplabs.com', 161))
               , ContextData()
               , ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysORDescr', 1)))

    errorIndication, errorStatus, errorIndex, varBinds = next(g)

    for varBind in varBinds:
            print(' = '.join([x.prettyPrint() for x in varBind]))


# Show initial value
show_item()
# Setting new value
g = setCmd(SnmpEngine()
           , UsmUserData("usr-sha-des"
                         , authProtocol=usmHMACSHAAuthProtocol
                         , authKey="authkey1"
                         , privProtocol=usmDESPrivProtocol
                         , privKey="privkey1" )
           , UdpTransportTarget(('demo.snmplabs.com', 161))
           , ContextData()
           , ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysORDescr', 1), 'Hello from Lannion using Kalray processor on Linux'))

errorIndication, errorStatus, errorIndex, varBinds = next(g)

print(errorIndication, varBinds)

show_item()
SNMPv2-MIB::sysORDescr.1 = Here is my new note
SNMPv2-MIB::sysORDescr.1 = Hello from Lannion using Kalray processor on Linux

Conclusion

Les commandes de base du protocole SNMP s'utilisent assez facilement une fois que l'on a compris comment configurer les différents paramètres qu'elles requièrent.

Cette seconde partie de l'initiation au protocole SNMP et à PySNMP doit normalement vous avoir donné :

  • Une compréhension globale des éléments de base de la librairie PySNMP

  • Les moyens de convertir vos MIBs au format ASN.1 en un code Python pour PySNMP

  • Les moyens de construire des sondes pour vos logiciels de monitoring

Il nous reste encore à voir quelques éléments plus avancés comme :

Nous réaliserons ces 2 dernières étapes dans la troisième et la quatrième partie de ce tutoriel.

ABONNEZ-VOUS À LA NEWSLETTER !
Voir aussi
Machine Learning : classer automatiquement vos données à l'import Machine Learning : classer automatiquement vos données à l'import 20/03/2018

Comment utiliser des algorithmes de machine learning pour importer correctement des données dans ...

Talend Tutoriel : comprendre les connexions iterate 20/12/2013

Le lien iterate est décrit assez succinctement dans le manuel utilisateur de Talend (User Guide). ...

Créer une carte avec Umap Créer une carte avec Umap 03/07/2019

[ Tuto ] créer une carte utilisant OpenStreetMap et y ajouter ou importer des données, puis ...

Utilisation de la vision par ordinateur pour redresser des images Utilisation de la vision par ordinateur pour redresser des images 14/05/2019

Dans un module de comparaison d'images, lorsque deux photographies ne sont pas cadrées de la même ...

Bien configurer ses tests Python avec tox et Travis Bien configurer ses tests Python avec tox et Travis 18/03/2019

Le plus difficile dans le développement des tests unitaires c'est souvent de se motiver à écrire ...