المحتويات

المقدمة

معلومات أساسية

إعلامات API ل EPNM

تكوين EPNM الأساسي

الإعلامات الموجهة للاتصال

تشغيل عميل Python لمآخذ ويب

اشتراك عميل موجه للاتصال

التحقق من الرسائل، إدخالات تصحيح الأخطاء، سجل العرض، اسم الملف المستخدم، مخرجات SQL

إعلامات بلا اتصال

تشغيل عميل REST WebService Python

اشتراك عميل بدون اتصال

التحقق من الرسائل، إدخالات تصحيح الأخطاء، سجل العرض، اسم الملف المستخدم، مخرجات SQL

القرار

معلومات ذات صلة

المقدمة

يوضح هذا المستند كيفية أستكشاف أخطاء EPNM وإصلاحها عند إستخدام REST API للوصول إلى معلومات أخطاء الجهاز.

معلومات أساسية

يجب أن يكون العميل الذي تقوم بتنفيذه قادرا على التعامل والاشتراك في أي من الآليتين اللتين يستخدمهما مدير الشبكة المتطورة القابلة للبرمجة (EPNM) لإرسال الإعلامات.

إعلامات API ل EPNM

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

يمكن أن يعالج EPNM أساليب مختلفة، مثل الإعلامات عبر البريد الإلكتروني أو إختبارات بروتوكول إدارة الشبكة البسيط (SNMP) لأجهزة الاستقبال المحددة أو رسائل syslog إلى خوادم syslog الخارجية. وبالإضافة إلى هذه الأساليب، يوفر برنامج إدارة الشبكات الحاسوبية أيضا واجهة برمجة تطبيقات نقل الدولة التمثيلية (REST API) يمكن إستخدامها من أجل إسترداد المعلومات المتعلقة بالمخزون والتنبيهات وتنشيط الخدمة وتنفيذ القوالب والتوفر العالي.

يتم دعم الإعلامات المستندة إلى واجهة برمجة التطبيقات حاليا باستخدام آليتين مختلفتين:

- الإعلامات الموجهة للاتصال: يشترك العميل في عنوان URL محدد مسبقا ويستخدم عميل WebSocket بمصادقة أساسية من خلال قناة HTTPS آمنة.

- إخطارات دون اتصال: من المتوقع أن يكون لدى المستخدم خدمة REST على ويب قادرة على قبول حمولات لغة الترميز القابلة للتوسيع (XML) و/أو تدوين كائن JavaScript (JSON) كطلب POST.

تشترك كافة الإعلامات في نفس المخطط ويمكن إستردادها بتنسيقات JSON أو XML.

تكوين EPNM الأساسي

بشكل افتراضي، يتم تعطيل إعلامات التنبيه والجرد. ولتمكينها، قم بتغيير restconf-config.properties الملف كما هو مشار إليه (ليس من الضروري إعادة تشغيل تطبيق EPNM):

/opt/CSCOlumos/conf/restconf/restconf-config.properties

epnm.restconf.inventory.notifications.enabled=true

epnm.restconf.alarm.notifications.enabled=true

الإعلامات الموجهة للاتصال

في الصورة، يقوم جهاز العميل بتشغيل WebSocket والاشتراك في EPNM باستخدام URL محدد مسبقا ومصادقة أساسية ومن خلال قناة HTTPS آمنة.

تشغيل عميل Python لمآخذ ويب

يمكن إستخدام مكتبة عميل WebSocket في Python لإنشاء WebSocket في جهاز العميل.

import websocket

import time

import ssl

import base64

def on_message(ws, message):

print(message)

def on_error(ws, error):

print(error)

def on_close(ws, close_status_code, close_msg):

print("### closed \###")

def on_open(ws):

ws.send("Hello, Server!")

if __name__ == "__main__":

username = "username"

password = "password"

credentials = base64.b64encode(f"{username}:{password}".encode("utf-8")).decode("utf-8")

headers = {"Authorization": f"Basic {credentials}"}

websocket.enableTrace(True)

