import json import logging from distutils.util import strtobool from flask import Blueprint, current_app, jsonify, Response, request from inventory_provider.tasks import monitor from inventory_provider.tasks import worker from inventory_provider.routes import common from inventory_provider.tasks.common import get_current_redis, get_latch routes = Blueprint("inventory-data-job-routes", __name__) logger = logging.getLogger(__name__) @routes.after_request def after_request(resp): return common.after_request(resp) @routes.route("/update", methods=['GET', 'POST']) @common.require_accepts_json def update(): force = request.args.get('force', default='false', type=str) try: force = strtobool(force) except ValueError: force = False config = current_app.config['INVENTORY_PROVIDER_CONFIG'] r = get_current_redis(config) if not force: latch = get_latch(r) if latch and latch['pending']: return Response( response='an update is already in progress', status=503, mimetype="text/html") phase2_task_id = worker.launch_refresh_cache_all(config) r.set('classifier-cache:update-task-id', phase2_task_id.encode('utf-8')) return jsonify({'task id': phase2_task_id}) @routes.route("reload-router-config/<equipment_name>", methods=['GET', 'POST']) @common.require_accepts_json def reload_router_config(equipment_name): result = worker.reload_router_config.delay(equipment_name) return jsonify({'task id': result.id}) @routes.route("check-task-status/<task_id>", methods=['GET', 'POST']) @common.require_accepts_json def check_task_status(task_id): return jsonify(list(worker.check_task_status(task_id))) @routes.route("check-update-status", methods=['GET', 'POST']) @common.require_accepts_json def check_update_status(): r = common.get_current_redis() task_id = r.get('classifier-cache:update-task-id') if not task_id: return Response( response='no pending update task found', status=404, mimetype="text/html") task_id = task_id.decode('utf-8') return jsonify(list(worker.check_task_status(task_id))) @routes.route("log", methods=['GET', 'POST']) @common.require_accepts_json def load_task_log(): FINALIZATION_EVENTS = {'task-succeeded', 'task-failed', 'task-revoked'} config = current_app.config['INVENTORY_PROVIDER_CONFIG'] r = get_current_redis(config) cache_key = 'joblog:cached-response' result = r.get(cache_key) if result: result = json.loads(result.decode('utf-8')) else: result = { 'pending': [], 'warnings': [], 'errors': [], 'failed': [] } found_tasks = False for task in monitor.load_task_log( current_app.config['INVENTORY_PROVIDER_CONFIG']).values(): found_tasks = True for event in task.get('task-warning', []): result['warnings'].append(event['message']) for event in task.get('task-error', []): result['errors'].append(event['message']) # build the description if task-received is available description = None if 'task-received' in task: event = task['task-received'][0] description = f'{event["name"]}{event["args"]}' if 'task-failed' in task: if not description: logger.error('found task-failed event without' f'task-received: {task}') description = task['task-failed'][0]['uuid'] result['failed'].append(description) if 'task-started' in task: finished = set(task.keys()) & FINALIZATION_EVENTS if not finished: if not description: logger.error('found task-started event without' f'task-received: {task}') description = task['task-started'][0]['uuid'] result['pending'].append(description) if found_tasks and not result['pending']: r.set(cache_key, json.dumps(result)) return jsonify(result)