Sonar corrections. Unit tests and code coverage added
[sim/a1-interface.git] / near-rt-ric-simulator / src / OSC_2.1.0 / 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 from pathlib import Path
25 from flask import Flask, escape, request, Response, jsonify
26 from jsonschema import validate
27 from var_declaration import policy_instances, policy_types, policy_status, policy_fingerprint, forced_settings, hosts_set
28 from maincommon import check_apipath, apipath, get_supported_interfaces_response, extract_host_name
29 from time import sleep
30
31 #Constants
32 TEXT_PLAIN='text/plain'
33
34 check_apipath()
35
36 app = connexion.FlaskApp(__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 @app.route('/ip', methods=['GET'])
45 def get_ip():
46     if request.environ.get('HTTP_X_FORWARDED_FOR') is None:
47         return jsonify({'ip': request.environ['REMOTE_ADDR']}), 200
48     else:
49         return jsonify({'ip': request.environ['HTTP_X_FORWARDED_FOR']}), 200
50
51 #Return the current and all supported yamls for the this container
52 @app.route('/container_interfaces', methods=['GET'])
53 def container_interfaces():
54
55     return get_supported_interfaces_response()
56
57 #Delete all created instances and status
58 @app.route('/deleteinstances', methods=['POST'])
59 def deleteinstances():
60
61   for i in policy_instances.keys():
62     policy_instances[i]={}
63
64   policy_status.clear()
65   forced_settings.clear()
66   forced_settings['code']=None
67   forced_settings['delay']=None
68   policy_fingerprint.clear()
69   return Response("All policy instances deleted", 200, mimetype=TEXT_PLAIN)
70
71 #Delete all - all reset
72 @app.route('/deleteall', methods=['POST'])
73 def deleteall():
74
75   policy_instances.clear()
76   policy_types.clear()
77   policy_status.clear()
78   forced_settings['code']=None
79   forced_settings['delay']=None
80   policy_fingerprint.clear()
81   return Response("All policy instances and types deleted", 200, mimetype=TEXT_PLAIN)
82
83 #Load a policy type
84 @app.route('/policytype', methods=['PUT'])
85 def policytype():
86
87   policy_type_id=request.args.get('id')
88   if (policy_type_id is None):
89     return Response('Parameter <id> missing in request', status=400, mimetype=TEXT_PLAIN)
90   try:
91     int(policy_type_id)
92   except Exception:
93     return Response("The policy type id is not an int", 400, mimetype=TEXT_PLAIN)
94   try:
95     data = request.data
96     data = json.loads(data)
97   except Exception:
98     return Response("The policy type is corrupt or missing", 400, mimetype=TEXT_PLAIN)
99
100   if ('name' not in data.keys() or 'description' not in data.keys() or 'policy_type_id' not in data.keys() or'create_schema' not in data.keys()):
101     return Response("The policy type missing atributes", 400, mimetype=TEXT_PLAIN)
102
103   retcode=201
104   if (policy_type_id in policy_types.keys()):
105     retcode=200
106     if (len(policy_instances[policy_type_id]) > 0):
107       return Response("The policy type already exists and instances exists", 400, mimetype=TEXT_PLAIN)
108
109   policy_types[policy_type_id]=data
110   policy_instances[policy_type_id]={}
111   return Response("Policy type " + policy_type_id + " is OK.", retcode, mimetype=TEXT_PLAIN)
112
113 #Delete a policy type
114 @app.route('/policytype', methods=['DELETE'])
115 def del_policytype():
116
117   policy_type_id=request.args.get('id')
118   if (policy_type_id is None):
119     return Response('Parameter <id> missing in request', status=400, mimetype=TEXT_PLAIN)
120   try:
121     int(policy_type_id)
122   except Exception:
123     return Response("The policy type id is not an int", 400, mimetype=TEXT_PLAIN)
124
125   if (policy_type_id in policy_types.keys()):
126     if (len(policy_instances[policy_type_id]) > 0):
127       return Response("The policy type already exists and instances exists", 400, mimetype=TEXT_PLAIN)
128
129     del policy_types[policy_type_id]
130     del policy_instances[policy_type_id]
131     return Response("Policy type " + policy_type_id + " is OK.", 204, mimetype=TEXT_PLAIN)
132
133   return Response("Policy type " + policy_type_id + " not found.", 204, mimetype=TEXT_PLAIN)
134
135
136 # Get all policy type ids
137 @app.route('/policytypes', methods=['GET'])
138 def get_policytype_ids():
139
140   return (json.dumps(list(policy_instances.keys())), 200)
141
142 #Set force response for one A1 response
143 #/forceresponse?code=<responsecode>
144 @app.route('/forceresponse', methods=['POST'])
145 def forceresponse():
146
147   try:
148     forced_settings['code']=int(request.args.get('code'))
149   except Exception:
150     forced_settings['code']=None
151   return Response("Force response code: " + str(forced_settings['code']) + " set for one single A1 response", 200, mimetype=TEXT_PLAIN)
152
153 #Set force delay response, in seconds, for all A1 responses
154 #/froceesponse?delay=<seconds>
155 @app.route('/forcedelay', methods=['POST'])
156 def forcedelay():
157
158   try:
159     forced_settings['delay']=int(request.args.get('delay'))
160   except Exception:
161     forced_settings['delay']=None
162   return Response("Force delay: " + str(forced_settings['delay']) + " sec set for all A1 responses", 200, mimetype=TEXT_PLAIN)
163
164
165 #Set status and reason
166 #/status?policyid=<policyid>&status=<status>[&deleted=<boolean>][&created_at=<timestamp>]
167 @app.route('/status', methods=['PUT'])
168 def setstatus():
169
170   policy_id=request.args.get('policyid')
171   if (policy_id is None):
172     return Response('Parameter <policyid> missing in request', status=400, mimetype=TEXT_PLAIN)
173
174   if policy_id not in policy_status.keys():
175     return Response('Policyid: '+policy_id+' not found.', status=404, mimetype=TEXT_PLAIN)
176   status=request.args.get('status')
177   if (status is None):
178     return Response('Parameter <status> missing in request', status=400, mimetype=TEXT_PLAIN)
179   policy_status[policy_id]["instance_status"]=status
180   msg = "Status set to "+status
181   deleted_policy=request.args.get('deleted')
182   if (deleted_policy is not None):
183     policy_status[policy_id]["has_been_deleted"]=deleted_policy
184     msg = msg + " and has_been_deleted set to "+deleted_policy
185   created_at = request.args.get('created_at')
186   if (created_at is not None):
187     policy_status[policy_id]["created_at"]=created_at
188     msg = msg + " and created_at set to "+created_at
189   msg=msg + " for policy: " + policy_id
190   return Response(msg, 200, mimetype=TEXT_PLAIN)
191
192
193 #Metrics function
194 #Get a named counter
195 @app.route('/counter/<string:countername>', methods=['GET'])
196 def getcounter(countername):
197
198   if (countername == "num_instances"):
199     return Response(str(len(policy_fingerprint)), 200, mimetype=TEXT_PLAIN)
200   elif (countername == "num_types"):
201     return Response(str(len(policy_instances)),200, mimetype=TEXT_PLAIN)
202   elif (countername == "interface"):
203     p=Path(os.getcwd())
204     pp=p.parts
205     return Response(str(pp[len(pp)-1]),200, mimetype=TEXT_PLAIN)
206   elif (countername == "remote_hosts"):
207     hosts=",".join(hosts_set)
208     return str(hosts),200
209   else:
210     return Response("Counter name: "+countername+" not found.",404, mimetype=TEXT_PLAIN)
211
212 port_number = 2222
213 if len(sys.argv) >= 2 :
214   if isinstance(sys.argv[1], int):
215     port_number = sys.argv[1]
216
217 app.add_api('openapi.yaml')
218
219 if __name__ == '__main__':
220   app.run(port=port_number, host="127.0.0.1", threaded=False)