Batfish をインストールしてコンフィグを分析する
Batfish を Linux にインストールする手順をメモしておきます。 公式のインストール手順は Getting Started with Batfish にあります。 今回は Ubuntu 21.0.4 へインストールしました。 Batfish は Docker イメージで起動する為、Ubuntu21 に docker / docker-compose をインストールする などを参考に docker をインストールしておきます。
尚、Jupyter Notebook を含む batfish/allinone Docker イメージの起動手順もメモしておきますが、今回のメモでは Jupyter Notebook は利用しません (その為、batfish/allinone イメージを使う必要はありません)。
Batfish のインストール¶
Batfish は Docker イメージ として提供されています。 以下の 3 種類があります。
- batfish/allinone
- Jupyter Notebook やサンプルコンフィグを含む
- batfish/batfish
- Jupyter Notebook やサンプルコンフィグを含まない
- batfish/ci-base
- CI 用イメージ
allinone イメージの起動¶
batfish/allinone イメージを利用する場合は、例えば以下のように起動します。 Jupyter Notebook 用に TCP/8888 をコンテナへ転送します。 また、ホストマシンとコンテナ間で永続ストレージでネットワーク機器のコンフィグなどを共有出来た方が便利なので、-v でホストのディレクトリをコンテナにマウントします。
docker pull batfish/allinone
docker run \
-d \
-p 8888:8888 \
-p 9996:9996 \
-p 9997:9997 \
-v ~/mynetworks:/notebooks/mynetworks \
--name batfish \
batfish/allinone
Jupyter Notebook へログインする際の Token はコンテナを起動した際に表示されます。 しかし -d オプションを指定してバックグラウンド起動した場合は起動メッセージが表示されず、Token が分からない為、docker exec -it batfish bash -c "jupyter notebook list" を実行して Token を確認します。 実行例は以下の通りです。 下記の場合、Token は 0123456789abcdef0123456789abcdef0123456789abcdef ですので、Jupyter Notebook のログイン画面でこの Token を入力します。
# docker exec -it batfish bash -c "jupyter notebook list"
Currently running servers:
http://0.0.0.0:8888/?token=0123456789abcdef0123456789abcdef0123456789abcdef :: /notebooks
batfish イメージの起動¶
batfish/batfish イメージを利用する場合は、例えば以下のように起動します。
docker pull batfish/batfish
docker run \
-d \
-p 9996:9996 \
-p 9997:9997 \
--name batfish \
batfish/batfish
pybatfish のインストール¶
Python から Batfish を利用するには pybatfish をインストールします。
コンフィグの用意¶
ネットワーク機器のコンフィグを保存するディレクトリを作成します。
configs ディレクトリへ Batfish の処理対象にするネットワーク機器のコンフィグをアップロードしておきます。 この時点のディレクトリ構造は以下となりました。
サンプルスクリプト¶
サンプルスクリプトは以下の通りです。 こだわりだすときりがありませんが、ip_node_properties として定義している DataFrame の結果は順序性が不明だった為 (何某か、ロジックがあるのだと思います…)、sort_values で Node, VRF, Interface をキーにソートしています。
#!/usr/bin/env python3
from pybatfish.client.commands import *
from pybatfish.question.question import load_questions, list_questions
from pybatfish.question import bfq
import pandas
import pprint
pandas.set_option('display.max_rows', None)
pandas.set_option('display.max_columns', None)
pandas.set_option('display.width', None)
pandas.set_option('display.max_colwidth', -1)
NETWORK_NAME = "mynetwork1_network"
SNAPSHOT_NAME = "mynetwork1_snapshot"
SNAPSHOT_PATH = "mynetwork1"
bf_set_network(NETWORK_NAME)
bf_init_snapshot(SNAPSHOT_PATH, name=SNAPSHOT_NAME, overwrite=True)
load_questions()
ip_node_properties = bfq.ipOwners().answer().frame()
print(ip_node_properties.sort_values(by=["Node", "VRF", "Interface"]))
サンプルスクリプトの実行例は以下の通りです。 上述の通り、ソート処理を行っている影響で結果表示のうち、左側の数字が順序通りでは無くなっています。
# ./sample.py
/root/./sample.py:13: FutureWarning: Passing a negative integer is deprecated in version 1.0 and will not be supported in future version. Instead, use None to not limit the column width.
pandas.set_option('display.max_colwidth', -1)
status: TRYINGTOASSIGN
.... no task information
status: CHECKINGSTATUS
.... no task information
status: TERMINATEDNORMALLY
.... 2021-08-28 16:06:12.908000+00:00 Deserializing objects of type 'org.batfish.datamodel.Configuration' from files 3 / 3.
Default snapshot is now set to mynetwork1_snapshot
status: TRYINGTOASSIGN
.... no task information
status: ASSIGNED
.... 2021-08-28 16:06:13.180000+00:00 Parse environment BGP tables.
status: TERMINATEDNORMALLY
.... 2021-08-28 16:06:13.180000+00:00 Parse environment BGP tables.
Successfully loaded 67 questions from remote
Successfully loaded 67 questions from remote
status: TRYINGTOASSIGN
.... no task information
status: TERMINATEDNORMALLY
.... 2021-08-28 16:06:13.603000+00:00 Begin job.
Node VRF Interface IP Mask Active
1 r1 default GigabitEthernet0/0 10.0.12.1 24 True
2 r1 default Loopback0 10.0.99.1 32 True
3 r2 default GigabitEthernet0/0 10.0.23.2 24 True
4 r2 default GigabitEthernet0/1 10.0.12.2 24 True
0 r2 default Loopback0 10.0.99.2 32 True
6 r3 default GigabitEthernet0/1 10.0.23.3 24 True
5 r3 default Loopback0 10.0.99.3 32 True
参考¶
今回利用したネットワーク機器のコンフィグは以下です。
R1.cfg¶
hostname R1
!
interface Loopback0
ip address 10.0.99.1 255.255.255.255
ip ospf network point-to-point
ip ospf 65000 area 0.0.0.0
!
interface GigabitEthernet0/0
ip address 10.0.12.1 255.255.255.0
ip ospf network broadcast
ip ospf 65000 area 0.0.0.0
no shutdown
!
router ospf 65000
router-id 10.0.99.1
!
end
R2.cfg¶
hostname R2
!
interface Loopback0
ip address 10.0.99.2 255.255.255.255
ip ospf network point-to-point
ip ospf 65000 area 0.0.0.0
!
interface GigabitEthernet0/0
ip address 10.0.23.2 255.255.255.0
ip ospf network broadcast
ip ospf 65000 area 0.0.0.0
no shutdown
!
interface GigabitEthernet0/1
ip address 10.0.12.2 255.255.255.0
ip ospf network broadcast
ip ospf 65000 area 0.0.0.0
no shutdown
!
router ospf 65000
router-id 10.0.99.2
!
end
R3.cfg¶
hostname R3
!
interface Loopback0
ip address 10.0.99.3 255.255.255.255
ip ospf network point-to-point
ip ospf 65000 area 0.0.0.0
!
interface GigabitEthernet0/1
ip address 10.0.23.3 255.255.255.0
ip ospf network broadcast
ip ospf 65000 area 0.0.0.0
no shutdown
!
router ospf 65000
router-id 10.0.99.3
!
end