تسعى مجموعة الوثائق لهذا المنتج جاهدة لاستخدام لغة خالية من التحيز. لأغراض مجموعة الوثائق هذه، يتم تعريف "خالية من التحيز" على أنها لغة لا تعني التمييز على أساس العمر، والإعاقة، والجنس، والهوية العرقية، والهوية الإثنية، والتوجه الجنسي، والحالة الاجتماعية والاقتصادية، والتمييز متعدد الجوانب. قد تكون الاستثناءات موجودة في الوثائق بسبب اللغة التي يتم تشفيرها بشكل ثابت في واجهات المستخدم الخاصة ببرنامج المنتج، أو اللغة المستخدمة بناءً على وثائق RFP، أو اللغة التي يستخدمها منتج الجهة الخارجية المُشار إليه. تعرّف على المزيد حول كيفية استخدام Cisco للغة الشاملة.
ترجمت Cisco هذا المستند باستخدام مجموعة من التقنيات الآلية والبشرية لتقديم محتوى دعم للمستخدمين في جميع أنحاء العالم بلغتهم الخاصة. يُرجى ملاحظة أن أفضل ترجمة آلية لن تكون دقيقة كما هو الحال مع الترجمة الاحترافية التي يقدمها مترجم محترف. تخلي Cisco Systems مسئوليتها عن دقة هذه الترجمات وتُوصي بالرجوع دائمًا إلى المستند الإنجليزي الأصلي (الرابط متوفر).
لا توجد متطلبات خاصة لهذا المستند.
تستند المعلومات الواردة في هذا المستند إلى إصدارات البرامج والمكونات المادية التالية:
switch(config)# feature nxsdk
switch(config)# feature bash-shell
switch(config)# run bash
bash-4.2$ vi /isan/bin/nxsdk-app.py
ملاحظة: أفضل ممارسة هي إنشاء ملفات Python في الدليل /isan/bin/. تحتاج ملفات Python إلى أذونات التنفيذ ليتم تشغيلها - لا تضع ملفات Python في دليل /bootflash أو أي من الدلائل الفرعية الخاصة بها.
ملاحظة: لا يلزم إنشاء ملفات Python وتحريرها من خلال NX-OS. قد يقوم المطور بإنشاء التطبيق باستخدام البيئة المحلية الخاصة به ونقل الملفات المكتملة إلى الجهاز باستخدام بروتوكول نقل الملفات الذي يختاره. ومع ذلك، قد يكون أكثر فعالية للمطور لتصحيح أخطاء البرنامج النصي الخاص به واستكشاف أخطائه وإصلاحها باستخدام أدوات NX-OS المساعدة.
دالة SDKthread
ملاحظة: بدءا من NX-SDK v1.5.0، يمكن تمرير معلمة منطقية ثالثة إلى طريقة NxSdk.getSdkInst، والتي تتيح إستثناءات متقدمة عندما تكون صحيحة وتعطل الاستثناءات المتقدمة عندما تكون خاطئة. تم توثيق هذه الطريقة هنا .
وتتضمن بعض الأساليب الشائعة الاستخدام ما يلي:
ملاحظة: تعمل تنسيقات بيانات R_JSON وR_XML فقط إذا كان الأمر يدعم المخرجات في تلك التنسيقات. في NX-OS، أنت يستطيع دققت ما إذا كان أمر يساند الإنتاج في تنسيق بيانات خاص عن طريق تحويل الإنتاج إلى تنسيق البيانات المطلوب. إذا كان الأمر البيني يرجع مخرجات ذات معنى، عندئذ يكون تنسيق البيانات هذا مدعوما. على سبيل المثال، إذا قمت بتشغيل إظهار ديناميكية جدول عناوين MAC | JSON في NX-OS يرجع إخراج JSON، ثم يكون تنسيق بيانات R_JSON مدعوما في NX-SDK أيضا.
بعض الطرق الاختيارية التي يمكن أن تكون مفيدة:
N9K-C93180LC-EX# show Tra?
track Tracking information
Transceiver_DOM.py Returns all interfaces with DOM-capable transceivers inserted
في تطبيق Python باستخدام NX-SDK، يتم إنشاء أوامر CLI المخصصة وتعريفها ضمن وظيفة sdkThread. هناك نوعان من الأوامر: أوامر show وأوامر config.
تتيح هاتان الطريقتان إنشاء أوامر show و config على التوالي:
ملاحظة: هذا الأمر عبارة عن فئة فرعية من cliP.newCliCmd("cmd_type"، "cmd_name"، "syntax") حيث يكون cmd_type إما CONF_CMD أو SHOW_CMD (استنادا إلى نوع الأمر الذي يتم تكوينه)، CMD_name هو اسم فريد للأمر الداخلي لتطبيق NX-SDK المخصص، وتصفبناء الجملة ما يمكن إستخدامه من كلمات أساسية ومعلمات في الأمر. ولهذا السبب، قد تكون وثائق واجهة برمجة التطبيقات الخاصة بهذا الأمر أكثر فائدة للمرجع.
ملاحظة: هذا الأمر عبارة عن فئة فرعية من cliP.newCliCmd("cmd_type"، "cmd_name"، "syntax") حيث يكون cmd_type إما CONF_CMD أو SHOW_CMD (يعتمد على نوع الأمر الذي تم تكوينه)، cmd_name هو اسم فريد للأمر الداخلي لتطبيق NX-SDK المخصص، وSyntax يصف الكلمات الأساسية والمعلمات التي يمكن إستخدامها في الأمر. ولهذا السبب، قد تكون وثائق واجهة برمجة التطبيقات الخاصة بهذا الأمر أكثر فائدة للمرجع.
يحتوي كلا النوعين من الأوامر على مكونين مختلفين: المعاملات والكلمات الأساسية:
1. المعلمات هي قيم تستخدم لتغيير نتائج الأمر. على سبيل المثال، في الأمر show ip route 192.168.1.0، هناك كلمة أساسية مسار متبوعة بمعلمة تقبل عنوان IP، والتي تحدد أنه يجب عرض الموجهات التي تتضمن عنوان IP المتوفر فقط.
2. تغير الكلمات الأساسية نتائج الأمر من خلال وجودها فقط. على سبيل المثال، في الأمر show mac address-table dynamic، هناك كلمة أساسية ديناميكية، والتي تحدد أن عناوين MAC التي تم التعرف عليها ديناميكيا فقط سيتم عرضها.
يتم تعريف كلا المكونات في صياغة أمر NX-SDK عند إنشائه. توجد طرق للكائن NxCliCmd لتعديل التنفيذ المحدد لكل من المكونات.
لعرض أمثلة التعليمات البرمجية لمكونات الأوامر المستخدمة بشكل شائع، اعرض قسم أمثلة أوامر واجهة سطر الأوامر (CLI) المخصصة في هذا المستند.
بعد إنشاء أوامر CLI المخصصة، يلزم إنشاء كائن من فئة pyCmdHandler الموضحة لاحقا في هذا المستند وتعيينه ككائن معالج رد واجهة سطر الأوامر (CLI) لكائن NxCliParser. ويتضح ذلك على النحو التالي:
cmd_handler = pyCmdHandler()
cliP.setCmdHandler(cmd_handler)
بعد ذلك، يلزم إضافة كائن NxCliParser إلى شجرة محلل واجهة سطر الأوامر (CLI) لنظام التشغيل NX-OS بحيث تكون أوامر واجهة سطر الأوامر (CLI) المخصصة مرئية للمستخدم. ويتم القيام بذلك باستخدام الأمر cliP.addToParseTree()، حيث يكون cliP هو كائن NxCliParser الذي تم إرجاعه بواسطة الأسلوب sdk.getCliParser().
مثال دالة sdkThread
فيما يلي مثال على وظيفة SDKthread نموذجية باستخدام الدوال الموضحة مسبقا. تستخدم هذه الوظيفة (من بين وظائف أخرى ضمن تطبيق بايثون NX-SDK مخصص نموذجي) متغيرات عمومية، والتي يتم إنشاء مثيل لها على تنفيذ البرنامج النصي.
cliP = "" sdk = "" event_hdlr = "" tmsg = "" def sdkThread(): global cliP, sdk, event_hdlr, tmsg sdk = nx_sdk_py.NxSdk.getSdkInst(len(sys.argv), sys.argv) if not sdk: return sdk.setAppDesc("Returns all interfaces with DOM-capable transceivers inserted") tmsg = sdk.getTracer() tmsg.event("[{}] Started service".format(sdk.getAppName())) cliP = sdk.getCliParser() nxcmd = cliP.newShowCmd("show_port_bw_util_cmd", "port bw utilization [<port>]") nxcmd.updateKeyword("port", "Port Information") nxcmd.updateKeyword("bw", "Port Bandwidth Information") nxcmd.updateKeyword("utilization", "Port BW utilization in (%)") nxcmd.updateParam("<port>", "Optional Filter Port Ex) Ethernet1/1", nx_sdk_py.P_INTERFACE) nxcmd1 = cliP.newConfigCmd("port_bw_threshold_cmd", "port bw threshold <threshold>") nxcmd1.updateKeyword("threshold", "Port BW Threshold in (%)") int_attr = nx_sdk_py.cli_param_type_integer_attr() int_attr.min_val = 1; int_attr.max_val = 100; nxcmd1.updateParam("<threshold>", "Threshold Limit. Default 50%", nx_sdk_py.P_INTEGER, int_attr, len(int_attr)) mycmd = pyCmdHandler() cliP.setCmdHandler(mycmd) cliP.addToParseTree() sdk.startEventLoop() # If sdk.stopEventLoop() is called or application is removed from VSH... tmsg.event("Service Quitting...!") nx_sdk_py.NxSdk.__swig_destroy__(sdk)
يتم توريث فئة pyCmdHandler من فئة NxCmdHandler داخل مكتبة nx_sdk_py. يتم إستدعاء الطريقة postCliCb(self، clicmd) المحددة ضمن فئة pyCmdHandler كلما أوامر CLI التي تنشأ من تطبيق NX-SDK. وبالتالي، فإن طريقة postCliCb(self، clicmd) هي المكان الذي تحدد فيه كيفية تصرف أوامر CLI المخصصة المعرفة ضمن دالة sdkThread على الجهاز.
الدالة postCliCb(self، clicmd) ترجع قيمة منطقية. إذا تم إرجاع True، فمن المفترض أن الأمر قد تم تنفيذه بنجاح. يجب إرجاع خطأ إذا لم يتم تنفيذ الأمر بنجاح لأي سبب.
تستخدم المعلمة clicmd الاسم الفريد الذي تم تعريفه للأمر عند إنشائه في دالة sdkThread. على سبيل المثال، إذا قمت بإنشاء أمر عرض جديد باسم فريد من show_xcvr_dom، فمن المستحسن الرجوع إلى هذا الأمر بنفس الاسم في الدالة postCliCb(self، clicmd) بعد التحقق مما إذا كان اسم وسيطة clicmd يحتوي على show_xcvr_dom. وهذا موضح هنا:
def sdkThread(): <snip> sh_xcvr_dom = cliP.newShowCmd("show_xcvr_dom", "dom") sh_xcvr_dom.updateKeyword("dom", "Show all interfaces with transceivers that are DOM-capable") </snip> class pyCmdHandler(nx_sdk_py.NxCmdHandler): def postCliCb(self, clicmd): if "show_xcvr_dom" in clicmd.getCmdName(): get_dom_capable_interfaces()
إذا تم إنشاء أمر يستخدم المعلمات، فستحتاج على الأرجح إلى إستخدام هذه المعلمات عند نقطة ما في وظيفة postCliCb(self، clicmd). ويمكن القيام بذلك باستخدام الطريقة clicmd.getParamValue("<parameter>)، حيث يكون <parameter> هو اسم معلمة الأمر التي ترغب في الحصول على قيمة محاطة بأقواس زاوية (<>). تم توثيق هذه الطريقة هنا. ومع ذلك، يجب تحويل القيمة التي تم إرجاعها بواسطة هذه الدالة إلى النوع الذي تحتاج إليه. ويمكن القيام بذلك باستخدام الأساليب التالية:
كما ستكون وظيفة postCliCb(self، clicmd) (أو أي وظائف تالية) بشكل نموذجي حيث تتم طباعة إخراج أمر show إلى وحدة التحكم. ويتم القيام بذلك باستخدام الأسلوب clicmd.printConsole().
ملاحظة: إذا صادف التطبيق خطأ أو إستثناء غير معالج أو يخرج بشكل مفاجئ، فلن يتم عرض الإخراج من الدالة clicmd.printConsole() على الإطلاق. ولهذا السبب، فإن أفضل ممارسة عند تصحيح أخطاء تطبيق Python هي تسجيل رسائل تصحيح الأخطاء إلى syslog باستخدام كائن NxTrace الذي تم إرجاعه بواسطة الطريقة sdk.getTracer()، أو إستخدام عبارات الطباعة وتنفيذ التطبيق عبر ثنائي BaseShell /isan/bin/python.
مثال فئة PyCmdHandler
تعتبر التعليمات البرمجية التالية مثالا لفئة pyCmdHandler الموضحة أعلاه. تم أخذ هذا الرمز من ملف ip_move.py في تطبيق NX-SDK الخاص ب ip-move المتاح هنا. الغرض من هذا التطبيق هو تعقب حركة عنوان IP المحدد من قبل المستخدم عبر واجهات جهاز Nexus. وللقيام بذلك، يعثر الرمز على عنوان MAC الخاص بإدخال عنوان IP من خلال المعلمة <ip> ضمن ذاكرة تخزين ARP الخاصة بالجهاز، ثم يتحقق من الشبكة المحلية الظاهرية (VLAN) التي يوجد فيها عنوان MAC باستخدام جدول عناوين MAC الخاص بالجهاز. باستخدام MAC وشبكة VLAN هذه، يعرض الأمر show system internal l2fm l2dbg macdb address <mac> vlan <vlan>قائمة بفهارس واجهة SNMP التي تم إقران هذه المجموعة بها مؤخرا. وبعد ذلك، يستخدم الرمز الأمر show interface snmp-ifindex لترجمة فهارس واجهة SNMP الأخيرة إلى أسماء واجهة قابلة للقراءة من قبل الإنسان.
class pyCmdHandler(nx_sdk_py.NxCmdHandler): def postCliCb(self, clicmd): global cli_parser if "show_ip_movement" in clicmd.getCmdName(): target_ip = nx_sdk_py.void_to_string(clicmd.getParamValue("<ip>")) target_mac = get_mac_from_arp(cli_parser, clicmd, target_ip) mac_vlan = "" if target_mac: mac_vlan = get_vlan_from_cam(cli_parser, clicmd, target_mac) if mac_vlan: find_mac_movement(cli_parser, clicmd, target_mac, mac_vlan) else: print("No entires in MAC address table") clicmd.printConsole("No entries in MAC address table for {}".format(target_mac)) else: clicmd.printConsole("No entries in ARP table for {}".format(target_ip)) return True def get_mac_from_arp(cli_parser, clicmd, target_ip): exec_cmd = "show ip arp {}".format(target_ip) arp_cmd = cli_parser.execShowCmd(exec_cmd, nx_sdk_py.R_JSON) if arp_cmd: try: arp_json = json.loads(arp_cmd) except ValueError as exc: return None count = int(arp_json["TABLE_vrf"]["ROW_vrf"]["cnt-total"]) if count: intf = arp_json["TABLE_vrf"]["ROW_vrf"]["TABLE_adj"]["ROW_adj"] if intf.get("ip-addr-out") == target_ip: target_mac = intf["mac"] clicmd.printConsole("{} is currently present in ARP table, MAC address {}\n".format(target_ip, target_mac)) return target_mac else: return None else: return None else: return None def get_vlan_from_cam(cli_parser, clicmd, target_mac): exec_cmd = "show mac address-table address {}".format(target_mac) mac_cmd = cli_parser.execShowCmd(exec_cmd, nx_sdk_py.R_JSON) if mac_cmd: try: cam_json = json.loads(mac_cmd) except ValueError as exc: return None mac_entry = cam_json["TABLE_mac_address"]["ROW_mac_address"] if mac_entry: if mac_entry["disp_mac_addr"] == target_mac: egress_intf = mac_entry["disp_port"] mac_vlan = mac_entry["disp_vlan"] clicmd.printConsole("{} is currently present in MAC address table on interface {}, VLAN {}\n".format(target_mac, egress_intf, mac_vlan)) return mac_vlan else: return None else: return None else: return None def find_mac_movement(cli_parser, clicmd, target_mac, mac_vlan): exec_cmd = "show system internal l2fm l2dbg macdb address {} vlan {}".format(target_mac, mac_vlan) l2fm_cmd = cli_parser.execShowCmd(exec_cmd) if l2fm_cmd: event_re = re.compile(r"^\s+(\w{3}) (\w{3}) (\d+) (\d{2}):(\d{2}):(\d{2}) (\d{4}) (0x\S{8}) (\d+)\s+(\S+) (\d+)\s+(\d+)\s+(\d+)") unique_interfaces = [] l2fm_events = l2fm_cmd.splitlines() for line in l2fm_events: res = re.search(event_re, line) if res: day_name = res.group(1) month = res.group(2) day = res.group(3) hour = res.group(4) minute = res.group(5) second = res.group(6) year = res.group(7) if_index = res.group(8) db = res.group(9) event = res.group(10) src=res.group(11) slot = res.group(12) fe = res.group(13) if "MAC_NOTIF_AM_MOVE" in event: timestamp = "{} {} {} {}:{}:{} {}".format(day_name, month, day, hour, minute, second, year) intf_dict = {"if_index": if_index, "timestamp": timestamp} unique_interfaces.append(intf_dict) if not unique_interfaces: clicmd.printConsole("No entries for {} in L2FM L2DBG\n".format(target_mac)) if len(unique_interfaces) == 1: clicmd.printConsole("{} has not been moving between interfaces\n".format(target_mac)) if len(unique_interfaces) > 1: clicmd.printConsole("{} has been moving between the following interfaces, from most recent to least recent:\n".format(target_mac)) unique_interfaces = get_snmp_intf_index(unique_interfaces) clicmd.printConsole("\t{} - {} (Current interface)\n".format(unique_interfaces[-1]["timestamp"], unique_interfaces[-1]["intf_name"])) for intf in unique_interfaces[-2::-1]: clicmd.printConsole("\t{} - {}\n".format(intf["timestamp"], intf["intf_name"]))
def get_snmp_intf_index(if_index_dict_list): global cli_parser snmp_ifindex = cli_parser.execShowCmd("show interface snmp-ifindex", nx_sdk_py.R_JSON) snmp_ifindex_json = json.loads(snmp_ifindex) snmp_ifindex_list = snmp_ifindex_json["TABLE_interface"]["ROW_interface"] for index_dict in if_index_dict_list: index = index_dict["if_index"] for ifindex_json in snmp_ifindex_list: if index == ifindex_json["snmp-ifindex"]: index_dict["intf_name"] = ifindex_json["interface"] return if_index_dict_list
يعرض هذا القسم بعض الأمثلة لمعلمة الصياغة المستخدمة عند إنشاء أوامر CLI المخصصة باستخدام الأساليب cliP.newShowCmd() أو cliP.newConfigCmd()، حيث يكون cliP هو كائن NxCliParser الذي تم إرجاعه بواسطة الأسلوب sdk.getCliParser().
ملاحظة: يتم تقديم دعم الصياغة مع الأقواس المفتوحة والأقواس المغلقة ("(" و ")") في NX-SDK الإصدار 1.5.0، المضمنة في الإصدار 7.0(3)I7(3) من NX-OS. يفترض أن المستخدم يستخدم NX-SDK v1.5.0 عندما يتبع أي من هذه الأمثلة المحددة التي تتضمن الصياغة باستخدام أقواس الفتح والإغلاق.
هذا عرض يأخذ أمر كلمة المفتاح وحيد ماك ويضيف خيط مساعد من عرض كل سيئ برمجة ماك عنوان على هذا أداة إلى الكلمة المفتاح.
nx_cmd = cliP.newShowCmd("show_misprogrammed", "mac")
nx_cmd.updateKeyword("mac", "Shows all misprogrammed MAC addresses on this device")
يأخذ أمر العرض هذا معلمة واحدة <mac>. تشير الأقواس المتضمنة حول الكلمة mac إلى أن هذه معلمة. تتم إضافة سلسلة مساعد من عنوان MAC للتحقق من عدم برمجة المعلمة بشكل صحيح. يتم إستخدام المعلمة nx_sdk_py.P_MAC_ADDR في الأسلوب nx_cmd.updateParam() لتعريف نوع المعلمة كعنوان MAC، والذي يمنع إدخال المستخدم النهائي من نوع آخر، مثل سلسلة أو عدد صحيح أو عنوان IP.
nx_cmd = cliP.newShowCmd("show_misprogrammed_mac", "<mac>")
nx_cmd.updateParam("<mac>", "MAC address to check for misprogramming", nx_sdk_py.P_MAC_ADDR)
قد يأخذ أمر العرض هذا إختياريا كلمة أساسية واحدة [mac]. تدل الأقواس المتضمنة حول الكلمة mac على أن هذه الكلمة الأساسية إختيارية. تتم إضافة سلسلة مساعد من إظهار جميع عناوين MAC التي تمت برمجتها بشكل غير صحيح على هذا الجهاز إلى الكلمة الأساسية.
nx_cmd = cliP.newShowCmd( "show_misprogrammed_mac" , "[mac]" )
nx_cmd.updateKeyword( "mac" , "Shows all misprogrammed MAC addresses on this device" )
قد يأخذ أمر العرض هذا بشكل إختياري معلمة واحدة [<mac>]. تدل الأقواس المتضمنة حول الكلمة </mac > على أن هذه المعلمة إختيارية. تشير الأقواس المتضمنة حول الكلمة mac إلى أن هذه معلمة. تتم إضافة سلسلة مساعد من عنوان MAC للتحقق من عدم برمجة المعلمة بشكل صحيح. يتم إستخدام المعلمة nx_sdk_py.P_MAC_ADDR في الأسلوب nx_cmd.updateParam() لتعريف نوع المعلمة كعنوان MAC، والذي يمنع إدخال المستخدم النهائي من نوع آخر، مثل سلسلة أو عدد صحيح أو عنوان IP.
nx_cmd = cliP.newShowCmd("show_misprogrammed_mac", "[<mac>]")
nx_cmd.updateParam("<mac>", "MAC address to check for misprogramming", nx_sdk_py.P_MAC_ADDR)
هذا عرض يأخذ أمر وحيد الكلمة المفتاح ماك فورا يتبعه المعلم <mac address>. تشير أقواس الزاوية المتضمنة حول كلمة عنوان MAC إلى أن هذه معلمة. تتم إضافة سلسلة مساعد لعنوان MAC للبرمجة الخاطئة إلى الكلمة الأساسية. تتم إضافة سلسلة مساعد من عنوان MAC للتحقق من عدم برمجة المعلمة بشكل صحيح. يتم إستخدام المعلمة nx_sdk_py.P_MAC_ADDR في الأسلوب nx_cmd.updateParam() لتحديد نوع المعلمة كعنوان MAC، مما يمنع إدخال المستخدم النهائي من نوع آخر، مثل سلسلة أو عدد صحيح أو عنوان IP.
nx_cmd = cliP.newShowCmd("show_misprogrammed", "mac <mac-address>")
nx_cmd.updateKeyword("mac", "Check MAC address for misprogramming")
nx_cmd.updateParam("<mac-address>", "MAC address to check for misprogramming", nx_sdk_py.P_MAC_ADDR)
يمكن أن يأخذ أمر العرض هذا أحد كلمتين رئيسيتين، وكلاهما يحتوي على معلمتين مختلفتين تتبعهما. تحتوي الكلمة الأساسية الأولى mac على معلمة <mac address>، بينما تحتوي الكلمة الأساسية الثانية ip على معلمة <ip-address>. تدل الأقواس المتضمنة حول كلمات عنوان MAC وعنوان IP على أنها معلمات. تتم إضافة سلسلة مساعد من التحقق من عنوان MAC لسوء البرمجة إلى الكلمة الأساسية MAC. تتم إضافة سلسلة مساعد من عنوان MAC للتحقق من عدم برمجة البيانات بشكل صحيح إلى المعلمة <mac address>. يتم إستخدام المعلمة nx_sdk_py.P_MAC_ADDR في الأسلوب nx_cmd.updateParam() لتعريف نوع المعلمة <mac-address> كعنوان MAC، والتي تمنع إدخال المستخدم النهائي من نوع آخر، مثل سلسلة أو عدد صحيح أو عنوان IP. تتم إضافة سلسلة مساعد لعنوان IP للتحقق من عدم برمجة الكلمة الأساسية ip. تتم إضافة سلسلة مساعد لعنوان IP للتحقق من عدم برمجة صحيحة إلى المعلمة <ip-address>. يتم إستخدام المعلمة nx_sdk_py.p_ip_addr في الأسلوب nx_cmd.updateParam() لتعريف نوع المعلمة <ip-address>كعنوان IP، والتي تمنع إدخال المستخدم النهائي من نوع آخر، مثل سلسلة أو عدد صحيح أو عنوان IP.
nx_cmd = cliP.newShowCmd("show_misprogrammed", "(mac <mac-address> | ip <ip-address>)")
nx_cmd.updateKeyword("mac", "Check MAC address for misprogramming")
nx_cmd.updateParam("<mac-address>", "MAC address to check for misprogramming", nx_sdk_py.P_MAC_ADDR)
nx_cmd.updateKeyword("ip", "Check IP address for misprogramming")
nx_cmd.updateParam("<ip-address>", "IP address to check for misprogramming", nx_sdk_py.P_IP_ADDR)
يمكن أن يأخذ أمر العرض هذا أحد كلمتين رئيسيتين، وكلاهما يحتوي على معلمتين مختلفتين تتبعهما. تحتوي الكلمة الأساسية الأولى mac على معلمة <mac address>، بينما تحتوي الكلمة الأساسية الثانية ip على معلمة <ip-address>. تدل الأقواس المتضمنة حول كلمات عنوان MAC وعنوان IP على أنها معلمات. تتم إضافة سلسلة مساعد من التحقق من عنوان MAC لسوء البرمجة إلى الكلمة الأساسية MAC. تتم إضافة سلسلة مساعد من عنوان MAC للتحقق من عدم برمجة البيانات بشكل صحيح إلى المعلمة <mac address>. يتم إستخدام المعلمة nx_sdk_py.P_MAC_ADDR في الأسلوب nx_cmd.updateParam() لتعريف نوع المعلمة <mac-address> كعنوان MAC، والتي تمنع إدخال المستخدم النهائي من نوع آخر، مثل سلسلة أو عدد صحيح أو عنوان IP. تتم إضافة سلسلة مساعد لعنوان IP للتحقق من عدم برمجة الكلمة الأساسية ip. تتم إضافة سلسلة مساعد لعنوان IP للتحقق من عدم برمجة صحيحة إلى المعلمة <ip-address>. يتم إستخدام المعلمة nx_sdk_py.p_ip_addr في الأسلوب nx_cmd.updateParam() لتعريف نوع المعلمة <ip-address>كعنوان IP، والتي تمنع إدخال المستخدم النهائي من نوع آخر، مثل سلسلة أو عدد صحيح أو عنوان IP. قد يأخذ أمر العرض هذا كلمة أساسية [clear] إختياريا. تتم إضافة سلسلة مساعد تمسح العناوين التي تم الكشف عن عدم برمجتها إلى هذه الكلمة الأساسية الاختيارية.
nx_cmd = cliP.newShowCmd("show_misprogrammed", "(mac <mac-address> | ip <ip-address>) [clear]")
nx_cmd.updateKeyword("mac", "Check MAC address for misprogramming")
nx_cmd.updateParam("<mac-address>", "MAC address to check for misprogramming", nx_sdk_py.P_MAC_ADDR)
nx_cmd.updateKeyword("ip", "Check IP address for misprogramming")
nx_cmd.updateParam("<ip-address>", "IP address to check for misprogramming", nx_sdk_py.P_IP_ADDR)
nx_cmd.updateKeyword("clear", "Clears addresses detected to be misprogrammed")
يمكن أن يأخذ أمر العرض هذا أحد كلمتين رئيسيتين، وكلاهما يحتوي على معلمتين مختلفتين تتبعهما. تحتوي الكلمة الأساسية الأولى mac على معلمة <mac address>، بينما تحتوي الكلمة الأساسية الثانية ip على معلمة <ip-address>. تدل الأقواس المتضمنة حول كلمات عنوان MAC وعنوان IP على أنها معلمات. سلسلة مساعد من التحقق من عنوان MAC ل misprogram أضفت إلى الكلمة المفتاح mac. تتم إضافة سلسلة مساعد من عنوان MAC للتحقق من عدم برمجة البيانات بشكل صحيح إلى المعلمة <mac address>. يتم إستخدام المعلمة nx_sdk_py.P_MAC_ADDR في الأسلوب nx_cmd.updateParam() لتعريف نوع المعلمة <mac-address> كعنوان MAC، والتي تمنع إدخال المستخدم النهائي من نوع آخر، مثل سلسلة أو عدد صحيح أو عنوان IP. تتم إضافة سلسلة مساعد لعنوان IP للتحقق من عدم برمجة الكلمة الأساسية ip. تتم إضافة سلسلة مساعد لعنوان IP للتحقق من عدم برمجة صحيحة إلى المعلمة <ip-address>. يتم إستخدام المعلمة nx_sdk_py.p_ip_addr في الأسلوب nx_cmd.updateParam() لتعريف نوع المعلمة <ip-address>كعنوان IP، والتي تمنع إدخال المستخدم النهائي من نوع آخر، مثل سلسلة أو عدد صحيح أو عنوان IP. قد يأخذ أمر العرض هذا بشكل إختياري معلمة [<module>]. تتم إضافة سلسلة مساعد إلى هذه المعلمة الاختيارية وهي تقوم فقط بمسح العناوين الموجودة على الوحدة النمطية المحددة.
nx_cmd = cliP.newShowCmd("show_misprogrammed", "(mac <mac-address> | ip <ip-address>) [<module>]")
nx_cmd.updateKeyword("mac", "Check MAC address for misprogramming")
nx_cmd.updateParam("<mac-address>", "MAC address to check for misprogramming", nx_sdk_py.P_MAC_ADDR)
nx_cmd.updateKeyword("ip", "Check IP address for misprogramming")
nx_cmd.updateParam("<ip-address>", "IP address to check for misprogramming", nx_sdk_py.P_IP_ADDR)
nx_cmd.updateParam("<module>", "Clears addresses detected to be misprogrammed", nx_sdk_py.P_INTEGER)
بمجرد إنشاء تطبيق بايثون NX-SDK، غالبا ما يحتاج إلى تصحيح الأخطاء. يقوم NX-SDK بإعلامك في حالة وجود أي أخطاء في بناء الجملة في الرمز، ولكن نظرا لأن مكتبة Python NX-SDK تستخدم SWIG لترجمة مكتبات C++ إلى مكتبات Python، فإن أي إستثناءات تتم مصادفتها في وقت تنفيذ الرمز ينتج عنها تفريغ أساسي للتطبيق مماثل لما يلي:
terminate called after throwing an instance of 'Swig::DirectorMethodException'
what(): SWIG director method error. Error detected when calling 'NxCmdHandler.postCliCb'
Aborted (core dumped)
نظرا للطبيعة الملتبسة لرسالة الخطأ هذه، فإن أفضل ممارسة لتصحيح أخطاء تطبيقات Python هي تسجيل رسائل تصحيح الأخطاء إلى syslog باستخدام كائن NxTrace الذي تم إرجاعه بواسطة الأسلوب sdk.getTracer(). ويتضح ذلك على النحو التالي:
#! /isan/bin/python tracer = 0 def evt_thread(): <snip> tracer = sdk.getTracer() tracer.event("[NXSDK-APP][INFO] Started service") <snip> class pyCmdHandler(nx_sdk_py.NxCmdHandler): def postCliCb(self, clicmd): global tracer tracer.event("[NXSDK-APP][DEBUG] Received command: {}".format(clicmd)) if "show_test_command" in clicmd.getCmdName(): tracer.event("[NXSDK-APP][DEBUG] `show_test_command` recognized")
إذا لم يكن تسجيل رسائل تصحيح الأخطاء إلى syslog خيارا، فطريقة بديلة هي إستخدام عبارات الطباعة وتنفيذ التطبيق عبر ثنائي BaseShell /isan/bin/python. ومع ذلك، فإن المخرجات من عبارات الطباعة هذه ستكون مرئية فقط عند تنفيذها بهذه الطريقة - تشغيل التطبيق عبر طبقة VSH لا ينتج أي مخرجات. يظهر هنا مثال على إستخدام عبارات الطباعة:
#! /isan/bin/python tracer = 0 def evt_thread(): <snip> print("[NXSDK-APP][INFO] Started service") <snip> class pyCmdHandler(nx_sdk_py.NxCmdHandler): def postCliCb(self, clicmd): print("[NXSDK-APP][DEBUG] Received command: {}".format(clicmd)) if "show_test_command" in clicmd.getCmdName(): print("[NXSDK-APP][DEBUG] `show_test_command` recognized")
بمجرد إختبار تطبيق Python بشكل كامل في طبقة BaseH وتجهيزه للنشر، يجب تثبيت التطبيق في عملية الإنتاج من خلال بروتوكول VSH. وهذا يسمح للتطبيق بالاستمرار عندما يعاد تحميل الجهاز أو عندما يحدث تبديل النظام في سيناريو المشرف المزدوج. لنشر تطبيق من خلال VSH، تحتاج إلى إنشاء حزمة RPM باستخدام بيئة إنشاء NX-SDK و ENXOS SDK. يوفر Cisco DevNet صورة Docker تسمح بإنشاء حزمة RPM بسهولة.
ملاحظة: للحصول على مساعدة لتثبيت Docker على نظام التشغيل الخاص بك، ارجع إلى وثائق تثبيت Docker.
على مضيف قادر على الإرساء، اسحب إصدار الصورة الذي تختاره باستخدام الأمر docker pull dockercisco/nxsdk:<tag> ، حيث <tag> هو علامة تمييز إصدار الصورة التي تختارها. يمكنك عرض إصدارات الصور المتوفرة والعلامات المقابلة لها هنا. وهذا موضح مع العلامة v1 هنا:
docker pull dockercisco/nxsdk:v1
بدء تشغيل حاوية باسم nxsdk من هذه الصورة وارفاقها بها. إذا كانت علامة التمييز التي إخترتها مختلفة، فاستبدل V1 بعلامة التمييز الخاصة بك:
docker run -it --name nxsdk dockercisco/nxsdk:v1 /bin/bash
قم بالتحديث إلى أحدث إصدار من NX-SDK وانتقل إلى دليل NX-SDK، ثم اسحب أحدث الملفات من git:
cd /NX-SDK/
git pull
إذا كنت بحاجة إلى إستخدام إصدار أقدم من NX-SDK، فيمكنك نسخ فرع NX-SDK باستخدام علامة الإصدار المقابلة باستخدام الأمر git clone -b v<version> https://github.com/CiscoDevNet/NX-SDK.git، حيث <version> هو إصدار NX-SDK الذي تحتاج إليه. وهذا موضح هنا مع NX-SDK v1.0.0:
cd /
rm -rf /NX-SDK
git clone -b v1.0.0 https://github.com/CiscoDevNet/NX-SDK.git
بعد ذلك، قم بنقل تطبيق Python إلى حاوية Docker. هناك عدة طرق مختلفة للقيام بذلك.
root@2dcbe841742a:~# exit
[root@localhost ~]# docker cp /app/python_app.py nxsdk:/root/
[root@localhost ~]# docker start nxsdk
nxsdk
[root@localhost ~]# docker attach nxsdk
root@2dcbe841742a:/# ls /root/
python_app.py
ثم أستخدم البرنامج النصي rpm_gen.py الموجود في /NX-SDK/Scripts/ لإنشاء حزمة RPM من تطبيق Python. يحتوي هذا البرنامج النصي على وسيطة مطلوبة واحدة، ومحولين مطلوبين:
ملاحظة: لا يلزم أن يحتوي اسم الملف على أي ملحقات ملفات، مثل .py. في هذا المثال، إذا كان اسم الملف هو python_app بدلا من python_app.py، فسيتم إنشاء حزمة RPM بدون حدوث مشكلة.
ويتم عرض إستخدام برنامج rpm_gen.py النصي هنا.
root@7bfd1714dd2f:~# python /NX-SDK/scripts/rpm_gen.py test_python_app -s /root/ -u #################################################################################################### Generating rpm package... <snip> RPM package has been built #################################################################################################### SPEC file: /NX-SDK/rpm/SPECS/test_python_app.spec RPM file : /NX-SDK/rpm/RPMS/test_python_app-1.0-1.0.0.x86_64.rpm
يتم الإشارة إلى الملف المعد لحزمة RPM في السطر الأخير من مخرجات البرنامج النصي rpm_gen.py. يجب نسخ هذا الملف من حاوية Docker إلى المضيف حتى يمكن نقله إلى جهاز Nexus الذي ترغب في تشغيل التطبيق عليه. بعد الخروج من حاوية Docker، يمكن القيام بذلك بسهولة باستخدام الأمر <container>:<container_filepath> <host_filepath> الذي يحمل <container>اسم حاوية Docker الخاصة ب NX-SDK (في هذه الحالة، nxsdk)، <container_filepath> هو الملف الكامل لحزمة RPM داخل الحاوية (في هذه الحالة، /NX-SDK/rpm/RPMS/test_python_app-1.0-1.0.0.x86_64.rpm)، و<host_ filepath> هو الملف الكامل على مضيف Docker حيث سيتم نقل حزمة RPM إلى (في هذه الحالة، /root/). ويتم توضيح هذا الأمر هنا:
root@7bfd1714dd2f:/# exit [root@localhost ~]# docker cp nxsdk:/NX-SDK/rpm/RPMS/test_python_app-1.0-1.0.0.x86_64.rpm /root/ [root@localhost ~]# ls /root/ anaconda-ks.cfg test_python_app-1.0-1.0.0.x86_64.rpm
قم بنقل حزمة RPM هذه إلى جهاز Nexus باستخدام طريقتك المفضلة لنقل الملفات. بمجرد أن تكون حزمة RPM على الجهاز، يجب تثبيتها وتنشيطها بطريقة مشابهة لوحدة SMU. ويتم توضيح ذلك على النحو التالي، بموجب افتراض نقل حزمة RPM إلى ذاكرة التمهيد الخاصة بالجهاز.
N9K-C93180LC-EX# install add bootflash:test_python_app-1.0-1.0.0.x86_64.rpm [####################] 100% Install operation 27 completed successfully at Tue May 8 06:40:13 2018 N9K-C93180LC-EX# install activate test_python_app-1.0-1.0.0.x86_64 [####################] 100% Install operation 28 completed successfully at Tue May 8 06:40:20 2018
ملاحظة: عند تثبيت حزمة RPM باستخدام الأمر install add، قم بتضمين جهاز التخزين واسم الملف الدقيق للحزمة. عندما تقوم بتنشيط حزمة RPM بعد التثبيت، لا تقم بتضمين جهاز التخزين واسم الملف - أستخدم اسم الحزمة نفسها. يمكنك التحقق من اسم الحزمة باستخدام الأمر show install inactive.
بمجرد تنشيط حزمة RPM، يمكنك بدء التطبيق باستخدام NX-SDK باستخدام أمر تكوين خدمة <application-name>، حيث يكون <application-name>هو اسم اسم اسم ملف Python (وبعد ذلك، التطبيق) الذي تم تعريفه عند إستخدام البرنامج النصي rpm_gen.py سابقا. ويتضح ذلك على النحو التالي:
N9K-C93180LC-EX# conf Enter configuration commands, one per line. End with CNTL/Z. N9K-C93180LC-EX(config)# nxsdk service-name test_python_app % This could take some time. "show nxsdk internal service" to check if your App is Started & Runnning
يمكنك التحقق من تشغيل التطبيق وبدء تشغيله باستخدام الأمر show nxsdk internal service:
N9K-C93180LC-EX# show nxsdk internal service NXSDK Started/Temp unavailabe/Max services : 1/0/32 NXSDK Default App Path : /isan/bin/nxsdk NXSDK Supported Versions : 1.0 Service-name Base App Started(PID) Version RPM Package ------------------------- --------------- ----------------- ---------- ------------------------ test_python_app nxsdk_app4 VSH(23195) 1.0 test_python_app-1.0-1.0.0.x86_64
يمكنك أيضا التحقق من إمكانية الوصول إلى أوامر CLI المخصصة التي تم إنشاؤها بواسطة هذا التطبيق في NX-OS:
N9K-C93180LC-EX# show test? test_python_app Nexus Sdk Application