Merge "Addition to the first commit"
[sim/a1-interface.git] / near-rt-ric-simulator / src / 1.1.x-alpha.2 / 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
23 from connexion import NoContent
24 from flask import Flask, escape, request, make_response
25 from jsonschema import validate
26 from random import random, choice
27 from var_declaration import policy_instances, policy_types, policy_status, policy_type_per_instance
28
29 def get_all_policy_identities():
30   if len(request.args) == 0:
31     return(list(policy_instances.keys()), 200)
32   elif 'policyTypeId' in request.args:
33     policyTypeId = request.args.get('policyTypeId')
34     if policyTypeId not in list(policy_types.keys()):
35       return(set_error(None, "The policy type provided does not exist.", 400, "The policy type " + data["policyTypeId"] + " is not defined as a policy type.", None, None, "policyTypeId", None))
36     else:
37       return(list({key for key in policy_instances.keys() if policy_type_per_instance[key]==policyTypeId}), 200)
38   else:
39     return(send_error_code(request.args))
40
41 def put_policy(policyId):
42   data = request.data.decode("utf-8")
43   data = data.replace("'", "\"")
44   data = json.loads(data)
45   ps = {}
46   if 'policyTypeId' in request.args:
47     policyTypeId = request.args.get('policyTypeId')
48
49     if policyTypeId not in list(policy_types.keys()):
50       return(set_error(None, "The policy type provided does not exist.", 400, "The policy type " + policyTypeId + " is not defined as a policy type.", None, None, "policyTypeId", None))
51
52     policy_schema = policy_types[policyTypeId]["policySchema"]
53     try:
54       validate(instance=data, schema=policy_schema)
55     except:
56       return(set_error(None, "The json does not validate against the schema.", 400, None, None, None, None, None))
57
58     for i in list(policy_instances.keys()):
59       if policyId != i and \
60          data == policy_instances[i] and \
61          policyTypeId == policy_type_per_instance[i]:
62         return(set_error(None, "The policy already exists with a different id.", 400, "No action has been taken. The id of the existing policy instance is: " + i + ".", None, None, None, None))
63
64   if policyId in list(policy_instances.keys()):
65     if data["scope"] != policy_instances[policyId]["scope"]:
66       return(set_error(None, "The policy already exists with a different scope.", 400, "The policy put involves a modification of the existing scope, which is not allowed.", None, None, "scope", None))
67
68   if 'code' in request.args:
69     return(send_error_code(request.args))
70
71   if policyId in policy_instances.keys():
72     code = 201
73   else:
74     code = 200
75
76   policy_instances[policyId] = data
77   policy_status[policyId] = set_status("UNDEFINED")
78   if 'policyTypeId' in request.args:
79     status_schema = policy_types[policyTypeId]["statusSchema"]
80     try:
81       validate(instance=policy_status[policyId], schema=status_schema)
82     except:
83       return(set_error(None, "The json does not validate against the status schema.", 400, None, None, None, None, None))
84     policy_type_per_instance[policyId] = policyTypeId
85   else:
86     policy_type_per_instance[policyId] = "UNDEFINED"
87
88   response = make_response(policy_instances[policyId], code)
89   if code == 201:
90     response.headers['Location'] = "http://localhost:8085/A1-P/v1/policies/" + policyId
91   return response
92
93 def set_status(*args):
94   ps = {}
95   ps["enforceStatus"] = args[0]
96   if len(args) == 2:
97     ps["enforceReason"] = args[1]
98   if len(args) > 2:
99     return(set_error(None, "Too many arguments", 400, "There should be no more than two status arguments: enforceStatus and enforceReason", None, None, None, None))
100   return ps
101
102 def get_policy(policyId):
103   if len(request.args) == 0:
104     if policyId in policy_instances.keys():
105       res = policy_instances[policyId]
106       res["enforceStatus"] = policy_status[policyId]["enforceStatus"]
107       return(res, 200)
108     else:
109       return(set_error(None, "The requested policy does not exist.", 404, None, None, None, "policyId", None))
110   else:
111     return(send_error_code(request.args))
112
113 def delete_policy(policyId):
114   if len(request.args) == 0:
115     if policyId in policy_instances.keys():
116       policy_instances.pop(policyId)
117       policy_status.pop(policyId)
118       policy_type_per_instance.pop(policyId)
119       return(None, 204)
120     else:
121       return(set_error(None, "The policy identity does not exist.", 404, "No policy instance has been deleted.", None, None, "policyId", None))
122   else:
123     return(send_error_code(request.args))
124
125 def get_policy_status(policyId):
126   if len(request.args) == 0:
127     if policyId in policy_instances.keys():
128       return(policy_status[policyId], 200)
129     else:
130       return(set_error(None, "The policy identity does not exist.", 404, "There is no existing policy instance with the identity: " + policyId, None, None, "policyId", None))
131   else:
132     return(send_error_code(request.args))
133
134 def get_all_policytypes_identities():
135   if len(request.args) == 0:
136     return(list(policy_types.keys()), 200)
137   else:
138     return(send_error_code(request.args))
139
140 def get_policytypes(policyTypeId):
141   if len(request.args) == 0:
142     if policyTypeId in policy_types.keys():
143       return(policy_types[policyTypeId], 200)
144     else:
145       return(set_error(None, "The requested policy type does not exist.", 404, None, None, None, "policyTypeId", None))
146   else:
147     return(send_error_code(request.args))
148
149 def set_error(type_of, title, status, detail, instance, cause, param, reason):
150   error = {}
151   params = {}
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   if cause is not None:
163     error["cause"] = cause
164   if param is not None:
165     params["param"] = param
166   if reason is not None:
167     params["reason"] = reason
168   if params:
169     error["invalidParams"] = params
170   return(error, error["status"])
171
172 def send_error_code(args):
173   if 'code' in args.keys():
174     code = args['code']
175     if code == '405':
176       return(set_error(None, "Method not allowed", 405, "Method not allowed for the URI", None, None, None, None))
177     elif code == '429':
178       return(set_error(None, "Too many requests", 429, "Too many requests have been sent in a given amount of time", None, None, None, None))
179     elif code == '507':
180       return(set_error(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, None, None, None))
181     elif code == '503':
182       return(set_error(None, "Service unavailable", 503, "The provider is currently unable to handle the request due to a temporary overload", None, None, None, None))
183     else:
184       return(set_error(None, "Not found", 400, "Object in payload not properly formulated or not related to the method", None, None, None, None))
185   else:
186     return(set_error(None, "Not found", 404, "No resource found at the URI", None, None, None, None))