LoginSignup
1
4

More than 3 years have passed since last update.

Cisco機器のshow inventory結果を表にする

Last updated at Posted at 2020-06-06

やること

Cisco機器の型番/シリアル番号を整理することが多いので、show inventoryの結果をcsvに出力するコードを書きました。
使うのはPythonモジュールのTextFSMと、そのテンプレート集であるntc-templatesです。

環境

Python 3.7.3
Anaconda 4.8.1
Windows10

フォルダ構成

入力フォルダ、出力フォルダ、templateフォルダを.pyと同ディレクトリに用意します。

フォルダ構成
.
  get_inventory.py

├─input
      catalyst.cfg
      nexus.cfg

├─output

└─template
        cisco_ios_show_inventory.template
        cisco_nxos_show_inventory.template
        cisco_nxos_show_inventory_r2.template

入力ファイル

WS-C2960X-24TS-L の『show inventory raw』と、N3K-C3172PQ-10GE の『show inventory all』の出力結果を入力用に用意しました。

Catalystのコマンド結果(入力用)
catalyst#sh inv raw
NAME: "C29xx Stacking", DESCR: "Catalyst C29xx Switch Stack"
PID:                   , VID:      , SN:            

NAME: "1", DESCR: "WS-C2960X-24TS-L"
PID: WS-C2960X-24TS-L  , VID: V05  , SN: FCW2115BXXX

NAME: "Switch 1 - Fan Container", DESCR: "Fan Container"
PID:                   , VID:      , SN:            

NAME: "Switch 1 - Power Supply Container", DESCR: "Power Supply Container"
PID:                   , VID:      , SN:            

NAME: "Switch 1 - RPS Container", DESCR: "RPS Container"
PID:                   , VID:      , SN:            

NAME: "Switch 1 - WS-C2960X-24TS-L - Power Supply 0", DESCR: "Switch 1 - WS-C2960X-24TS-L - Power Supply 0"
PID:                   , VID:      , SN: LIT21123XXX

NAME: "Switch 1 - WS-C2960X-24TS-L - Fan 0", DESCR: "Switch 1 - WS-C2960X-24TS-L - Fan 0"
PID:                   , VID:      , SN:            

NAME: "Switch 1 - WS-C2960X-24TS-L - Sensor 0", DESCR: "Switch 1 - WS-C2960X-24TS-L - Sensor 0"
PID:                   , VID:      , SN:            

NAME: "Switch 1 - WS-C2960X-24TS-L - Fixed Module 0", DESCR: "Switch 1 - WS-C2960X-24TS-L - Fixed Module 0"
PID:                   , VID:      , SN:            

NAME: "GigabitEthernet1/0/25 Container", DESCR: "GigabitEthernet Container"
PID:                   , VID:      , SN:            

NAME: "GigabitEthernet1/0/26 Container", DESCR: "GigabitEthernet Container"
PID:                   , VID:      , SN:            

NAME: "GigabitEthernet1/0/27 Container", DESCR: "GigabitEthernet Container"
PID:                   , VID:      , SN:            

NAME: "GigabitEthernet1/0/27", DESCR: "1000BaseSX SFP"
PID: GLC-SX-MMD          , VID: V01  , SN: FNS17070XXX     

NAME: "Gi1/0/27 Module Temperature Sensor", DESCR: "GigabitEthernet1/0/27 Module Temperature Sensor"
PID:                   , VID:      , SN:            

NAME: "Gi1/0/27 Supply Voltage Sensor", DESCR: "GigabitEthernet1/0/27 Supply Voltage Sensor"
PID:                   , VID:      , SN:            

NAME: "Gi1/0/27 Bias Current Sensor", DESCR: "GigabitEthernet1/0/27 Bias Current Sensor"
PID:                   , VID:      , SN:            

NAME: "Gi1/0/27 Transmit Power Sensor", DESCR: "GigabitEthernet1/0/27 Transmit Power Sensor"
PID:                   , VID:      , SN:            

NAME: "Gi1/0/27 Receive Power Sensor", DESCR: "GigabitEthernet1/0/27 Receive Power Sensor"
PID:                   , VID:      , SN:            

NAME: "GigabitEthernet1/0/28 Container", DESCR: "GigabitEthernet Container"
PID:                   , VID:      , SN:            

