In dem Dokumentationssatz für dieses Produkt wird die Verwendung inklusiver Sprache angestrebt. Für die Zwecke dieses Dokumentationssatzes wird Sprache als „inklusiv“ verstanden, wenn sie keine Diskriminierung aufgrund von Alter, körperlicher und/oder geistiger Behinderung, Geschlechtszugehörigkeit und -identität, ethnischer Identität, sexueller Orientierung, sozioökonomischem Status und Intersektionalität impliziert. Dennoch können in der Dokumentation stilistische Abweichungen von diesem Bemühen auftreten, wenn Text verwendet wird, der in Benutzeroberflächen der Produktsoftware fest codiert ist, auf RFP-Dokumentation basiert oder von einem genannten Drittanbieterprodukt verwendet wird. Hier erfahren Sie mehr darüber, wie Cisco inklusive Sprache verwendet.
Cisco hat dieses Dokument maschinell übersetzen und von einem menschlichen Übersetzer editieren und korrigieren lassen, um unseren Benutzern auf der ganzen Welt Support-Inhalte in ihrer eigenen Sprache zu bieten. Bitte beachten Sie, dass selbst die beste maschinelle Übersetzung nicht so genau ist wie eine von einem professionellen Übersetzer angefertigte. Cisco Systems, Inc. übernimmt keine Haftung für die Richtigkeit dieser Übersetzungen und empfiehlt, immer das englische Originaldokument (siehe bereitgestellter Link) heranzuziehen.
In diesem Dokument wird die Fehlerbehebung für EPNM-Benachrichtigungen beschrieben, wenn die REST-API für den Zugriff auf Gerätefehlerinformationen verwendet wird.
Der von Ihnen implementierte Client muss in der Lage sein, die beiden Mechanismen zu verarbeiten und zu abonnieren, die vom Evolved Programmable Network Manager (EPNM) zum Senden von Benachrichtigungen verwendet werden.
Benachrichtigungen benachrichtigen Netzwerkadministratoren und -betreiber über wichtige Ereignisse oder Probleme im Zusammenhang mit dem Netzwerk. Diese Benachrichtigungen tragen dazu bei, dass potenzielle Probleme schnell erkannt und behoben werden, wodurch Ausfallzeiten reduziert und die Netzwerkleistung insgesamt verbessert wird.
EPNM kann verschiedene Methoden verarbeiten, z. B. Benachrichtigungen per E-Mail, SNMP-Traps (Simple Network Management Protocol) an bestimmte Empfänger oder Syslog-Meldungen an externe Syslog-Server. Zusätzlich zu diesen Methoden bietet EPNM auch eine REST-API (Representational State Transfer Application Programming Interface), mit der Informationen zu Bestand, Alarmen, Serviceaktivierung, Vorlagenausführung und Hochverfügbarkeit abgerufen werden können.
API-basierte Benachrichtigungen werden derzeit unter Verwendung von zwei verschiedenen Mechanismen unterstützt:
Alle Benachrichtigungen haben dasselbe Schema und können im JSON- oder XML-Format abgerufen werden.
Standardmäßig sind Alarm- und Bestandsbenachrichtigungen deaktiviert. Um sie zu aktivieren, ändern Sie die restconf-config.properties
Datei wie angegeben (es ist nicht erforderlich, die EPNM-Anwendung neu zu starten):
/opt/CSCOlumos/conf/restconf/restconf-config.properties
epnm.restconf.inventory.notifications.enabled=true
epnm.restconf.alarm.notifications.enabled=true
In der Abbildung führt der Client-Computer einen WebSocket aus und abonniert den EPNM mit einer vordefinierten URL, einer grundlegenden Authentifizierung und über einen sicheren HTTPS-Kanal.
Die WebSocket-Clientbibliothek in Python kann verwendet werden, um ein WebSocket auf dem Clientcomputer zu erstellen.
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})
Mit diesem Code wird ein WebSocket-Client eingerichtet, der EPNM abonniert unter wss://10.122.28.3/restconf/streams/v1/inventory.json.
Es verwendet den Python WebSocket
-Bibliothek, um die Verbindung herzustellen und ein- und ausgehende Nachrichten zu verarbeiten. Das Abonnement kann auch sein (auf der Grundlage der Art der Benachrichtigung, die Sie abonnieren möchten):
/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}
Die Fehlermeldung on_message
, on_error
und on_close
-Funktionen sind Rückruffunktionen, die aufgerufen werden, wenn die WebSocket-Verbindung eine Nachricht empfängt, auf einen Fehler trifft bzw. geschlossen wird. Die Fehlermeldung on_open
-Funktion ist ein Rückruf, der aufgerufen wird, wenn die WebSocket-Verbindung hergestellt und einsatzbereit ist.
Die Fehlermeldung username
und password
-Variablen werden auf die Anmeldeinformationen festgelegt, die für den Zugriff auf den Remoteserver erforderlich sind. Diese Anmeldeinformationen werden dann mit dem base64
-Moduls und wurde den Headern der WebSocket-Anforderung hinzugefügt.
Die Fehlermeldung run_forever
-Methode wird für das WebSocket-Objekt aufgerufen, um die Verbindung zu starten, sie unbegrenzt offen zu halten und auf Meldungen zu warten, die vom Server kommen. Die Fehlermeldung sslopt
-Parameter wird verwendet, um die SSL/TLS-Optionen für die Verbindung zu konfigurieren. Die Fehlermeldung CERT_NONE
deaktiviert die Zertifizierungsvalidierung.
Führen Sie den Code aus, damit WebSocket für den Empfang der Benachrichtigungen bereit ist:
(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!
Mit dieser DB-Abfrage können Sie die Benachrichtigungsabonnements für den Server überprüfen:
ade # ./sql_execution.sh "SELECT * from RstcnfNtfctnsSbscrptnMngr WHERE CONNECTIONTYPE = 'connection-oriented';" > /localdisk/sftp/conn-oriented.txt
Zur besseren Visualisierung der conn-oriented.txt
-Datei (das Ergebnis der DB-Abfrage), können Sie sie mit einem Tool wie aha
(hier wird seine Verwendung auf einem Ubuntu-Computer veranschaulicht):
devasc@labvm:~/tmp$ sudo apt-get install aha
devasc@labvm:~/tmp$ cat conn-oriented.txt | aha > conn-oriented.html
Dann öffnen Sie conn-oriented.html
Datei in einem Browser:
Aus der EPNM-Online-Dokumentation wird nach der Einrichtung die gleiche Verbindung über den gesamten Lebenszyklus der Anwendung aufrechterhalten:
Wenn Sie aus irgendeinem Grund ein bestimmtes Abonnement löschen müssen, können Sie eine HTTP DELETE
Anforderung an die SUBSCRIPTIONID
angegeben in der URL https://
. Beispiele:
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'
Überprüfung von Meldungen, DEBUG-Einträge, show log
, Verwendeter Dateiname, SQL-Ausgaben
Um zu ermitteln, warum ein Client, der einen verbindungsorientierten Mechanismus verwendet, keine richtigen Benachrichtigungen empfängt, können Sie die angegebene DB-Abfrage ausführen und überprüfen, ob das Abonnement vorhanden ist. Wenn es nicht vorhanden ist, bitten Sie den Client-Besitzer, sicherzustellen, dass das Abonnement ausgegeben wird.
In der Zwischenzeit können Sie die DEBUG-Ebene in
com.cisco.nms.nbi.epnm.restconf.notifications.handler.NotificationsHandlerAdapter
So können Sie es abfangen, wenn das Abonnement gesendet wird:
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 .
Nachdem das Abonnement gesendet wurde, können Sie überprüfen, ob ein Eintrag mit der IP-Adresse des WebSocket Clients in
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 -
Überprüfen Sie abschließend noch einmal die DB (beachten Sie, dass der Zeitstempel mit dem Eintrag in
localhost_access_log.txt
).
Das nächste Protokoll zeigt, wann die POST-Abonnementanforderungen gesendet werden:
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
Solange die Verbindung aufrechterhalten wird, wird eine Benachrichtigung vom Typ "push-change-update" vom EPN-M-Server an alle Clients gesendet, die Benachrichtigungen abonniert haben. Das Beispiel zeigt eine der Benachrichtigungen, die vom EPNM gesendet werden, wenn der Hostname eines NCS2k geändert wird:
{ "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" } } } }
Verbindungslose Benachrichtigungen
Als Nächstes wird der Workflow im Fall von
connectionless
Benachrichtigungen:
Ausführen eines REST-Webservice-Python-Clients
Es wird erwartet, dass der Benutzer über einen REST-Webdienst verfügt, der XML- und/oder JSON-Payloads als POST-Anforderung akzeptieren kann. Dieser REST-Dienst ist der Endpunkt, an den der Cisco EPNMDas restconf-Benachrichtigungs-Framework veröffentlicht Benachrichtigungen. Dies ist eine Beispiel für einen auf dem Remote-Computer zu installierenden REST-Webdienst:
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)
Dies ist eine Python Flask-Webanwendung, die einen einzelnen Endpunkt definiert.
/api/posts
die HTTP POST
Anforderungen. Die Fehlermeldung create_post()
-Funktion immer dann aufgerufen, wenn eine HTTP POST
Anforderung erfolgt an /api/posts
.
Innerhalb des create_post()
-Funktion, werden die Daten aus der eingehenden Anforderung unter Verwendung von request.get_json()
, der ein Dictionary der JSON-Nutzlast zurückgibt. Die Nutzlast wird dann mit print(post_data)
für Debugzwecke. Anschließend wird eine Antwortnachricht mit dem Schlüssel erstellt message
und Wert Post created successfully
(im Wörterbuchformat). Diese Antwortnachricht wird dann an den Client mit dem HTTP-Statuscode 201 (erstellt) zurückgegeben.
Die Fehlermeldung
if __name__ == '__main__':
block ist ein standardmäßiges Python-Konstrukt, das überprüft, ob das Skript als Hauptprogramm ausgeführt wird, anstatt als Modul importiert zu werden. Wenn das Skript als Hauptprogramm ausgeführt wird, startet es die Flask-Anwendung und führt sie an der angegebenen IP-Adresse und dem angegebenen Port aus. Die Fehlermeldung debug=True
-Argument aktiviert den Debugmodus, der detaillierte Fehlermeldungen und ein automatisches Neuladen des Servers bereitstellt, wenn Änderungen am Code vorgenommen werden.
Führen Sie das Programm aus, um das
REST
Webdienst:
(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
Abonnement eines verbindungslosen Clients
Der Benutzer abonniert Benachrichtigungen: die
REST
-Dienstendpunkt zusammen mit dem Thema gesendet, um ihn zu abonnieren. In diesem Fall lautet das Thema 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" > }'
Die erwartete Antwort ist eine Antwort aus dem Jahr 2010, zusammen mit den Details aus dem Abonnement im Text der Antwort:
{ "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" } }
Die Liste der Benachrichtigungen, für die der Benutzer mit einer GET-Anforderung abonniert wurde, kann abgerufen werden:
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'
Die Antwort lautet:
{ "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" } ] } } }
Überprüfung von Meldungen, DEBUG-Einträge, show log,
Verwendeter Dateiname, SQL-Ausgaben
Aus der Antwort geht hervor, dass es zwei Abonnements gibt: eines für
all ("push.topic": "all")
und eine für den Bestand ("push.topic": "inventory")
. Sie können dies mit einer Abfrage an die Datenbank bestätigen (beachten Sie, dass der Abonnementtyp 'verbindungslos' ist und die SUBSCRIPTIONID
-Felder entsprechen der Ausgabe des GET
(gelb hervorgehoben):
ade # ./sql_execution.sh "SELECT * from RstcnfNtfctnsSbscrptnMngr WHERE CONNECTIONTYPE = 'connection-less';" > /localdisk/sftp/connectionless.txt
Wenn Sie ein verbindungsloses Abonnement löschen müssen, können Sie eine
HTTP DELETE
-Anfrage mit der Abonnement-ID, die Sie löschen möchten. Angenommen, Sie möchten 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'
Wenn Sie die DB erneut abfragen, wird nur das Abonnement mit
SUBSCRIPTIONID
gleich 7969974728822328535
.
Wenn eine Bestandsänderung erfolgt, druckt der Client die Benachrichtigungen (die vom gleichen Typ sind wie die
connection-oriented
Benachrichtigungen, die im Abschnitt über connected-oriented
Clients), gefolgt von der Antwort 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 -
Schlussfolgerung
In diesem Dokument werden die beiden Typen von API-basierten Benachrichtigungen beschrieben, die in EPNM konfiguriert werden können (
connectionless
und connection-oriented
) werden erläutert und die Beispiele der jeweiligen Clients, die als Basis für Simulationszwecke genutzt werden können, angegeben.
Zugehörige Informationen
Überarbeitung | Veröffentlichungsdatum | Kommentare |
---|---|---|
1.0 |
10-Apr-2023 |
Erstveröffentlichung |