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=================================================
26 from pathlib import Path
27 from flask import Flask, request, Response
28 from jsonschema import validate
29 from var_declaration import policy_instances, policy_types, policy_status, callbacks, forced_settings, policy_fingerprint, hosts_set, data_delivery_counter, app
30 from maincommon import check_apipath, apipath, get_supported_interfaces_response, extract_host_name
33 TEXT_PLAIN='text/plain'
34 APPL_JSON='application/json'
39 # app is created in var_declarations
41 import payload_logging # app var need to be initialized
44 @app.route('/', methods=['GET'])
47 return Response("OK", 200, mimetype=TEXT_PLAIN)
49 #Return the current and all supported yamls for the this container
50 @app.route('/container_interfaces', methods=['GET'])
51 def container_interfaces():
53 return get_supported_interfaces_response()
55 #Delete all created instances and status
56 @app.route('/deleteinstances', methods=['POST'])
57 def delete_instances():
59 for i in policy_instances.keys():
60 policy_instances[i]={}
63 forced_settings['code']=None
64 forced_settings['delay']=None
65 policy_fingerprint.clear()
66 return Response("All policy instances deleted", 200, mimetype=TEXT_PLAIN)
68 #Delete all - all reset
69 @app.route('/deleteall', methods=['POST'])
71 global data_delivery_counter
73 policy_instances.clear()
77 forced_settings['code']=None
78 forced_settings['delay']=None
79 policy_fingerprint.clear()
80 data_delivery_counter=0
81 return Response("All policy instances and types deleted", 200, mimetype=TEXT_PLAIN)
84 @app.route('/policytype', methods=['PUT'])
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)
93 data = json.loads(data)
95 return Response("The policy type is corrupt or missing", 400, mimetype=TEXT_PLAIN)
97 if ('policySchema' not in data.keys()):
98 return Response("The policy type atribute policySchema is missing", 400, mimetype=TEXT_PLAIN)
101 if (policy_type_id in policy_types.keys()):
103 if (len(policy_instances[policy_type_id]) > 0):
104 return Response("The policy type already exists and instances exists", 400, mimetype=TEXT_PLAIN)
106 policy_types[policy_type_id]=data
107 policy_instances[policy_type_id]={}
108 return Response("Policy type " + policy_type_id + " is OK.", retcode, mimetype=TEXT_PLAIN)
110 #Delete a policy type
111 @app.route('/policytype', methods=['DELETE'])
112 def del_policytype():
114 policy_type_id=request.args.get('id')
115 if (policy_type_id is None):
116 return Response('Parameter <id> missing in request', status=400, mimetype=TEXT_PLAIN)
118 if (policy_type_id in policy_types.keys()):
119 if (len(policy_instances[policy_type_id]) > 0):
120 return Response("The policy type already exists and instances exists", 400, mimetype=TEXT_PLAIN)
122 del policy_types[policy_type_id]
123 del policy_instances[policy_type_id]
124 return Response("Policy type " + policy_type_id + " is OK.", 204, mimetype=TEXT_PLAIN)
126 return Response("Policy type " + policy_type_id + " not found.", 204, mimetype=TEXT_PLAIN)
129 # Get all policy type ids
130 @app.route('/policytypes', methods=['GET'])
131 def get_policytype_ids():
133 return (json.dumps(list(policy_instances.keys())), 200)
136 #Set force response for one A1 response
137 #/forceresponse?code=<responsecode>
138 @app.route('/forceresponse', methods=['POST'])
142 forced_settings['code']=request.args.get('code')
144 forced_settings['code']=None
145 return Response("Force response code: " + str(forced_settings['code']) + " set for one single A1 response", 200, mimetype=TEXT_PLAIN)
147 #Set force delay response, in seconds, for all A1 responses
148 #/froceesponse?delay=<seconds>
149 @app.route('/forcedelay', methods=['POST'])
153 forced_settings['delay']=request.args.get('delay')
155 forced_settings['delay']=None
156 return Response("Force delay: " + str(forced_settings['delay']) + " sec set for all A1 responses", 200, mimetype=TEXT_PLAIN)
159 #Set status and reason
160 #/status?policyid=<policyid>&status=<status>[&reason=<reason>]
161 @app.route('/status', methods=['PUT'])
164 policy_id=request.args.get('policyid')
165 if (policy_id is None):
166 return Response('Parameter <policyid> missing in request', status=400, mimetype=TEXT_PLAIN)
167 if policy_id not in policy_status.keys():
168 return Response('Policyid: '+policy_id+' not found.', status=404, mimetype=TEXT_PLAIN)
169 status=request.args.get('status')
171 return Response('Parameter <status> missing in request', status=400, mimetype=TEXT_PLAIN)
172 reason=request.args.get('reason')
174 ps["enforceStatus"] = status
175 msg="Status set to "+status
176 if (reason is not None):
177 ps["enforceReason"] = reason
178 msg=msg+" and "+reason
179 policy_status[policy_id] = ps
180 msg=msg+" for policy: " + policy_id
181 return Response(msg, 200, mimetype=TEXT_PLAIN)
184 #/status?policyid=<policyid>
185 @app.route('/sendstatus', methods=['POST'])
187 policyid=request.args.get('policyid')
188 if (policyid is None):
189 return Response('Parameter <policyid> missing in request', status=400, mimetype=TEXT_PLAIN)
191 if (policyid not in policy_status.keys()):
192 return Response('Policyid: '+policyid+' not found.', status=404, mimetype=TEXT_PLAIN)
194 ps=policy_status[policyid]
195 cb=callbacks[policyid]
197 resp=requests.post(cb,json=json.dumps(ps), verify=False) # NOSONAR
199 return Response('Post status failed, could not send to: '+str(cb), status=500, mimetype=TEXT_PLAIN)
200 if (resp.status_code<199 & resp.status_code > 299):
201 return Response('Post status failed with code: '+resp.status_code, status=500, mimetype=TEXT_PLAIN)
203 return Response(None, 204, mimetype=APPL_JSON)
205 #Receive status (only for testing callbacks)
207 @app.route('/statustest', methods=['POST', 'PUT'])
211 data = json.loads(data)
213 return Response("The status data is corrupt or missing.", 400, mimetype=TEXT_PLAIN)
215 return Response(json.dumps(data), 200, mimetype=APPL_JSON)
217 #Receive a data delivery package
219 @app.route('/datadelivery', methods=['POST'])
221 global data_delivery_counter
224 data = json.loads(data)
226 return Response("The data is corrupt or missing.", 400, mimetype=TEXT_PLAIN)
227 data_delivery_counter += 1
228 return Response("", 200, mimetype=TEXT_PLAIN)
232 @app.route('/counter/<string:countername>', methods=['GET'])
233 def getcounter(countername):
235 if (countername == "num_instances"):
236 return Response(str(len(policy_fingerprint)), 200, mimetype=TEXT_PLAIN)
237 elif (countername == "num_types"):
238 return Response(str(len(policy_instances)),200, mimetype=TEXT_PLAIN)
239 elif (countername == "interface"):
242 return Response(str(pp[len(pp)-1]),200, mimetype=TEXT_PLAIN)
243 elif (countername == "remote_hosts"):
244 hosts=",".join(hosts_set)
245 return str(hosts),200
246 elif (countername == "datadelivery"):
247 return Response(str(data_delivery_counter),200, mimetype=TEXT_PLAIN)
249 return Response("Counter name: "+countername+" not found.",404, mimetype=TEXT_PLAIN)
252 if len(sys.argv) >= 2:
253 if isinstance(sys.argv[1], int):
254 port_number = sys.argv[1]
256 app.add_api('ORAN_A1-p_V2.0.0_api.yaml')
258 if __name__ == '__main__':
259 app.run(port=port_number, host="127.0.0.1")