はじめに
この記事はシスコの同志による Advent Calendar の一部として投稿しています
- 2017年版: https://qiita.com/advent-calendar/2017/cisco
- 2018年版: https://qiita.com/advent-calendar/2018/cisco
- 2019年版: https://qiita.com/advent-calendar/2019/cisco (<<< 今年)
私自身は、ネットワーク自動化開発についての連載を2017年に宣言 してから 3回目の投稿となります(1年に1記事というところはどうか触れないでください)。
今回は、Jupyter Notebook を使ってネットワーク自動化のデモをすることを考えてみたいと思います。
ネットワーク自動化をデモしたい
ネットワーク自動化を推進するためには、その手法や効果をデモしていろんな人々にみせたい。ところがネットワークエンジニアとしては言うのが悲しいことですが、ネットワークのデモというのはそもそも、地味です。
私自身は、CLI コンソール画面を映して、「ほら、Ping が通りました!」 というデモを何度やってきたことでしょうか。
現場のエンジニアの方は見た目よりも本質的な技術のところを理解してくださることが多いのですが、ビジネス部門の方へのデモや、イベントなどで一般の方へのデモとなると、どうしても見た目のインパクトに欠けてしまいます。
かといって、デモのために専用の Web ポータルを自分で Javascript を書いて用意する、というのもネットワークエンジニアにとっては辛い作業です(最近はコーディング能力的にはできる方も多いですが、本質的な作業でない割に手がかかる、という意味で)。もう少し手軽に見栄えのよいデモをすることはできないものでしょうか?
そんなときに、ネットワーク自動化を社内や業界でアピール・推進したい我々にとってありがたい武器になるのが今回使う Jupyter Notebook です。もちろん、自動化に限らずいろんなネットワーク製品のデモに活用できます。
Jupyter Notebook とは
Jupyter Notebook はオープンソースの Project Jupyter の成果物の一つです。最近はデータサイエンスや機械学習の分野でもデータ分析の一次的なツールとして活用されている人気のソフトウェアです。
簡単に説明すると、Pythonの対話環境である iPython をブラウザ上で実行しようという目的で開発され、その後改良が加えられてきました。現在では Python だけでなくほかのプログラミング言語にも対応しています。
今回はこの Jupyter Notebook と、前回ご紹介した PyATS ライブラリを使ってネットワーク自動化のデモをするところまでを目標にします。
Jupyter Notebook のインストール
Jupyter Notebook は pypi から簡単にインストールして利用可能です。
今回私が利用している環境は以下の通りです。お手元の環境が異なる場合は、適宜変更しながら実施してみてください。
- Macbook Pro 10.14.6
- Python 3.6.8
- Jupyter-notebook 5.7.4
pip コマンドで jupyter モジュール一式をインストールします
$ python -V
3.6.8
$ pip install jupyter
pip 完了後、以下のコマンドで jupyter-notebook を起動します
jupyter-notebook
デフォルトのブラウザが開き、Jupyter Notebook の操作画面が表示されます
まずは右側の New ボタンを押して Python3 を選択します
これで Python3 がカーネルとして動く Notebook が開きます。この画面上でインタラクティブに Python を実行することができるのです!
Jupyter Notebook の操作
この記事のゴールはこの Jupyter Notebook の画面の上で自動化のデモを実行しようというものになります。が、その前に Jupyter Notebook 自体の操作に簡単に慣れておきましょう。
画面上には In [] などと書かれた、ユーザが文字入力可能なエリア(=セル)が表示されています。ここに Python のコマンドを書いて、メニューから Run コマンド (または Shift + Enter) を押すと、画面上に Python コードの実行結果が表示される仕組みです
上の通り、import
コマンドでモジュールを読み込んだり、数値に代入したりできます。そして print()
コマンドの結果が出力として画面に表示されていることがわかります。
セルの内容はあとから自由に書き換えて再実行することができます。こうして試行錯誤しながらインタラクティブにコーディングができるのが Jupyter Notebook の強みです。
画像をインライン表示させることもできます。
例:
実は Jupyter Notebook は Markdown 方式での表記もサポートされていて、ノートという名前の通り、コードに加えて様々な文章を記載することができます。セルを選択してメニューから Markdown を選択します。
例えば、セルに以下のように記述して Shift-Enter を押すと
以下のように画面に表示されます
Jupyter Notebook 上からネットワーク機器を操作する
いよいよネットワーク機器の操作を行ってみましょう。前回の記事で、 PyATS/Genie を使って Python コードでネットワーク機器にアクセスする方法を紹介しました。これを応用します。
先に、Jupyter Notebook を動かしているのと同じ PC で pyats & genie をインストールしておきましょう。これも pip でインストール可能です
$ pip install pyats genie
これで pyats/genie の各種ライブラリが使えるようになります。これを使って実際にルータに接続してみます。今回は IOS ルータを用意し、telnet アクセスができるようにしておきます (Appendix 参照)。
Jupyter Notebook に戻ってコードを書いてみます。まずルータに接続するためのテストベッド情報を記述して読み込ませます。以下では telnet で接続していますが ssh でも問題ありません。
from pyats.topology import loader
testbed_file = "testbed.yaml"
testbed = """
devices:
CSR1kv-R1:
type: router
os: iosxe
credentials:
default:
password: admin
username: admin
enable:
password: admin
connections:
cli:
protocol: telnet
ip: 10.x.x.x
port: 10021
"""
with open(testbed_file, 'w') as f:
f.write(testbed)
tb = loader.load(testbed_file)
r1 = tb.devices['CSR1kv-R1']
これを Jupyter Notebook 上のセルに記述して実行します。
これで、r1
というオブジェクトをデバイスとして操作できるようになりました。r1 に接続してコマンドを実行してみましょう。
r1.connect(learn_hostname=True)
out = r1.execute('show ip int br')
Jupyter Notebook での実行結果は、以下のようになります。
このように PyATS の Unicon モジュールを使ってデバイスに接続して、CLI セッション上でコマンドを実行することができました。標準出力の結果が上記のように実行と同時に出力されます。上のコードでは out
変数に出力結果を代入しました。
print(out)
Jupyter Notebook 上での結果の整形
結果が変数として手に入ってしまえば、あとは Python を使って結果をさまざまな形で処理することができます。
デモや検証データの整理といった用途のためには、結果をできるだけ美しく表示したいところです。
たとえば前のセクションで out
変数に入ったコマンド出力結果をテーブル形式で表示したいとします。統計処理でよく使われる pandas モジュールを使えば以下のように書けます。
import pandas as pd
table = [ x.split() for x in out.splitlines() ]
df = pd.DataFrame(table[1:], columns=table[0])
df
Jupyter Notebook では、Pandas のデータフレームを自動的に HTML テーブルに表示することができます。実行結果は、以下のようになります。
このような表示ができると、単にターミナル上のテキストを見せるよりも少しは見栄えのするデモになりそうな気がしてきませんか?
同様に pandas を使って、もう少し検証で使いそうな処理を試してみたいと思います。今度は show interface
の出力を PyATS のツールである Genie を使ってパースしてみます。
from genie.conf import Genie
tb = Genie.init(testbed_file)
r1 = tb.devices['CSR1kv-R1']
r1.connect()
out = r1.parse('show interfaces')
from pprint import pprint
pprint(out)
結果は以下のように show interfaces の結果が自動的にパースされディクショナリ形式で保存されました。
インターフェイスごとの input packets / output packets を読み取ってグラフにしてみましょう。上記で使った pandas モジュールに加えて matplotlib モジュールも利用します。
サンプルコード:
%matplotlib inline
import matplotlib
import pandas as pd
table = []
intf_list = ['GigabitEthernet1', 'GigabitEthernet2', 'GigabitEthernet3']
headers = ['intf', 'in_pkts', 'out_pkts']
for k,v in out.items():
for intf in intf_list:
if intf == k:
line = [
k,
v.get('counters').get('in_pkts'),
v.get('counters').get('out_pkts'),
]
table.append(line)
df = pd.DataFrame(table, columns=headers)
df
これをグラフにプロットしてみましょう
%matplotlib inline
df.plot()
結果:
このように Jupyter Notebook を使えば、ネットワークデバイスから取得したデータを Pandas で処理して、テーブルデータは HTML で表示、数値データは matplotlib でグラフ表示、など工夫次第で様々な表現ができることがわかります。
ネットワーク自動化のデモ
本記事のゴールである、ネットワーク自動化デモを Jupyter Notebook 上に書いてみます。
シナリオとして以下のような簡単なものを考えてみました
- r1, r2 の2台の IOS ルータが接続されている
- r1, r2 の2台の疎通性があることを確認する
- 2台に OSPF 設定を投入する
- OSPF ネイバーが Up することを確認する
以下がJupyter Notebook 上のコードです。これを記述した上でメニューから Cell > Run All を実行すると、自動的にコードが上から実行され、結果が画面上に表示されていきます。
r1, r2 の2台の IOS ルータが接続されている
testbed_file = "testbed.yaml"
testbed = """
devices:
CSR1kv-R1:
type: router
os: iosxe
credentials:
default:
password: admin
username: admin
enable:
password: admin
connections:
cli:
protocol: telnet
ip: 10.71.157.163
port: 10021
CSR1kv-R2:
type: router
os: iosxe
credentials:
default:
password: admin
username: admin
enable:
password: admin
connections:
cli:
protocol: telnet
ip: 10.71.157.163
port: 10022
"""
with open(testbed_file, 'w') as f:
f.write(testbed)
from genie.conf import Genie
tb = Genie.init(testbed_file)
r1 = genie_tb.devices['CSR1kv-R1']
r2 = genie_tb.devices['CSR1kv-R2']
r1.connect()
r2.connect()
r1, r2 の2台の疎通性があることを確認する
r1.connect()
r2.connect()
r1_out = r1.execute('ping 10.0.12.2')
r2_out = r2.execute('ping 10.0.12.1')
print('----------------------')
print('Results')
print('----------------------')
if '!!!!' in r1_out.splitlines()[2]:
print('r1 to r2: pass')
if '!!!!' in r2_out.splitlines()[2]:
print('r2 to r1: pass')
2台に OSPF 設定を投入する
事前確認
r1_ospf_out = r1.execute('show ip ospf neighbor')
r2_ospf_out = r2.execute('show ip ospf neighbor')
table = [ x.split() for x in r1_ospf_out.splitlines() ][1:]
table[0][0:2] = [' '.join(table[0][0:2])]
table[0][3:5] = [' '.join(table[0][3:5])]
table[1][2:4] = [' '.join(table[1][2:4])]
df = pd.DataFrame(table[1:], columns=table[0])
df
設定実行
r1_ospf_config = """
!
router ospf 1
router-id 10.0.255.1
network 10.0.12.0 0.0.0.255 area 0
!
interface Gi2
ip ospf network point-to-point
"""
r2_ospf_config = """
!
router ospf 1
router-id 10.0.255.2
network 10.0.12.0 0.0.0.255 area 0
!
interface Gi2
ip ospf network point-to-point
"""
genie_r1.configure(r1_ospf_config)
genie_r2.configure(r2_ospf_config)
OSPF ネイバーが Up することを確認する
result = False
while not result:
r1_ospf_out = genie_r1.parse('show ip ospf neighbor')
r2_ospf_out = genie_r2.parse('show ip ospf neighbor')
table = []
for k,v in r1_ospf_out.get('interfaces', {}).get('GigabitEthernet2', {}).get('neighbors', {}).items():
print('r1', k, v.get('state'))
if 'FULL' in v.get('state'):
r1_result = True
table.append(['r1', k, v.get('state')])
for k,v in r2_ospf_out.get('interfaces', {}).get('GigabitEthernet2', {}).get('neighbors', {}).items():
print('r2', k, v.get('state'))
if 'FULL' in v.get('state'):
r2_result = True
table.append(['r2', k, v.get('state')])
result = all([r1_result, r2_result])
df = pd.DataFrame(table, columns=['Router','Neighbor','State'])
df
このように Jupyter Notebook 上で一連のテストを自動的に実行し、同じ画面上に結果も出力することができました。Python コーディングを活用することで結果の表示が美しくなり、デモとしての見栄えや、結果レポートとしての見易さも向上したと言えないでしょうか。
まとめ
本記事では、Jupyter Notebook と PyATS/Genie を使ってネットワーク自動化のデモをしてみる、という内容をご紹介しました。
Jupyter Notebook はサーバで動かして複数人で共有して編集したり、ノートのまま保存して配布したりと、チームでのネットワーク開発・運用およびナレッジの蓄積に大変優れています。みなさんの環境でも活用してみていただけたら大変幸いです。
さて次回ですが、「ネットワークデバイス・ネットワークサービスのモデル化」というテーマにしたいと考えています。本記事のように少ない台数ですと、個別にコンフィグを投入したり、確認コマンドを打ったりしてもなんとかなりますが、大規模なネットワークへの設定投入となると厳しいものがあります。次回はそういった課題へのアプローチについても考えてみたいと思います。
目次
前回: 第2回: ネットワーク自動化開発実践 - Python でルータを操作する
次回: 第4回: ネットワーク自動化開発実践 - デバイスのモデル化のご利益を感じよう - Cisco NSO を使う
Appendix
Appendix: IOS Router Configuration
hostname CSR1kv-R1
!
vrf definition management
rd 1:1
!
address-family ipv4
exit-address-family
!
!
interface GigabitEthernet1
vrf forwarding management
ip address 192.168.1.121 255.255.255.0
negotiation auto
!
ip route vrf management 0.0.0.0 0.0.0.0 192.168.1.254
!
no aaa new-model
!
enable secret !admin
username admin secret admin
!
line vty 0 4
exec-timeout 0 0
login local
!
Appendix: Reference
サンプルコードの作成にあたって、私が書く前にすでに PyATS/Genie を記事にされていた以下を参考にさせていただきました。素晴らしい記事をありがとうございます。
また pandas と matplotlib をより活用するには以下の記事が参考になります。
免責事項
本サイトおよび対応するコメントにおいて表明される意見は、投稿者本人の個人的意見であり、シスコの意見ではありません。本サイトの内容は、情報の提供のみを目的として掲載されており、シスコや他の関係者による推奨や表明を目的としたものではありません。各利用者は、本Webサイトへの掲載により、投稿、リンクその他の方法でアップロードした全ての情報の内容に対して全責任を負い、本Web サイトの利用に関するあらゆる責任からシスコを免責することに同意したものとします。