blob: 9e04d5759720badd44638d583c7d8e93fe507a57 [file] [log] [blame]
BjornMagnussonXA80a92002020-03-19 14:31:06 +01001
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
BjornMagnussonXA49f0e5a2020-11-08 22:41:39 +010019from flask import Flask, request, Response
BjornMagnussonXA80a92002020-03-19 14:31:06 +010020from time import sleep
21import time
BjornMagnussonXA7b36db62020-11-23 10:57:57 +010022from datetime import datetime
BjornMagnussonXA80a92002020-03-19 14:31:06 +010023import json
BjornMagnussonXA80a92002020-03-19 14:31:06 +010024import traceback
BjornMagnussonXA7b36db62020-11-23 10:57:57 +010025import logging
BjornMagnussonXAc963b732021-01-20 14:24:13 +010026import socket
BjornMagnussonXA7b36db62020-11-23 10:57:57 +010027
28# Disable all logging of GET on reading counters and db
29class AjaxFilter(logging.Filter):
30 def filter(self, record):
31 return ("/counter/" not in record.getMessage()) and ("/db" not in record.getMessage())
32
33log = logging.getLogger('werkzeug')
34log.addFilter(AjaxFilter())
BjornMagnussonXA80a92002020-03-19 14:31:06 +010035
36app = Flask(__name__)
37
38# list of callback messages
39msg_callbacks={}
40
41# Server info
BjornMagnussonXA72667f12020-04-24 09:20:18 +020042HOST_IP = "::"
ecaiyanlinux113bf092020-08-01 14:05:17 +000043HOST_PORT = 2222
BjornMagnussonXA80a92002020-03-19 14:31:06 +010044
45# Metrics vars
46cntr_msg_callbacks=0
47cntr_msg_fetched=0
BjornMagnussonXA49f0e5a2020-11-08 22:41:39 +010048cntr_callbacks={}
BjornMagnussonXA80a92002020-03-19 14:31:06 +010049
50# Request and response constants
51CALLBACK_URL="/callbacks/<string:id>"
52APP_READ_URL="/get-event/<string:id>"
BjornMagnussonXA49f0e5a2020-11-08 22:41:39 +010053APP_READ_ALL_URL="/get-all-events/<string:id>"
54DUMP_ALL_URL="/db"
BjornMagnussonXA80a92002020-03-19 14:31:06 +010055
56MIME_TEXT="text/plain"
57MIME_JSON="application/json"
58CAUGHT_EXCEPTION="Caught exception: "
59SERVER_ERROR="Server error :"
BjornMagnussonXA7b36db62020-11-23 10:57:57 +010060TIME_STAMP="cr-timestamp"
BjornMagnussonXA80a92002020-03-19 14:31:06 +010061
BjornMagnussonXAc963b732021-01-20 14:24:13 +010062# Remote host lookup and print host name
63def remote_host_logging(request):
64
65 if request.environ.get('HTTP_X_FORWARDED_FOR') is None:
66 host_ip=str(request.environ['REMOTE_ADDR'])
67 else:
68 host_ip=str(request.environ['HTTP_X_FORWARDED_FOR'])
69 prefix='::ffff:'
70 if (host_ip.startswith('::ffff:')):
71 host_ip=host_ip[len(prefix):]
72 try:
73 name, alias, addresslist = socket.gethostbyaddr(host_ip)
74 print("Calling host: "+str(name))
75 except Exception:
76 print("Calling host not possible to retrieve IP: "+str(host_ip))
77
78
BjornMagnussonXA80a92002020-03-19 14:31:06 +010079#I'm alive function
80@app.route('/',
81 methods=['GET'])
82def index():
83 return 'OK', 200
84
85### Callback interface, for control
86
87# Fetch the oldest callback message for an id
88# URI and parameter, (GET): /get-event/<id>
BjornMagnussonXA49f0e5a2020-11-08 22:41:39 +010089# response: message + 200 or just 204 or just 500(error)
BjornMagnussonXA80a92002020-03-19 14:31:06 +010090@app.route(APP_READ_URL,
91 methods=['GET'])
92def receiveresponse(id):
93 global msg_callbacks
94 global cntr_msg_fetched
95
96 try:
97 if ((id in msg_callbacks.keys()) and (len(msg_callbacks[id]) > 0)):
98 cntr_msg_fetched+=1
BjornMagnussonXA49f0e5a2020-11-08 22:41:39 +010099 cntr_callbacks[id][1]+=1
100 msg=msg_callbacks[id][0]
101 print("Fetching msg for id: "+id+", msg="+str(msg))
BjornMagnussonXA7b36db62020-11-23 10:57:57 +0100102 del msg[TIME_STAMP]
BjornMagnussonXA80a92002020-03-19 14:31:06 +0100103 del msg_callbacks[id][0]
BjornMagnussonXA49f0e5a2020-11-08 22:41:39 +0100104 return json.dumps(msg),200
BjornMagnussonXA80a92002020-03-19 14:31:06 +0100105 print("No messages for id: "+id)
106 except Exception as e:
107 print(CAUGHT_EXCEPTION+str(e))
BjornMagnussonXA49f0e5a2020-11-08 22:41:39 +0100108 traceback.print_exc()
109 return "",500
BjornMagnussonXA80a92002020-03-19 14:31:06 +0100110
111 return "",204
112
BjornMagnussonXA49f0e5a2020-11-08 22:41:39 +0100113# Fetch all callback message for an id in an array
114# URI and parameter, (GET): /get-all-events/<id>
115# response: message + 200 or just 500(error)
116@app.route(APP_READ_ALL_URL,
117 methods=['GET'])
118def receiveresponse_all(id):
119 global msg_callbacks
120 global cntr_msg_fetched
121
122 try:
123 if ((id in msg_callbacks.keys()) and (len(msg_callbacks[id]) > 0)):
124 cntr_msg_fetched+=len(msg_callbacks[id])
125 cntr_callbacks[id][1]+=len(msg_callbacks[id])
126 msg=msg_callbacks[id]
127 print("Fetching all msgs for id: "+id+", msg="+str(msg))
BjornMagnussonXA7b36db62020-11-23 10:57:57 +0100128 for sub_msg in msg:
129 del sub_msg[TIME_STAMP]
BjornMagnussonXA49f0e5a2020-11-08 22:41:39 +0100130 del msg_callbacks[id]
131 return json.dumps(msg),200
132 print("No messages for id: "+id)
133 except Exception as e:
134 print(CAUGHT_EXCEPTION+str(e))
135 traceback.print_exc()
136 return "",500
137
138 msg=[]
139 return json.dumps(msg),200
BjornMagnussonXA80a92002020-03-19 14:31:06 +0100140
141# Receive a callback message
BjornMagnussonXA49f0e5a2020-11-08 22:41:39 +0100142# URI and payload, (PUT or POST): /callbacks/<id> <json messages>
BjornMagnussonXA80a92002020-03-19 14:31:06 +0100143# response: OK 200 or 500 for other errors
144@app.route(CALLBACK_URL,
145 methods=['PUT','POST'])
146def events_write(id):
147 global msg_callbacks
148 global cntr_msg_callbacks
149
150 try:
151 print("Received callback for id: "+id +", content-type="+request.content_type)
BjornMagnussonXAc963b732021-01-20 14:24:13 +0100152 remote_host_logging(request)
BjornMagnussonXA80a92002020-03-19 14:31:06 +0100153 try:
BjornMagnussonXA80a92002020-03-19 14:31:06 +0100154 if (request.content_type == MIME_JSON):
BjornMagnussonXA49f0e5a2020-11-08 22:41:39 +0100155 data = request.data
156 msg = json.loads(data)
BjornMagnussonXA80a92002020-03-19 14:31:06 +0100157 print("Payload(json): "+str(msg))
BjornMagnussonXA80a92002020-03-19 14:31:06 +0100158 else:
BjornMagnussonXA49f0e5a2020-11-08 22:41:39 +0100159 msg={}
160 print("Payload(content-type="+request.content_type+"). Setting empty json as payload")
161 except Exception as e:
162 msg={}
163 print("(Exception) Payload does not contain any json, setting empty json as payload")
164 traceback.print_exc()
BjornMagnussonXA80a92002020-03-19 14:31:06 +0100165
166 cntr_msg_callbacks += 1
BjornMagnussonXA7b36db62020-11-23 10:57:57 +0100167 msg[TIME_STAMP]=str(datetime.now())
BjornMagnussonXA80a92002020-03-19 14:31:06 +0100168 if (id in msg_callbacks.keys()):
169 msg_callbacks[id].append(msg)
170 else:
171 msg_callbacks[id]=[]
172 msg_callbacks[id].append(msg)
BjornMagnussonXA49f0e5a2020-11-08 22:41:39 +0100173
174 if (id in cntr_callbacks.keys()):
175 cntr_callbacks[id][0] += 1
176 else:
177 cntr_callbacks[id]=[]
178 cntr_callbacks[id].append(1)
179 cntr_callbacks[id].append(0)
180
BjornMagnussonXA80a92002020-03-19 14:31:06 +0100181 except Exception as e:
182 print(CAUGHT_EXCEPTION+str(e))
BjornMagnussonXA49f0e5a2020-11-08 22:41:39 +0100183 traceback.print_exc()
184 return 'NOTOK',500
BjornMagnussonXA80a92002020-03-19 14:31:06 +0100185
186 return 'OK',200
187
BjornMagnussonXA49f0e5a2020-11-08 22:41:39 +0100188### Functions for test ###
189
190# Dump the whole db of current callbacks
191# URI and parameter, (GET): /db
192# response: message + 200
193@app.route(DUMP_ALL_URL,
194 methods=['GET'])
195def dump_db():
196 return json.dumps(msg_callbacks),200
BjornMagnussonXA80a92002020-03-19 14:31:06 +0100197
198### Functions for metrics read out ###
199
200@app.route('/counter/received_callbacks',
201 methods=['GET'])
202def requests_submitted():
BjornMagnussonXA49f0e5a2020-11-08 22:41:39 +0100203 req_id = request.args.get('id')
204 if (req_id is None):
205 return Response(str(cntr_msg_callbacks), status=200, mimetype=MIME_TEXT)
206
207 if (req_id in cntr_callbacks.keys()):
208 return Response(str(cntr_callbacks[req_id][0]), status=200, mimetype=MIME_TEXT)
209 else:
210 return Response(str("0"), status=200, mimetype=MIME_TEXT)
BjornMagnussonXA80a92002020-03-19 14:31:06 +0100211
212@app.route('/counter/fetched_callbacks',
213 methods=['GET'])
214def requests_fetched():
BjornMagnussonXA49f0e5a2020-11-08 22:41:39 +0100215 req_id = request.args.get('id')
216 if (req_id is None):
217 return Response(str(cntr_msg_fetched), status=200, mimetype=MIME_TEXT)
218
219 if (req_id in cntr_callbacks.keys()):
220 return Response(str(cntr_callbacks[req_id][1]), status=200, mimetype=MIME_TEXT)
221 else:
222 return Response(str("0"), status=200, mimetype=MIME_TEXT)
BjornMagnussonXA80a92002020-03-19 14:31:06 +0100223
224@app.route('/counter/current_messages',
225 methods=['GET'])
226def current_messages():
BjornMagnussonXA49f0e5a2020-11-08 22:41:39 +0100227 req_id = request.args.get('id')
228 if (req_id is None):
229 return Response(str(cntr_msg_callbacks-cntr_msg_fetched), status=200, mimetype=MIME_TEXT)
BjornMagnussonXA80a92002020-03-19 14:31:06 +0100230
BjornMagnussonXA49f0e5a2020-11-08 22:41:39 +0100231 if (req_id in cntr_callbacks.keys()):
232 return Response(str(cntr_callbacks[req_id][0]-cntr_callbacks[req_id][1]), status=200, mimetype=MIME_TEXT)
233 else:
234 return Response(str("0"), status=200, mimetype=MIME_TEXT)
BjornMagnussonXA80a92002020-03-19 14:31:06 +0100235
236
237### Admin ###
238
239# Reset all messsages and counters
240@app.route('/reset',
241 methods=['GET', 'POST', 'PUT'])
242def reset():
243 global msg_callbacks
244 global cntr_msg_fetched
245 global cntr_msg_callbacks
BjornMagnussonXA7b36db62020-11-23 10:57:57 +0100246 global cntr_callbacks
BjornMagnussonXA80a92002020-03-19 14:31:06 +0100247
248 msg_callbacks={}
249 cntr_msg_fetched=0
250 cntr_msg_callbacks=0
BjornMagnussonXA7b36db62020-11-23 10:57:57 +0100251 cntr_callbacks={}
BjornMagnussonXA80a92002020-03-19 14:31:06 +0100252
253 return Response('OK', status=200, mimetype=MIME_TEXT)
254
255### Main function ###
256
257if __name__ == "__main__":
258 app.run(port=HOST_PORT, host=HOST_IP)