본문 바로가기

파이썬 코드

network automation -5-

import paramiko, time
from getpass import getpass
import re
import openpyxl
from openpyxl.utils.dataframe import dataframe_to_rows
import pandas as pd

def juniper_parse_fixed(df):
    fpc_rows = df[df["item"].astype(str).str.startswith("FPC")].reset_index(drop=True)
    ps_rows = df[df["item"].astype(str).str.startswith("Power Supply")].reset_index(drop=True)
    
    paired_rows = []
    ps_idx = 0
    
    for _, fpc_rows in fpc_rows.iterrows():
        paired_rows.append(fpc_rows)
        
        ps_to_add = 2 if  len(ps_rows) - ps_idx>=2 else 1
        for _ in range (ps_to_add):
            paired_rows.append(ps_rows.iloc[ps_idx])
            ps_idx+=1
    return pd.DataFrame(paired_rows)

def juniper_parse(ip_a, u_id, u_pas):
        ssh = paramiko.SSHClient()
        ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        ssh.connect("IP address", username=u_id, password=u_pas)
        
        host = re.compile(r"Hostname: (\w{1,30})")
       #model = re.compile(r"Model: (\w{1,7}-\w{1,7})")
        ver1 = re.compile(r"JUNOS Base OS boot \[(\w{1,2}.\w{1,4}.\w{1,2})\]")
        ver2 = re.compile(r"Junos: (\w{1,2}.\w{1,3})")
        f_na = re.compile(r"(FPC \d{1})            \w{1,3} \d{1,2}   \w{1,3}-\w{1,6}   \w{1,13}      \w{1,6}-\w{1,3}")
        f_re = re.compile(r"FPC \d{1}            (\w{1,3} \d{1,2})   \w{1,3}-\w{1,6}   \w{1,13}      \w{1,6}-\w{1,3}")
        f_pa = re.compile(r"FPC \d{1}            \w{1,3} \d{1,2}   (\w{1,3}-\w{1,6})   \w{1,13}      \w{1,6}-\w{1,3}")
        f_se = re.compile(r"FPC \d{1}            \w{1,3} \d{1,2}   \w{1,3}-\w{1,6}   (\w{1,13})      \w{1,6}-\w{1,3}")
        f_me = re.compile(r"FPC \d{1}            \w{1,3} \d{1,2}   \w{1,3}-\w{1,6}   \w{1,13}      (\w{1,6}-\w{1,3})")
        p_na = re.compile(r"(Power Supply \d{1})   \w{1,3} \d{1,2}   \w{1,3}-\w{1,6}   \w{1,13}       \w{4}-\w{1,4}-\w{1,2}-\w{1,3}")
        p_re = re.compile(r"Power Supply \d{1}   (\w{1,3} \d{1,2})   \w{1,3}-\w{1,6}   \w{1,13}       \w{4}-\w{1,4}-\w{1,2}-\w{1,3}")
        p_pa = re.compile(r"Power Supply \d{1}   \w{1,3} \d{1,2}   (\w{1,3}-\w{1,6})   \w{1,13}       \w{4}-\w{1,4}-\w{1,2}-\w{1,3}")
        p_se = re.compile(r"Power Supply \d{1}   \w{1,3} \d{1,2}   \w{1,3}-\w{1,6}   (\w{1,13})       \w{4}-\w{1,4}-\w{1,2}-\w{1,3}")
        p_me = re.compile(r"Power Supply \d{1}   \w{1,3} \d{1,2}   \w{1,3}-\w{1,6}   \w{1,13}       (\w{4}-\w{1,4}-\w{1,2}-\w{1,3})")
        p_na_f = re.compile(r"  (Power Supply \d{1}) \w{1,3} \d{1,2}   \w{1,3}-\w{1,6}   \w{1,13}       \w{4}-\w{1,4}-\w{1,2}-\w{1,3}")
        p_re_f = re.compile(r"  Power Supply \d{1} (\w{1,3} \d{1,2})   \w{1,3}-\w{1,6}   \w{1,13}       \w{4}-\w{1,4}-\w{1,2}-\w{1,3}")
        p_pa_f = re.compile(r"  Power Supply \d{1} \w{1,3} \d{1,2}   (\w{1,3}-\w{1,6})   \w{1,13}       \w{4}-\w{1,4}-\w{1,2}-\w{1,3}")
        p_se_f = re.compile(r"  Power Supply \d{1} \w{1,3} \d{1,2}   \w{1,3}-\w{1,6}   (\w{1,13})       \w{4}-\w{1,4}-\w{1,2}-\w{1,3}")
        p_me_f = re.compile(r"  Power Supply \d{1} \w{1,3} \d{1,2}   \w{1,3}-\w{1,6}   \w{1,13}       (\w{4}-\w{1,4}-\w{1,2}-\w{1,3})")
        
        #interactive shell 선언
        connection = ssh.invoke_shell()
        print("core 연결 완료")
        for ip in ip_a: 
            time.sleep(1)          
            connection.send(f"ssh {ip}\n")
            time.sleep(2)
            connection.send(f"{u_pas}\n")
            time.sleep(1)
            print(f"{ip} connectecd complete ")
            time.sleep(1)

            time.sleep(1)
            connection.send(f"set cli screen-length 0\n")
            time.sleep(0.5)

            connection.send(f"show version\n")
            time.sleep(4)
        
            connection.send(f"show chassis hard\n")
            time.sleep(1)

            connection.send(f"exit\n")
            time.sleep(0.5)
        
            data = connection.recv(65535)
            data = (data.decode())
            with open("juniper_test.txt", 'a',newline="") as f:
                f.write(str(data))

            ex_match = re.search(r"ex2200", data)
            vc_match = re.findall(r"FPC (\d{1})", data)
            vc = int(len(vc_match))
            if ex_match:
                print("2200")
                h=host.search(data).group(1)
                v=ver1.search(data).group(1)
                f_n=f_na.findall(data)
                f_r=f_re.findall(data)
                f_p=f_pa.findall(data)
                f_s=f_se.findall(data)
                f_m=f_me.findall(data)
                p_n=["Power Supply 0"]
                p_r=["Not Support"]
                p_s=["Not Support"]
                p_p=["Not Support"]
                p_m=["PS 550W AC"]
               
            elif vc >= 2:
                print("virtual chassis")
                h=host.search(data).group(1)
                v=ver2.search(data).group(1)
                f_n=f_na.findall(data)
                f_r=f_re.findall(data)
                f_p=f_pa.findall(data)
                f_s=f_se.findall(data)
                f_m=f_me.findall(data)
                p_n=p_na_f.findall(data)
                p_r=p_re_f.findall(data)
                p_p=p_pa_f.findall(data)
                p_s=p_se_f.findall(data)
                p_m=p_me_f.findall(data)
                 
            else:
                print("stand alone")
                h=host.search(data).group(1)
                v=ver2.search(data).group(1)
                f_n=f_na.findall(data)
                f_r=f_re.findall(data)
                f_p=f_pa.findall(data)
                f_s=f_se.findall(data)
                f_m=f_me.findall(data)
                p_n=p_na.findall(data)
                p_r=p_re.findall(data)
                p_p=p_pa.findall(data)
                p_s=p_se.findall(data)
                p_m=p_me.findall(data)
                                 
            raw_data1 = {"hostname" : h,
                        "ipaddr" : ip,
                        "version" : v,
                        "item" : f_n + p_n,
                        "rev_ver" : f_r + p_r,
                        "part_num" : f_p + p_p,
                        "serial" : f_s + p_s,
                        "model": f_m + p_m, 
                        }
                        
            df1 = pd.DataFrame(raw_data1)
            df1 = juniper_parse_fixed(df1)
            print(df1)  
           
                
            wb = openpyxl.load_workbook("juniper_test.xlsx")
            ws = wb["Sheet1"]
            rows = dataframe_to_rows(df1, index=False, header=False)
            for r_idx,row in enumerate(rows, ws.max_row+1):
                for c_idx, value in enumerate(row, 1):
                    ws.cell(row=r_idx, column=c_idx, value=value)
            
            wb.save("juniper_test.xlsx")
        
        ssh.close()
        