ws = websocket.WebSocketApp("wss://10.122.28.3/restconf/streams/v1/inventory.json",

on_message=on_message,

on_error=on_error,

on_close=on_close,

header=headers)

ws.on_open = on_open

ws.run_forever(sslopt={"cert_reqs": ssl.CERT_NONE})

اشتراك عميل موجه للاتصال

يقوم هذا الرمز بإعداد عميل WebSocket الذي يشترك في EPNM على  wss://10.122.28.3/restconf/streams/v1/inventory.json. انه يستخدم بايثون  WebSocketمكتبة لإنشاء الاتصال ومعالجة الرسائل الواردة والمخرجة. يمكن أن يكون الاشتراك (على أساس نوع الإعلام الذي ترغب في الاشتراك فيه):

- /restconf/streams/v1/alarm{.xml | .json}

- /restconf/streams/v1/service-activation{.xml | .json}

- /restconf/streams/v1/template-execution{.xml | .json}

- /restconf/streams/v1/all{.xml | .json}

يعرض الأمر  on_message، on_error و on_close الدالات هي وظائف رد الاتصال التي يتم استدعاؤها عند تلقي اتصال WebSocket رسالة أو مواجهة خطأ أو إغلاقه على التوالي. يعرض الأمر  on_open الدالة هي رد اتصال يتم استدعاؤه عند تأسيس اتصال WebSocket وجاهزية للاستخدام.

يعرض الأمر  username  و  password  تم تعيين المتغيرات على بيانات اعتماد تسجيل الدخول المطلوبة للوصول إلى الخادم البعيد. يتم بعد ذلك تشفير بيانات الاعتماد هذه باستخدام  base64  تمت إضافة الوحدة النمطية إلى رؤوس طلب WebSocket.

يعرض الأمر  run_forever  يتم إستدعاء الأسلوب على كائن WebSocket لبدء الاتصال، وإبقائه مفتوحا إلى أجل غير مسمى، والاستماع للرسائل التي تأتي من الخادم. يعرض الأمر  sslopt تستخدم المعلمة لتكوين خيارات SSL/TLS للاتصال. يعرض الأمر  CERT_NONE تقوم العلامة بتعطيل التحقق من صحة الاعتماد.

قم بتشغيل الرمز لجعل WebSocket جاهزا لتلقي الإعلامات:

(env) devasc@labvm:~/epnm$ python conn-oriented.py

--- request header ---

GET /restconf/streams/v1/inventory.json HTTP/1.1

Upgrade: websocket

Host: 10.122.28.3

Origin: https://10.122.28.3

Sec-WebSocket-Key: YYYYYYYYYYY

Sec-WebSocket-Version: 13

Connection: Upgrade

Authorization: Basic XXXXXXXXXXXX

-----------------------

--- response header ---

HTTP/1.1 101

Set-Cookie: JSESSIONID=5BFB68B0126226A0A13ABE595DC63AC9; Path=/restconf; Secure; HttpOnly

Strict-Transport-Security: max-age=31536000;includeSubDomains

X-Content-Type-Options: nosniff

X-XSS-Protection: 1; mode=block

Upgrade: websocket

Connection: upgrade

Sec-WebSocket-Accept: Ozns7PGgHjrXj0nAgnlhbyVKPjc=

Date: Thu, 30 Mar 2023 16:18:19 GMT

Server: Prime

-----------------------

Websocket connected

++Sent raw: b'\x81\x8es\x99ry;\xfc\x1e\x15\x1c\xb5R*\x16\xeb\x04\x1c\x01\xb8'

++Sent decoded: fin=1 opcode=1 data=b'Hello, Server!'

++Rcv raw: b'\x81\x0eHello, Server!'

++Rcv decoded: fin=1 opcode=1 data=b'Hello, Server!'

Hello, Server!

يمكنك التحقق من اشتراكات الإعلام للخادم باستخدام استعلام قاعدة البيانات هذا:

ade # ./sql_execution.sh "SELECT * from RstcnfNtfctnsSbscrptnMngr WHERE CONNECTIONTYPE = 'connection-oriented';" > /localdisk/sftp/conn-oriented.txt