NAME: "GigabitEthernet1/0/28", DESCR: "1000BaseSX SFP"
PID: GLC-SX-MMD          , VID: V01  , SN: FNS17070XXX     

NAME: "Gi1/0/28 Module Temperature Sensor", DESCR: "GigabitEthernet1/0/28 Module Temperature Sensor"
PID:                   , VID:      , SN:            

NAME: "Gi1/0/28 Supply Voltage Sensor", DESCR: "GigabitEthernet1/0/28 Supply Voltage Sensor"
PID:                   , VID:      , SN:            

NAME: "Gi1/0/28 Bias Current Sensor", DESCR: "GigabitEthernet1/0/28 Bias Current Sensor"
PID:                   , VID:      , SN:            

NAME: "Gi1/0/28 Transmit Power Sensor", DESCR: "GigabitEthernet1/0/28 Transmit Power Sensor"
PID:                   , VID:      , SN:            

NAME: "Gi1/0/28 Receive Power Sensor", DESCR: "GigabitEthernet1/0/28 Receive Power Sensor"
PID:                   , VID:      , SN:            

NAME: "StackPort1", DESCR: "StackPort1"
PID:                   , VID:      , SN:            

NAME: "GigabitEthernet1/0/1", DESCR: "GigabitEthernet1/0/1"
PID:                   , VID:      , SN:            

NAME: "GigabitEthernet1/0/2", DESCR: "GigabitEthernet1/0/2"
PID:                   , VID:      , SN:            

NAME: "GigabitEthernet1/0/3", DESCR: "GigabitEthernet1/0/3"
PID:                   , VID:      , SN:            

NAME: "GigabitEthernet1/0/4", DESCR: "GigabitEthernet1/0/4"
PID:                   , VID:      , SN:            

NAME: "GigabitEthernet1/0/5", DESCR: "GigabitEthernet1/0/5"
PID:                   , VID:      , SN:            

NAME: "GigabitEthernet1/0/6", DESCR: "GigabitEthernet1/0/6"
PID:                   , VID:      , SN:            

NAME: "GigabitEthernet1/0/7", DESCR: "GigabitEthernet1/0/7"
PID:                   , VID:      , SN:            

NAME: "GigabitEthernet1/0/8", DESCR: "GigabitEthernet1/0/8"
PID:                   , VID:      , SN:            

NAME: "GigabitEthernet1/0/9", DESCR: "GigabitEthernet1/0/9"
PID:                   , VID:      , SN:            

NAME: "GigabitEthernet1/0/10", DESCR: "GigabitEthernet1/0/10"
PID:                   , VID:      , SN:            

NAME: "GigabitEthernet1/0/11", DESCR: "GigabitEthernet1/0/11"
PID:                   , VID:      , SN:            

NAME: "GigabitEthernet1/0/12", DESCR: "GigabitEthernet1/0/12"
PID:                   , VID:      , SN:            

NAME: "GigabitEthernet1/0/13", DESCR: "GigabitEthernet1/0/13"
PID:                   , VID:      , SN:            

NAME: "GigabitEthernet1/0/14", DESCR: "GigabitEthernet1/0/14"
PID:                   , VID:      , SN:            

NAME: "GigabitEthernet1/0/15", DESCR: "GigabitEthernet1/0/15"
PID:                   , VID:      , SN:            

NAME: "GigabitEthernet1/0/16", DESCR: "GigabitEthernet1/0/16"
PID:                   , VID:      , SN:            

NAME: "GigabitEthernet1/0/17", DESCR: "GigabitEthernet1/0/17"
PID:                   , VID:      , SN:            

NAME: "GigabitEthernet1/0/18", DESCR: "GigabitEthernet1/0/18"
PID:                   , VID:      , SN:            

NAME: "GigabitEthernet1/0/19", DESCR: "GigabitEthernet1/0/19"
PID:                   , VID:      , SN:            

NAME: "GigabitEthernet1/0/20", DESCR: "GigabitEthernet1/0/20"
PID:                   , VID:      , SN:            

NAME: "GigabitEthernet1/0/21", DESCR: "GigabitEthernet1/0/21"
PID:                   , VID:      , SN:            

