Junos PyEZ sử dụng ví dụ về nhiệm vụ tìm kiếm mạng con ipv4 miễn phí

Một bài viết về cách làm việc với Junos PyEZ - “Microframework Python cho phép bạn quản lý và tự động hóa các thiết bị chạy Junos OS”, tự động hóa và quản lý, mọi thứ chúng tôi yêu thích. Việc viết tập lệnh được mô tả trong bài viết này nhằm một số mục tiêu - học Python và tự động hóa các tác vụ thu thập thông tin hoặc thay đổi cấu hình trên thiết bị chạy Junos OS. Việc lựa chọn sự kết hợp cụ thể giữa Python + Junos PyEZ này được thực hiện do rào cản tiếp cận ngôn ngữ lập trình Python thấp và tính dễ sử dụng của thư viện Junos PyEZ, không yêu cầu kiến ​​thức chuyên môn về Junos OS.

Nhiệm vụ

Kiểm tra các mạng con ipv4 miễn phí của công ty. Tiêu chí để đánh giá một mạng con là miễn phí là không có mục nào về nó trong các tuyến trên bộ chuyển mạch hoạt động như một bộ định tuyến chạy hệ điều hành Junos.

Thực hiện

Python + Junos PyEZ, mặc dù có sự cám dỗ để thực hiện điều đó thông qua paramiko và ssh.exec_command, Do đó, bạn sẽ cần định cấu hình giao thức quản lý mạng thiết bị netconf trên thiết bị đang được thăm dò. Netconf hoạt động với phần cứng thông qua lệnh gọi thủ tục từ xa RPC và sử dụng XML, trong ví dụ này, để cung cấp thông tin mà nó nhận được.

Việc cài đặt phiên bản hiện tại của Junos PyEZ từ PyPI được thực hiện bằng lệnh sau:

$ pip install junos-eznc

Bạn cũng có thể cài đặt từ nhánh chính của dự án trên GitHub bằng lệnh sau:

$ pip install git+https://github.com/Juniper/py-junos-eznc.git

Và một lựa chọn nữa thông qua

$ pip install -r requirements.txt 

Lệnh này sẽ cài đặt các thư viện còn thiếu trong hệ thống và cần thiết cho hoạt động. Trong phiên bản của tôi Yêu cầu.txt Chỉ có hai trong số đó, các phiên bản mới nhất được chỉ ra tại thời điểm viết kịch bản:

junos-eznc
netaddr

Theo mặc định, tập lệnh lấy tên của người dùng hiện tại trong hệ thống; bạn có thể đăng nhập dưới tên của người dùng khác bằng phím show_route.py -u getpass.getpass lấy mật khẩu từ stdin nên mật khẩu sẽ không còn trong hệ thống. Để kết nối với thiết bị, bạn cũng cần nhập tên máy chủ hoặc địa chỉ IP của thiết bị khi được nhắc. Tất cả dữ liệu cần thiết để ủy quyền trên thiết bị đã được nhận.

Junos PyEZ hỗ trợ kết nối với thiết bị chạy Junos OS bằng console, telnet hoặc netconf qua ssh. Bài viết thảo luận về lựa chọn thứ hai.

Để kết nối với thiết bị, hãy sử dụng lớp Thiết bị của mô-đun jnpr.junos

with jnpr.junos.Device(host=router,
                           user=args.name,
                           passwd=password) as dev:

Một yêu cầu được thực hiện cho tất cả các tuyến mà bộ định tuyến biết thông qua cuộc gọi thủ tục từ xa hoặc cuộc gọi thủ tục từ xa, tùy theo cách nào thuận tiện hơn.

data = dev.rpc.get_route_information()

Lệnh tương tự trên Junos OS

user@router> show route | display xml

Bằng cách thêm rpc vào cuối lệnh, chúng ta nhận được thẻ yêu cầu và có thể khớp nó với tên của phương thức RPC, bằng cách này, chúng ta có thể tìm ra các tên khác mà chúng ta quan tâm. Điều đáng chú ý là cú pháp viết thẻ yêu cầu khác với tên phương thức, cụ thể là bạn nên thay thế dấu gạch nối bằng dấu gạch dưới.

user@router> show route | display xml rpc
<rpc-reply >route_list = data.xpath("//rt-destination/text()")

