# under the License.
#
+import json
+import Queue
+import uuid
+
from flask import Flask
from flask import jsonify
from flask import render_template
from flask_socketio import emit
from flask_socketio import SocketIO
+from summarizer import NFVBenchSummarizer
-import json
from log import LOG
-import Queue
-import traceback
from utils import byteify
from utils import RunLock
-import uuid
# this global cannot reside in Ctx because of the @app and @socketio decorators
app = None
# --------- socketio requests ------------
@socketio.on('start_run')
- def socketio_start_run(config):
+ def _socketio_start_run(config):
if not Ctx.is_busy():
Ctx.enqueue(config, get_uuid(), from_socketio=True)
else:
emit('error', {'reason': 'there is already an NFVbench request running'})
@socketio.on('echo')
- def socketio_echo(config):
+ def _socketio_echo(config):
emit('echo', config)
# --------- HTTP requests ------------
@app.route('/')
- def index():
+ def _index():
return render_template('index.html')
@app.route('/echo', methods=['GET'])
- def echo():
+ def _echo():
config = request.json
return jsonify(config)
@app.route('/start_run', methods=['POST'])
- def start_run():
+ def _start_run():
config = load_json(request.json)
+ if not config:
+ config = {}
if Ctx.is_busy():
return jsonify(busy_json)
- else:
- request_id = get_uuid()
- Ctx.enqueue(config, request_id)
- return jsonify(result_json(STATUS_PENDING, pending_msg, request_id))
+ request_id = get_uuid()
+ Ctx.enqueue(config, request_id)
+ return jsonify(result_json(STATUS_PENDING, pending_msg, request_id))
@app.route('/status', defaults={'request_id': None}, methods=['GET'])
@app.route('/status/<request_id>', methods=['GET'])
- def get_status(request_id):
+ def _get_status(request_id):
if request_id:
if Ctx.is_busy() and request_id == Ctx.get_current_request_id():
# task with request_id still pending
if res:
# found result for given request_id
return jsonify(res)
- else:
- # result for given request_id not found
- return jsonify(result_json(STATUS_NOT_FOUND, not_found_msg, request_id))
+ # result for given request_id not found
+ return jsonify(result_json(STATUS_NOT_FOUND, not_found_msg, request_id))
else:
if Ctx.is_busy():
# task still pending, return with request_id
res = Ctx.get_result()
if res:
return jsonify(res)
- else:
- return jsonify(not_busy_json)
+ return jsonify(not_busy_json)
class WebSocketIoServer(object):
notifications using websocket events (send_ methods). Caller should simply create an instance
of this class and pass a runner object then invoke the run method
"""
- def __init__(self, http_root, runner, logger):
+
+ def __init__(self, http_root, runner, fluent_logger):
self.nfvbench_runner = runner
setup_flask(http_root)
- self.fluent_logger = logger
+ self.fluent_logger = fluent_logger
def run(self, host='127.0.0.1', port=7556):
# print 'main thread waiting for requests...'
config = Ctx.dequeue()
# print 'main thread processing request...'
- print config
+ # print config
try:
# remove unfilled values as we do not want them to override default values with None
config = {k: v for k, v in config.items() if v is not None}
with RunLock():
+ if self.fluent_logger:
+ self.fluent_logger.start_new_run()
results = self.nfvbench_runner.run(config, config)
except Exception as exc:
- print 'NFVbench runner exception:'
- traceback.print_exc()
results = result_json(STATUS_ERROR, str(exc))
- LOG.exception()
+ LOG.exception('NFVbench runner exception:')
if Ctx.request_from_socketio:
socketio.emit('run_end', results)
else:
# this might overwrite a previously unfetched result
Ctx.set_result(results)
+ try:
+ summary = NFVBenchSummarizer(results['result'], self.fluent_logger)
+ LOG.info(str(summary))
+ except KeyError:
+ # in case of error, 'result' might be missing
+ if 'error_message' in results:
+ LOG.error(results['error_message'])
+ else:
+ LOG.error('REST request completed without results or error message')
Ctx.release()
- self.fluent_logger.send_run_summary(True)
+ if self.fluent_logger:
+ self.fluent_logger.send_run_summary(True)
def send_interval_stats(self, time_ms, tx_pps, rx_pps, drop_pct):
stats = {'time_ms': time_ms, 'tx_pps': tx_pps, 'rx_pps': rx_pps, 'drop_pct': drop_pct}