NSO を SNMP マネージャとして使う

# はじめに
この記事はシスコの同志による Advent Calendar の一部として投稿しています。

|年度|URL|
|:-:|:-:|
|2017年|https://qiita.com/advent-calendar/2017/cisco|
|2018年|https://qiita.com/advent-calendar/2018/cisco|
|2019年|https://qiita.com/advent-calendar/2019/cisco|
|2020年|https://qiita.com/advent-calendar/2020/cisco|
|2020年 2枚目|https://qiita.com/advent-calendar/2020/cisco2|
|2021年|https://qiita.com/advent-calendar/2021/cisco|
|2021年 2枚目|https://qiita.com/advent-calendar/2021/cisco2|

# NSO の インターフェース

NSO には、通信するためのインターフェースとして以下のようなものがあります。

- Northbound (基本的に接続待受側)
  - RESTCONF
  - NETCONF
  - JSON-RPC
  - SNMP
- Southbound （基本的に接続開始側）
  - NETCONF
  - SNMP
  - CLI/Generic NED を使用した、種々のプロトコル

# NSO と SNMP

/devices/device リストに設定したデバイスの ned-type に snmp を使用することで、リモートデバイスに対して、get/set をすることが可能です。これらは NSO 側から接続を開始するものです。

別の使用方法として、NSO でリモート機器からの trap (や inform) を受信することが可能です。NETCONF 機器に対して subscribe し、notification を受信することはよくされていますが、同じ様に snmp manager として trap を受信し処理すると言ったことも一つの機能です。これによって、SNMP trap 受信を契機として何らかの動作をさせることができますので、NETCONFをサポートしない機器との間でも動的なデプロイが可能となります。

本投稿では、後者について実施した際の記録です。

# SNMP Trap を受信する際の動作の様子

![adv1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140504/c80037c8-03a5-5952-0e71-17b3040e4791.png)

## SNMP サーバ

ルータ等の通信機器から送信された SNMP Trap を受信するサーバが必要となりますが、NSO に付属の Java ライブラリに含まれており、NSO のみで実現が可能です。SNMP Inform に対しては、その Ack 送信も行います。

NotificationReceiver インスタンスを Singletonで作成し、ビジネスロジックを記述した Handler をそれに登録します。Trapを受信すると、都度 Handler が呼ばれ必要な処理を行います。

## ビジネスロジック

SNMP Trap の受信イベントをトリガーとして、processPdu method が都度呼ばれます。イベントの内容を自由に使い、必要な動作を記述出来ます。

例えば、受信したことを CDB へ記録することがあるかもしれません。また、受信した Trap 情報を、上位 NMS へ何らかの情報を付加した上で Notification として送信することもあると思います。もちろん、NSO のサービスインスタンスを作成することも可能ですので、実現可能な内容は無限大です。

# 実装のアイデア

以下の例では、数々の southbound 機器が登録されている状態で、それらから SNMP Trap を受信しています。

![adv2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140504/69d397ac-db9b-4e12-b492-f7b4d3530622.png)

例えば、NSO が全機器に対して reload/restart コマンドを発行し、機器には起動時に SNMP Trap で起動完了のメッセージが送信されるように設定されているとします。NSO は起動完了した通知をデバイス毎に受信し、CDBへ記録します。全デバイスの起動が確認出来たら、上位 NMS へ機器の準備完了の旨を Notification 等で通知します。

Northbound には RESTCONF/NETCONFなどが標準で使用できますので、上位サーバでの運用時に受信する方法が使用できます。つまり、上位サーバ側での変更は最小限で済むことになります。

# 実装

添付されているサンプルコード、snmp-notification-receiver を使用して説明しています。実際に使用する場合は、このサンプルを元に、必要なコードを追加していく事で事足りるかもしれません。

## Handler の作成

受信した SNMP PDU の中身を確認し、それを元に何らかの動作をさせます。一つの PDU には複数の Varbind が含まれているため、それぞれについて処理をします。

SNMP 対応のライブラリとして、snmp4j が使用されています。CommandResponderEvent オブジェクトから PDU を取り出した後、内容を処理しています。

```
public class ExampleHandler implements NotificationHandler {

    public HandlerResponse processPdu(
            EventContext context,
            CommandResponderEvent event,
            Object opaque) throws Exception {

        PDU pdu = event.getPDU();
　　　　　for (int i = 0; i < pdu.size(); i++) {
　　　　　　　VariableBinding vb = pdu.get(i);
            String oid = vb.getOid().toString();
            String var = vb.getVariable().toString();

            < Trap を処理 >
　　　　　}
    }
```

処理部分では、NSO の通常使用するライブラリが使用できますので、Maapi API をしてトランザクションを開始したり、CDB API で CDBの編集を行うことが出来ます。また、上で上げた例である Alarm API を使用して、Alarm を作成することも出来ます。

```
        Alarm al = new Alarm(new ManagedDevice(device),
                             new ManagedObject(managedObject),
                             alarmType,
                             severity,
                             false,
                              alarmText,
                              null,
                              null,
                              null,
                              timeStamp);

        AlarmSink sink = new AlarmSink();
        sink.submitAlarm(al);
```


## Handler の登録

Handler の登録は、NotificationReceiver へ register することで完了します。
このサンプルコードでは、ApplicationComponent インターフェースを実装した Application となっています。つまり、パッケージがロードされた時点で起動されるもので、使用用途によっては NSO Package とする必要はないかもしれません。

```
    public void init() throws Exception {
        handl = new ExampleHandler();
        notifRec =
            NotificationReceiver.getNotificationReceiver();
        // register example filter
        notifRec.register(handl, null);
    }
```

NSO の Application については、以前の AdventCalendar 記事で説明していますので、よろしければご参照ください。
[NSO を使って、サーバに公開APIを実装してみる](https://qiita.com/akiraiwamoto/items/ecbc14b0914532ba4ab0)

# 一旦完成。。。

Alarm の作成を行うと、つまりそれの Subscriber はその内容を受信します。よって、上記コードのみで完成です。管理しているSNMP Trap を受信すると、その都度上位 NMS へ通知しますので、SNMP Proxyサーバのようなものとなりました。


当初のアイデアでは、複数デバイスからの受信をまって Notification を送信する、ということでしたので、

- Trap を受信したら、それを CDB に Operational Data として保存する
- 既存の保存された Operational Data を確認し、全台での受信が確認できたら Alarm を作成する

といったコードを追加する必要があります。今回の記事では作成していませんが、NSO のパッケージ作成で必要な知識のみです。


# 最後に

毎年書いている気がしますが、、、。
NSO をデバイスへのConfigマシーンとするだけではなく、色々な機能がありますので、是非試してみてください。

# 免責事項

本サイトおよび対応するコメントにおいて表明される意見は、投稿者本人の個人的意見であり、シスコの意見ではありません。本サイトの内容は、情報の提供のみを目的として掲載されており、シスコや他の関係者による推奨や表明を目的としたものではありません。各利用者は、本Webサイトへの掲載により、投稿、リンクその他の方法でアップロードした全ての情報の内容に対して全責任を負い、本Web サイトの利用に関するあらゆる責任からシスコを免責することに同意したものとします。