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