TextFSMとitertoolsを使って、NEC IX2105の正常判定に必要な値を取ってみた


# はじめに
先日参加したネットワークプログラミング勉強会にて、
AnsibleとTextFSMを組み合わせてshowコマンドの値を取った話を聞いたのがきっかけ。

大量にあるNW機器のOperation logを、人手で一個一個確認し、
機器の異常な箇所を見つけるのはとても大変な作業なので、
Python3でTextFSMとitertoolsを使い、NEC IX2105の正常判定に必要な値だけをいい感じで取ってみた。

# 参考資料
**参考1.TextFSMでシスコルータの型名とシリアルを抽出する方法**
http://kooshin.hateblo.jp/entry/2017/11/28/000800

**参考2.show コマンド結果をパースする方法あれこれ #npstudy**
https://www.slideshare.net/akira6592/npstudy18-command-parser


# IX2105用のテンプレートを作成してみた
Ciscoのテンプレートを参考にして、IX用にテンプレートを作り、実行してみたらとあっさりと値は取れた。
テンプレートは以下の通りです。

```text:IX2105_tmp.txt
Value VERSION (.+?)
Value SYSTEM_START_TIME (.*)
Value VERSION_FILE (.*)
Value VERSION_FILE2 (.*)
Value SN (.*)
Value LINK_STATUS0 (\w+)
Value LINK_STATUS1 (\w+)
Value PORT_STATUS1 (\w+)
Value PORT_STATUS2 (\w+)
Value PORT_STATUS3 (\w+)
Value PORT_STATUS4 (\w+)
Value STATUS_1V (.*)
Value STATUS_1_8V (.*)
Value STATUS_2_5V (.*)
Value STATUS_3_3V (.*)
Value STATUS_5V (.*)
Value TEMPERTURE_STATUS (.*)

Start
  ^.*Software,\s+Version\s+${VERSION},\s+MAINTENANCE\s+RELEASE\s+SOFTWARE
  ^.*System\s+started\s+at\s+${SYSTEM_START_TIME}
  ^.*System\s+image\s+file\s+is\s+"+${VERSION_FILE}"
  ^.*S/N:\s+${SN}
  ^.*1.0\s+volt\s+line\s+${STATUS_1V}
  ^.*1.8\s+volt\s+line\s+${STATUS_1_8V}
  ^.*2.5\s+volt\s+line\s+${STATUS_2_5V}
  ^.*3.3\s+volt\s+line\s+${STATUS_3_3V}
  ^.*5.0\s+volt\s+line\s+${STATUS_5V}
  ^.*Internal\s+temperature\s+measured\s+${TEMPERTURE_STATUS}
  ^.*Interface\s+GigaEthernet0.0\s+is\s+${LINK_STATUS0}
  ^.*Interface\s+GigaEthernet1.0\s+is\s+${LINK_STATUS1}
  ^.*Port\s+1\s+status\s+is\s+${PORT_STATUS1}
  ^.*Port\s+2\s+status\s+is\s+${PORT_STATUS2}
  ^.*Port\s+3\s+status\s+is\s+${PORT_STATUS3}
  ^.*Port\s+4\s+status\s+is\s+${PORT_STATUS4}
  ^.*\s+\s+\s+\s+${VERSION_FILE2}\s+\s+\s+\s+\s+\s+\s+\s+MA
```


見よう見真似でテンプレートは作成でき、実際に値が取れると嬉しい。
実際に取れた値は以下の通り。
![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417512/63c46b10-50a1-af2d-d185-fe1eac368231.png)
**① 機器のuptime**
**② Version**
**③ Serial Number**
**④ IFのLink状態**
**⑤ show envの値**
一応、③のS/Nの値については取れていないように見えるが、わざとマスクしている。


#TextFSMとitertoolsを合わせて使ってみる
指定したディレクトリ内に複数のOperation logがあれば、連続で値を取得できる。
下記Pythonコードの中身はこんな感じ。

-1. ライブラリー itertoolsを使い、Operateion logから
    "show tech"コマンドの値のみ抜き出し、test.txtに保存
-2. test.txtをTextFSMのIX用テンプレート(IX2105_tmp.txt)に読ませる
-3. 取れた値をCSV(inventory.csv)に保存

```
import textfsm,pprint,itertools,os,csv
datafolder = directory 　       ###　opelogがあるDirectoryを指定
textfms = "IX2105_tmp.txt"      ### 上記のテンプレートを指定
testfile = "test.txt"　 　 　 　 ###　opelogから”show tech”の値を貼り付けるテキストファイル名
csvfile = "inventory.csv"       ### 取得した値を貼り付けるcsvファイル名

files=os.listdir(datafolder)    ###　指定したDirectoryのopelog情報を取得
count=0

if files != []:
    while count < len(files):
         data=datafolder+files[count]
         with open(data) as f_in:
              lines = [line for line in f_in]
         for i in lines:
              if "show tech-support" in i:
                   startpoint=lines.index(i)
         for i2 in lines:
              if "(config)# 　" in i2:
                   if lines.index(i2) > startpoint:
                           endpoint=lines.index(i2)
         if startpoint != [] and endpoint != []:
              with open(data) as f:
                   user_list=[line for line in itertools.islice(f, startpoint, endpoint)]
              p=open(testfile, 'w')
              p.write(pprint.pformat(user_list))
              p.close()
              with open(testfile) as f:
                   inventory_text=f.read()
              with open(textfms) as f:
                   table=textfsm.TextFSM(f)
                   result=table.ParseText(inventory_text)
              pprint.pprint(result)
              with open(csvfile, 'w', newline='') as f:
                   w=csv.writer(f)
                   w.writerow(table.header)
                   w.writerows(result)
              count=count+1
         else:
            count=count+1
else:
   print("done")
```

取れた値はCSVに保存され、機器のシリアル、Version、正常性(IFのリンク状態、電源周りの状態等)を証跡として残せる。
あとは、取れた値が異常状態かどうかの判定は関数等の仕組みで対応できそう。



![IMG_6087.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417512/8ffce245-acfe-64ef-e5ea-0a3dcf240fcf.jpeg)