blob: 116303458231ce998125d4648f0a8281c3d289a0 [file] [log] [blame]
Rohan Patela99e5742019-09-23 15:04:19 -04001# 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
16from flask import Flask, request, make_response, jsonify, g
17import json
18import uuid
19import traceback
20import pyping
21import paramiko
22import socket
23import os
24import subprocess
25import datetime
26import logging
27from logging import FileHandler
28
29#redirect http to https
30app = Flask(__name__)
31
32
33# Prevents print statement every time an endpoint is triggered.
34logging.getLogger("werkzeug").setLevel(logging.WARNING)
35
36def unix_time_millis(dt):
37 epoch = datetime.datetime.utcfromtimestamp(0)
38 return (dt - epoch).total_seconds() * 1000.0
39
40def pingServer(targetHost):
41 try:
42 response = subprocess.check_output(
43 ['ping', '-c', '1', targetHost], # execute the ping command
44 stderr = subprocess.STDOUT, # retrieve all the output
45 universal_newlines = True # return as string
46 )
47 except subprocess.CalledProcessError as e:
48 app.logger.error(e)
49 app.logger.error('failed getting response from ' + str(targetHost))
50 response = None
51
52 return response
53
54@app.route("/otf/vth/ping/v1/health", methods = ['GET'])
55def getHealth():
56 return "UP"
57
58@app.route('/otf/vth/sample/v1', methods = ['POST'])
59def sample():
60 startTime = unix_time_millis(datetime.datetime.now())
61 responseData = {
62 "vthResponse": {
63 "testDurationMS": "",
64 "dateTimeUTC": "",
65 "abstractMessage": "Success",
66 "resultData": {}
67 }
68 }
69 responseData['vthResponse']['dateTimeUTC'] = str(datetime.datetime.now())
70 endTime = unix_time_millis(datetime.datetime.now())
71 responseData['vthResponse']['testDurationMS'] = endTime - startTime
72 responseData['vthResponse']['resultData']['result'] = "Executed test successfully in " + str(responseData['vthResponse']['testDurationMS']) + " milliseconds."
73 app.logger.info('hit sample endpoint. response: ' + str(responseData))
74 return jsonify(responseData)
75
76@app.route('/otf/vth/ping/v1', methods = ['POST'])
77def testHead():
78 responseData = {
79 "vthResponse": {
80 "testDurationMS": "",
81 "dateTimeUTC": "",
82 "abstractMessage": "",
83 "resultData": {}
84 }
85 }
86
87 responseData['vthResponse']['dateTimeUTC'] = str(datetime.datetime.now())
88 startTime = unix_time_millis(datetime.datetime.now())
89
90 try:
91 if not request.is_json:
92 raise ValueError('Request must be a valid JSON object.')
93
94 requestData = request.get_json()
95 app.logger.info('ping endpoint. request: ' + str(requestData))
96
97 if 'vthInput' in requestData:
98 vthInput = requestData['vthInput']
99 expectedKeys = ['vthName', 'testConfig', 'testData']
100 receivedKeys = vthInput.keys();
101 testData = ""
102 testConfig = ""
103
104 if sorted(expectedKeys) == sorted(receivedKeys):
105 testData = vthInput['testData']
106
107 # Check if a target host is provided.
108 if 'targetHost' not in testData:
109 raise KeyError('targetHost is required to ping server.')
110
111 # Check if the target host IP address is in the correct format.
112 # This excludes IPv6. Use IPy to check both IPv6/IPv4.
113 try:
114 socket.inet_aton(testData['targetHost'])
115 except socket.error:
116 raise ValueError('Invalid IP address assigned to targetHost')
117
118 # Don't use a jump server by default.
119 if 'useJumpServer' not in testData:
120 testData['useJumpServer'] = False
121 else:
122 raise ValueError('Missing one or more expected keys: {expectedKeys}.'.format(expectedKeys = expectedKeys))
123
124 if testData['useJumpServer'] == False:
125 responseData['vthResponse']['resultData']['result'] = pingServer(testData['targetHost'])
126 else:
127 testConfig = vthInput['testConfig']
128
129 if 'jumpServer' not in testConfig:
130 raise KeyError('Cannot use jump server when jumpServer key is missing.')
131
132 jumpServer = testConfig['jumpServer']
133
134 if 'host' not in testConfig['jumpServer']:
135 raise KeyError('Missing host value in jumpServer.')
136
137 host = testConfig['jumpServer']['host']
138
139 if 'credentials' not in jumpServer:
140 raise KeyError('Missing credentials in jumpServer.')
141
142 credentials = jumpServer['credentials']
143
144 if 'username' not in credentials:
145 raise KeyError('Missing username in credentials.')
146
147 username = credentials['username']
148
149 if 'password' not in credentials:
150 raise KeyError('Missing password in credentials.')
151
152 password = credentials['password']
153
154 ssh = paramiko.SSHClient()
155 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
156 ssh.connect(host, username = username, password = password)
157 command = "ping -c 1 " + testData['targetHost']
158 ssh_stdin, ssh_stdout, ssh_stderr = ssh.exec_command(command)
159 output = ssh_stdout.read()
160 error = ssh_stderr.read()
161
162 responseData['vthResponse']['resultData']['result'] = output
163 else:
164 raise KeyError('Missing vthInput parameter(s)')
165
166 # record the end time of the test
167 endTime = unix_time_millis(datetime.datetime.now())
168
169 # Calculate the total duration of the test
170 totalTime = endTime - startTime
171
172 # Set the test duration in the result
173 responseData['vthResponse']['testDurationMS'] = totalTime
174
175 responseData['vthResponse']['abstractMessage'] = 'Result from pinging {host}'.format(host = testData['targetHost'])
176 app.logger.info('ping endpoint. response: ' + str(responseData))
177
178 return jsonify(responseData)
179 except Exception as e:
180 app.logger.info(e)
181 responseData['vthResponse']['abstractMessage'] = str(e)
182 resp = make_response(json.dumps(responseData))
183 endTime = unix_time_millis(datetime.datetime.now())
184
185 totalTime = endTime - startTime
186 return resp
187
188if __name__ == '__main__':
189 logHandler = FileHandler('otf/logs/pingVTH.log', mode='a')
190 # logHandler = FileHandler('pingVTH.log', mode='a')
191 logHandler.setLevel(logging.INFO)
192 app.logger.setLevel(logging.INFO)
193 app.logger.addHandler(logHandler)
194 context = ('opt/cert/otf.pem', 'opt/cert/privateKey.pem')
195 app.run(debug = False, host = '0.0.0.0', port = 5000, ssl_context = context)
196 # app.run(debug = False, host = '0.0.0.0', port = 5000)