python3
blockdiag
ネットワークグラフ

ネットワーク構成図の自動作成を目指す!(2)

More than 1 year has passed since last update.

 さてさて、第2弾となりました。
 今回は、Pythonでtftpサーバに格納されたconfigからネットワーク構成図を作るのに必要な情報を抽出する機能を実装してみます。tftpサーバにあるコンフィグならばアクセスしても商用には影響が出ないので、担当の方々から安心感を得られるという配慮からそうする仕組みを考えることにしました。

必要情報とは?

必要情報をまとめてみると

  • ネットワーク構成図を描く際に必要な情報は下記になるかと思います。
    • ホスト名
    • IPアドレス
    • VLAN番号/VLAN名
    • NWアドレス
  • これらが前回お話ししたnwdiagが構成図を書くときに、必要な情報となってくると思いますので、これらをtftpサーバ上のconfigから抽出できるようなスクリプトを書いていきたいと思います。

参考資料

-ネットワーク生成ツールのnwdiagについてはこちらから。
http://blockdiag.com/ja/nwdiag/

どうやってconfigから必要情報を抜き出すか

 下記のページで紹介されている「textfsm」が実装するうえで有用そうだったので、使ってみることにしました。
http://mocas.hatenablog.com/entry/2015/11/13/164509

 せっかくなので、先ほどのページに記載されているCiscoのConfigを例に実装できるか実験してみたいと思います。

実験①Textfsmで必要情報を抽出できるか?

実験方法

 これは先ほどのページで紹介されているコードで実装できますので省略します。
 具体的にどのような結果が出力されるか、だけ引用させていただきます。

実験結果

In [7]: pprint.pprint(result)
[['tky-rt-01',
'GigabitEthernet9.901',
'tagged WAN 1',
'10.240.1.1 255.255.255.128'],
['tky-rt-01', 'Vlan1', 'Tokyo office LAN', '10.1.1.252 255.255.255.0'],
['tky-rt-01', 'Vlan2', 'Tokyo office LAN', '10.1.2.252 255.255.255.0'],
['tky-rt-01', 'Vlan3', 'Tokyo office LAN', '10.1.3.252 255.255.255.0'],
['tky-rt-01', 'Vlan4', 'Tokyo office LAN', '10.1.4.252 255.255.255.0']]

In [8]: table.header
Out[8]: ['hostname', 'interface', 'description', 'primary_ip']

考察

 CiscoのCatalystについてはこれで十分役立ちそうな気がする。
 あとはJUNOSやNexusOSなど色々なパターンが当てはまるように複数スクリプトを用意するか、条件分岐で作りこむかを考えてみます。

実験②どうやってMySQLに格納するか

実験手法

テーブル

 CentOSにMySQLをyumで入れて実装します。
 超適当に作ったテーブルなので、各々で確かめられる際はご注意ください。

  • config_data
    • IP_ADDRESS:機器についているIPアドレス
    • HOST:機器のホスト名
    • NETMASK:ネットマスク(今考えたら不要かも…)
    • VLAN:VLAN番号またはVLAN名
    • NW_ADDRESS:そのVLANのNWアドレス

コード

zisaku.py
import textfsm
import pprint
import mysql.connector
from netaddr import *

conn=mysql.connector.connect(
        host='127.0.0.1',
        port=3306,
        user='******',
        passwd='********',
        db='nw_config')

cur=conn.cursor()

with open('sample.log','r') as f:
        config = f.read()

with open('template_tmp.txt','r') as f:
        table = textfsm.TextFSM(f)
        result = table.ParseText(config)


for row in result:
        (ipaddr,netmask) = row[3].split(" ")
        nw = IPNetwork(ipaddr)
        nw.prefixlen=IPAddress(netmask).netmask_bits()
        nw=nw.cidr
        host = row[0]
        vlan = row[1]
        sql="INSERT INTO config_data (IP_ADDRESS, HOST, NETMASK,VLAN,NW_ADDRESS) values (%s,%s,%s,%s,%s)"
        cur.execute(sql,(str(ipaddr), host, str(netmask), vlan, str(nw)))
        conn.commit()
        print(row)

cur.close()
conn.close()

実験結果

mysql> select * from config_data;
+-----------------+-------------------------------+-----------------+----------------------+------------------+
| IP_ADDRESS      | HOST                          | NETMASK         | VLAN                 | NW_ADDRESS       |
+-----------------+-------------------------------+-----------------+----------------------+------------------+
| 10.240.1.1      | tky-rt-01                     | 255.255.255.128 | GigabitEthernet9.901 | 10.240.1.0/25    |
| 10.1.1.252      | tky-rt-01                     | 255.255.255.0   | Vlan1                | 10.1.1.0/24      |
| 10.1.2.252      | tky-rt-01                     | 255.255.255.0   | Vlan2                | 10.1.2.0/24      |
| 10.1.3.252      | tky-rt-01                     | 255.255.255.0   | Vlan3                | 10.1.3.0/24      |
| 10.1.4.252      | tky-rt-01                     | 255.255.255.0   | Vlan4                | 10.1.4.0/24      |
+-----------------+-------------------------------+-----------------+----------------------+------------------+
5 rows in set (0.00 sec)

考察

 VLANじゃないインターフェースの情報のものまで入ってしまいましたが、ホスト情報とIPアドレス情報、そしてVLAN情報を格納することができてます。Python歴1か月のヘタレで概ねやれることをやれたので、ひと先ずはここで満足します。

課題点

 本来であれば、DB上にデータが存在するか否かを判定するロジックを作らないといけません。今のコードだと、問答無用でinsertを続けるため、データが重複してしまいますので。。そこは引き続き考えて、何か思いつけば追記で書くようにします。

次は何をするの?

 次は、MySQLの情報を参照して、そのVLANのIPレンジには何が存在するかをスキャンしてMySQLにinsertする仕組みをPerlまたはPythonで実装していきます。その後は、取り込んだ情報をもとにnwdiagが読み込むconfigファイルを自動生成するスクリプトを実装します。

 今回はここまで、ありがとうございました。