Profile picture

[Python] netmiko 라이브러리를 활용한 시스코 장비 백업 자동화

JaehyoJJAng2024년 02월 28일

netmiko

파이썬에서 SSH를 사용하여 네트워크 자동화를 수행하는 대표적인 모듈 중 paramikonetmiko 가 있는데,

paramiko는 netmiko에 비해 사용법이 복잡하기 때문에, 네트워크 장비에 SSH 접속 후 자동화를 수행하는 작업에는 netmiko가 많이 사용된다.


구성도

실습을 진행할 네트워크 구성도는 다음과 같다.
image


사전 준비

netmiko 설치

pip install netmiko

netmiko 함수

netmiko에서는 아래 세 가지 함수를 주로 사용한다.

  • send_command()
    • sh version, sh run 등의 Privileged Mode 명령어에 사용됨.
  • send_config_set()
    • conf t [명령어], Global Mode 명령어에 사용됨.
    • conf t, exit는 자동으로 작성해주기 때문에 사용할 명령어만 입력하면 된다.
  • save_config()
    • 스위치 설정 저장(write memory)할 때 사용됨.
  • net_connect = ConnectHandler(**ios)
    • net_connect 객체를 netmiko 모듈의 ConnectHandler 클래스를 사용해 생성함.
  • output = net_connect.send_command('show ip int br')
    • output 변수에 show ip int br 명령어에 대한 결과 값을 담음.

스위치 설정

원활한 실습을 위해서는 자동화하려는 스위치 장비에 관리 IP 및 SSH 설정이 되어있어야 한다.


관리 IP 설정

먼저, 스위치의 VLAN 1 인터페이스에 관리 IP를 설정하자
(관리 IP를 꼭 vlan 1에 설정할 필요는 없다.)

Switch> enable
Switch# configure terminal
Switch(config)# interface vlan 1
Switch(config-if)# ip address 192.168.219.155 255.255.255.0
Switch(config-if)# no shutdown

그리고 스위치가 다른 네트워크와 통신할 수 있도록 기본 게이트웨이를 설정하자.

Switch(config)# ip default-gateway 192.168.219.1

마지막으로 인터페이스 구성 모드에서 나와 설정을 완료하자.

Switch(config-if)# exit

SSH 설정

SSH를 사용하려면 도메인 이름을 설정해야 한다.

Switch(config)# ip domain-name example.com

SSH를 위해 RSA 키를 생성하자.

Switch(config)# crypto key generate rsa

키 크기(모듈러스 크기)를 묻는 메시지가 나타나면, 보통 1024 또는 2048 비트를 입력하자.

How many bits in the modulus [512]: 1024

SSH 버전을 설정하자. 일반적으로 SSH 버전 2를 사용하는 것이 안전하다.

Switch(config)# ip ssh version 2

SSH 접속에 사용할 사용자 계정과 권한을 만들어주자.

Switch(config)# username admin privilege 15 secret cisco123
Switch(config)# enable password cisco123

마지막으로 SSH를 허용하기 위해 VTY 라인을 설정하자.

Switch(config)# line vty 0 4
Switch(config-line)# login local
Switch(config-line)# transport input ssh
Switch(config-line)# exit

스위치 접속

스위치에 SSH 접속이 정상적으로 수행되는지 테스트해보자.

$ ssh <사용자계정>@<스위치IP>
$ ssh admin@192.168.219.50

image


자동화 스크립트 작성

  • 여러가지 자동화 스크립트를 작성해보자.

장비별 VLAN 출력

반복문 for를 사용하여 스위치 3개를 반복하고, 스위치마다 설정되어 있는 vlan을 출력하도록 해보자.


from netmiko import ConnectHandler

def config_ssh(switches: list[tuple[str]]) -> None:        
    for ip, username, password, enable, port, device_type in switches:
        devices = {
            'ip': ip,
            'username': username,
            'password': password,
            'secret': enable,
            'port': port,
            'device_type': device_type,
            }
        net_connect = ConnectHandler(**devices)
        net_connect.enable()

        command = ('sh vlan')
        output = net_connect.send_command(command)
        print(output)

if __name__ == "__main__":
    fname = "L2-switch.txt"
    with open(file=fname, mode='r', encoding='utf-8') as fp:
        switches = [tuple(switch.strip('\n').split()) for switch in fp.readlines()]

    config_ssh(switches=switches)

L2-switch.txt 의 파일 내용은 아래와 같다.

192.168.219.180 admin cisco123 cisco123 22 cisco_ios

실행 결과

$ python3 main.py

VLAN Name                             Status    Ports
---- -------------------------------- --------- -------------------------------
1    default                          active    Gi0/0, Gi0/1, Gi0/2, Gi0/3, Gi1/0, Gi1/1, Gi1/2, Gi1/3
1002 fddi-default                     act/unsup 
1003 token-ring-default               act/unsup 
1004 fddinet-default                  act/unsup 
1005 trnet-default                    act/unsup 

VLAN Type  SAID       MTU   Parent RingNo BridgeNo Stp  BrdgMode Trans1 Trans2
---- ----- ---------- ----- ------ ------ -------- ---- -------- ------ ------
1    enet  100001     1500  -      -      -        -    -        0      0   
1002 fddi  101002     1500  -      -      -        -    -        0      0   
1003 tr    101003     1500  -      -      -        -    -        0      0   
1004 fdnet 101004     1500  -      -      -        ieee -        0      0   
1005 trnet 101005     1500  -      -      -        ibm  -        0      0   

Remote SPAN VLANs
------------------------------------------------------------------------------


Primary Secondary Type              Ports
------- --------- ----------------- ------------------------------------------

장비별 config 백업

파이썬을 활용한 네트워크 자동화 중 가장 많이 사용되는 config backup 이다.

스위치 config를 백업하기 위해서는 파이썬으로 파일을 생성하여, 명령어 결과를 파일에 저장하는 작업이 필요하다.


from netmiko import ConnectHandler
from datetime import datetime

# 장비 정보 설정
def read_switches_file(file_name: str) -> list[tuple[str]]:
    with open(file_name, 'r', encoding='utf-8') as fp:
        return [tuple(switch.strip('\n').split()) for switch in fp.readlines()]

def backup_config(switches: list[tuple[str]]) -> None:
    for ip, username, password, enable, port, device_type in switches:
        device = {
            'device_type': device_type,
            'ip': ip,
            'username': username,
            'password': password,
            'secret': enable,
            'port': port,
        }
        
        # 장비 연결
        with ConnectHandler(**device) as net_connect:
            hostname :str = net_connect.send_command('show run | include hostname').split()[-1]
            config :str = net_connect.send_command('show run')
            
            with open(f'{hostname}_backup.txt', 'w', encoding='utf-8') as fp:
                fp.write(config)

if __name__ == '__main__':
    file_name :str = 'switches.txt'
    switches = read_switches_file(file_name=file_name)
    backup_config(switches=switches)

switches.txt 의 파일 내용은 아래와 같다.

192.168.219.50 test cisco123 cisco123 22 cisco_ios

실행 결과

$ python main.py
$ ls -lh .
-rw-r--r-- 1 a-user a-user 3.4K  9216:18 test-swtich1_backup.txt

Loading script...