1 # Copyright (c) 2019 AT&T Intellectual Property. #
\r
3 # Licensed under the Apache License, Version 2.0 (the "License"); #
\r
4 # you may not use this file except in compliance with the License. #
\r
5 # You may obtain a copy of the License at #
\r
7 # http://www.apache.org/licenses/LICENSE-2.0 #
\r
9 # Unless required by applicable law or agreed to in writing, software #
\r
10 # distributed under the License is distributed on an "AS IS" BASIS, #
\r
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
\r
12 # See the License for the specific language governing permissions and #
\r
13 # limitations under the License. #
\r
14 ################################################################################
\r
15 # File name: a1-mediator-vth.py #
\r
16 # Description: vth for a1-mediator-vth service #
\r
17 # Date created: 08/22/2019 #
\r
18 # Last modified: 04/02/2020 #
\r
19 # Python Version: 3.7.4 #
\r
20 # Author: Jackie Chen (jv246a) #
\r
21 # Email: jv246a@att.com #
\r
22 ################################################################################
\r
26 from logging import FileHandler
\r
30 from flask import Flask, request, jsonify
\r
32 # redirect http to https
\r
33 app = Flask(__name__)
\r
35 # Prevents print statement every time an endpoint is triggered.
\r
36 logging.getLogger("werkzeug").setLevel(logging.WARNING)
\r
39 def sendCallback(url, data):
\r
41 if type(data) is not dict:
\r
42 data = {"msg": data}
\r
43 app.logger.info("sending callback")
\r
44 requests.post(url, json=data)
\r
45 except Exception as e:
\r
49 def unix_time_millis(dt):
\r
50 epoch = datetime.datetime.utcfromtimestamp(0)
\r
51 return (dt - epoch).total_seconds() * 1000.0
\r
54 @app.route("/otf/vth/oran/a1/v1/health", methods=['GET'])
\r
59 @app.route("/otf/vth/oran/a1/v1", methods=['POST'])
\r
60 def executeRicRequest():
\r
64 'dateTimeUTC': str(datetime.datetime.now()),
\r
65 'abstractMessage': '',
\r
70 startTime = unix_time_millis(datetime.datetime.now())
\r
71 ret_url = request.args.get('retURL')
\r
73 if not request.is_json:
\r
74 raise ValueError("request must be json")
\r
76 requestData = request.get_json()
\r
78 app.logger.info("A1 requestData:" + str(requestData))
\r
80 action = requestData['action'].lower()
\r
81 _check_incoming_request(requestData)
\r
83 os.environ['NO_PROXY'] = '127.0.0.1' # TODO testing purpose w/ mock server. Needs to remove on final version
\r
84 with open('config.json') as configFile:
\r
85 config = json.load(configFile)
\r
87 baseAddress = config['base_address']
\r
88 if action == 'health_check' or action == 'list_policy':
\r
89 res = requests.get(baseAddress + config['actions_path'][action])
\r
90 response_data['vthResponse']['resultData']['statusCode'] = res.status_code
\r
91 if action == 'health_check':
\r
92 response_data['vthResponse']['resultData']['resultOutput'] = res.text
\r
94 response_data['vthResponse']['resultData']['resultOutput'] = res.json()
\r
95 elif action == 'list_policy_instance':
\r
96 res = requests.get(baseAddress + config['actions_path'][action]
\r
97 .format(policy_type_id=requestData['policy_type_id']))
\r
98 response_data['vthResponse']['resultData']['statusCode'] = res.status_code
\r
99 response_data['vthResponse']['resultData']['resultOutput'] = res.json()
\r
100 elif action == 'get_policy_instance_status':
\r
101 res = requests.get(baseAddress + config['actions_path'][action]
\r
102 .format(policy_type_id=requestData['policy_type_id'],
\r
103 policy_instance_id=requestData['policy_instance_id']))
\r
104 response_data['vthResponse']['resultData']['statusCode'] = res.status_code
\r
105 response_data['vthResponse']['resultData']['resultOutput'] = res.json()
\r
106 elif action == 'edit_policy':
\r
107 res = _send_edit_request(requestData, config)
\r
108 response_data['vthResponse']['resultData']['statusCode'] = res.status_code
\r
109 if requestData['request_type'].lower() == 'get' and res.status_code == 200:
\r
110 response_data['vthResponse']['resultData']['resultOutput'] = res.json()
\r
112 response_data['vthResponse']['resultData']['resultOutput'] = res.text
\r
113 elif action == 'edit_policy_instance':
\r
114 res = _send_edit_request(requestData, config)
\r
115 response_data['vthResponse']['resultData']['statusCode'] = res.status_code
\r
116 if requestData['request_type'].lower() == 'get' and res.status_code == 200:
\r
117 response_data['vthResponse']['resultData']['resultOutput'] = res.json()
\r
119 response_data['vthResponse']['resultData']['resultOutput'] = res.text
\r
121 except Exception as ex:
\r
122 endTime = unix_time_millis(datetime.datetime.now())
\r
123 totalTime = endTime - startTime
\r
124 response_data['vthResponse']['testDuration'] = totalTime
\r
125 response_data['vthResponse']['abstractMessage'] = str(ex)
\r
126 return jsonify(response_data)
\r
128 endTime = unix_time_millis(datetime.datetime.now())
\r
129 totalTime = endTime - startTime
\r
131 response_data['vthResponse']['testDuration'] = totalTime
\r
133 if ret_url is not None:
\r
134 sendCallback(ret_url, response_data)
\r
137 return jsonify(response_data), 200
\r
140 def _send_edit_request(request_data, config):
\r
141 baseAddress = config['base_address']
\r
143 action = request_data['action']
\r
144 policy_type_id = request_data['policy_type_id']
\r
145 request_type = request_data['request_type']
\r
146 if action == "edit_policy":
\r
147 path = baseAddress + config['actions_path'][action].format(policy_type_id=policy_type_id)
\r
148 if action == 'edit_policy_instance':
\r
149 instance_id = request_data['policy_instance_id']
\r
150 path = baseAddress + config['actions_path'][action].format(policy_type_id=policy_type_id,
\r
151 policy_instance_id=instance_id)
\r
152 if request_type == 'get':
\r
153 return requests.get(path)
\r
154 if request_type == 'put':
\r
155 payload = request_data['payload']
\r
156 return requests.put(path, payload)
\r
157 if request_type == 'delete':
\r
158 return requests.delete(path)
\r
161 def _check_incoming_request(requestData): # check if the request is valid
\r
162 if 'action' not in requestData:
\r
163 raise KeyError('no action was specify')
\r
165 action = requestData['action'].lower()
\r
166 edit_actions = ['edit_policy', 'edit_policy_instance']
\r
167 requires_policy_id = ['edit_policy', 'list_policy_instance'
\r
168 , 'edit_policy_instance', 'get_policy_instance_status']
\r
169 requires_policy_instance_id = ['edit_policy_instance', 'get_policy_instance_status']
\r
170 possible_actions = ['health_check', 'list_policy', 'edit_policy', 'list_policy_instance'
\r
171 , 'edit_policy_instance', 'get_policy_instance_status']
\r
172 possible_request_type = ['get', 'put', 'delete']
\r
174 if action not in possible_actions:
\r
175 raise KeyError("invalid action")
\r
176 if action in edit_actions: # request type is required
\r
177 if 'request_type' not in requestData:
\r
178 raise KeyError('this action: ' + action + ' requires a request type')
\r
179 if requestData['request_type'] not in possible_request_type:
\r
180 raise KeyError('this request_type: ' + requestData['request_type'] + ' is not valid')
\r
181 if requestData['request_type'] == 'put' and 'payload' not in requestData:
\r
182 raise KeyError('put request requires a payload')
\r
183 if action in requires_policy_id:
\r
184 if 'policy_type_id' not in requestData:
\r
185 raise KeyError('this action: ' + action + ' requires a policy_type_id')
\r
186 if action in requires_policy_instance_id:
\r
187 if 'policy_instance_id' not in requestData:
\r
188 raise KeyError('this action: ' + action + ' requires a policy_instance_id')
\r
191 if __name__ == '__main__':
\r
192 logHandler = FileHandler('a1-mediator-vth.log', mode='a')
\r
193 logHandler.setLevel(logging.INFO)
\r
194 app.logger.setLevel(logging.INFO)
\r
195 app.logger.addHandler(logHandler)
\r
196 # context = ('opt/cert/otf.pem', 'opt/cert/privateKey.pem')
\r
197 # app.run(debug = False, host = '0.0.0.0', port = 5000, ssl_context = context)
\r
198 app.run(debug=False, host='0.0.0.0', port=5000)
\r