LoginSignup
63

More than 5 years have passed since last update.

Cisco/Juniperルータのコンフィグを一元取得するツール

Last updated at Posted at 2015-05-06

概要

ルータ群のコンフィグを一元取得するツールを作りました。作ったツールはgithubで公開しています。
https://github.com/taijiji/ConfigCollector

作った動機

管理しているルータのコンフィグを全機器分を一気に取得してGit管理したかったので作りました。

元々の想定では、[ルータ一覧ファイルの読み込み]->[ルータコンフィグの一元取得]->[Gitリモートレポジトリにpush] までの一連の工程をツール化しようと考えていたのですが、Git管理は運用者が手動でするほうがよいという考えのもと、ルータコンフィグの一元取得する部分だけを切り出してツール化しました。
ルータコンフィグ取得だけにフォーカスしたことでツール自体がシンプルになったことに加えて、結果的に他のツールとの連携がしやすくなったように感じています。

ツールのインストール

githubからダウンロードしてきます。

git clone git@github.com:taijiji/ConfigCollector.git

ダウンロードしたツールのディレクトリに移動します。

cd ConfigCollector

pipを使って関連モジュールをインストールします。
- pip未使用の場合は、事前にpipをインストールしてください。

pip install -r requirements.txt

以上で準備完了です。

ツールの使い方

"get_router_config.py"に対して、JSON形式で作成したルータ一覧情報をコマンドライン引数にして実行します。

python get_router_config.py [json file]

ルータ一覧情報のjson fileは以下のように記述します。
このように書くと、全ルータに対してSSH経由でコンフィグを取得します。

my_router.json
[
    {
        "hostname" : "router1",
        "username" : "user1",
        "password" : "aaabbbccc",
        "ipv4"     : "192.168.0.1",
        "os"       : "JUNOS"
    },
    {
        "hostname" : "router2",
        "username" : "user2",
        "password" : "aaabbbccc",
        "ipv4"     : "192.168.0.2",
        "os"       : "IOS-XR"
    },
    {
        "hostname" : "router3",
        "username" : "user3",
        "password" : "aaabbbccc",
        "ipv4"     : "192.168.0.3",
        "os"       : "IOS"
    }
]

ルータOSは手元でテストできたものだけを対象としています。
- JUNOS
- IOS
- IOS-XE
- IOS-XR

出力されるもの

ツールを実行して成功すると、"router_config"ディレクトリ配下に各ルータごとのコンフィグが保存されます。ファイル名は「ルータホスト名.txt」になっています。

以下は、上記の"my_router.json"ファイルで実行させた場合の結果です。

$ ls router_config
router1.txt  router2.txt  router3.txt
$ less router_config/router1.txt

show configuration | no-more
## Last commit: 2015-05-01 17:00:00 JST by user1
version 10.x.x;
system {
    host-name router1;
    time-zone Asia/Tokyo;
(snip)

最後に管理者が手動で、"router_config"ディレクトリを丸ごと[git add]->[git commit]->[git push]を実施してGithubやGitlabなどで管理することで、ルータのコンフィグを一元的にバージョン管理することができます。

コード

参考までにコードを記載しておきます。全体的にそこまで難しいことはしていません。

ルータへのSSH + 情報取得はExscript というモジュールを使っています。
SSHツールではexpectが有名ですが、ExscriptはLinux/Unixの他にも、IOS, IOS-XR, JunOS, VRP,などに対応されています。ルータを制御する際に別途ルータ用に構文解析する必要がないので便利です。

JSONファイルを読み込み、ルータ操作を呼び出すファイル

get_router_config.py
#! /usr/bin/env python
import sys
import traceback
import json

from ssh_router import Router

# Open json input file
try:
    # argument is routers' information with JSON formt.
    input_filename = sys.argv[1]
    input_file = open(input_filename ,'r')
    print 'Reading router info from "' + input_filename + '"...' 
except ( IOError, IndexError):
    print 'Cannot open JSON file.'
    print 'Please use bellow: " python get_router_config [JSON file] " '
    sys.exit()
else:
    router_info_json = input_file.read()
    input_file.close()

# Convert format from json to dictionary_type
try:
    router_info = json.loads(router_info_json)
except ValueError as error:
    print 'JSON format error : '
    print router_info_json
    print error
    sys.exit()

# Login and get config each routers using ssh
for num in range( len(router_info) ):
    router = Router( router_info[num] )

    # Login Router
    print 'Accessing router: ' + router_info[num]['hostname'] + '...'
    try:
        router.login()
        router_config = router.get_config()
    except:
        print 'Router login error'
        print router_info[num]
        router.logout()
        sys.exit()

    # Get config of Router
    try:
        router_config = router.get_config()
    except:
        print 'Router get configuration error'
        print router_info[num]
        router.logout()
        sys.exit()
    else:
        router.logout()

    # Create output file written config
    try:
        output_filename = 'router_config/' + router_info[num]['hostname'] + '.txt'
        print 'Writing output file "' + output_filename + '"...'
    except AtributeError:
        print 'cannot read dictionary of router_info[' + num + '][hostname]'
        sys.exit()

    try:
        output_file = open ( output_filename, 'w')
    except:
        print 'cannot open "' + output_filename + '"'
        output_file.close
        sys.exit()
    else:
        output_file.write( router_config )
        output_file.close

    print 'Success to create "'  + output_filename + '" !'

ルータへの制御を構成するファイル

ここではほとんどExscriptを呼び出しているだけです。

ssh_router.py
! /usr/bin/env python
# -*- coding: utf-8 -*-

from Exscript.protocols import SSH2
from Exscript.Account import Account

class Router:
    def __init__(self, router_info):
        self.hostname   = router_info['hostname']
        self.username   = router_info['username']
        self.password   = router_info['password']
        self.ipv4           = router_info['ipv4']
        self.os              = router_info['os']

    def login(self):
        self.session = SSH2()
        self.session.connect(self.ipv4)
        self.session.login( Account(name=self.username, password=self.password) )

    def logout(self):
        if self.session :
            self.session.send('exit\r')
            self.session.close()
        else:
            raise AttributeError( 'cannot find a living session.' )

    def get_config(self):
        if( self.os=='IOS-XR' or self.os=='IOS' or self.os=='IOS-XE'):
            self.session.execute('terminal length 0')
            self.session.execute('show running-config')
            result = self.session.response
        elif( self.os == 'JUNOS'):
            self.session.execute('show configuration | no-more')
            result = self.session.response
        else:
            raise ValueError( 'OS is unknown value. Please describe from  JUNOS / IOS / IOS-XE / IOS-XR.' )

        return result

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
  3. You can use dark theme
What you can do with signing up
63