search
LoginSignup
45

More than 5 years have passed since last update.

posted at

updated at

マルチベンダルータ制御APIライブラリ NAPALMを触ってみた

(追記)2016年12月24日に本記事の続編を書きました。そちらのほうがより詳しく記載してますので、ご興味あればみてください。
続・マルチベンダルータ制御APIライブラリ NAPALMを触ってみた

NAPALM概要

NAPALMというルータ制御APIライブラリが、NANOG64にて紹介されました。
https://www.nanog.org/meetings/abstract?id=2588

NAPALM (読み方は、日本人的には「ナパーム」でしょうか。NANOGでは「ネイパーム」と呼ばれていました)は、Spotify社が提供しているOSSのPythonライブラリであり、名前は「Network Automation and Programmability Abstraction Layer with Multivendor support」の略のようです。
ソースコードはgithubで公開されています。
https://github.com/spotify/napalm

NAPALMはその名の通り、下記の複数メーカの装置を統一化されたAPIにて制御することが可能です。今後さらに対応するルータOSが増えてくるかもしれません。

対応ルータOS

  • Arista製スイッチOSのEOS
  • Juniper製ルータOSのJUNOS
  • Cisco製ルータOSのIOS-XR
  • Fortinet製アプライアンスOSのFortiOS

NAPALMでできること

Githubのcommit logを見る限り 2015年3月頃から本格的な開発が始まっており、実装されている機能はコンフィグ設定部分にフォーカスされています。NAPALM自身では、現在のソフトウェアをversion0.12と位置付けているようです。(setup.pyに記載があります)

NANOG64発表資料では、NAPALMが持つ機能を下記のように紹介されています。

Supported Methods v0.1

  • load_replace_config
    • 全てのコンフィグの上書き
  • load_merge_config
    • 一部コンフィグのマージ
  • diff_config
    • 投入コンフィグと動作しているコンフィグの差分取得
  • discard
    • 投入コンフィグの廃棄
  • commit
    • 投入コンフィグのコミット
  • rollback
    • 前回コミットした状態へのロールバック

Supported Methods v0.2(beta)

  • get_facts
    • 機器の基本情報の取得
  • get_interfaces
    • インタフェースごとの情報の取得
  • get_bgp_neighbors
    • BGPセッションの情報取得
  • get_lldp_neighbors
    • LLDPネイバーの状態取得

2015年6月7日時点では、v0.1の部分のみ実装されているようです。

これらに加えて、構成管理ツールであるAnsibleから呼び出すための拡張モジュールが提供されており、NANOG64ではAnsibleを活用したコンフィグをルータに投入/commitするデモが行われてました。

Ansible Modules

  • Module to push configurations
  • Module to get facts

当日の発表とデモの風景はNANOG Youtubeチャンネルで公開されています。

NAPALMを使ってみた

napalmの使い方を理解するために公式ドキュメントのチュートリアルを眺めながら進めました。

NAPALMのインストールは簡単です。

pip install napalm 

pipを使ったことがない方はこちらの記事を参考にpipをインストールしてください。

Pythonで一番最初に入れるべきパッケージ setuptools と pip
http://www.lifewithpython.com/2012/11/Python-package-setuptools-pip.html

IOS-XRで試してみた

