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