Junos PyEZ باستخدام مثال مهمة البحث عن شبكات فرعية ipv4 مجانية

مقال عن العمل مع Junos PyEZ - "Python microframework الذي يمكّنك من إدارة وأتمتة الأجهزة التي تعمل بنظام Junos OS" أتمتة وإدارة، كل ما نحبه. كان لكتابة البرنامج النصي الموصوف في هذه المقالة عدة أهداف - تعلم لغة Python وأتمتة المهام لجمع المعلومات أو تغيير التكوينات على الأجهزة التي تعمل بنظام Junos OS. تم اختيار هذه المجموعة المحددة من Python + Junos PyEZ بسبب انخفاض حاجز الدخول إلى لغة برمجة Python وسهولة استخدام مكتبة Junos PyEZ، والتي لا تتطلب معرفة متخصصة بنظام التشغيل Junos.

مهمة

تدقيق شبكات فرعية ipv4 المجانية التابعة للشركة. المعيار الذي يجعل الشبكة الفرعية مجانية هو عدم وجود إدخال عنها في المسارات الموجودة على المحول الذي يعمل كموجه يعمل بنظام Junos OS.

تطبيق

Python + Junos PyEZ، على الرغم من وجود إغراء للقيام بذلك من خلال paramiko وssh.exec_command، ونتيجة لذلك، سوف تحتاج إلى تكوين بروتوكول إدارة شبكة جهاز netconf على الجهاز الذي يتم استقصاؤه. يعمل Netconf مع الأجهزة من خلال استدعاء الإجراء البعيد RPC ويستخدم XML، في هذا المثال، لتوفير المعلومات التي يتلقاها.

يتم تثبيت الإصدار الحالي من Junos PyEZ من PyPI باستخدام الأمر التالي:

$ pip install junos-eznc

يمكنك أيضًا التثبيت من الفرع الرئيسي للمشروع على GitHub باستخدام الأمر التالي:

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

وخيار آخر عبر

$ pip install -r requirements.txt 

سيقوم هذا الأمر بتثبيت المكتبات المفقودة من النظام والضرورية للتشغيل. في نسختي requirements.txt لا يوجد سوى اثنين منهم، تتم الإشارة إلى أحدث الإصدارات في وقت كتابة البرنامج النصي:

junos-eznc
netaddr

افتراضيًا، يأخذ البرنامج النصي اسم المستخدم الحالي في النظام، ويمكنك تسجيل الدخول باسم مستخدم آخر باستخدام المفتاح show_route.py -u يأخذ getpass.getpass كلمة المرور من stdin لذلك لن تبقى كلمة المرور في النظام. للاتصال بالجهاز، ستحتاج أيضًا إلى إدخال اسم المضيف أو عنوان IP الخاص به عندما يُطلب منك ذلك. تم استلام كافة البيانات اللازمة للحصول على ترخيص على الجهاز.

يدعم Junos PyEZ الاتصال بالأجهزة التي تعمل بنظام Junos OS باستخدام وحدة التحكم أو telnet أو netconf عبر ssh. تتناول المقالة الخيار الأخير.

للاتصال بالمعدات، استخدم فئة الجهاز الخاصة بوحدة jnpr.junos

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

يتم إجراء طلب لجميع المسارات المعروفة لجهاز التوجيه عبر استدعاء الإجراء عن بعد أو استدعاء الإجراء عن بعد، أيهما أكثر ملاءمة.

data = dev.rpc.get_route_information()

أمر مماثل على Junos OS

user@router> show route | display xml

من خلال إضافة rpc إلى نهاية الأمر، نحصل على علامة طلب ويمكننا مطابقتها مع اسم طريقة RPC، وبهذه الطريقة يمكننا معرفة الأسماء الأخرى ذات الاهتمام. تجدر الإشارة إلى أن بناء جملة كتابة علامة الطلب يختلف عن اسم الطريقة، أي أنه يجب عليك استبدال الواصلات بشرطات سفلية.

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

تم لف باقي الجزء في حلقة زمنية، حتى لا يتم تكرار الطلب إلى جهاز التوجيه إذا كان من الضروري التحقق من شبكة فرعية أخرى من تلك التي يعرفها جهاز التوجيه بالفعل. تجدر الإشارة إلى أن جهاز التوجيه الذي أقوم بتقديم الطلب عليه يعرف المسارات فقط من خلال OSPF، لذلك بالنسبة لجهاز توجيه الحافة، من الأفضل تغيير الطلب قليلاً لتقليل وقت تشغيل البرنامج النصي

data = dev.rpc.get_ospf_route_information()

الآن دعونا نلقي نظرة على محتويات الحلقة while

في البداية، سيُطلب من المستخدم إدخال شبكة فرعية بقناع وما لا يزيد عن ثلاث ثمانيات من شبكة نفس الشبكة الفرعية، وهذا ضروري لتعيين نطاق البحث. لا أحب حقًا هذا التنفيذ لتحديد المعايير ونطاق البحث، لكن حتى الآن لم أجد حلاً أفضل. بعد ذلك، من القائمة الناتجة للشبكات الفرعية Route_list، باستخدام متغير لا يحتوي على أكثر من ثلاث ثمانيات، قمت بتحديد الشبكات الفرعية التي تهمني

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

من خلال وحدة IPNetwork، netaddr، أستقبل الشبكات الفرعية على شكل قائمة عناوين ipv4

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

باستخدام IPNetwork، أحصل على نطاق من العناوين من شبكة يدخلها المستخدم باستخدام قناع، ثم أقوم بإنشاء قائمة بجميع العناوين من هذا النطاق للمقارنة مع قائمة العناوين المشغولة.

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

أعرض القائمة الناتجة للعناوين المجانية في شكل شبكات فرعية

print(netaddr.IPSet(freeip))

فيما يلي النص الكامل، الذي تم اختباره على المحولات المستخدمة كجهاز توجيه، موديلات 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

المصدر: www.habr.com

إضافة تعليق