まずはcisco IOS-XRで試してみます。
NAPALMで使っているpyIOSXR( https://github.com/fooelisa/pyiosxr )というモジュールでは、CISCO XML APIを利用してIOS-XRの設定を実現しています。
そのためIOS-XRが動くルータでXML入力を許可するために、事前に以下のコンフィグを設定しておく必要があります。タイマー値は適当ですので、必要に応じて変更してください。

xml agent tty
 session timeout 30
!

公式ドキュメントのチュートリアルを参考にして、下記のようなPythonアプリケーションを作ってみました。

アプリケーションの流れとしては、ルータホスト名を'router1_changed_by_NAPALM'という名前に変更するコンフィグファイル(change_hostname_configIOSXR.txt)をルータに設定投入し、コンフィグ差分を確認して、問題がなければcommit、もしくはdiscardする流れになっています。
一つ一つ正常に動作しているか途中経過を確認したかったので、見栄えは悪いですがprint文多めにしています。

run_napalm.py
#! /usr/bin/env python

from napalm import get_network_driver


driver = get_network_driver('IOSXR')
print 'Step.1 Create ios-xr instance : OK'


device = driver('192.168.0.1', 'test_user', 'test_passwd')
print 'Step.2 Set router information : OK'


device.open()
print 'Step.3 Open session : OK'


device.load_merge_candidate(filename='./change_hostname_configIOSXR.txt')
print 'Step.4 load_merge_candidate : OK'


print '### CHECK CANDIDATE CONFIG ###'
print device.compare_config()
print '### END CONFIG###'
print 'Step.5 Compare_config : OK'


print 'Do you commit? y/n'
choice = raw_input().lower()
if choice == 'y':
    device.commit_config()
    print 'Step.6 commit_config : OK'
elif choice == 'n':
    device.discard_config()
    print 'Step.6 Discard_config : OK'
else:
    print 'Please input y or n. Discard candidate config'
    device.discard_config()
    print 'Step.6 Discard_config : OK'


device.close()
print 'Step.7 Close session : OK'


print 'Successful !!'
change_hostname_configIOSXR.txt
hostname router1_changed_by_NAPALM

まず、上記のツールを実行する前に、IOS-XRルータのコンフィグの状態をルータ上で確認します。

RP/0/RSP0/CPU0:router1#show running-config

Sun Jun  7 10:53:33.157 JST
Building configuration...
!! IOS XR Configuration #####
!! Last configuration change at Sun Jun  7 10:42:57 2015 by test_user
!
hostname router1
clock timezone JST 9
logging trap debugging
logging console debugging
...
...
...

では次に、作成したツール(run_napalm.py)を実行してみます。実行すると以下のように結果が出力されます。

$ python run_napalm.py

Step.1 Create ios-xr instance : OK
Step.2 Set router information : OK
Step.3 Open session : OK
Step.4 load_merge_candidate : OK
### CHECK CANDIDATE CONFIG ###
---
+++
@@ -3 +3 @@
-hostname router1
+hostname router1_changed_by_NAPALM
@@ -280,0 +281 @@
+!

### END CONFIG###
Step.5 Compare_config : OK
Do you commit? y/n
y
Step.6 commit_config : OK
Step.7 Close session : OK
Successful !!

ツール実行後、ルータで実際に設定が反映されているか確認してみます。

RP/0/RSP0/CPU0:router1_changed_by_NAPALM#show running-config
Sun Jun  7 10:59:42.313 JST
Building configuration...
!! IOS XR Configuration ######
!! Last configuration change at Sun Jun  7 10:56:07 2015 by test_user!
hostname router1_changed_by_NAPALM
clock timezone JST 9
logging trap debugging
logging console debugging
...
...
...

正しくIOS-XRルータのホスト名を変更できたようです。
NAPALMで用意された関数を使うことで、比較的簡単にルータ設定のアプリケーションを書くことができました。

JUNOSで試してみた

次は、IOS-XRで使ったプログラムとほぼ同じスクリプトを使って、JUNOSルータのホスト名を変更してみます。

実施したアプリケーションのソースコードです。

run_napalm.py

#! /usr/bin/env python

from napalm import get_network_driver

driver = get_network_driver('JUNOS')
print 'Step.1 Create junos instance : OK'

device = driver('192.168.0.2', 'test_user', 'test_passwd')
print 'Step.2 Set router information : OK'

device.open()
print 'Step.3 Open session : OK'

device.load_merge_candidate(filename='./change_hostname_configJUNOS.txt')
print 'Step.4 load_merge_candidate : OK'

print '### CHECK CANDIDATE CONFIG ###'
print device.compare_config()
print '### END CONFIG###'
print 'Step.5 Compare_config : OK'


print 'Do you commit? y/n'
choice = raw_input().lower()
if choice == 'y':
    device.commit_config()
    print 'Step.6 commit_config : OK'
elif choice == 'n':
    device.discard_config()
    print 'Step.6 Discard_config : OK'
else:
    print 'Please input y or n. Discard candidate config'
    device.discard_config()
    print 'Step.6 Discard_config : OK'


device.close()
print 'Step.7 Close session : OK'

print 'Successful !!'

実行結果はこちらです。

$ python run_napalm.py

Step.1 Create junos instance : OK
Step.2 Set router information : OK
No handlers could be found for logger "paramiko.hostkeys"
Traceback (most recent call last):
  File "./run_napalm.py", line 14, in <module>
    device.open()
  File "/usr/lib/python2.7/site-packages/napalm/junos.py", line 32, in open
    self.device.open()
  File "/usr/lib/python2.7/site-packages/jnpr/junos/device.py", line 433, in open
    raise EzErrors.ConnectTimeoutError(self)
jnpr.junos.exception.ConnectTimeoutError: ConnectTimeoutError(192.168.0.2)

あれ、失敗してしまいました。。。
SSHモジュールであるparamikoのログイン認証の部分で失敗しているようです。こちらはJUNOSルータの設定不足(netconfの部分?)か、プログラムのbugかも知れないので、引き続き調査してみます。

もしJUNOSルータに対して、うまく動作できた方がいればご教授いただきたいです。

所感

実装が始まったばかりのNAPALMですが、機種やメーカを意識せずにルータを操作するアプリケーションが書けるので、ツール開発が非常にやりやすくなりました。まだコンフィグ設定機能しか実装されていないものの、複数のルータに対して同じ設定を入れるような場面では、現段階の実装でも十分に使えそうです。

ただし、現時点では実装途中の機能やbugも含まれそうなので、利用する際は十分な検証を行ってから実施してください。

NAPALM自身のソースコードを覗いた感じでは、プログラム的に難しい処理をしているわけではなく、基本部分(base.py)でも100行程度であり、個人レベルでも十分に開発に参加できそうな感じでした。

githubのソースコードを見ていて驚いたのが、このNAPALMに限らず、中で呼び出しているpyIOSXRやpyEOS、pyFGの大部分を、AutherであるDavid Barroso、Elisa Jasinskaの両氏がほぼ単独で実装していることでした。「メーカが用意しないなら自分たち自身でAPIを作ってしまおう!」という意気込みがこのプロジェクトから感じられました。

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
What you can do with signing up
45