NAME: "GigabitEthernet1/0/22", DESCR: "GigabitEthernet1/0/22"
PID:                   , VID:      , SN:            

NAME: "GigabitEthernet1/0/23", DESCR: "GigabitEthernet1/0/23"
PID:                   , VID:      , SN:            

NAME: "GigabitEthernet1/0/24", DESCR: "GigabitEthernet1/0/24"
PID:                   , VID:      , SN:            


catalyst#


Nexusのコマンド結果(入力用)
nexus# sh inv all
NAME: "Chassis",  DESCR: "Nexus 3172 Chassis"                    
PID: N3K-C3172PQ-10GE    ,  VID: V02 ,  SN: FOC2325RXXX          

NAME: "Slot 1",  DESCR: "48x10GE + 6x40G Supervisor"            
PID: N3K-C3172PQ-10GE    ,  VID: V02 ,  SN: FOC23248XXX          

NAME: "Power Supply 1",  DESCR: "Nexus 3172 Chassis Power Supply"       
PID: N2200-PAC-400W-B    ,  VID: V03 ,  SN: LIT23192XXX          

NAME: "Power Supply 2",  DESCR: "Nexus 3172 Chassis Power Supply"       
PID: N2200-PAC-400W-B    ,  VID: V03 ,  SN: LIT23193XXX          

NAME: "Fan 1",  DESCR: "Nexus 3172 Chassis Fan Module"         
PID: NXA-FAN-30CFM-B     ,  VID: V00 ,  SN: N/A                  

NAME: "Fan 2",  DESCR: "Nexus 3172 Chassis Fan Module"         
PID: NXA-FAN-30CFM-B     ,  VID: V00 ,  SN: N/A                  

NAME: "Fan 3",  DESCR: "Nexus 3172 Chassis Fan Module"         
PID: NXA-FAN-30CFM-B     ,  VID: V00 ,  SN: N/A                  

NAME: "Fan 4",  DESCR: "Nexus 3172 Chassis Fan Module"         
PID: NXA-FAN-30CFM-B     ,  VID: V00 ,  SN: N/A                  

NAME: Ethernet1/47,  DESCR: CISCO-AVAGO                             
PID: 10Gbase-SR          ,  VID: SFBR-709SMZ-CS1 ,  SN: AVD23059XXX          

NAME: Ethernet1/48,  DESCR: CISCO-OPLINK                            
PID: 10Gbase-SR          ,  VID: TPP4XGDS0CCISE2G,  SN: OPM23050XXX          

nexus# 

Templatesファイル

Catalyst、Nexusともに『show inventory』のTemplatesを使用。1
Catalystはそのままで問題なさそうでしたが、Nexusは少し編集しました。
編集後のTemplatesは末尾『_r2』としています。

cisco_ios_show_inventory.template
cisco_ios_show_inventory.template
Value NAME (.*)
Value DESCR (.*)
Value PID (([\S+]+|.*))
Value VID (.*)
Value SN ([\w+\d+]+)

Start
  ^NAME:\s+"${NAME}",\s+DESCR:\s+"${DESCR}"
  ^PID:\s+${PID}.*,.*VID:\s+${VID},.*SN:\s+${SN} -> Record
  ^PID:\s+,.*VID:\s+${VID},.*SN: -> Record
  ^PID:\s+${PID}.*,.*VID:\s+${VID},.*SN: -> Record
  ^PID:\s+,.*VID:\s+${VID},.*SN:\s+${SN} -> Record
  ^PID:\s+${PID}.*,.*VID:\s+${VID}.*
  ^PID:\s+,.*VID:\s+${VID}.*
  ^.*SN:\s+${SN} -> Record
  ^.*SN: -> Record

cisco_nxos_show_inventory_r2.template
cisco_nxos_show_inventory_r2.template
Value NAME (.*)
Value DESCR (.*)
Value PID ([^,]\S+)
Value VID ((V\d+)|[^,]\S+)  #変更:Vから始まらない場合を考慮 ex.SFBR-709SMZ-CS1
Value SN ([\d+\w+/]+)

