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