with open ("switch_list_testdevice.txt") as f:
    content=f.read().splitlines()

u_id = input("Enter your Username:")
if not u_id:
    u_id = "eknow"
    print(f"if you No Username input please Enter to keep goning default ID {u_id}")

u_pas= getpass(f"Enter Password of the user {u_id}: ")or "eknow"    
        
juniper_parse(content, u_id, u_pas)

 

코드의 결과 값

해당 코드를 실행하면 switch_list_testdevice.txt에서 IP 정보를 불러온 후 ID 와 PASS를 입력 받은 후 

점프장비에 SSH 접속 후 swtich_list_testdevice.txt에서 불러온 IP로 입력 받은 ID와 PASS 를 사용하여 점프장비에서 SSH를 시도한다 SSH 접속 후 show version 과 show chassis hardware를 입력 후 나온 정보를 data에 저장한다

그 후 data를 dataframe 형태로 변경하게 되면 FPC 리트스와 Power Supply가 분리되어 리스트가 만들어 지는데 이걸 juniper_parse_fixed 함수로 보내서 EX3400인 경우 FPC 하나에 Power supply 두개를 묶고 EX2200인 경우 FPC 하나에 Power Supply 한개를 묶어서 재정렬 후 리턴한다

그후 openpyxl로 지정된 파일에 append 되게 작성한다

 

이런 식으로 코드를 돌려도 장비별 데이터가 썩이지 않는 이유는 re.findall로 정규식을 매칭 시키게 되면 위에서 아래로 먼저 매칭된 순서대로 리스트가 작성 되기 때문이다

 

이 코드는 show version과 show chassis hardware의 출력 형태가 ex3400 또는 ex2200과 같다면 어느 기종이든지 사용 가능하다

'파이썬 코드' 카테고리의 다른 글

파이썬 자동화 -7-  (0) 2023.05.18
파이썬 자동화 -6-  (0) 2023.03.20
Network Automation -4-  (0) 2023.02.24
networkautomation -3-  (0) 2023.02.23
텍스트 파일에서 주니퍼 장비 정보 파싱하기  (0) 2023.02.22