Cisco 스위치 간단 점검 보고서 생성 스크립트 [python script]

Cisco 스위치 간단 점검 보고서 생성 스크립트 [python script]

1. 지원 스위치 및 테스트
지원 스위치: C3560, C3550, C2960, C2950
테스트 : IOS 12.2(55)SE1 (C3550, C2950)

2. python 버전 및 필요 패키지.
테스트: Python 3.5.6 에서 테스트 진행.
필요패키지: paramiko, openpyxl
라이센스: GPL

3. 사용법 및 점검결과

* 점검대상 스위치리스트를 화일 이름 switch.txt 로 작성한다. 아래 형식으로 작성하되, 필드 구분은 space 또는 tab으로 구분한다.

스위치 접속은, ssh 또는 telnet 프로토콜을 사용한다.

* genreport.py 스크립트를 실행한다.

* 결과는 엑셀화일 report.xlsx 에 저장되며, report.xlsx를 삭제하면 안된다.
1대의 장비당 결과는 1행에 저장이된다.
점검 항목은, CPU 사용율, 메모리 사용율, 팬 상태, 온도, 파워 상태이다.

4. 스크린샷.

5. 만든 이유.
네트워크 스위치 300여대를 사용하는 곳에서 Cisco L2 스위치를 100여대 사용하고 있다. NMS를 사용하고 있지만, FAN 이나 장비 온도는 사용중인 NMS상에 보이지 않는다. 이에, 주기적으로 간단히 점검할 수 있도록 파이썬 스크립트를 작성했고, 스위치 100여대 정도 점검을 5분 이내에 끝낼 수 있게 되었다.

6. 배포
배포 및 재사용시 출처를 표시해 주시기 바랍니다.

다운로드: Report4CiscoL2

7. 버그 및 제약사항(2019/3/19 추가)