من أجل تصور أفضل conn-oriented.txt ملف (والذي هو نتيجة استعلام DB)، يمكنك تحويله إلى HTML باستخدام أداة مثل aha (هنا يتضح إستخدامه في جهاز أوبونتو):

devasc@labvm:~/tmp$ sudo apt-get install aha

devasc@labvm:~/tmp$ cat conn-oriented.txt | aha > conn-oriented.html

ثم افتحوا conn-oriented.html ملف في متصفح:

من وثائق EPNM عبر الإنترنت، بمجرد إنشائها، يتم الحفاظ على نفس الاتصال حيا طوال دورة حياة التطبيق:

- إلى أن يتم قطع اتصال العميل بالخادم

- إلى أن يتعطل الخادم إما للصيانة أو أثناء تجاوز الفشل

إذا احتجت، لسبب ما، إلى حذف اشتراك محدد، يمكنك إرسال اشتراك HTTP DELETE طلب مع  SUBSCRIPTIONID  محدد في URL https://

. على سبيل المثال:

devasc@labvm:~/tmp$ curl --location --insecure --request DELETE 'https://10.122.28.3/restconf/data/v1/cisco-notifications:subscription/3648313822269611499' \ > --header 'Accept: application/json' \ > --header 'Content-Type: application/json' \ > --header 'Authorization: Basic XXXXXXXX'

التحقق من الرسائل، إدخالات تصحيح الأخطاء، show log، اسم الملف المستخدم، مخرجات SQL

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

في هذه الأثناء، يمكنك تمكين مستوى تصحيح الأخطاء في  com.cisco.nms.nbi.epnm.restconf.notifications.handler.NotificationsHandlerAdapter علشان تلحق كلما تم إرسال الاشتراك:

ade # sudo /opt/CSCOlumos/bin/setLogLevel.sh com.cisco.nms.nbi.epnm.restconf.notifications.handler.NotificationsHandlerAdapter DEBUG 2>/dev/null Loglevel set to DEBUG for com.cisco.nms.nbi.epnm.restconf.notifications.handler.NotificationsHandlerAdapter .

بعد إرسال الاشتراك، يمكنك التحقق من ظهور إدخال بعنوان IP الخاص بعميل WebSocket في localhost_access_log.txt:

ade # zgrep -h '"GET /restconf/streams/.* HTTP/1.1" 101' $(ls -1t /opt/CSCOlumos/logs/localhost_access_log.txt*) 10.82.244.205 - - [28/Aug/2023:16:13:03 -0300] "GET /restconf/streams/v1/inventory.json HTTP/1.1" 101 - 10.82.244.205 - - [28/Aug/2023:22:17:05 -0300] "GET /restconf/streams/v1/inventory.json HTTP/1.1" 101 -

أخيرا، تحقق مرة أخرى من DB (لاحظ أن الطابع الزمني يطابق الإدخال في  localhost_access_log.txt).

يظهر السجل التالي عند إرسال طلبات POST للاشتراكات:

ade # grep -Eh 'DEBUG com.cisco.nms.nbi.epnm.restconf.notifications.handler.NotificationsHandlerAdapter - (Successfully subscribed a connection-oriented|Requested resource uuid)' $(ls -1t /opt/CSCOlumos/logs/restconf-nbi.log*) 2023-08-28 22:17:06,221: DEBUG com.cisco.nms.nbi.epnm.restconf.notifications.handler.NotificationsHandlerAdapter - Successfully subscribed a connection-oriented subscription with user: root and topic: inventory 2023-08-28 22:17:06,221: DEBUG com.cisco.nms.nbi.epnm.restconf.notifications.handler.NotificationsHandlerAdapter - Successfully subscribed a connection-oriented subscription with user: root and topic: inventory 2023-08-28 22:17:06,221: DEBUG com.cisco.nms.nbi.epnm.restconf.notifications.handler.NotificationsHandlerAdapter - Requested resource uuid 852a674a-e3d0-4ecc-8ea0-787af30f1305 2023-08-28 22:17:06,221: DEBUG com.cisco.nms.nbi.epnm.restconf.notifications.handler.NotificationsHandlerAdapter - Requested resource uuid 852a674a-e3d0-4ecc-8ea0-787af30f1305

