Nên xem các bài dưới đây trước khi xem bài này:
- Cài đặt python tại đây
- Dictionnary trong python tại đây
- Import thư viện tại đây
- Cách cấu hình ssh tại đây
- Cách xử lý file tại đây
- Loop if tại đây
- Netmiko basic tại đây
- Regular Expression tại đây
- Cách nối chuỗi tại đây
- Giao thức CDP/LLDP tại đây
Sơ đồ lab:
Dùng thư viện netmiko và các câu lệnh show cdp để thực hiện, thông tin
thiết bị như file device_listCDP.csv dưới:
Yêu cầu:
1. Ghi lại thông tin đấu nối các cổng của các thiết bị trong sơ đồ lab.
2. Cấu hình cdp run trên Sw_13 (dùng netmiko để cấu hình), thực hiện show cdp
để lấy thông tin đấu nối và ghi tiếp vào kết quả của yêu cầu 1
Chuẩn bị:
Thực hiện:
1. Ghi lại thông tin đấu nối các cổng của các thiết bị trong sơ đồ
lab.
- Code
Hàm xử lý show cdp (1):
from netmiko import ConnectHandler
import re
import os
file_cdp = "show_cdp_neighbors.txt"
file_cdp_not = "show_cdp_NOT_enable.csv"
path = os.getcwd() # lấy đường dẫn hiện tại
cdp_device = {}
def show_cdp(txt):
cmd = "show cdp neighbors"
cmd2 = "show cdp entry"
filename = txt
print(f"Dang ket noi vao IP:'{values[1]}' voi Username: '{values[2]}'")
net_connect = ConnectHandler(**cdp_device)
output = net_connect.send_command(cmd)
if "CDP is not enabled" in output: # nếu cdp không được enable
with open (file_cdp_not,"a") as afile: # mở file ghi log và sẽ xử lý sau
afile.write(values[1] + "," + values[2] + "," + values[3] + "," + values[4] + "," + output + "\n") # nội dung là IP, dấu 2 chấm, lỗi trả về, xuống hàng
else:
with open (file_cdp, "a") as afile:
afile.write("\n\n" + "*" * 40 + values[1] + "*" * 40 +"\n")
afile.write(output)
'''
output của lệnh: "show cdp neighbors" trả về có dạng:
---------------------------------------------------------------------------
Capability Codes: R - Router, T - Trans Bridge, B - Source Route Bridge
S - Switch, H - Host, I - IGMP, r - Repeater, P - Phone,
D - Remote, C - CVTA, M - Two-port Mac Relay
Device ID Local Intrfce Holdtme Capability Platform Port ID
Sw_12.netmiko.lab
Eth 0/2 137 R S I Linux Uni Eth 0/0
Sw_11.netmiko.lab
Eth 0/1 135 R S I Linux Uni Eth 0/0
Total cdp entries displayed : 2
---------------------------------------------------------------------------
bỏ 5 dòng đầu tiên là header,
lấy từ dòng số 6 đến cuối kết quả và bỏ 2 dòng cuối cùng
mỗi dòng chuyển thành list
'''
lines = output.splitlines()[5:-2]
'''
xử lý và trích lọc trong lệnh show cdp neighbors, show cdp entry *
-
-
'''
hostname = None
for line in lines:
fields = line.split() # chuyển mỗi dòng sang list
if len(fields) == 1: # đối với những hostname dài kết quả của neighbors sẽ trả về 2 dòng cho mỗi neighbors
hostname = fields[0]
elif hostname == None: # kết quả của neighbors sẽ trả về là 1 dòng thì thực hiện trong elif này
hostname = fields[0] # lấy ra hostname của láng giềng
localint = "".join(fields[1:3]) # lấy ra local interface (lấy trường số 1 đến số 2)
remoteint = "".join(fields[-2:]) # lấy ra remote interface
outputentry = net_connect.send_command(cmd2 + " " + hostname)
regex = r'\d{1,3}(?:\.\d{1,3}){3}' # định nghĩa regular expression của IPv4 có dạng
ips = re.findall(regex, outputentry) # trích lọc lấy IPv4 ra, IP trả về là dạng list
ips = "".join(list(set(ips))) # remove duplicate IP và convert to string
with open ("show_cdp_neighbors.txt", "a") as afile:
afile.write("{}{}".format("\n\n","-" * 80))
afile.write("\nThe information of the neighbors:\n")
afile.write("\nNeighbors hostname is: " + hostname)
afile.write("\nIP address: " + ips)
afile.write("\n\nLocal interface: " + localint + " of " + values[1] + " connect to interface: " + remoteint + " of IP(s) " + ips)
else:
outputentry = net_connect.send_command(cmd2 + " " + hostname)
regex = r'\d{1,3}(?:\.\d{1,3}){3}' # định nghĩa regular expression của IPv4 có dạng
ips = re.findall(regex, outputentry) # trích lọc lấy IPv4 ra, IP trả về là dạng list
ips = "".join(list(set(ips))) # remove duplicate IP và convert to string
localint = "".join(fields[:2]) # lấy 2 trường đầu tiên
remoteint = "".join(fields[-2:]) # lấy 2 trường cuối cùng
with open ("show_cdp_neighbors.txt", "a") as afile:
afile.write("{}{}".format("\n\n","-" * 80))
afile.write("\nThe information of the neighbors:\n")
afile.write("\nNeighbors hostname is: " + hostname)
afile.write("\n\nLocal interface: " + localint + " of " + values[1] + " connect to interface: " + remoteint + " of IP(s) " + ips)
Mở file và gọi hàm xử lý (2):
with open ("device_listCDP.csv","r") as rfile: # mở file
keys = rfile.readline().split(",")
values = rfile.read()
#print(keys)
#print(values)
for values in values.splitlines():
values = values.split(",")
for i in range(1,len(keys)-1,1):
cdp_device[keys[i]] = values[i]
#print(f"Dang ket noi vao IP:'{values[1]}' voi Username: '{values[2]}'")
show_cdp(values[1])
print("Thong tin neighbors da luu vao file: '{}' tai duong dan '{}'".format(file_cdp,path))
Nối 2 đoạn code trên thành code chạy (1) + (2) = (3):
from netmiko import ConnectHandler
import re
import os
file_cdp = "show_cdp_neighbors.txt"
file_cdp_not = "show_cdp_NOT_enable.csv"
path = os.getcwd() # lấy đường dẫn hiện tại
cdp_device = {}
def show_cdp(txt):
cmd = "show cdp neighbors"
cmd2 = "show cdp entry"
filename = txt
print(f"Dang ket noi vao IP:'{values[1]}' voi Username: '{values[2]}'")
net_connect = ConnectHandler(**cdp_device)
output = net_connect.send_command(cmd)
if "CDP is not enabled" in output: # nếu cdp không được enable
with open (file_cdp_not,"a") as afile: # mở file ghi log và sẽ xử lý sau
afile.write(values[1] + "," + values[2] + "," + values[3] + "," + values[4] + "," + output + "\n") # nội dung là IP, dấu 2 chấm, lỗi trả về, xuống hàng
else:
with open (file_cdp, "a") as afile:
afile.write("\n\n" + "*" * 40 + values[1] + "*" * 40 +"\n")
afile.write(output)
'''
output của lệnh: "show cdp neighbors" trả về có dạng:
---------------------------------------------------------------------------
Capability Codes: R - Router, T - Trans Bridge, B - Source Route Bridge
S - Switch, H - Host, I - IGMP, r - Repeater, P - Phone,
D - Remote, C - CVTA, M - Two-port Mac Relay
Device ID Local Intrfce Holdtme Capability Platform Port ID
Sw_12.netmiko.lab
Eth 0/2 137 R S I Linux Uni Eth 0/0
Sw_11.netmiko.lab
Eth 0/1 135 R S I Linux Uni Eth 0/0
Total cdp entries displayed : 2
---------------------------------------------------------------------------
bỏ 5 dòng đầu tiên là header,
lấy từ dòng số 6 đến cuối kết quả và bỏ 2 dòng cuối cùng
mỗi dòng chuyển thành list
'''
lines = output.splitlines()[5:-2]
'''
xử lý và trích lọc trong lệnh show cdp neighbors, show cdp entry *
-
-
'''
hostname = None
for line in lines:
fields = line.split() # chuyển mỗi dòng sang list
if len(fields) == 1: # đối với những hostname dài kết quả của neighbors sẽ trả về 2 dòng cho mỗi neighbors
hostname = fields[0]
elif hostname == None: # kết quả của neighbors sẽ trả về là 1 dòng thì thực hiện trong elif này
hostname = fields[0] # lấy ra hostname của láng giềng
localint = "".join(fields[1:3]) # lấy ra local interface (lấy trường số 1 đến số 2)
remoteint = "".join(fields[-2:]) # lấy ra remote interface
outputentry = net_connect.send_command(cmd2 + " " + hostname)
regex = r'\d{1,3}(?:\.\d{1,3}){3}' # định nghĩa regular expression của IPv4 có dạng
ips = re.findall(regex, outputentry) # trích lọc lấy IPv4 ra, IP trả về là dạng list
ips = "".join(list(set(ips))) # remove duplicate IP và convert to string
with open ("show_cdp_neighbors.txt", "a") as afile:
afile.write("{}{}".format("\n\n","-" * 80))
afile.write("\nThe information of the neighbors:\n")
afile.write("\nNeighbors hostname is: " + hostname)
afile.write("\nIP address: " + ips)
afile.write("\n\nLocal interface: " + localint + " of " + values[1] + " connect to interface: " + remoteint + " of IP(s) " + ips)
else:
outputentry = net_connect.send_command(cmd2 + " " + hostname)
regex = r'\d{1,3}(?:\.\d{1,3}){3}' # định nghĩa regular expression của IPv4 có dạng
ips = re.findall(regex, outputentry) # trích lọc lấy IPv4 ra, IP trả về là dạng list
ips = "".join(list(set(ips))) # remove duplicate IP và convert to string
localint = "".join(fields[:2]) # lấy 2 trường đầu tiên
remoteint = "".join(fields[-2:]) # lấy 2 trường cuối cùng
with open ("show_cdp_neighbors.txt", "a") as afile:
afile.write("{}{}".format("\n\n","-" * 80))
afile.write("\nThe information of the neighbors:\n")
afile.write("\nNeighbors hostname is: " + hostname)
afile.write("\n\nLocal interface: " + localint + " of " + values[1] + " connect to interface: " + remoteint + " of IP(s) " + ips)
with open ("device_listCDP.csv","r") as rfile: # mở file
keys = rfile.readline().split(",")
values = rfile.read()
#print(keys)
#print(values)
for values in values.splitlines():
values = values.split(",")
for i in range(1,len(keys)-1,1):
cdp_device[keys[i]] = values[i]
#print(f"Dang ket noi vao IP:'{values[1]}' voi Username: '{values[2]}'")
show_cdp(values[1])
print("Thong tin neighbors da luu vao file: '{}' tai duong dan '{}'".format(file_cdp,path))
- Kết quả:
C:\python>python Demo.pyDang ket noi vao IP:'192.168.0.1' voi Username: 'admin'Dang ket noi vao IP:'192.168.0.11' voi Username: 'admin'Dang ket noi vao IP:'192.168.0.12' voi Username: 'admin'Dang ket noi vao IP:'192.168.0.13' voi Username: 'admin'Thong tin neighbors da luu vao file: 'show_cdp_neighbors.txt' tai duong dan 'C:\python'C:\python>
Nội dung file
Chúng ta thấy rằng thông tin neighbor của Sw_13 chưa được thể hiện trong
file, vì thiết bị này cdp không được cài đặt. Thông tin các thiết bị đã cấu
hình tắt cdp được lưu ở file show_cdp_NOT_enable.csv (file này sinh ra
trong khi thực thi chương trình)
2. Cấu hình cdp run trên Sw_13 (dùng netmiko để cấu hình), thực hiện show
cdp để lấy thông tin đấu nối và ghi tiếp vào kết quả của yêu cầu 1
- Code
Định nghĩa hàm show_cdp_not_running (4):
from netmiko import ConnectHandler
import time
file_cdp_not = "show_cdp_NOT_enable.csv"
conf_t = "conf t"
cdp_run = "cdp run"
keys = "no., host, username, password, device_type, remark" # header cho file show_cdp_NOT_enable.csv
txt = file_cdp_not
cdp_device = {}
def show_cdp_not_running(txt):
cmd_run = "cdp run"
net_connect = ConnectHandler(**cdp_device)
#output = net_connect.send_command(cmd)
output = net_connect.send_command_timing(conf_t) # vào mode config t
output += net_connect.send_command_timing(cdp_run) # cấu hình cdp run
'''
đợi 65s sau đó gọi hàm show_cdp(txt).
Mặc định cứ 60s/lần cdp sẽ gửi thông tin cdp cho láng giềng, để chắc ăn chúng ta thêm vài giây
'''
time.sleep(65)
show_cdp(txt) # gọi hàm show_cdp như bình thường, vì đã cấu hình cdp run
output += net_connect.send_command_timing("no " + cdp_run) # trả lại cấu hình ban đầu
Mở file và gọi hàm xử lý (5)
try:
with open (file_cdp_not,"r") as rfile:
keys = key_csv.split(", ") #
values = rfile.read()
for values in values.splitlines():
values = values.split(",")
for i in range(1,len(keys)-1,1):
cdp_device[keys[i]] = values[i]
show_cdp_not_running(file_cdp_not) # truyền chuỗi vào nhằm mục đích ghi chú
except NameError:
print("File'{}' khong ton tai!".format(file_cdp_not))
pass
Vì file "show_cdp_NOT_enable.csv" có thể tồn tại hoặc không, chúng ta thực
bắt lỗi để khi nếu có lỗi về việc này chương trình vẫn tiếp tục.
- Code chính gộp các đoạn (3) + (4) + (5) = (6)
from netmiko import ConnectHandler
import re
import os
import time
file_cdp = "show_cdp_neighbors.txt"
file_cdp_not = "show_cdp_NOT_enable.csv"
path = os.getcwd() # lấy đường dẫn hiện tại
conf_t = "conf t"
cdp_run = "cdp run"
key_csv = "no., host, username, password, device_type, remark" # header cho file show_cdp_NOT_enable.csv
txt = file_cdp_not
cdp_device = {}
def show_cdp(txt):
cmd = "show cdp neighbors"
cmd2 = "show cdp entry"
if txt == file_cdp_not:
print(f"Dang ket noi vao IP:'{values[1]}' voi Username: '{values[2]}' '{txt}'") # sau khi enable cdp sẽ thông báo dòng này
else:
print(f"Dang ket noi vao IP:'{values[1]}' voi Username: '{values[2]}'")
net_connect = ConnectHandler(**cdp_device)
output = net_connect.send_command(cmd)
i = 0 # định nghĩa biến đếm chỉ dùng trong trường hợp CDP not enable
if "CDP is not enabled" in output: # nếu cdp không được enable
i += 1
with open (file_cdp_not,"a") as afile: # mở file ghi log và sẽ xử lý sau
afile.write(str(i) + "," + values[1] + "," + values[2] + "," + values[3] + "," + values[4] + "," + output + "\n") # ghi thông tin ip, username, password.... vào file
else:
with open (file_cdp, "a") as afile:
if txt == file_cdp_not:
afile.write("\n\n" + "=" * 40 + txt + "=" * 40) # chèn thêm dòng này file log nếu nếu cdp không được enable
afile.write("\n\n" + "*" * 40 + values[1] + "*" * 40 +"\n")
afile.write(output)
'''
output của lệnh: "show cdp neighbors" trả về có dạng:
---------------------------------------------------------------------------
Capability Codes: R - Router, T - Trans Bridge, B - Source Route Bridge
S - Switch, H - Host, I - IGMP, r - Repeater, P - Phone,
D - Remote, C - CVTA, M - Two-port Mac Relay
Device ID Local Intrfce Holdtme Capability Platform Port ID
Sw_12.netmiko.lab
Eth 0/2 137 R S I Linux Uni Eth 0/0
Sw_11.netmiko.lab
Eth 0/1 135 R S I Linux Uni Eth 0/0
Total cdp entries displayed : 2
---------------------------------------------------------------------------
bỏ 5 dòng đầu tiên là header,
lấy từ dòng số 6 đến cuối kết quả và bỏ 2 dòng cuối cùng
mỗi dòng chuyển thành list
'''
lines = output.splitlines()[5:-2]
'''
xử lý và trích lọc trong lệnh show cdp neighbors, show cdp entry *
-
-
'''
hostname = None
for line in lines:
fields = line.split() # chuyển mỗi dòng sang list
if len(fields) == 1: # đối với những hostname dài kết quả của neighbors sẽ trả về 2 dòng cho mỗi neighbors
hostname = fields[0]
elif hostname == None: # kết quả của neighbors sẽ trả về là 1 dòng thì thực hiện trong elif này
hostname = fields[0] # lấy ra hostname của láng giềng
localint = "".join(fields[1:3]) # lấy ra local interface (lấy trường số 1 đến số 2)
remoteint = "".join(fields[-2:]) # lấy ra remote interface
outputentry = net_connect.send_command(cmd2 + " " + hostname)
regex = r'\d{1,3}(?:\.\d{1,3}){3}' # định nghĩa regular expression của IPv4 có dạng
ips = re.findall(regex, outputentry) # trích lọc lấy IPv4 ra, IP trả về là dạng list
ips = "".join(list(set(ips))) # remove duplicate IP và convert to string
with open ("show_cdp_neighbors.txt", "a") as afile:
afile.write("{}{}".format("\n\n","-" * 80))
afile.write("\nThe information of the neighbors:\n")
afile.write("\nNeighbors hostname is: " + hostname)
afile.write("\nIP address: " + ips)
afile.write("\n\nLocal interface: " + localint + " of " + values[1] + " connect to interface: " + remoteint + " of IP(s) " + ips)
else:
outputentry = net_connect.send_command(cmd2 + " " + hostname)
regex = r'\d{1,3}(?:\.\d{1,3}){3}' # định nghĩa regular expression của IPv4 có dạng
ips = re.findall(regex, outputentry) # trích lọc lấy IPv4 ra, IP trả về là dạng list
ips = "".join(list(set(ips))) # remove duplicate IP và convert to string
localint = "".join(fields[:2]) # lấy 2 trường đầu tiên
remoteint = "".join(fields[-2:]) # lấy 2 trường cuối cùng
with open ("show_cdp_neighbors.txt", "a") as afile:
afile.write("{}{}".format("\n\n","-" * 80))
afile.write("\nThe information of the neighbors:\n")
afile.write("\nNeighbors hostname is: " + hostname)
afile.write("\n\nLocal interface: " + localint + " of " + values[1] + " connect to interface: " + remoteint + " of IP(s) " + ips)
def show_cdp_not_running(txt):
cmd_run = "cdp run"
net_connect = ConnectHandler(**cdp_device)
#output = net_connect.send_command(cmd)
output = net_connect.send_command_timing(conf_t) # vào mode config t
output += net_connect.send_command_timing(cdp_run) # cấu hình cdp run
'''
đợi 65s sau đó gọi hàm show_cdp(txt).
Mặc định cứ 60s/lần cdp sẽ gửi thông tin cdp cho láng giềng, để chắc ăn chúng ta thêm vài giây
'''
time.sleep(65)
show_cdp(txt) # gọi hàm show_cdp như bình thường, vì đã cấu hình cdp run
output += net_connect.send_command_timing("no " + cdp_run) # trả lại cấu hình ban đầu
with open ("device_listCDP.csv","r") as rfile: # mở file
keys = rfile.readline().split(",")
values = rfile.read()
#print(keys)
#print(values)
for values in values.splitlines():
values = values.split(",")
for i in range(1,len(keys)-1,1):
cdp_device[keys[i]] = values[i]
#print(f"Dang ket noi vao IP:'{values[1]}' voi Username: '{values[2]}'")
show_cdp(values[1]) # trong trường hợp này biến values[1] truyền vào nhưng không dùng đến
'''
dùng trong trường hợp cdp run đã được tắt
danh sách này có được khi ta thực hiện lệnh show cdp không thành lưu nó lại
bây giờ mở ra để xử lý
'''
try:
with open (file_cdp_not,"r") as rfile:
keys = key_csv.split(", ") #
values = rfile.read()
for values in values.splitlines():
values = values.split(",")
for i in range(1,len(keys)-1,1):
cdp_device[keys[i]] = values[i]
show_cdp_not_running(file_cdp_not) # truyền chuỗi vào nhằm mục đích ghi chú
except NameError:
print("File'{}' khong ton tai!".format(file_cdp_not))
pass
print("Thong tin neighbors da luu vao file: '{}' tai duong dan '{}'".format(file_cdp,path))
P/s: trong phần code của hàm show_cdp có chèn thêm các dòng 20 -> 22 và
36,37 như hình dưới:
- Chạy code
C:\python>python Demo.pyDang ket noi vao IP:'192.168.0.1' voi Username: 'admin'Dang ket noi vao IP:'192.168.0.11' voi Username: 'admin'Dang ket noi vao IP:'192.168.0.12' voi Username: 'admin'Dang ket noi vao IP:'192.168.0.13' voi Username: 'admin'Dang ket noi vao IP:'192.168.0.13' voi Username: 'admin' 'show_cdp_NOT_enable.csv'Thong tin neighbors da luu vao file: 'show_cdp_neighbors.txt' tai duong dan 'C:\python'
Chúng ta thấy ip 192.168.0.13 được kết nối vào 2 lần:
- Lần 1: kiểm tra show cdp không thành công => đưa ip này vào danh sách thiết bị cdp không được cấu hình/hay tắt- Lần 2: kết nối vào cấu hinh cdp run rồi thực hiện show cdp như bình thường, xong trả lại cấu hình ban đầu cho thiết bị
- Kết quả
Xong!
No comments:
Post a Comment