PythonでSNMPを扱うためのメモ

SNMP SETを送信したかったんだけど、ろくに情報がないのでメモしておく。

  • Python SNMP framework
    とりあえずこれがメジャーなのかな?
  • TwistedSNMP, PySNMP-SE
    これはよくわからない。Twistedのサブプロジェクト?TwistedSNMPにはPySNMPまたはPySNMP-SEが必要?PySNMP-SEは同じところでダウンロードできる。とはいえSNMPを扱うだけならPySNMP-SEだけあればいいのか?
  • PythonのNET-SNMPラッパー
    これはさらに良く分からない。使えないって怒ってるページもあった。

という感じなので、とりあえずPySNMP2.0.9を試してみた。
examplesフォルダにいろいろサンプルがあるけど、いきなり使い方が分からず困った。いろいろソース読んだり試行錯誤した結果、snmpset.pyはこう使うみたい。

python snmpset.py agent_address community oid1 type1 value1 oid2 type2 value2 ...

一応目的は果たせたので、サンプルから必要な分だけを抜き出してみた。

# -*- encoding: utf-8 -*-
import sys
from pysnmp import asn1, v1, v2c
from pysnmp import role

def snmp_set(ip, community, oid_values, port=161, retries=5, timeout=1, version='1'):
    """
    usage: snmp_set('192.168.10.1', 'comunity', [('1.3.6.1.2.1.43.10.2.1.4.1.1', 'i', 1),])
    """
    client = role.manager((ip, port))
    client.timeout = timeout
    client.retries = retries
    varargs = []
    for oid, type, value in oid_values:
        if type == 'i':
            varargs.append((oid, 'INTEGER', int(value)))
        elif type == 'u':
            varargs.append((oid, 'UNSIGNED32', int(value)))
        elif type == 't':
            varargs.append((oid, 'TIMETICKS', int(value)))
        elif type == 'a':
            varargs.append((oid, 'IPADDRESS', value))
        elif type == 'o':
            varargs.append((oid, 'OBJECTID', value))
        elif type == 's':
            varargs.append((oid, 'OCTETSTRING', value))
        elif type == 'U':
            varargs.append((oid, 'COUNTER64', long(value)))
        else:
            print 'Unknown value type \'%s\'' % (type)
            sys.exit(-1)

    try:
        req = eval('v' + version).SETREQUEST()
        rsp = eval('v' + version).GETRESPONSE()
    except (NameError, AttributeError):
        print 'Unsupported SNMP protocol version: %s\n%s' % (version, usage)
        sys.exit(-1)

    encoded_oids = []
    encoded_vals = []
    for (oid, type, val) in varargs:
        encoded_oids.append(asn1.OBJECTID().encode(oid))
        encoded_vals.append(eval('asn1.'+type+'()').encode(val))

    return client.send_and_receive(req.encode(community=community, encoded_oids=encoded_oids, encoded_vals=encoded_vals))