Skip to content

Python で CiscoConfParse2 を使って Cisco コンフィグから必要部分を抽出する

Python の ciscoconfparse を使うと Cisco 機器のコンフィグファイルから必要な箇所を抽出することが出来ます。 このライブラリに関して以前に以下のメモを書きました。

このライブラリは後継になるバージョン 2 が別パッケージとしてリリースされています。

バージョン 1 のページには「バージョン 2 へアップグレードすべき理由」として下記の記載があります。

  • It supports all major network vendor text configuration files (Arista, Cisco, F5, Juniper, Palo Alto)
  • It supports searching across any number of configuration levels (ciscoconfparse only supports two config levels : a parent and child)
  • It adds a string methods so you don't need to use regex matching if you don't want to
  • It adds a CLI command
  • Revamped documentation
  • It simplifies the user interface and fixes broken ciscoconfparse default parameters (this could require changing old scripts using the original API)
  • It intentionally uses a new python import to minimize confusion between itself and the original

今回は ciscoconfparse2 のチュートリアルページに掲載されている簡単な使い方をメモしておきます。

検証環境

対象 バージョン
macOS 14.5
Python 3.11.9
ciscoconfparse2 0.7.74

インストール

pip でインストールします。 但し、macOS 上でインストールしようとするとエラーになってしまいました。

$ uv pip install ciscoconfparse2
(...snip...)
--- stderr:
scrypt-1.2.1/libcperciva/crypto/crypto_aes.c:6:10: fatal error: 'openssl/aes.h' file not found
#include <openssl/aes.h>
         ^~~~~~~~~~~~~~~
1 error generated.
error: command '/usr/bin/clang' failed with exit code 1
---
  Caused by: This error likely indicates that you need to install a library that provides "openssl/aes.h" for scrypt==0.8.24

回避方法は openssl/aes.h' file not found on Mac に書かれていました。 まず環境変数を定義します。

export CFLAGS="-I$(brew --prefix openssl)/include"
export LDFLAGS="-L$(brew --prefix openssl)/lib"

再度、pip を実行します。 今回は正常に終了しました。

$ uv pip install ciscoconfparse2
Resolved 17 packages in 35ms
   Built scrypt==0.8.24
Prepared 1 package in 3.68s
Installed 17 packages in 53ms
 + attrs==23.2.0
 + ciscoconfparse2==0.7.74
 + dnspython==2.6.1
 + hier-config==2.2.3
 + loguru==0.7.2
 + macaddress==2.0.2
 + markdown-it-py==3.0.0
 + mdurl==0.1.2
 + passlib==1.7.4
 + pygments==2.18.0
 + pyparsing==3.1.1
 + pyyaml==6.0.1
 + rich==13.7.1
 + scrypt==0.8.24
 + tomlkit==0.12.4
 + typeguard==4.1.5
 + typing-extensions==4.12.2

サンプル 1:shutdown しているインターフェイスの抽出

入力ファイル

config.txt
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
hostname router
!
interface GigabitEthernet0/1
 ip address 10.0.1.1 255.255.255.0
 no shutdown
!
interface GigabitEthernet0/2
 ip address 10.0.2.2 255.255.255.0
 shutdown
!
interface GigabitEthernet0/3
 ip address 10.0.3.3 255.255.255.0
 no shutdown
!
interface GigabitEthernet0/4
 ip address 10.0.4.4 255.255.255.0
 shutdown
!
end

サンプルスクリプト

sample.py
1
2
3
4
5
6
7
8
#!/usr/bin/env python3

from ciscoconfparse2 import CiscoConfParse

parse = CiscoConfParse('config.txt')
intf_cmds = parse.find_parent_objects(['interface', '^ shutdown'])
shut_intf_names = [" ".join(cmd.split()[1:]) for cmd in intf_cmds]
print(shut_intf_names)

実行結果

$ python3 sample.py
['GigabitEthernet0/2', 'GigabitEthernet0/4']

サンプル 2:BGP Neighbor の抽出

入力ファイル

config.txt
router bgp 65534
  bgp router-id 10.0.0.100
  address-family ipv4 unicast
  !
  neighbor 10.0.0.37
    remote-as 64000
    route-policy EBGP_IN in
    route-policy EBGP_OUT out
  !
  neighbor 10.0.0.1
    remote-as 65534
    update-source Loopback0
    route-policy MANGLE_IN in
    route-policy MANGLE_OUT out
      next-hop-self
  !
  neighbor 10.0.0.34
    remote-as 64000
    route-policy EBGP_IN in
    route-policy EBGP_OUT out

サンプルスクリプト

sample.py
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
#!/usr/bin/env python3

from ciscoconfparse2 import CiscoConfParse

parse = CiscoConfParse('config.txt')
branches = parse.find_object_branches(('router bgp',
                                       'neighbor',
                                       'remote-as'))

bgp_cmd = branches[0][0]
local_asn = bgp_cmd.split()[-1]

for branch in branches:
    neighbor_addr = branch[1].split()[-1]
    remote_asn = branch[2].split()[-1]
    if local_asn != remote_asn:
        print("EBGP NEIGHBOR", neighbor_addr)

実行結果

$ python3 sample.py
EBGP NEIGHBOR 10.0.0.37
EBGP NEIGHBOR 10.0.0.34