Update O-RU Fronthaul Recovery usecase
[nonrtric.git] / test / usecases / oruclosedlooprecovery / scriptversion / simulators / sdnr_simulator.py
1
2 #  ============LICENSE_START===============================================
3 #  Copyright (C) 2021 Nordix Foundation. All rights reserved.
4 #  ========================================================================
5 #  Licensed under the Apache License, Version 2.0 (the "License");
6 #  you may not use this file except in compliance with the License.
7 #  You may obtain a copy of the License at
8 #
9 #       http://www.apache.org/licenses/LICENSE-2.0
10 #
11 #  Unless required by applicable law or agreed to in writing, software
12 #  distributed under the License is distributed on an "AS IS" BASIS,
13 #  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 #  See the License for the specific language governing permissions and
15 #  limitations under the License.
16 #  ============LICENSE_END=================================================
17 #
18
19 from flask import Flask
20 from flask import Response
21 from flask_httpauth import HTTPBasicAuth
22 import json
23 import os
24 import random
25 import requests
26 import threading
27 import time
28
29 # Provides an endpoint for the "UNLOCK" configuration change for an O-DU.
30 # Stores the ID of the O-DU and randomly, after between 0 and 10 seconds, sends an Alarm Notification that clears the
31 # "CUS Link Failure" alarm event to MR.
32 app = Flask(__name__)
33 auth = HTTPBasicAuth()
34
35 mr_host = "http://localhost"
36 mr_port = "3904"
37 MR_PATH = "/events/unauthenticated.SEC_FAULT_OUTPUT"
38
39 # Server info
40 HOST_IP = "::"
41 HOST_PORT = 9990
42 APP_URL = "/rests/data/network-topology:network-topology/topology=topology-netconf/node=<string:o_du_id>/yang-ext:mount/o-ran-sc-du-hello-world:network-function/distributed-unit-functions=<string:o_du_id2>/radio-resource-management-policy-ratio=rrm-pol-1"
43
44 USERNAME = "admin"
45 PASSWORD = "Kp8bJ4SXszM0WXlhak3eHlcse2gAw84vaoGGmJvUy2U"
46
47 FAULT_ID = "28"
48
49 linkFailureMessage = {
50     "event": {
51         "commonEventHeader": {
52             "domain": "fault",
53             "eventId": "nt:network-topology/nt:topology/nt:node/nt:node-id",
54             "eventName": "fault_O-RAN-RU-Fault_Alarms_CUS_Link_Failure",
55             "eventType": "O-RAN-RU-Fault_Alarms",
56             "sequence": 0,
57             "priority": "High",
58             "reportingEntityId": "SDNR",
59             "reportingEntityName": "",
60             "sourceId": "",
61             "sourceName": "oru1",
62             "startEpochMicrosec": "@timestamp@",
63             "lastEpochMicrosec": "@timestamp@",
64             "nfNamingCode": "",
65             "nfVendorName": "ietf-hardware (RFC8348) /hardware/component[not(parent)][1]/mfg-name",
66             "timeZoneOffset": "+00:00",
67             "version": "4.1",
68             "vesEventListenerVersion": "7.2.1"
69         },
70         "faultFields": {
71             "faultFieldsVersion": "4.0",
72             "alarmCondition": FAULT_ID,
73             "alarmInterfaceA": "o-ran-fm:alarm-notif/fault-source",
74             "eventSourceType": "ietf-hardware (RFC8348) /hardware/component[not(parent)][1]/mfg-model or \"O-RU\"",
75             "specificProblem": "",
76             "eventSeverity": "NORMAL",
77             "vfStatus": "Active",
78             "alarmAdditionalInformation": {
79                 "eventTime": "@eventTime@",
80                 "equipType": "@type@",
81                 "vendor": "@vendor@",
82                 "model": "@model@"
83             }
84         }
85     }
86 }
87
88
89 class AlarmClearThread (threading.Thread):
90
91     def __init__(self, sleep_time, o_du_id):
92         threading.Thread.__init__(self)
93         self.sleep_time = sleep_time
94         self.o_du_id = o_du_id
95
96     def run(self):
97         print(f'Sleeping: {self.sleep_time} before clearing O-DU: {self.o_du_id}')
98         time.sleep(self.sleep_time)
99         msg_as_json = json.loads(json.dumps(linkFailureMessage))
100         msg_as_json["event"]["commonEventHeader"]["sourceName"] = self.o_du_id
101         print("Sedning alarm clear for O-DU: " + self.o_du_id)
102         requests.post(mr_host + ":" + mr_port + MR_PATH, json=msg_as_json);
103
104
105 # I'm alive function
106 @app.route('/',
107     methods=['GET'])
108 def index():
109     return 'OK', 200
110
111
112 @auth.verify_password
113 def verify_password(username, password):
114     if username == USERNAME and password == PASSWORD:
115         return username
116
117
118 @app.route(APP_URL,
119     methods=['PUT'])
120 @auth.login_required
121 def sendrequest(o_du_id, o_du_id2):
122     print("Got request with O-DU ID: " + o_du_id)
123     random_time = int(10 * random.random())
124     alarm_clear_thread = AlarmClearThread(random_time, o_du_id)
125     alarm_clear_thread.start()
126
127     return Response(status=200)
128
129
130 if __name__ == "__main__":
131     if os.getenv("MR-HOST") is not None:
132         mr_host = os.getenv("MR-HOST")
133         print("Using MR Host from os: " + mr_host)
134     if os.getenv("MR-PORT") is not None:
135         mr_port = os.getenv("MR-PORT")
136         print("Using MR Port from os: " + mr_port)
137
138     app.run(port=HOST_PORT, host=HOST_IP)