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