from flask import Flask,jsonify,request,abort, make_response,send_file from werkzeug.exceptions import HTTPException from nornir import InitNornir from flask_cors import CORS import os from werkzeug.utils import secure_filename import json ALLOWED_EXTENSIONS = {'conf'} UPLOAD_FOLDER = 'fastprod/upload_files/' def init_nornir(): app.config['nr'] = InitNornir(config_file="fastprod/inventory/config.yaml") def allowed_file(filename): return '.' in filename and \ filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS app = Flask(__name__) app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER CORS(app) from services.devices import ( get_inventory, add_device,get_device_by_name,delete_device,get_device_interfaces,get_device_interfaces_ip,get_device_technical_info) from services.config import (get_config_by_device,run_config_from_file_by_device) from services.tasks import (run_show_commands_by_device,run_config_commands_by_device) from services.snapshots import (get_snapshot_by_name,create_snapshot_by_device,get_snapshots_by_device) init_nornir() @app.route("/") def hello_world(): return jsonify({ "env": "DEV", "name": "fastprod_backend", "version": 1.0 }) @app.route("/devices", methods=['GET', 'POST']) def devices(): if request.method == 'GET': init_nornir() devices = get_inventory() return jsonify(devices=devices, total_count=len(devices)) if request.method == 'POST': data = request.get_json() new_device = add_device(data) return jsonify(device=new_device) @app.route("/devices/", methods=['GET', 'DELETE']) def device_by_name(device_name): if request.method == 'GET': device = get_device_by_name(device_name) return jsonify(device=device) if request.method == 'DELETE': device = get_device_by_name(device_name) delete_device(device) return jsonify(message="Device deleted") @app.route("/devices//interfaces", methods=['GET']) def get_interfaces(device_name): device = get_device_by_name(device_name) interfaces = get_device_interfaces(device) return jsonify(interfaces=interfaces) @app.route("/devices//interfaces/ip", methods=['GET']) def get_interfaces_ip(device_name): if request.method == 'GET': device = get_device_by_name(device_name) interfaces_ip = get_device_interfaces_ip(device) return jsonify(interfaces_ip=interfaces_ip) @app.route("/devices//facts", methods=['GET']) def get_technical_info(device_name): if request.method == 'GET': device = get_device_by_name(device_name) technical_info = get_device_technical_info(device) return jsonify(facts=technical_info) @app.route("/devices//config", methods=['GET','POST']) def get_config(device_name): device = get_device_by_name(device_name) if request.method == 'GET': config = get_config_by_device(device) return jsonify(interfaces_ip=config) if request.method == 'POST': if request.files.to_dict(flat=False).get('config_file'): file = request.files['config_file'] if not allowed_file(file.filename): abort(make_response(jsonify(message="file extension not allowed"), 403)) filename = secure_filename(file.filename) file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename)) result = run_config_from_file_by_device(device,file_path=os.path.join(app.config['UPLOAD_FOLDER'], filename)) return jsonify(result=result) if request.get_json().get('mode') == 'enable': commands = request.get_json().get('commands') result = run_show_commands_by_device(device, commands=commands) return jsonify(result=result) if request.get_json().get('mode') == 'config': commands = request.get_json().get('commands') result = run_config_commands_by_device(device, commands=commands) return jsonify(result=result, commands=commands) @app.route("/devices//snapshots", methods=['GET','POST']) def snapshot(device_name): device = get_device_by_name(device_name) print(device) if request.method == 'GET': data = get_snapshots_by_device(device) return jsonify({ "result": True, "snapshots": data }) if request.method == 'POST': snapshot_path = create_snapshot_by_device(device) return jsonify({ "result": True, "snapshots": snapshot_path }) @app.route("/snapshots/", methods=['GET']) def snapshot_by_name(filename): if request.method == 'GET': try: return send_file('snapshots/'+filename) except FileNotFoundError: abort(make_response(jsonify(message="snapshot not found"), 404)) @app.errorhandler(HTTPException) def handle_exception(e): """Return JSON instead of HTML for HTTP errors.""" # start with the correct headers and status code from the error response = e.get_response() # replace the body with JSON response.data = json.dumps({ "code": e.code, "name": e.name, "description": e.description, }) response.content_type = "application/json" return response