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
9 # http://www.apache.org/licenses/LICENSE-2.0
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=================================================
25 from pathlib import Path
26 from flask import Flask, request, Response
27 from jsonschema import validate
28 from var_declaration import policy_instances, policy_types, policy_status, callbacks, forced_settings, policy_fingerprint, hosts_set, data_delivery_counter, app
29 from maincommon import check_apipath, apipath, get_supported_interfaces_response, extract_host_name
32 TEXT_PLAIN='text/plain'
33 APPL_JSON='application/json'
38 # app is created in var_declarations
40 import payload_logging # app var need to be initialized
43 @app.route('/', methods=['GET'])
46 return Response("OK", 200, mimetype=TEXT_PLAIN)
48 #Return the current and all supported yamls for the this container
49 @app.route('/container_interfaces', methods=['GET'])
50 def container_interfaces():
52 return get_supported_interfaces_response()
54 #Delete all created instances and status
55 @app.route('/deleteinstances', methods=['POST'])
56 def delete_instances():
58 for i in policy_instances.keys():
59 policy_instances[i]={}
62 forced_settings['code']=None
63 forced_settings['delay']=None
64 policy_fingerprint.clear()
65 return Response("All policy instances deleted", 200, mimetype=TEXT_PLAIN)
67 #Delete all - all reset
68 @app.route('/deleteall', methods=['POST'])
70 global data_delivery_counter
72 policy_instances.clear()
76 forced_settings['code']=None
77 forced_settings['delay']=None
78 policy_fingerprint.clear()
79 data_delivery_counter=0
80 return Response("All policy instances and types deleted", 200, mimetype=TEXT_PLAIN)
83 @app.route('/policytype', methods=['PUT'])
86 policy_type_id=request.args.get('id')
87 if (policy_type_id is None):
88 return Response('Parameter <id> missing in request', status=400, mimetype=TEXT_PLAIN)
92 data = json.loads(data)
94 return Response("The policy type is corrupt or missing", 400, mimetype=TEXT_PLAIN)
96 if ('policySchema' not in data.keys()):
97 return Response("The policy type atribute policySchema is missing", 400, mimetype=TEXT_PLAIN)
100 if (policy_type_id in policy_types.keys()):
102 if (len(policy_instances[policy_type_id]) > 0):
103 return Response("The policy type already exists and instances exists", 400, mimetype=TEXT_PLAIN)
105 policy_types[policy_type_id]=data
106 policy_instances[policy_type_id]={}
107 return Response("Policy type " + policy_type_id + " is OK.", retcode, mimetype=TEXT_PLAIN)
109 #Delete a policy type
110 @app.route('/policytype', methods=['DELETE'])
111 def del_policytype():
113 policy_type_id=request.args.get('id')
114 if (policy_type_id is None):
115 return Response('Parameter <id> missing in request', status=400, mimetype=TEXT_PLAIN)
117 if (policy_type_id in policy_types.keys()):
118 if (len(policy_instances[policy_type_id]) > 0):
119 return Response("The policy type already exists and instances exists", 400, mimetype=TEXT_PLAIN)
121 del policy_types[policy_type_id]
122 del policy_instances[policy_type_id]
123 return Response("Policy type " + policy_type_id + " is OK.", 204, mimetype=TEXT_PLAIN)
125 return Response("Policy type " + policy_type_id + " not found.", 204, mimetype=TEXT_PLAIN)
128 # Get all policy type ids
129 @app.route('/policytypes', methods=['GET'])
130 def get_policytype_ids():
132 return (json.dumps(list(policy_instances.keys())), 200)
135 #Set force response for one A1 response
136 #/forceresponse?code=<responsecode>
137 @app.route('/forceresponse', methods=['POST'])
141 forced_settings['code']=request.args.get('code')
143 forced_settings['code']=None
144 return Response("Force response code: " + str(forced_settings['code']) + " set for one single A1 response", 200, mimetype=TEXT_PLAIN)
146 #Set force delay response, in seconds, for all A1 responses
147 #/froceesponse?delay=<seconds>
148 @app.route('/forcedelay', methods=['POST'])
152 forced_settings['delay']=request.args.get('delay')
154 forced_settings['delay']=None
155 return Response("Force delay: " + str(forced_settings['delay']) + " sec set for all A1 responses", 200, mimetype=TEXT_PLAIN)
158 #Set status and reason
159 #/status?policyid=<policyid>&status=<status>[&reason=<reason>]
160 @app.route('/status', methods=['PUT'])
163 policy_id=request.args.get('policyid')
164 if (policy_id is None):
165 return Response('Parameter <policyid> missing in request', status=400, mimetype=TEXT_PLAIN)
166 if policy_id not in policy_status.keys():
167 return Response('Policyid: '+policy_id+' not found.', status=404, mimetype=TEXT_PLAIN)
168 status=request.args.get('status')
170 return Response('Parameter <status> missing in request', status=400, mimetype=TEXT_PLAIN)
171 reason=request.args.get('reason')
173 ps["enforceStatus"] = status
174 msg="Status set to "+status
175 if (reason is not None):
176 ps["enforceReason"] = reason
177 msg=msg+" and "+reason
178 policy_status[policy_id] = ps
179 msg=msg+" for policy: " + policy_id
180 return Response(msg, 200, mimetype=TEXT_PLAIN)
183 #/status?policyid=<policyid>
184 @app.route('/sendstatus', methods=['POST'])
186 policyid=request.args.get('policyid')
187 if (policyid is None):
188 return Response('Parameter <policyid> missing in request', status=400, mimetype=TEXT_PLAIN)
190 if (policyid not in policy_status.keys()):
191 return Response('Policyid: '+policyid+' not found.', status=404, mimetype=TEXT_PLAIN)
193 ps=policy_status[policyid]
194 cb=callbacks[policyid]
196 resp=requests.post(cb,json=json.dumps(ps), verify=False) # NOSONAR
198 return Response('Post status failed, could not send to: '+str(cb), status=500, mimetype=TEXT_PLAIN)
199 if (resp.status_code<199 & resp.status_code > 299):
200 return Response('Post status failed with code: '+resp.status_code, status=500, mimetype=TEXT_PLAIN)
202 return Response(None, 204, mimetype=APPL_JSON)
204 #Receive status (only for testing callbacks)
206 @app.route('/statustest', methods=['POST', 'PUT'])
210 data = json.loads(data)
212 return Response("The status data is corrupt or missing.", 400, mimetype=TEXT_PLAIN)
214 return Response(json.dumps(data), 200, mimetype=APPL_JSON)
216 #Receive a data delivery package
218 @app.route('/datadelivery', methods=['POST'])
220 global data_delivery_counter
223 data = json.loads(data)
225 return Response("The data is corrupt or missing.", 400, mimetype=TEXT_PLAIN)
226 data_delivery_counter += 1
227 return Response("", 200, mimetype=TEXT_PLAIN)
231 @app.route('/counter/<string:countername>', methods=['GET'])
232 def getcounter(countername):
234 if (countername == "num_instances"):
235 return Response(str(len(policy_fingerprint)), 200, mimetype=TEXT_PLAIN)
236 elif (countername == "num_types"):
237 return Response(str(len(policy_instances)),200, mimetype=TEXT_PLAIN)
238 elif (countername == "interface"):
241 return Response(str(pp[len(pp)-1]),200, mimetype=TEXT_PLAIN)
242 elif (countername == "remote_hosts"):
243 hosts=",".join(hosts_set)
244 return str(hosts),200
245 elif (countername == "datadelivery"):
246 return Response(str(data_delivery_counter),200, mimetype=TEXT_PLAIN)
248 return Response("Counter name: "+countername+" not found.",404, mimetype=TEXT_PLAIN)
251 if len(sys.argv) >= 2:
252 if isinstance(sys.argv[1], int):
253 port_number = sys.argv[1]
255 app.add_api('ORAN_A1-p_V2.0.0_api.yaml')
257 if __name__ == '__main__':
258 app.run(port=port_number, host="127.0.0.1")