Added multiple A1 support in Near-RT RIC simulator
[sim/a1-interface.git] / near-rt-ric-simulator / src / STD_1.1.3 / a1.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 copy
19 import datetime
20 import json
21 import logging
22 import collections
23 import time
24
25 from connexion import NoContent
26 from flask import Flask, escape, request, Response, make_response
27 from var_declaration import policy_instances, policy_status, callbacks, forced_settings, policy_fingerprint
28 from utils import calcFingerprint
29
30 # API Function: Get all policy ids
31 def get_all_policy_identities():
32
33   if ((r := check_modified_response()) is not None):
34     return r
35
36   return (list(policy_instances.keys()), 200)
37
38 # API Function: Create or update a policy
39 def put_policy(policyId):
40
41   if ((r := check_modified_response()) is not None):
42     return r
43
44   try:
45     data = request.data
46     data = json.loads(data)
47   except:
48     pjson=create_problem_json(None, "The policy is corrupt or missing.", 400, None, policyId)
49     return Response(json.dumps(pjson), 400, mimetype='application/problem+json')
50
51   fpPrevious=None
52   retcode=201
53   if policyId in policy_instances.keys():
54     retcode=200
55     fpPrevious=calcFingerprint(policy_instances[policyId])
56
57   fp=calcFingerprint(data)
58   if (fp in policy_fingerprint.keys()):
59     id=policy_fingerprint[fp]
60     if (id != policyId):
61       pjson=create_problem_json(None, "The policy json already exists.", 400, None, policyId)
62       return Response(json.dumps(pjson), 400, mimetype='application/problem+json')
63
64   if (fpPrevious is not None):
65     del policy_fingerprint[fpPrevious]
66
67   policy_fingerprint[fp]=policyId
68
69   noti=request.args.get('notificationDestination')
70   callbacks[policyId]=noti
71
72   policy_instances[policyId]=data
73   ps={}
74   ps["enforceStatus"] = "UNDEFINED"
75   policy_status[policyId]=ps
76
77   if (retcode == 200):
78     return Response(json.dumps(data), 200, mimetype='application/json')
79   else:
80     headers={}
81     headers['Location']='/A1-P/v1/policies/' + policyId
82     return Response(json.dumps(data), 201, headers=headers, mimetype='application/json')
83
84 # API Function: Get a policy
85 def get_policy(policyId):
86
87   if ((r := check_modified_response()) is not None):
88     return r
89
90   if policyId in policy_instances.keys():
91     return Response(json.dumps(policy_instances[policyId]), 200, mimetype='application/json')
92
93   pjson=create_problem_json(None, "The requested policy does not exist.", 404, None, policyId)
94   return Response(json.dumps(pjson), 404, mimetype='application/problem+json')
95
96 # API Function: Delete a policy
97 def delete_policy(policyId):
98
99   if ((r := check_modified_response()) is not None):
100     return r
101
102   if policyId in policy_instances.keys():
103     fpPrevious=calcFingerprint(policy_instances[policyId])
104     policy_fingerprint.pop(fpPrevious)
105     policy_instances.pop(policyId)
106     policy_status.pop(policyId)
107     callbacks.pop(policyId)
108     return Response('', 204, mimetype='application/json')
109
110   pjson=create_problem_json(None, "The policy identity does not exist.", 404, "No policy instance has been deleted.", policyId)
111   return Response(json.dumps(pjson), 404, mimetype='application/problem+json')
112
113 # API Function: Get status for a policy
114 def get_policy_status(policyId):
115
116   if ((r := check_modified_response()) is not None):
117     return r
118
119   if policyId in policy_instances.keys():
120     return Response(json.dumps(policy_status[policyId]), status=200, mimetype='application/json')
121
122   pjson=create_problem_json(None, "The policy identity does not exist.", 404, "There is no existing policy instance with the identity: " + policyId, policyId)
123   return Response(json.dumps(pjson), 404, mimetype='application/problem+json')
124
125 # Helper: Create a response object if forced http response code is set
126 def get_forced_response():
127   if (forced_settings['code'] is not None):
128     pjson=create_error_response(forced_settings['code'])
129     forced_settings['code']=None
130     return Response(json.dumps(pjson), pjson['status'], mimetype='application/problem+json')
131   return None
132
133 # Helper: Delay if delayed response code is set
134 def do_delay():
135   if (forced_settings['delay'] is not None):
136     try:
137       val=int(forced_settings['delay'])
138       time.sleep(val)
139     except:
140       return
141   return
142
143 # Helper: Check if response shall be delayed or a forced response shall be sent
144 def check_modified_response():
145   do_delay()
146   return get_forced_response()
147
148 # Helper: Create a problem json object
149 def create_problem_json(type_of, title, status, detail, instance):
150
151   error = {}
152   if type_of is not None:
153     error["type"] = type_of
154   if title is not None:
155     error["title"] = title
156   if status is not None:
157     error["status"] = status
158   if detail is not None:
159     error["detail"] = detail
160   if instance is not None:
161     error["instance"] = instance
162   return error
163
164 # Helper: Create a problem json based on a generic http response code
165 def create_error_response(code):
166
167     if code == '400':
168       return(create_problem_json(None, "Bad request", 400, "Object in payload not properly formulated or not related to the method", None))
169     elif code == '404':
170       return(create_problem_json(None, "Not found", 404, "No resource found at the URI", None))
171     elif code == '405':
172       return(create_problem_json(None, "Method not allowed", 405, "Method not allowed for the URI", None))
173     elif code == '409':
174       return(create_problem_json(None, "Conflict", 409, "Request could not be processed in the current state of the resource", None))
175     elif code == '429':
176       return(create_problem_json(None, "Too many requests", 429, "Too many requests have been sent in a given amount of time", None))
177     elif code == '507':
178       return(create_problem_json(None, "Insufficient storage", 507, "The method could not be performed on the resource because the provider is unable to store the representation needed to successfully complete the request", None))
179     elif code == '503':
180       return(create_problem_json(None, "Service unavailable", 503, "The provider is currently unable to handle the request due to a temporary overload", None))
181     else:
182       return(create_problem_json(None, "Unknown", code, "Not implemented response code", None))