Start
  ^NAME:\s+"${NAME}",\s+DESCR:\s+"${DESCR}"
  ^NAME:\s+${NAME},\s+DESCR:\s+${DESCR}   # 追加:""で囲まれない場合を考慮 ex.Ethernet1/47
  ^PID:\s+${PID}\s+,.*VID:\s+${VID}\s*,.*SN:\s+${SN} -> Record   # 追加:VID直後に,が入る場合を考慮 ex.TPP4XGDS0CCISE2G,
  ^PID:\s+${PID}.*,.*VID:\s+${VID}.*SN:\s+${SN} -> Record
  ^PID:\s+,.*VID:\s+${VID}.*SN: -> Record
  ^PID:\s+${PID}.*,.*VID:\s+${VID}.*SN: -> Record
  ^PID:\s+,.*VID:\s+${VID}.*SN:\s+${SN} -> Record
  ^PID:\s+${PID}.*,.*VID:\s+${VID}.*
  ^PID:\s+,.*VID:\s+${VID}.*
  ^.*SN:\s+${SN} -> Record
  ^.*SN: -> Record

Templateを使用する場合は#コメントを削除してください。(Templatesのコメントアウト方法が分かりませんでした。)

cisco_nxos_show_inventory.template(参考)
cisco_nxos_show_inventory.template
Value NAME (.*)
Value DESCR (.*)
Value PID ([^,]\S+)
Value VID (V\d+)
Value SN ([\d+\w+/]+)

Start
  ^NAME:\s+"${NAME}",\s+DESCR:\s+"${DESCR}"
  ^PID:\s+${PID}.*,.*VID:\s+${VID}.*SN:\s+${SN} -> Record
  ^PID:\s+,.*VID:\s+${VID}.*SN: -> Record
  ^PID:\s+${PID}.*,.*VID:\s+${VID}.*SN: -> Record
  ^PID:\s+,.*VID:\s+${VID}.*SN:\s+${SN} -> Record
  ^PID:\s+${PID}.*,.*VID:\s+${VID}.*
  ^PID:\s+,.*VID:\s+${VID}.*
  ^.*SN:\s+${SN} -> Record
  ^.*SN: -> Record

実装

get_inventory.py
import os
from datetime import datetime
import pandas as pd
import textfsm
import pathlib
import re


# outputフォルダ作成
def make_output_folder(out_path):
    # outputフォルダ作成
    date_str = datetime.now().strftime("%Y%m%d_%H-%M-%S")
    output_f = os.path.join(out_path, "output_" + date_str)
    os.mkdir(output_f)
    return output_f


if __name__ == '__main__':
    # カレントディレクトリを.pyフォルダに移動
    current_path = os.path.dirname(os.path.abspath(__file__))
    os.chdir(current_path)

    # inputフォルダ、ouputフォルダを指定
    input_folder = os.path.join(current_path, "input")
    output_folder = make_output_folder(os.path.join(current_path, "output"))

    # inputフォルダを読み込む 拡張子はtxt,cfg,log
    input_cfg_file_list = [str(p) for p in pathlib.Path(input_folder).glob("**/*")
                           if re.search(".*\.(txt|cfg|log)$", str(p))]

    # merge用DataFrame
    merge_result_df = pd.DataFrame()

    # inputファイルを一つずつ処理
    for cfg_path in input_cfg_file_list:
        cfg_base_name = os.path.basename(cfg_path)
        with open(cfg_path) as f:
            cfg_text = f.read()

        # TextFSMのテンプレートを決定する処理
        tmp_cfg_list = cfg_text.split("\n")
        for line in tmp_cfg_list:
            # showコマンドの出力1行目までスキップ
            if line in "#" or line in ">" or line == "":
                continue
            # showコマンドの出力からテンプレートを決定
            # NX-OSのテンプレート
            if re.search("Nexus ", line) is not None:
                template_path = r'./template/cisco_nxos_show_inventory_r2.template'
                break
            # IOSのテンプレート
            elif re.search("(WS-|Cisco|Catalyst)", line) is not None:
                template_path = r'./template/cisco_ios_show_inventory.template'
                break

        # fsmで結果を解析、抽出
        with open(template_path) as f:
            fsm = textfsm.TextFSM(f)
        output = fsm.ParseText(cfg_text)

        # 解析結果をDataFrameに変換
        df = pd.DataFrame(output, columns=fsm.header)

        # ファイルをcsvに保存
        out_name = os.path.splitext(cfg_base_name)[0] + ".csv"
        df.to_csv(os.path.join(output_folder, out_name), index=False, header=fsm.header)

        # 各出力結果を集積
        df["HOST"] = cfg_base_name
        merge_result_df = merge_result_df.append(df, sort=False)

    # 集積した出力結果をcsvに保存(HOSTを1列目に移動)
    cols = ['HOST'] + [col for col in df if col != 'HOST']
    merge_result_df = merge_result_df[cols]
    merge_result_df.to_csv(os.path.join(output_folder, "merge_output_file.csv"), index=False, header=True)