طالما تم الحفاظ على الاتصال حيا، يتم إرسال إعلام من النوع push-change-update من خادم EPN-M إلى جميع العملاء الذين اشتركوا في الإعلامات. يوضح المثال أحد الإعلامات التي يتم إرسالها بواسطة EPNM عند تغيير اسم المضيف الخاص ب NCS2k:

{ "push.push-change-update":{ "push.notification-id":2052931975556780123, "push.topic":"inventory", "push.time-of-update":"2023-03-31 13:50:36.608", "push.time-of-update-iso8601":"2023-03-31T13:50:39.681-03:00", "push.operation":"push:modify", "push.update-data":{ "nd.node":{ "nd.description":"SOFTWARE=ONS,IPADDR=10.10.1.222,IPMASK=255.255.255.0,DEFRTR=255.255.255.255,IPV6ENABLE=N,IIOPPORT=57790,NAME=\\"tcc222c\\",SWVER=11.1.23,LOAD=11.123-022-D2911-W,PROTSWVER=none,PROTLOAD=none,DEFDESC=\\"Factory Defaults\\",PLATFORM=NCS2KFS-M15,SECUMODE=NORMAL,SUPPRESSIP=NO,MODE=MULTISHELF,AUTOPM=NO,SERIALPORTECHO=N,OSIROUTINGMODE=IS1,OSIL1BUFSIZE=512,NET=39840F800000000000000000000E67AD8A01DE00,SYSTEMMODE=SONET,ALARMSUPPRESS=N,CVSTATUS=VERIFICATION_IDLE,DEGILTHR=1.5,FAILILTHR=4.0,LATITUDE=N381343,LONGITUDE=W1223808,LCDSETTING=ALLOW-CONFIGURATION,NODEID=AD8A01DE,NODECVSTATUS=TRUE,ENABLESOCKSPROXY=FALSE,PROXYPORT=1080,ALARMPROFILENAME=\\"Default\\",COOLINGPROFILECTRL=AUTO,MACADDR=0e-67-ffffffad-ffffff8a-01-ffffffde,SUBNETMASKLEN=24,FORWARDDHCPENABLE=N,UPTIME=\\"217days\/14hours\/40mins\/17secs\\",DISCARDOTDRALARM=YES,CVTIMEBTWRUN=360", "nd.equipment-list":"", "nd.fdn":"MD=CISCO_EPNM!ND=tcc222c", "nd.sys-up-time":"217 days, 14:40:170.00" } } } }

إعلامات بلا اتصال

التالي هو سير العمل في حالة connectionless إخطارات:

تشغيل عميل REST WebService Python

من المتوقع أن يكون لدى المستخدم خدمة REST على ويب قادرة على قبول حمولات XML و/أو JSON كطلب POST. خدمة REST هذه هي نقطة النهاية التي Cisco EPNMيقوم إطار عمل إعلامات إعادة الاتصال بنشر الإعلامات. هذا هو مثال على خدمة REST عبر الويب ليتم تثبيتها في الجهاز البعيد:

from flask import Flask, request, jsonify app = Flask(__name__) @ app.route('/api/posts', methods=['POST']) def create_post(): post_data = request.get_json() response = {'message': 'Post created successfully'} print(post_data) return jsonify(response), 201 if __name__ == '__main__': app.run(debug=True, host='10.122.28.2', port=8080)

هذا تطبيق ويب Python Flask الذي يحدد نقطة نهاية واحدة /api/posts تقبل  HTTP POST الطلبات. يعرض الأمر  create_post()   الدالة تسمى كلما HTTP POST تم تقديم طلب إلى  /api/posts. داخل create_post() الدالة، البيانات من الطلب الذي يأتي في يتم إستردادها باستخدام request.get_json()الذي يرجع قاموسا لحمولة JSON. ثم تتم طباعة الحمولة باستخدام print(post_data) لأغراض تصحيح الأخطاء. وبعد ذلك، يتم إنشاء رسالة إستجابة باستخدام المفتاح message وقيمة Post created successfully (بتنسيق القاموس). يتم بعد ذلك إرجاع رسالة الاستجابة هذه إلى العميل الذي يحتوي على رمز حالة HTTP رقم 201 (تم إنشاؤه).