Phần còn lại được gói trong một vòng lặp while, để không lặp lại yêu cầu tới bộ định tuyến nếu cần kiểm tra mạng con khác từ những mạng con mà bộ định tuyến đã biết. Điều đáng nói là bộ định tuyến mà tôi đang thực hiện yêu cầu chỉ biết các tuyến thông qua OSPF, vì vậy đối với bộ định tuyến biên, tốt hơn hết bạn nên thay đổi yêu cầu một chút để giảm thời gian chạy của tập lệnh

data = dev.rpc.get_ospf_route_information()

Bây giờ hãy xem nội dung của vòng lặp while

Khi bắt đầu, người dùng sẽ được yêu cầu nhập một mạng con có mặt nạ và không quá ba octet từ mạng của cùng một mạng con, điều này là cần thiết để đặt phạm vi tìm kiếm. Tôi thực sự không thích việc triển khai chỉ định tiêu chí và phạm vi tìm kiếm này, nhưng cho đến nay tôi vẫn chưa tìm được giải pháp nào tốt hơn. Tiếp theo, từ danh sách kết quả của các mạng con Route_list, sử dụng một biến chứa không quá ba octet, tôi chọn các mạng con mà tôi quan tâm

tmp = re.search(r'^%sS*' % subnet_search, route_list[i])

Thông qua IPNetwork, mô-đun netaddr, tôi nhận được các mạng con dưới dạng danh sách các địa chỉ ipv4

range_subnet = netaddr.IPNetwork(tmp.group(0))

Bằng cách sử dụng IPNetwork, tôi lấy được một dải địa chỉ từ mạng do người dùng nhập có mặt nạ và tạo danh sách tất cả các địa chỉ từ dải này để so sánh với danh sách các địa chỉ bị chiếm đóng.

for i in set(net_list).difference(set(busyip)):
        freeip.append(i)

Tôi hiển thị danh sách kết quả các địa chỉ miễn phí dưới dạng mạng con

print(netaddr.IPSet(freeip))

Dưới đây là tập lệnh hoàn chỉnh, được thử nghiệm trên các thiết bị chuyển mạch được sử dụng làm bộ định tuyến, model ex4550, ex4600


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import argparse
import getpass
import netaddr
import re
import sys

import jnpr.junos

parser = argparse.ArgumentParser()
parser.add_argument('-u', '--user',
                    action='store',
                    dest='name',
                    help='Enter login from tacacs if it differs from the '
                         'username in the system.')
args = parser.parse_args()

if not args.name:
    args.name = getpass.getuser()    # Return the “login name” of the user.
router = input("Full routers name: ")
password = getpass.getpass("Password: ")

try:
    # Authenticates to a device running Junos, for get information about routs
    # into xml format and selects by tag.
    route_list = []
    with jnpr.junos.Device(host=router,
                           user=args.name,
                           passwd=password) as dev:
        data = dev.rpc.get_route_information()
    route_list = data.xpath("//rt-destination/text()")
except (jnpr.junos.exception.ConnectRefusedError,
        jnpr.junos.exception.ConnectUnknownHostError) as err:
    print("Equipment name or password wrong.")
    sys.exit(1)

while True:
    subnet = input("Net with mask: ")
    subnet_search = input("Input no more three octet: ")
    # Gets a list of busy IP addresses from the received subnets.
    busyip = []
    for i in range(len(route_list)):
        tmp = re.search(r'^%sS*' % subnet_search, route_list[i])
        if tmp:
            range_subnet = netaddr.IPNetwork(tmp.group(0))
            for ip in range_subnet:
                busyip.append("%s" % ip)
    range_subnet = netaddr.IPNetwork(subnet)
    # Gets list ip adresses from subnetworks lists.
    net_list = []
    for ip in range_subnet:
        net_list.append("%s" % ip)
    # Сomparing lists.
    freeip = []
    for i in set(net_list).difference(set(busyip)):
        freeip.append(i)
    print(netaddr.IPSet(freeip))

    request = input("To run request again enter yes or y, "
                    "press 'enter', complete request: ")
    if request in ("yes", "y"):
        continue
    else:
        print('Bye')
        break

Nguồn: www.habr.com

Thêm một lời nhận xét