SNMPに代わるネットワーク管理技術gNMIの実験:gNMIcからSNMPのTRAPをTWSNMP FCに送信できた
助手の猫さんは12時に起こしてきていましたが、ご飯をあげてから、まだ寝る時間だと説得して寝てもらいました。
今朝は3時15分に自力で起きました。猫さんは4時すぎに、私の部屋に呼びに来ました。
早起きして昨日のgNMIcからSNMPのTRAPを送信する実験の問題を解決できました。
のサンプルに従って設定したのですが、
2024/09/26 11:51:41.751284 [cache:oc] failed cache query:target "192.168.1.50:57400" not found in cache
2024/09/26 11:51:41.751310 [snmp_output:snmp_trap] failed to build PDU from binding index 0: failed to build PDU, corresponding value not found or too many values found
のようなエラーが多数記録されていて、TRAPにいくつかのMIBが抜けていました。
どうやらgNMIcのバグのようです。
targets:
192.168.1.50:57400:
のようにtargetsの設定でポート番号を指定すると、このエラーがでるようです。
2024/09/26 11:51:36.750558 [cache:oc] target "192.168.1.50" added to local cache "sub1"
キャッシュに書き込む時は、"192.168.1.50"をターゲットだと思っているのに、読み出す時には、"192.168.1.50:57400"をターゲットに指定していて、ないと言っています。
とりあえず、
targets:
192.168.1.50:
のように変更すればエラーはなくなりました。
TWSNMP FCでTARPを受信した時、TRAPの種別が空欄になっていました。
TRAPの種類をsnmpTrapOID.0で送るようにgNMIcの設定ファイルを変更しました。
username: admin
password: NokiaSrl1!
skip-verify: true
log: true
targets:
192.168.1.50:
subscriptions:
sub1:
paths:
- /interface/admin-state
- /interface/oper-state
- /interface/ifindex
- /system/name/host-name
stream-mode: on-change
encoding: ascii
outputs:
snmp_trap:
type: snmp
address: 192.168.1.250
port: 162
community: public
cache:
type: oc
# duration, default: 60s.
# updates older than the expiration value will not be read from the cache.
expiration: 60s
# enable extra logging
debug: true
traps:
- trigger:
path: /interface/oper-state # static path
oid: '".1.3.6.1.2.1.2.2.1.8"' # ifOperStatus
type: int
value: if (.values."/interface/oper-state" == "up")
then 1
else 2
end
bindings:
- path: '"/system/name/host-name"' # jq script
oid: '".1.3.6.1.2.1.1.5"' # sysName
type: octetString
value: '.values."/system/name/host-name"'
- path: '"/interface[name="+.tags.interface_name+"]/admin-state"' # jq script
oid: '".1.3.6.1.2.1.2.2.1.7"' # ifAdminStatus
type: int
value: if (.values."/interface/admin-state" == "enable")
then 1
else 2
end
- path: '"/interface[name="+.tags.interface_name+"]/oper-state"' # jq script
oid: '".1.3.6.1.6.3.1.1.4.1.0"' # sysTrapOID.0
type: objectID
value: if (.values."/interface/oper-state" == "up")
then ".1.3.6.1.6.3.1.1.5.4"
else ".1.3.6.1.6.3.1.1.5.3"
end
- path: '"/interface[name="+.tags.interface_name+"]/ifindex"' # jq script
oid: '".1.3.6.1.2.1.2.2.1.1"' # ifIndex
type: int
value: '.values."/interface/ifindex" | tonumber' # jq script
これで送ると
いい感じのTRAPを受信できました。SR Linuxの接続先をup/downすれば、ちゃんとTRAPを受信します。
これでgNMIcとTWSNMP FCのSNMP TRAP連携ができることを確認できました。これはTWSNMP FC側を変更しなくても使えます。
次に、gNMIcのTCPアウトプット
との連携テストです。
まず、受信するTCPサーバーを作りました。
package main
import (
"encoding/json"
"fmt"
"log"
"net"
"os"
"strings"
"github.com/itchyny/gojq"
)
func main() {
l, err := net.Listen("tcp", ":3333")
if err != nil {
fmt.Println("Error listening:", err.Error())
os.Exit(1)
}
defer l.Close()
fmt.Println("Listening on :3333")
for {
// Listen for an incoming connection.
conn, err := l.Accept()
if err != nil {
fmt.Println("Error accepting: ", err.Error())
os.Exit(1)
}
// Handle connections in a new goroutine.
go handleRequest(conn)
}
}
func handleRequest(conn net.Conn) {
query, err := gojq.Parse(".timestamp")
if err != nil {
fmt.Println("Error: ", err)
}
buf := make([]byte, 1024*1024)
for {
n, err := conn.Read(buf)
if err != nil {
log.Println("Error reading:", err.Error())
break
}
log.Printf("%+v", buf[:n])
for _, l := range strings.Split(string(buf[:n]), "\n") {
if len(l) < 2 {
continue
}
log.Println(l)
var data interface{}
if err := json.Unmarshal([]byte(l), &data); err != nil {
log.Println(err)
continue
}
iter := query.Run(data)
for {
v, ok := iter.Next()
if !ok {
break
}
if err, ok := v.(error); ok {
fmt.Println("Error: ", err)
break
}
fmt.Printf("%#v\n", v)
}
}
}
conn.Close()
}
取得したデータからtimestampを数値取得するようになっています。
gNMIcの設定ファイルを
#TCP output
username: admin
password: NokiaSrl1!
skip-verify: true
encoding: json_ietf
log: true
targets:
192.168.1.50:57400:
subscriptions:
sub1:
paths:
- /interface/statistics
stream-mode: sample
sample-interval: 10s
outputs:
tcp-output:
type: tcp
address: 192.168.1.250:3333
format: json
delimiter: "\n"
のようにすると、ちゃんと送信されました。
2024/09/27 06:13:40 {"source":"192.168.1.50:57400","subscription-name":"sub1","timestamp":1727385221015459535,"time":"2024-09-27T06:13:41.015459535+09:00","updates":[{"Path":"srl_nokia-interfaces:interface[name=ethernet-1/57]/statistics","values":{"srl_nokia-interfaces:interface/statistics":{}}},{"Path":"srl_nokia-interfaces:interface[name=ethernet-1/58]/statistics","values":{"srl_nokia-interfaces:interface/statistics":{}}},{"Path":"srl_nokia-interfaces:interface[name=mgmt0]/statistics","values":{"srl_nokia-interfaces:interface/statistics":{"carrier-transitions":"1","in-broadcast-packets":"0","in-discarded-packets":"47","in-error-packets":"0","in-fcs-error-packets":"0","in-multicast-packets":"0","in-octets":"2752137","in-packets":"36627","in-unicast-packets":"36580","out-broadcast-packets":"7","out-discarded-packets":"0","out-error-packets":"0","out-mirror-octets":"0","out-mirror-packets":"0","out-multicast-packets":"65","out-octets":"8353988","out-packets":"32035","out-unicast-packets":"31963"}}}]}
1.7273852210154596e+18
timestampも数値で取得できます。受信する機能をTWSNMP FCに組み込めば連携できそうです。暗号化したTLSの実験をしてから、組み込もうと思います。
かなり、TWSNMPシリーズをgNMIに対応する方向性が見えてきました。
早く起きすぎて眠くなってきたので、今朝は、ここまで
明日に続く