時間が空いてしまいましたが、前回までに環境構築とJUNOSの情報取得をしたため、今回は、JUNOSの設定変更を試してみる。
#1.概要
PyEzのjnpr.junos.utils.config.Configモジュールを使用することで、ASCII text, Junos XML, or Junos OS setコマンドのファイルを読み込み、設定変更をしたり、Jinja2 Template objectsを使ったテンプレートベースの設定変更が可能。
設定変更を行う場合は、JUNOSのCLIと同じように設定読込とCommitによる反映という、以下のようなプロセスで行われる。
Configuration Process
- lock() - コンフィグレーションのロック
- load() - 設定の読込 (rollback()やrescue()による設定戻しも可)
- commit() - 設定の反映
- unlock() - コンフィグレーションのアンロック
commit時のオプションを指定して、コメントを残したり、RE冗長時にsynchさせたりすることもできる。
尚、設定の読込は、 こちらもJUNOSのCLIの load replace, load merge, or load overwriteと同じく、上書きや追加の指定して設定変更する。
これは、loadオペレーションのときに、mergeおよびoverwriteパラメータを指定することで、選択可能。
今回はASCII textのファイルを読み込んで設定追加をする方法と、Jinja2を使ったテンプレートベースの設定追加を試してみる。
#2.ファイルからのコンフィグレーション読み込み
ファイルの読み込みの場合、拡張子でASCII text(.conf,.text,.txt), Junosのsetコマンド(.set), XML(.xml)を指定する。
読み読み時に、pathパラメータでファイルのパスを指定することで、そのファイルを読み込む。
例えば、
conf_file = "configs/junos-config-add-syslog-ntp.conf"
cu.load(path=conf_file, format="text", merge=True)
サンプルとして、syslogのntp notice設定を追加するのをPyEzで行う場合を示す。
pythonファイルの他に読込用のコンフィグレーションファイルを用意。
system {
syslog {
file messages {
ntp notice;
}
}
}
こちらがPythonのサンプル。
from jnpr.junos import Device
from jnpr.junos.utils.config import Config
conf_file = 'configs/junos-config-add-syslog-ntp.conf'
# open a connection with the device and start a NETCONF session
dev = Device(host='10.0.0.243', user='xxx', password='xxx', port='22', gather_facts=False)
dev.open()
dev.bind(cu=Config)
# Lock the configuration, load configuration changes, and commit as load merge
print "Locking the configuration"
dev.cu.lock()
print "Loading configuration changes"
dev.cu.load(path=conf_file, merge=True)
print "Committing the configuration"
dev.cu.commit(comment='Loaded by example.')
print "Unlocking the configuration"
dev.cu.unlock()
# End the NETCONF session and close the connection
dev.close()
尚、 jnpr.junos.exceptionモジュールでexceptionも用意されているため、実行できなかったときのエラー確認のために、それぞれのプロセスでexceptしておくと以下のようになる。
from jnpr.junos import Device
from jnpr.junos.utils.config import Config
from jnpr.junos.exception import ConnectError
from jnpr.junos.exception import LockError
from jnpr.junos.exception import UnlockError
from jnpr.junos.exception import ConfigLoadError
from jnpr.junos.exception import CommitError
conf_file = 'configs/junos-config-add-syslog-ntp.conf'
def main():
# open a connection with the device and start a NETCONF session
try:
dev = Device(host='10.0.0.243', user='xxxx', password='xxxx', port='22
', gather_facts=False)
dev.open()
except ConnectError as err:
print "Cannot connect to device: {0}".format(err)
return
dev.bind(cu=Config)
# Lock the configuration, load configuration changes, and commit
print "Locking the configuration"
try:
dev.cu.lock()
except LockError as err:
print "Unable to lock configuration: {0}".format(err)
dev.close()
return
print "Loading configuration changes"
try:
dev.cu.load(path=conf_file, merge=True)
except (ConfigLoadError, Exception) as err:
print "Unable to load configuration changes: {0}".format(err)
print "Unlocking the configuration"
try:
dev.cu.unlock()
except UnlockError:
print "Unable to unlock configuration: {0}".format(err)
dev.close()
return
print "Committing the configuration"
try:
dev.cu.commit(comment='Loaded by example.')
except CommitError as err:
print "Unable to commit configuration: {0}".format(err)
print "Unlocking the configuration"
try:
dev.cu.unlock()
except UnlockError as err:
print "Unable to unlock configuration: {0}".format(err)
dev.close()
return
print "Unlocking the configuration"
try:
dev.cu.unlock()
except UnlockError as err:
print "Unable to unlock configuration: {0}".format(err)
# End the NETCONF session and close the connection
dev.close()
if __name__ == "__main__":
main()
#3.Jinja2テンプレートの活用
Jinja2を使うことで、テンプレートを利用して、類似コンフィグが容易に作成することもできる。
Jinja2とは、Pythonのテンプレートエンジンで、名前の由来は、テンプレート ⇒ テンプル ⇒ 神社、のようだ。
Jinja2のテンプレートは、ファイル読込と同じく、サポートされたフォーマットのASCII text, Junos XML elements, Junos OS setコマンドを使用する。
Jinjaのテンプレートのフォーマットは、{% ... %} や {{ ... }} が可変部分で、それ以外の部分はすべて定型文となる。
{% ... %} は変数宣言・代入やループ処理などを実行
{{ ... }} は結果の表示
{%に使用するの制御構造はこちらを参照。
テンプレートを使用する方法は、load()メソッドのオプションでテンプレートを指定。
template_pathでテンプレートのファイルを指定し、template_varsでパラメータを指定。
cu.load(template_path=conf_file, template_vars=config, merge=True)
今回は、各interfaceにmpls,rsvpの設定追加をするテンプレートを使用し、パラメータであるinterface名などはyamlファイルで読込んでみる。テンプレートもASCII textにしている。
テンプレートファイルはこちら
interfaces {
{% for item in interfaces %}
{{ item }} {
description "{{ description }}";
unit 0 {
family {{ family }};
}
} {% endfor %}
}
protocols {
mpls {
{% for item in interfaces %}
interface {{ item }};
{% endfor %}
}
rsvp {
{% for item in interfaces %}
interface {{ item }};
{% endfor %}
}
}
パラメータファイルはこちら
---
interfaces:
- ge-0/0/0
- ge-0/0/1
description: 'MPLS interface'
family: mpls
基本的には、ファイル読み込みの時と同じスクリプト(ch-config-ntp-exception.py)をベースにして、load()でテンプレートやパラメータを指定しているだけのため、異なる部分だけ抜粋する。
import yaml
conf_file = 'configs/junos-config-interfaces-mpls.conf'
yml_config = yaml.load(open('configs/mpls_interface.yml'))
dev.cu.load(template_path=conf_file, template_vars=yml_config, merge=Tru
e)
これで指定したinterfaceに対するmpls, rsvpの設定が追加できる。
#4.まとめ
今回もつらつら書いたが、PyEzを使って、JUNOSの設定変更ができることが確認できた。
PyEzでは、情報取得や設定変更以外にも、configの比較、OSのアップグレード、scpによるファイル転送なども可能。
JUNOSとPyEzの両方を把握しないと触りにくいかもしれないが、Pythonを詳しく知らないエンジニアでも、簡単に必要なパラメータの確認や、設定変更ができそう。これらを使って、webで叩けるように仕組みを作っておくと、エキスパートのネットワークエンジニア以外でも確認や変更ができたり、他システムと連携させることで、ダイナミックに状況にあわせて設定変更が可能なネットワークインフラを作るなど、アイデア次第で活用方法は広がりそうだ。
今後は不定期に、ほかのAutomation Stackなども試してみる予定。