يعرض الأمر  if __name__ == '__main__': الكتلة هي بناء بيثون قياسي يتحقق مما إذا كان البرنامج النصي يعمل كبرنامج رئيسي، بدلا من أن يتم إدراجه كوحدة نمطية. إذا كان البرنامج النصي يعمل كبرنامج رئيسي، فإنه يبدأ تطبيق Flask ويتشغيله على عنوان IP ومنفذ محدد. يعرض الأمر debug=True تمكن الوسيطة وضع تصحيح الأخطاء، الذي يوفر رسائل خطأ تفصيلية وإعادة تحميل الخادم تلقائيا عند إجراء تغييرات على الرمز.

تشغيل البرنامج لبدء REST  خدمة الإنترنت:

(venv) [apinelli@centos8_cxlabs_spo app]$ python connectionless.py * Serving Flask app 'connectionless' (lazy loading) * Environment: production WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. * Debug mode: on * Running on http://10.122.28.2:8080/ (Press CTRL+C to quit) * Restarting with stat * Debugger is active! * Debugger PIN: 117-025-064

اشتراك عميل بدون اتصال

يشترك المستخدم في الإعلامات: RESTيتم إرسال نقطة نهاية الخدمة مع الموضوع للاشتراك فيه. في هذه الحالة، الموضوع هو all.

[apinelli@centos8_cxlabs_spo ~]$ curl --location -X POST --insecure 'https://10.122.28.3/restconf/data/v1/cisco-notifications:subscription' \ > --header 'Accept: application/json' \ > --header 'Content-Type: application-json' \ > --header 'Authorization: Basic XXXXXXXXX' \ > --data '{ > "push.endpoint-url":"http://10.122.28.2:8080/api/posts", > "push.topic":"all", > "push.format": "json" > }'

الاستجابة المتوقعة هي 201 إستجابة مع التفاصيل من الاشتراك في نص الرد:

{ "push.notification-subscription": { "push.subscription-id": 7969974728822328535, "push.subscribed-user": "root", "push.endpoint-url": "http:\/\/10.122.28.2:8080\/api\/posts", "push.topic": "all", "push.creation-time": "Tue Aug 29 10:02:05 BRT 2023", "push.creation-time-iso8601": "2023-08-29T10:02:05.887-03:00", "push.time-of-update": "Tue Aug 29 10:02:05 BRT 2023", "push.time-of-update-iso8601": "2023-08-29T10:02:05.887-03:00", "push.format": "json", "push.connection-type": "connection-less" } }

من الممكن الحصول على قائمة بالإعلامات التي اشترك فيها المستخدم مع طلب GET:

curl --location --insecure 'https://10.122.28.3/restconf/data/v1/cisco-notifications:subscription' \ --header 'Accept: application/json' \ --header 'Content-Type: application/json' \ --header 'Authorization: Basic XXXXXXXXXXX'

وكانت النتيجة كما يلي:

{ "com.response-message": { "com.header": { "com.firstIndex": 0, "com.lastIndex": 1 }, "com.data": { "push.notification-subscription": [ { "push.subscription-id": 2985507860170167151, "push.subscribed-user": "root", "push.endpoint-url": "http://10.122.28.2:8080/api/posts", "push.session-id": 337897630, "push.topic": "inventory", "push.creation-time": "Fri Mar 31 17:45:47 BRT 2023", "push.time-of-update": "Fri Mar 31 17:45:47 BRT 2023", "push.format": "json", "push.connection-type": "connection-less" }, { "push.subscription-id": 7969974728822328535, "push.subscribed-user": "root", "push.endpoint-url": "http://10.122.28.2:8080/api/posts", "push.session-id": 0, "push.topic": "all", "push.creation-time": "Tue Aug 29 10:02:05 BRT 2023", "push.time-of-update": "Tue Aug 29 10:02:05 BRT 2023", "push.format": "json", "push.connection-type": "connection-less" } ] } } }