出力結果

outputフォルダにホストごとのcsvファイルとすべての結果をマージしたcsvファイルが作成されます。
マージ版のcsvファイルは以下の通りです(一部抜粋)。『show inventory』の結果に加え、1列目にファイル名が追加されています。

HOST NAME DESCR PID VID SN
catalyst.cfg C29xx Stacking Catalyst C29xx Switch Stack
catalyst.cfg 1 WS-C2960X-24TS-L WS-C2960X-24TS-L V05 FCW2115BXXX
catalyst.cfg Switch 1 - Fan Container Fan Container
catalyst.cfg Switch 1 - Power Supply Container Power Supply Container
catalyst.cfg Switch 1 - RPS Container RPS Container
catalyst.cfg Switch 1 - WS-C2960X-24TS-L - Power Supply 0 Switch 1 - WS-C2960X-24TS-L - Power Supply 0 LIT21123XXX
catalyst.cfg Switch 1 - WS-C2960X-24TS-L - Fan 0 Switch 1 - WS-C2960X-24TS-L - Fan 0
catalyst.cfg Switch 1 - WS-C2960X-24TS-L - Sensor 0 Switch 1 - WS-C2960X-24TS-L - Sensor 0
catalyst.cfg Switch 1 - WS-C2960X-24TS-L - Fixed Module 0 Switch 1 - WS-C2960X-24TS-L - Fixed Module 0
catalyst.cfg GigabitEthernet1/0/25 Container GigabitEthernet Container
catalyst.cfg GigabitEthernet1/0/26 Container GigabitEthernet Container
catalyst.cfg GigabitEthernet1/0/27 Container GigabitEthernet Container
catalyst.cfg GigabitEthernet1/0/27 1000BaseSX SFP GLC-SX-MMD V01 FNS17070XXX
catalyst.cfg GigabitEthernet1/0/28 1000BaseSX SFP GLC-SX-MMD V01 FNS17070XXX
nexus.cfg Chassis Nexus 3172 Chassis N3K-C3172PQ-10GE V02 FOC2325RXXX
nexus.cfg Slot 1 48x10GE + 6x40G Supervisor N3K-C3172PQ-10GE V02 FOC23248XXX
nexus.cfg Power Supply 1 Nexus 3172 Chassis Power Supply N2200-PAC-400W-B V03 LIT23192XXX
nexus.cfg Power Supply 2 Nexus 3172 Chassis Power Supply N2200-PAC-400W-B V03 LIT23193XXX
nexus.cfg Fan 1 Nexus 3172 Chassis Fan Module NXA-FAN-30CFM-B V00 N/A
nexus.cfg Fan 2 Nexus 3172 Chassis Fan Module NXA-FAN-30CFM-B V00 N/A
nexus.cfg Fan 3 Nexus 3172 Chassis Fan Module NXA-FAN-30CFM-B V00 N/A
nexus.cfg Fan 4 Nexus 3172 Chassis Fan Module NXA-FAN-30CFM-B V00 N/A
nexus.cfg Ethernet1/47 CISCO-AVAGO 10Gbase-SR SFBR-709SMZ-CS1 AVD23059XXX
nexus.cfg Ethernet1/48 CISCO-OPLINK 10Gbase-SR TPP4XGDS0CCISE2G OPM23050XXX

参照

TextFSMでシスコルータの型名とシリアルを抽出する方法


  1. 2020年5月時点では、show inventory "all"、show inventory "raw"のTemplatesは無い模様(https://github.com/networktocode/ntc-templates/tree/master/templates

1
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
4