시스코 스위치는 AAA인증을 사용하여 telnet 또는 ssh 접속시 enable 상태로 접속되어야한다.(AAA 설정은 https://blog.boxcorea.com/wp/archives/2529 를 참고)

openpyxl 버전은 2.5.1 을 사용하여야 하며, 상위버전 사용시 오류가 발생한다.
설치는 pip install openpyxl==2.5.1

35 comments

Skip to comment form

    • 김희성 on 2019년 3월 7일 at 9:59 오전
    • Reply

    switch.txt 마지막에 있는 cisco 문구는 뭘 의미하나요?

    1. 기존 코드를 재활용하다 보니, 장비 구별을 위해 필요하게 되었네요…

    • 네트워크 엔지니어 on 2019년 3월 15일 at 4:10 오후
    • Reply

    Traceback (most recent call last):
    File “genreport.py”, line 4, in
    from openpyxl import *
    ImportError: No module named openpyxl
    이런 에러가 뜨면서 실행이 안되네요 ㅠ !

    • 네트워크초보 on 2019년 3월 15일 at 4:11 오후
    • Reply

    Traceback (most recent call last):
    File “genreport.py”, line 4, in
    from openpyxl import *
    ImportError: No module named openpyxl
    이런 에러가 뜨면서 실행이 안되네요 ㅠ

    1. openpyxl 모듈이 없어서 그런듯 합니다.
      pip install openpyxl==2.5.1 명령으로 필요한 패키지를 설치해 주면 될겁니다.

        • LEE on 2019년 4월 19일 at 11:39 오전
        • Reply

        저도 같은 openpyxl에러 가 나네요 ㅠ
        우분투설
        pip install openpyxl==2.5.1 로 설치해서
        두번하니까 already satifi~~ openpyxl2.5.1 나오네요
        그래도 안돼는데 혹시 찾으신거 있으실까요 ㅜ

        1. pip freeze 결과좀 알려주실 수 있나요?

    • 초보자 on 2020년 5월 11일 at 10:37 오전
    • Reply

    만약에 enable 모드로 바로 들어갈 수 없어서 enable 커맨드 후 비밀번호를 재입력 후 들어가야 하는 경우에는 어떻게 처리할 수 있나요?

    1. 명령어에 enable , enable비밀번호를 추가해 주면 됩니다.
      물론 비밀번호를 파일에서 읽어오는 것 처럼 파일에서 읽어와도 되고요.
      비밀번호 입력할 때는 로그인 id 하고 비밀번호 입력하는 부분을 참고하시면 될것 같네요.

    • 초보자22 on 2020년 5월 15일 at 11:56 오전
    • Reply

    genreport.py를 실행하면 maintenance tool … ~~ 이 출력되고 아무런 동작이 없습니다
    혹시 뭐가 문제일까요?

    • 네크워크_초보 on 2020년 5월 15일 at 4:40 오후
    • Reply

    해당 파일을 실행하면 배너 출력 후 종료됩니다

    무엇이 원인인지 알수 있을까요?

    1. 음, 살펴보니 맨 아래줄이 주석처리 되었세요. 다시 업로드 했습니다.
      genreport.py 의 맨 아랫줄에 # 을 제거하시거나 다시 다운로드 받으시면 될겁니다.

    • 네트워크_초보 on 2020년 5월 18일 at 4:28 오후
    • Reply

    Something is wrong…
    ‘ascii’ codec can’t decode byte 0xb0 in position 120: ordinal not in range(128)
    이런 메세지를 출력합니다 어디서 해결방법을 찾아야 할까요?

    1. 혹시 switch.txt 파일의 인코딩 확인 가능할까요?
      윈도우면 인코딩을 ANSI로 바꿔 저장하고 실행해 보시고요.
      혹시 접속방식이 telnet 이면 c35xx 디렉토리 아래 getrawdata.py 파일에서 tn.setdebuglevel(1) 부분의 #을 제거하고 실행하면 좀 더 자세한 내용을 볼 수 있습니다.

    • 초보 on 2020년 5월 21일 at 6:16 오후
    • Reply

    ===================== RESTART: C:\Users\Admin\Desktop\Report4CiscoL2 (2)\C35xx\getrawdata.py =====================
    Telnet(192.168.2.246,23): recv b’\xff\xfb\x01\xff\xfb\x03\xff\xfd\x18\xff\xfd\x1f\r\n\r\nUser Access Verification\r\n\r\nUserna’
    Telnet(192.168.2.246,23): IAC WILL 1
    Telnet(192.168.2.246,23): IAC WILL 3
    Telnet(192.168.2.246,23): IAC DO 24
    Telnet(192.168.2.246,23): IAC DO 31
    Telnet(192.168.2.246,23): recv b’me: \xff\xfc\x01\xff\xfc\x03\xff\xfe\x18′
    Telnet(192.168.2.246,23): IAC WONT 1
    Telnet(192.168.2.246,23): IAC WONT 3
    Telnet(192.168.2.246,23): IAC DONT 24
    Telnet(192.168.2.246,23): send b’cisco\n’
    Telnet(192.168.2.246,23): recv b’\xff\xfe\x1f’
    Telnet(192.168.2.246,23): IAC DONT 31
    Telnet(192.168.2.246,23): recv b’cis’
    Telnet(192.168.2.246,23): recv b’co\r\nPassword: ‘
    Telnet(192.168.2.246,23): send b’ password\n’
    Telnet(192.168.2.246,23): send b’term length 0\nshow hardware\nshow env all\nshow process cpu\nshow process mem\nexit\n\n’
    Telnet(192.168.2.246,23): recv b’\r\n\r\n% Authentication failed.\r\n\r\nUsername: ‘
    Telnet(192.168.2.246,23): recv b’term length 0\r\nPassword: \r\n\r\n% Authentication fail’
    Telnet(192.168.2.246,23): recv b’ed.\r\n\r\nUsername: show env all\r\nPassword: \r\n\r\n% Aut’
    Telnet(192.168.2.246,23): recv b’hentication failed.\r\n’
    Telnet(192.168.2.246,23): recv b”
    192.168.2.246 23 cisco password telnet cisco
    [‘ipaddr: 192.168.2.246’, ‘\r’, ‘\r’, ‘% Authentication failed.\r’, ‘\r’, ‘Username: term length 0\r’, ‘Password: \r’, ‘\r’, ‘% Authentication failed.\r’, ‘\r’, ‘Username: show env all\r’, ‘Password: \r’, ‘\r’, ‘% Authentication failed.\r’, ”]
    Traceback (most recent call last):
    File “C:\Users\Admin\Desktop\Report4CiscoL2 (2)\C35xx\getrawdata.py”, line 82, in
    protocol=switch[4]
    IndexError: list index out of range

    이런 메시지를 출력하는데 혹시 어떤부부니 잘못되어을까요???

    1. 메시지를 보면 인증이 실패했다고 하네요.
      switch.txt  파일의 id 가 cisco 비밀번호가 password 가 맞나요? 맞다면, 각 줄의 정보를 탭키 나 공백으로 구분하신게 맞는지요?

    • 초보 on 2020년 5월 22일 at 1:12 오후
    • Reply

    아 password가 cisoc인데 말씀하신데로 수정하니 되었습니다. 감사합니다.

    • 초보 on 2020년 5월 22일 at 2:19 오후
    • Reply

    혹시 show ntp status , show clock 내용을 추가하고 싶은데 어디부분을 추가하면 될지 알수있을까요..

    엑셀부분이이랑 명령어 부분 추가하고 parse.py에 내용 추가만 하면 될련지요?

    1. getrawdata.py 의 self.cmd에 명령어 추가 하고, parse.py에 결과를 추출하는 메소드를 만들고, genreport.py에서 엑셀에 결과를 추가하는 코드를 작성하시면 될 겁니다.

    • 상균 on 2020년 6월 26일 at 1:33 오후
    • Reply

    안녕하세요. 혹시 enable password 가 있는 경우에 적용하려고 한다면 어떻게 해야할까요..

    self.cmd=[‘en’ , ‘cisco’, 에 해당 내용을 추가하는 방법 말고는 없을까요??

    enable password가 장비 마다 다른 경우가 있어서요???

      • snowffox on 2020년 6월 26일 at 5:06 오후
      • Reply

      스위치 정보를 기록하는 파일(switch.txt)의 마지막에 enable 비밀번호를 추가하고, C35xx/getrawdata.py의
      get_telnet, get_ssh 메소드에, 이것을 추가합니다.
      enpasswd = self.switch[-1] 요렇게(맨 마지막항목이 enable password)
      그리고, telnet 의 경우,
      tn.write(‘enable’.encode(‘ascii’)+b’\n’)
      tn.read_until(‘” ‘.encode(‘ascii’))
      tn.write(enpasswd.encode(‘ascii’)+b’\n’)
      요 부분을 추가하면 장비별로 설정된 enable passwodrd 입력이 가능하고, 이후 명령어를 실행하면 됩니다.

      또 다른 방법으로는, cmf에 [‘en’, enpasswd , ….]
      요렇게 비밀번호를 변수로 지정하는 방법도 있습니다.(이게 더 간단)
      이경우도, enable password를 파일에서 읽어와서, get_telnet, get_ssh에 넣어야 합니다.
      테스트는 안해봤어요;^^

    • 상균 on 2020년 6월 29일 at 5:16 오후
    • Reply

    회신 감사드립니다.

    테스트 한번 해보도록 하겠습니다.

    • TEDTM on 2020년 7월 15일 at 5:22 오후
    • Reply

    cisco c3650모델에서 read_all() 명령어에서
    Traceback (most recent call last):
    File “test.py”, line 98, in
    data = tn.read_all().decode(‘ascii’)
    File “C:\Python\Python36\lib\telnetlib.py”, line 333, in read_all
    self.fill_rawq()
    File “C:\Python\Python36\lib\telnetlib.py”, line 524, in fill_rawq
    buf = self.sock.recv(50)
    socket.timeout: timed out
    위와 같은 오류가 발생합니다…
    어떻게 하면 오류없이 값을 읽어 올수 있을까요??

      • snowffox on 2020년 7월 17일 at 2:03 오후
      • Reply

      남겨주신 내용으로는 파악하기가 힘드네요. telnetlib 문제라는 내용도 있고해서…
      혹시 터미널에서 접속은 이상없이 되는지요?
      접속 이상이 없다면,
      tn.set_debuglevel(1) 부분을 주석제거하시고 나요는 내용을 남겨주실 수 있는지요?

    • Python초보 on 2020년 8월 21일 at 3:36 오후
    • Reply

    저도 PC에서 작업수행중 극히 일부Cisco 장비에서 동일한 에러가 아래와 같이 발생합니다.
    Traceback (most recent call last):
    File “C:/Users/29054/Desktop/파이선/PycharmProjects/selfstudy/telnet_sample/config_backup_excel.py”, line 225, in
    result = main(content)
    File “C:/Users/29054/Desktop/파이선/PycharmProjects/selfstudy/telnet_sample/config_backup_excel.py”, line 177, in main
    result = runTELNET(switch, command)
    File “C:/Users/29054/Desktop/파이선/PycharmProjects/selfstudy/telnet_sample/config_backup_excel.py”, line 61, in runTELNET
    data = tn.read_all().decode(‘ascii’)
    File “C:\Users\29054\AppData\Local\Programs\Python\Python38\lib\telnetlib.py”, line 335, in read_all
    self.fill_rawq()
    File “C:\Users\29054\AppData\Local\Programs\Python\Python38\lib\telnetlib.py”, line 526, in fill_rawq
    buf = self.sock.recv(50)
    ConnectionResetError: [WinError 10054] 현재 연결은 원격 호스트에 의해 강제로 끊겼습니다.

    snowffox 님 의견을 보고 tn.set_debuglevel(1) 부분을 주석제거하시고 나온는 내용을 살펴보니
    정상적으로 종료되는 장비와 에러가 발생하는 장비의 차이는 맨 마지막에 있는것 같습니다.

    1) 정상적인 경우 (IP와 Hostname은 변경처리 함)
    Telnet(10.1.1.1,23): recv b’PN_4221#exi’
    Telnet(10.1.1.1,23): recv b’t’
    Telnet(10.1.1.1,23): recv b’\r\n’
    Telnet(10.1.1.1,23): recv b”

    2) 에러가 발생하는 경우 (IP와 Hostname은 변경처리 함)
    Telnet(10.1.1.2,23): recv b’AAAA_1F_3850_1#’
    Telnet(10.1.1.2,23): recv b’e’
    Telnet(10.1.1.2,23): recv b’x’
    Telnet(10.1.1.2,23): recv b’i’
    Telnet(10.1.1.2,23): recv b’t’
    Telnet(10.1.1.2,23): recv b’\r\n’

    1. 위, 아래 모두 호스트네임다음에 exit 명령이 찍히는게 보이는데요?
      그 이전 것을 봐야할듯 합니다.
      debug level(1)로 놓고 실행했을 때 나오는 메시지 전부를 올려주실수 있는지요?

    • 한덕자 on 2020년 9월 1일 at 1:15 오후
    • Reply

    안녕하세요, 내용 감사드립니다.

    현재 내용을 먼저 파악을 하기 위해 하나하나 공부를 하고 있는 중입니다.
    혹시

    def get_switch_info(file):
    sw = []
    switch = []
    f = open(file, ‘r’)
    if f:
    s = f.read()
    else:
    print(“file %s not found” %file)
    f.close()

    if s:
    sw = s.split(‘\n’)
    print(sw)
    for i in sw:
    if i != ‘ ‘:
    i = i.split(‘\t’)
    #i = ‘ ‘.join(i.split())
    switch.append(i)

    ”’
    if i !=’ ‘:
    tmp = i.split(‘ ‘)
    print(“tmp is %s” %tmp)
    switch.append(tmp)
    ”’
    return switch

    위의 기존 내용을 보면 s 문자열의 개행을 제거 하여 sw리스트를 만들고 여기에 탭 제거 및 공백을 추가 하여 다시 문자열을 만든 다음 공백을 제거하여 리스트를 만든 것으로 이해를 했습니다.

    혹시

    if s:
    sw = s.split(‘\n’)
    print(sw)
    for i in sw:
    if i != ‘ ‘:
    i = i.split(‘\t’)
    #i = ‘ ‘.join(i.split())
    switch.append(i)
    return switch
    이 부분에서 바로 탭을 제거한 뒤 내용을 switch에 저장을 하여 리턴해도 되지 않을까 해서 문의를 드립니다.

    • snowffox on 2020년 9월 1일 at 1:47 오후
    • Reply

    return 되는 스위치 정보가

    sw = [
    [‘172.16.210.5′, ’23’, ‘admin’, ‘passwd’, ‘telnet’, ‘cisco’],
    [‘172.16.210.6′, ’23’, ‘admin’, ‘passwd’, ‘telnet’, ‘cisco’],
    [‘172.16.210.7′, ’23’, ‘admin’, ‘passwd’, ‘telnet’, ‘cisco’]
    ]

    이런 리스트 형태로 된다면, 어디서 어떻게 처리를 해도 상관 없습니다.

    지금 다시보니 코드가 많이 지저분하네요. 워낙 초보일때 만든 코드라… ;^^

      • 한덕자 on 2020년 9월 1일 at 2:10 오후
      • Reply

      별말씀을요~ 좋은 정보 너무 감사드립니다. 🙂

    • 한덕자 on 2020년 9월 12일 at 10:52 오후
    • Reply

    안녕하세요

    덕분에 많이 배웠습니다.
    Brocade는 Paramiko로 하는게 좀 힘들어 보여 netmiko로 하였습니다. (총 87대)
    모니터링 시스템이 있어 기타 시스템에 관련된 것은 알람이 왔지만 Err-disable, disable된 포트 또는 stack중 에러가 난 스위치 등 은 확인을 할 수 없어서 고민 끝에 작성을 하여 필요 정보를 덕분에 잘 관리 할 수 있을 것 같습니다.

    궁금한 것은 제가 87대롤 확인 하는데 걸리는 시간이 거의 1시간이 걸렸습니다. 🙁
    (외부에서 한거라 VPN 으로 인한 네트워크 이슈도 있을 것으로 짐작이 됩니다)
    혹시 시간을 단축 시킬 만한 것이 있을런지요? 저는 클래스를 사용하지 않고 함수 만으로 작성을 하였습니다.
    (Ansible을 이용하면 더욱 효과적이라고는 하지만 현재 파이썬을 배우고 있는 단계라 우선 파이썬 부터 좀 더 습득을 하고자 합니다.)

    감사합니다.

    1. 브로케이드도 오래걸리는군요? 저도 일하는 환경에서 시스코 스위치는 엄청빠른데, 익스트림 스위치는 매우 오래걸리는 문제가 있습니다.

      당연히 해결방법은 있습니다. 제가만든 스크립트는 한번에 장비 하나만 접속해서 점검 끝나면 다음장비 접속하여 점검하는 방식인데요, 이렇게 만든 이유가 엑셀파일이 열려있을 때 같은 엑셀파일에 쓰기 작업 하려면 오류가 발생하기 때문입니다. 그래서, 순차적으로 점검-엑셀열기-결과쓰기-엑셀닫기 를 반복하는거지요.
      하지만, 한 단계 더 거치면 속도 문제 해결이 가능합니다.
      점검은 스레드를 만들어서 동시에 여러장비(5대 정도)를 점검하고, 결과는 mysql같은 데이타베이스에 저장하는거죠. (데이타베이스는 동시에 여럿이 읽기쓰기 작업이 가능하니까요.)
      그리고, 보고서는 맨 마지막에 데이타베이스에서 점검 결과를 가져와서 한번에 작성하면 끝나는 방식입니다.

      파이썬 concurrent 모듈을 이용해서 멀티쓰레드 방식으로 동시에 여러 장비 접속하면 되고요, 제대로 된다면 시간 많이 줄일 수 있을 거예요.

      혹시 더 좋은 방법이 있다면, 저한테도 알려주시면 고맙겠습니다. ;^^

    • 한덕자 on 2020년 9월 13일 at 8:19 오후
    • Reply

    안녕하세요~~~

    자세한 답변 너무 감사드리며 , 말씀하신 concurrent도 확인을 해보겠습니다.
    감사합니다.

    • 한덕자 on 2020년 9월 16일 at 12:54 오후
    • Reply

    안녕하세요 !!

    이것저것 확인을 하던 중 Invoke_shell을 이용하니 한 세션에 여러 명령어 실행을 할 수 있어 시간이 많이 단축이 되는 것 같습니다.
    현재는 10대 정도만 했는데 기존에는 rawdata를 얻는 데 5분 정도 걸렸는데 지금은 30초정도 걸리네요.
    너무 단축 되는 것을 보면 제가 기존에 뭘 잘 못 한거 같기도 합니다. ^^;

    항상 좋은 정보 너무 감사드립니다.

    1. 우와! 엄청 줄었네요?
      paramiko invoke_shell 세션유지가 sleep 없이는 잘 안됐던 경험이 있습니다.
      암튼, 도움이 됐다니 저도 좋군요.
      ;^^

        • 한덕자 on 2020년 9월 17일 at 1:20 오후
        • Reply

        안녕하세요!!

        네 확실히 많이 줄어들었습니다. 다만 말씀 하신대로 sleep없이는 많은 명령어가 실행이 안되는 것을 확인 하였는데 아마도 제 짧은 생각으로는 버퍼에 쓰고 읽어가는 시간이 없어서 그렇지 않을까 하는 생각입니다.
        좀 더 확인을 해봐야 될 것 같네요 ^^

        덕분에 하고싶은 내용을 적용 할 수 있어 너무 감사드립니다. (–)(__)

댓글 남기기

Your email address will not be published.

%d 블로거가 이것을 좋아합니다: