本產品的文件集力求使用無偏見用語。針對本文件集的目的,無偏見係定義為未根據年齡、身心障礙、性別、種族身分、民族身分、性別傾向、社會經濟地位及交織性表示歧視的用語。由於本產品軟體使用者介面中硬式編碼的語言、根據 RFP 文件使用的語言,或引用第三方產品的語言,因此本文件中可能會出現例外狀況。深入瞭解思科如何使用包容性用語。
思科已使用電腦和人工技術翻譯本文件,讓全世界的使用者能夠以自己的語言理解支援內容。請注意,即使是最佳機器翻譯,也不如專業譯者翻譯的內容準確。Cisco Systems, Inc. 對這些翻譯的準確度概不負責,並建議一律查看原始英文文件(提供連結)。
本文檔介紹在使用REST API訪問裝置故障資訊時,如何排除EPNM通知故障。
您執行的客戶端必須能夠處理和訂閱進化的可程式設計網路管理器(EPNM)用來傳送通知的兩種機制中的任何一種。
通知就有關網路的重要事件或問題向網路管理員和操作員發出警報。 這些通知有助於確保快速檢測並解決潛在問題,從而減少停機時間,提高整體網路效能。
EPNM可以處理不同的方法,例如通過電子郵件傳送通知、向指定接收者傳送簡單網路管理協定(SNMP)陷阱或向外部系統日誌伺服器傳送系統日誌消息。除了這些方法外,EPNM還提供一個具代表性的狀態傳輸應用程式設計介面(REST API),可用於檢索有關庫存、警報、服務啟用、模板執行和高可用性的資訊。
目前支援使用兩種不同機制進行基於API的通知:
所有通知都共用相同的架構,可以以JSON或XML格式檢索。
預設情況下,警報和庫存通知處於禁用狀態。若要啟用它們,請更改 restconf-config.properties
檔案(無需重新啟動EPNM應用程式):
/opt/CSCOlumos/conf/restconf/restconf-config.properties
epnm.restconf.inventory.notifications.enabled=true
epnm.restconf.alarm.notifications.enabled=true
在圖片中,客戶端電腦運行WebSocket,並使用預定義的URL、基本身份驗證和通過安全HTTPS通道訂閱EPNM。
Python中的WebSocket-client庫可用於在客戶端電腦中建立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.
它使用Python 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
檔案(即資料庫查詢的結果),您可以使用類似工具將其轉換為HTML aha
(此處在Ubuntu機器中說明了其用途):
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 .
傳送訂閱後,您可以檢查中是否顯示包含WebSocket客戶端IP地址的條目
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
只要連線保持活動狀態,就會從EPN-M伺服器向訂閱通知的所有客戶端傳送推送更改更新型別的通知。此示例顯示當NCS2k的主機名更改時EPNM傳送的一個通知:
{ "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 Web服務Python客戶端
使用者應具有能夠接受XML和/或JSON負載作為POST請求的REST Web服務。此REST服務是 Cisco EPNMrestconf通知框架發佈通知。這是 要在遠端電腦上安裝的REST Web服務示例:
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 Web應用程式,用於定義單個端點
/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__':
block是標準Python構造,檢查指令碼是否作為主程式運行,而不是作為模組匯入。如果指令碼作為主程式運行,它將啟動Flask應用程式並在指定的IP地址和埠上運行該應用程式。其 debug=True
引數啟用調試模式,該模式提供詳細的錯誤消息,並在對代碼進行更改時自動重新載入伺服器。
運行程式以啟動
REST
web服務:
(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" > }'
預期回覆是2011年的回覆,以及回覆正文中訂閱的細節:
{ "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
請求,包含您要刪除的訂閱ID。假設您要刪除 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
客戶端),然後是201響應:
(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
文中給出了各個客戶端的示例,這些客戶端可以作為模擬的依據。
相關資訊
修訂 | 發佈日期 | 意見 |
---|---|---|
1.0 |
10-Apr-2023 |
初始版本 |