본 제품에 대한 문서 세트는 편견 없는 언어를 사용하기 위해 노력합니다. 본 설명서 세트의 목적상, 편견 없는 언어는 나이, 장애, 성별, 인종 정체성, 민족 정체성, 성적 지향성, 사회 경제적 지위 및 교차성에 기초한 차별을 의미하지 않는 언어로 정의됩니다. 제품 소프트웨어의 사용자 인터페이스에서 하드코딩된 언어, RFP 설명서에 기초한 언어 또는 참조된 서드파티 제품에서 사용하는 언어로 인해 설명서에 예외가 있을 수 있습니다. 시스코에서 어떤 방식으로 포용적인 언어를 사용하고 있는지 자세히 알아보세요.
Cisco는 전 세계 사용자에게 다양한 언어로 지원 콘텐츠를 제공하기 위해 기계 번역 기술과 수작업 번역을 병행하여 이 문서를 번역했습니다. 아무리 품질이 높은 기계 번역이라도 전문 번역가의 번역 결과물만큼 정확하지는 않습니다. Cisco Systems, Inc.는 이 같은 번역에 대해 어떠한 책임도 지지 않으며 항상 원본 영문 문서(링크 제공됨)를 참조할 것을 권장합니다.
이 문서에서는 REST API를 사용하여 디바이스 결함 정보에 액세스하는 경우 EPNM 알림 문제를 해결하는 방법에 대해 설명합니다.
구현하는 클라이언트는 알림을 전송하기 위해 EPNM(Evolved Programmable Network Manager)에서 사용되는 두 가지 메커니즘 중 하나를 처리하고 가입할 수 있어야 합니다.
알림은 네트워크 관리자와 운영자에게 네트워크와 관련된 중요한 이벤트 또는 문제에 대해 알립니다. 이러한 알림은 잠재적인 문제를 신속하게 탐지 및 해결하여 다운타임을 줄이고 전체적인 네트워크 성능을 향상시킵니다.
EPNM은 전자 메일을 통한 알림, 지정된 수신자에 대한 SNMP(Simple Network Management Protocol) 트랩 또는 외부 Syslog 서버에 대한 Syslog 메시지 등 다양한 방법을 처리할 수 있습니다. EPNM은 이러한 방법 외에도 인벤토리, 알람, 서비스 활성화, 템플릿 실행 및 고가용성에 대한 정보를 검색하기 위해 사용할 수 있는 REST API(Representational State Transfer Application Programming Interface)를 제공합니다.
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을 실행하고 기본 인증과 보안 HTTPS 채널을 통해 미리 정의된 URL로 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})
이 코드는 EPNM에 가입하는 WebSocket 클라이언트를 설정합니다. 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!
다음 DB 쿼리로 서버에 대한 알림 등록을 확인할 수 있습니다.
ade # ./sql_execution.sh "SELECT * from RstcnfNtfctnsSbscrptnMngr WHERE CONNECTIONTYPE = 'connection-oriented';" > /localdisk/sftp/conn-oriented.txt
Cisco의 Advanced Threat Defense conn-oriented.txt 파일(DB 쿼리의 결과)은 다음과 같은 도구를 사용하여 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 쿼리를 실행하고 구독이 있는지 여부를 확인할 수 있습니다. 없는 경우 클라이언트 소유자에게 서브스크립션을 발급하도록 요청합니다.
그 동안 DEBUG 레벨을 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
연결이 활성 상태로 유지되는 한 push-change-update 유형의 알림이 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 웹 서비스 Python 클라이언트 실행사용자는 XML 및/또는 JSON 페이로드를 POST 요청으로 수락할 수 있는 REST 웹 서비스를 사용해야 합니다. 이 REST 서비스는 Cisco EPNMrestconf 알림 프레임워크는 알림을 게시합니다. 이는 원격 시스템에 설치할 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 ISE를 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 웹 서비스:
(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 삭제할 서브스크립션 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 -
결론이 문서에서는 EPNM에서 구성할 수 있는 두 가지 유형의 API 기반 알림(connectionless및 connection-oriented)에 대해 설명하고 시뮬레이션을 위한 기반으로 사용할 수 있는 각 클라이언트의 예를 들어 보겠습니다.
관련 정보
| 개정 | 게시 날짜 | 의견 |
|---|---|---|
1.0 |
10-Apr-2023
|
최초 릴리스 |
피드백