Junos PyEZ على سبيل المثال مهمة العثور على شبكات IPv4 المجانية

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

مهمة


تدقيق شبكات IPv4 المجانية المملوكة للشركة. يتمثل المعيار القائل بأن الشبكة الفرعية مجانية في عدم وجود إدخالات حولها في المسارات الموجودة على المحول الذي يعمل كموجه يعمل بنظام تشغيل Junos.

تطبيق


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

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

$ pip install junos-eznc 

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

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

وخيار آخر من خلال

 $ pip install -r requirements.txt 

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

 junos-eznc netaddr 

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

يدعم Junos PyEZ الاتصال بالمعدات التي تعمل بنظام تشغيل Junos باستخدام وحدة التحكم أو التلنت أو 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 xmlns:junos="http://xml.juniper.net/junos/15.1R1/junos"> <rpc> <get-route-information> </get-route-information> </rpc> </rpc-reply> 

تلقيت بيانات المسار بتنسيق xml ، والتي حددتها فقط تلك التي تهمني بالعلامة <rt-destination> xxx.xxx.xxx.xxx/yy </rt-destination> وكتبتها في متغير كقائمة بتنسيق السلسلة ، وبالتالي حصلت على قائمة شبكات فرعية مشغولة.

 route_list = data.xpath("//rt-destination/text()") 

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

 data = dev.rpc.get_ospf_route_information() 

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


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

 tmp = re.search(r'^%s\S*' % 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'^%s\S*' % 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 

Source: https://habr.com/ru/post/ar481648/


All Articles