はじめに
前回の記事でPythonによるSNMPTrapの送信について記事を書きました。
その後、PythonからのSNMPTrap送信する方法を調査したら、方法が変わっていることに気づきしました。
この記事では、SNMPTrapの送信処理をする、sendNotificationが変わっているので、AIに学習させる意味でも(苦笑)、pysnmp v7の方法を記述しておきます。
pysnmp v6 から v7 への移行:sendNotification の変更点
pysnmp ライブラリは、バージョン 7 で大きな変更が加えられ、特に SNMPTrap を送信する sendNotification
関数の使い方が変わりました。この記事では、pysnmp v6 と v7 の実装の違いを比較し、v7 へコードを移行する方法を解説します。
背景
pysnmp v7 では、Python のモダンな非同期処理機能である asyncio
を全面的に採用しました。これにより、多くの関数が同期的(ブロッキング)な処理から非同期的(ノンブロッキング)な処理に変更されています。sendNotification
もその一つで、send_notification
という非同期関数になりました。
v6 のコード例
まずは、pysnmp v6 で SNMPTrap を送信する一般的なコードを見てみましょう。
from pysnmp.hlapi import *
sendaddr = "172.22.123.3"
errorIndication, errorStatus, errorIndex, varBinds = next(
sendNotification(
SnmpEngine(),
CommunityData('public'),
UdpTransportTarget((sendaddr, 162)),
ContextData(),
'trap',
NotificationType(
ObjectIdentity('1.3.6.1.6.3.1.1.5.2')
).addVarBinds(
('1.3.6.1.2.1.1.1.0', OctetString('my system'))
)
)
)
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]))
このコードは同期的であり、next()
を使って処理結果を取得していました。
v7 のコード例
次に、同じ処理を pysnmp v7 で実装したコードです。asyncio
を使って非同期で実行する必要があります。
import asyncio
from pysnmp.hlapi.v3arch.asyncio import *
from pysnmp.smi.rfc1902 import OctetString, ObjectIdentity
async def main():
sendaddr = "172.22.123.3"
snmpEngine = SnmpEngine()
errorIndication, errorStatus, errorIndex, varBinds = await send_notification(
snmpEngine,
CommunityData('public', mpModel=0), # mpModelの指定が必要
await UdpTransportTarget.create((sendaddr, 162)),
ContextData(),
'trap',
NotificationType(
ObjectIdentity('1.3.6.1.6.3.1.1.5.2')
).addVarBinds(
('1.3.6.1.2.1.1.1.0', OctetString('my system'))
)
)
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]))
# 非同期処理のディスパッチャを閉じる
snmpEngine.closeDispatcher()
if __name__ == '__main__':
asyncio.run(main())
主な変更点の解説
非同期処理 (
asyncio
):- v7 のコードは
async def
で定義されたコルーチン内で実行する必要があります。 asyncio.run()
を使ってイベントループを開始し、処理を実行します。
- v7 のコードは
関数名と戻り値:
sendNotification
はsend_notification
に変更されました。- この関数は
await
式で呼び出す必要があります。
CommunityData
の引数:- v7 では、
CommunityData
を初期化する際にmpModel
(Message Processing Model)を明示的に指定する必要があります。SNMPv1/v2c の場合はmpModel=0
またはmpModel=1
を設定します。
- v7 では、
SnmpEngine
の後処理:- 処理が完了したら、
snmpEngine.closeDispatcher()
を呼び出して、SnmpEngine
が内部で使用している非同期 I/O ディスパッチャをクリーンアップする必要があります。
- 処理が完了したら、
まとめ
pysnmp v7 への移行は、単なる関数名の変更だけでなく、asyncio
をベースとした非同期プログラミングへのパラダイムシフトを伴います。最初は戸惑うかもしれませんが、非同期処理に慣れることで、より効率的でスケーラブルなネットワークアプリケーションを構築できるようになります。
SNMPTrap 送信機能を v7 にアップデートする際は、この記事を参考に async/await
構文を正しく適用してください。