التحقق من الرسائل، إدخالات تصحيح الأخطاء، show log, اسم الملف المستخدم، مخرجات SQL

إخطار من الاستجابة بأن هناك اشتراكين: أحدهما من أجل all ("push.topic": "all") وواحد للمخزون ("push.topic": "inventory"). يمكنك تأكيدها باستخدام استعلام في قاعدة البيانات (لاحظ أن نوع الاشتراك 'لا يوجد اتصال' و SUBSCRIPTIONID تطابق الحقول مخرجات GET أمر كما هو مبرز في الأصفر):

ade # ./sql_execution.sh "SELECT * from RstcnfNtfctnsSbscrptnMngr WHERE CONNECTIONTYPE = 'connection-less';" > /localdisk/sftp/connectionless.txt

إذا كنت بحاجة إلى حذف اشتراك بدون اتصال، فيمكنك إرسال اشتراك HTTP DELETE طلب بمعرف الاشتراك الذي تريد حذفه. افترض أنك تريد الحذف subscription-id 2985507860170167151:

curl --location --insecure --request DELETE 'https://10.122.28.3/restconf/data/v1/cisco-notifications:subscription/2985507860170167151' \ --header 'Accept: application/json' \ --header 'Content-Type: application-json' \ --header 'Authorization: Basic XXXXXXXXXX'

الآن إذا قمت باستعلام DB مرة أخرى، سترى الاشتراك مع SUBSCRIPTIONID يساوي 7969974728822328535.

عند حدوث تغيير في المخزون، يقوم العميل بطباعة الإعلامات (التي من نفس النوع مثل connection-oriented  الإخطارات التي تم عرضها في القسم حول connected-oriented العملاء)، تليها إستجابة عام 2011:

(venv) [apinelli@centos8_cxlabs_spo app]$ python connectionless.py * Serving Flask app 'connectionless' (lazy loading) * Environment: production WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. * Debug mode: on * Running on http://10.122.28.2:8080/ (Press CTRL+C to quit) * Restarting with stat * Debugger is active! * Debugger PIN: 117-025-064 {'push.push-change-update': {'push.notification-id': -2185938612268228828, 'push.topic': 'inventory', 'push.time-of-update': '2023-03-31 17:47:04.865', 'push.time-of-update-iso8601': '2023-03-31T17:47:10.846-03:00', 'push.operation': 'push:modify', 'push.update-data': {'nd.node': {'nd.collection-status': 'Synchronizing', 'nd.equipment-list': '', 'nd.fdn': 'MD=CISCO_EPNM!ND=tcc221'}}}} 10.122.28.3 - - [31/Mar/2023 16:47:23] "POST /api/posts HTTP/1.1" 201 - {'push.push-change-update': {'push.notification-id': -1634959052215805274, 'push.topic': 'inventory', 'push.time-of-update': '2023-03-31 17:47:12.786', 'push.time-of-update-iso8601': '2023-03-31T17:47:14.935-03:00', 'push.operation': 'push:modify', 'push.update-data': {'nd.node': {'nd.equipment-list': '', 'nd.fdn': 'MD=CISCO_EPNM!ND=tcc221c', 'nd.name': 'tcc221c'}}}} 10.122.28.3 - - [31/Mar/2023 16:47:27] "POST /api/posts HTTP/1.1" 201 -

القرار

في هذا المستند، يمكن تكوين النوعين من الإعلامات المستندة إلى واجهة برمجة التطبيقات (API) في EPNM (connectionlessو connection-oriented) كما يتم توضيح أمثلة عن العملاء المعنيين الذين يمكن إستخدامهم كقاعدة لأغراض المحاكاة.

معلومات ذات صلة

- https://www.cisco.com/c/dam/en/us/td/docs/net_mgmt/epn_manager/RESTConf/Cisco_Evolved_Programmable_Network_Manager_5_1_2_REST_API_Guide.zip

- الدعم التقني والمستندات - Cisco Systems