7cdda0c4a8d537a95eb7f46a1e1c970b792a6366
[sim/a1-interface.git] / near-rt-ric-simulator / src / STD_1.1.3 / main.py
1 #  ============LICENSE_START===============================================
2 #  Copyright (C) 2023 Nordix Foundation. All rights reserved.
3 #  Copyright (C) 2023 OpenInfra Foundation Europe. 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 import connexion
20 import json
21 import sys
22 import os
23 import requests
24
25
26 from pathlib import Path
27 from flask import Flask, escape, request, Response
28 from jsonschema import validate
29 from var_declaration import policy_instances, policy_status, callbacks, forced_settings, policy_fingerprint, hosts_set, app
30 from maincommon import check_apipath, apipath, get_supported_interfaces_response, extract_host_name
31
32 #Constants
33 TEXT_PLAIN='text/plain'
34
35 check_apipath()
36
37 # app is created in var_declarations
38
39 import payload_logging   # app var need to be initialized
40
41 #Check alive function
42 @app.route('/', methods=['GET'])
43 def test():
44
45   return Response("OK", 200, mimetype=TEXT_PLAIN)
46
47 #Return the current and all supported yamls for the this container
48 @app.route('/container_interfaces', methods=['GET'])
49 def container_interfaces():
50
51     return get_supported_interfaces_response()
52
53 #Delete all created instances and status
54 @app.route('/deleteinstances', methods=['POST'])
55 def delete_instances():
56
57   policy_instances.clear()
58   policy_status.clear()
59   callbacks.clear()
60   forced_settings['code']=None
61   forced_settings['delay']=None
62   policy_fingerprint.clear()
63   return Response("All policy instances deleted", 200, mimetype=TEXT_PLAIN)
64
65 #Delete all - all reset
66 #(same as delete_instances but kept to in order to use the same interface as other version of the simulator)
67 @app.route('/deleteall', methods=['POST'])
68 def delete_all():
69   return delete_instances()
70
71 #Set force response for one A1 response
72 #/forceresponse?code=<responsecode>
73 @app.route('/forceresponse', methods=['POST'])
74 def forceresponse():
75
76   try:
77     forced_settings['code']=request.args.get('code')
78   except Exception:
79     forced_settings['code']=None
80   return Response("Force response code: " + str(forced_settings['code']) + " set for one single A1 response", 200, mimetype=TEXT_PLAIN)
81
82 #Set force delay response, in seconds, for all A1 responses
83 #/froceesponse?delay=<seconds>
84 @app.route('/forcedelay', methods=['POST'])
85 def forcedelay():
86
87   try:
88     forced_settings['delay']=request.args.get('delay')
89   except Exception:
90     forced_settings['delay']=None
91   return Response("Force delay: " + str(forced_settings['delay']) + " sec set for all A1 responses", 200, mimetype=TEXT_PLAIN)
92
93
94 #Set status and reason
95 #/status?policyid=<policyid>&status=<status>[&reason=<reason>]
96 @app.route('/status', methods=['PUT'])
97 def setstatus():
98
99   policy_id=request.args.get('policyid')
100   if (policy_id is None):
101     return Response('Parameter <policyid> missing in request', status=400, mimetype=TEXT_PLAIN)
102   if policy_id not in policy_instances.keys():
103     return Response('Policyid: '+policy_id+' not found.', status=404, mimetype=TEXT_PLAIN)
104   status=request.args.get('status')
105   if (status is None):
106     return Response('Parameter <status> missing in request', status=400, mimetype=TEXT_PLAIN)
107   reason=request.args.get('reason')
108   ps = {}
109   ps["enforceStatus"] = status
110   msg="Status set to "+status
111   if (reason is not None):
112     ps["enforceReason"] = reason
113     msg=msg+" and "+reason
114   policy_status[policy_id] = ps
115   msg=msg+" for policy: " + policy_id
116   return Response(msg, 200, mimetype=TEXT_PLAIN)
117
118 #Send status
119 #/status?policyid=<policyid>
120 @app.route('/sendstatus', methods=['POST'])
121 def sendstatus():
122   policyid=request.args.get('policyid')
123   if (policyid is None):
124     return Response('Parameter <policyid> missing in request', status=400, mimetype=TEXT_PLAIN)
125
126   if (policyid not in policy_status.keys()):
127     return Response('Policyid: '+policyid+' not found.', status=404, mimetype=TEXT_PLAIN)
128
129   ps=policy_status[policyid]
130   cb=callbacks[policyid]
131   try:
132     resp=requests.post(cb,json=json.dumps(ps), verify=False) # NOSONAR
133   except Exception:
134     return Response('Post status failed, could not send to: '+str(cb), status=500, mimetype=TEXT_PLAIN)
135   if (resp.status_code<199 & resp.status_code > 299):
136     return Response('Post status failed with code: '+resp.status_code, status=500, mimetype=TEXT_PLAIN)
137
138   data = resp.json()
139   return Response(data, 200, mimetype='application/json')
140
141 #Receive status (only for testing callbacks)
142 #/statustest
143 @app.route('/statustest', methods=['POST', 'PUT'])
144 def statustest():
145   try:
146     data = request.data
147     data = json.loads(data)
148   except Exception:
149     return Response("The status data is corrupt or missing.", 400, mimetype=TEXT_PLAIN)
150
151   return Response(json.dumps(data), 200, mimetype='application/json')
152
153 #Metrics function
154 #Get a named counter
155 @app.route('/counter/<string:countername>', methods=['GET'])
156 def getcounter(countername):
157
158   if (countername == "num_instances"):
159     return Response(str(len(policy_instances)), 200, mimetype=TEXT_PLAIN)
160   elif (countername == "num_types"):
161     return Response("0",200, mimetype=TEXT_PLAIN)
162   elif (countername == "interface"):
163     p=Path(os.getcwd())
164     pp=p.parts
165     return Response(str(pp[len(pp)-1]),200, mimetype=TEXT_PLAIN)
166   elif (countername == "remote_hosts"):
167     hosts=",".join(hosts_set)
168     return str(hosts),200
169   elif (countername == "datadelivery"):
170     return Response(str(0),200, mimetype=TEXT_PLAIN)
171   else:
172     return Response("Counter name: "+countername+" not found.",404, mimetype=TEXT_PLAIN)
173
174 port_number = 2222
175 if len(sys.argv) >= 2:
176   if isinstance(sys.argv[1], int):
177     port_number = sys.argv[1]
178
179 app.add_api('STD_A1.yaml')
180
181 if __name__ == '__main__':
182   app.run(port=port_number, host="127.0.0.1")