# flask routes for storage summary API # import external libraries from flask import Flask, jsonify, request, Response, abort #from flask_apscheduler import APScheduler from typing import Dict, Union import json, time, redis, yaml, datetime import secrets, string import requests from requests import RequestException, Response # import needed Class Libraries from Storage import * from Helpers import * #SummaryServer = DriveHealthServer(get_hostname()) SummaryServer = load_state() if SummaryServer is None: SummaryServer = DriveHealthServer(get_hostname()) print("Created new SummaryServer") # declare flask apps app = Flask(__name__) #scheduler = APScheduler() # Flask routes # client update @app.route('/storage_client_update', methods=['POST']) def storage_client_update(): payload = request.get_json(silent=False) if payload is None: abort(400, description="Request body must be valid JSON") payload["IP Address"] = request.remote_addr # offload processing to helper processed_payload = client_update_helper(payload) return jsonify(processed_payload), 200 # remove client @app.route('/storage_client_delete', methods=['POST']) def storage_client_delete(): payload = request.get_json(silent=False) print(payload) if payload is None: abort(400, description="Request body must be valid JSON") result = client_remove_helper(payload) print(result) return jsonify(result) # client details @app.route('/client_details', methods=['GET']) def client_details(): result = [] for client in SummaryServer.clients: result.append(client.get_details()) return jsonify(result) # client summary @app.route('/client_summary', methods=['GET']) def client_summary(): result = [] for client in SummaryServer.clients: result.append(client.get_summary()) return jsonify(result) # client brief summary @app.route('/brief_summary', methods=['GET']) def brief_summary(): result = [] for client in SummaryServer.clients: result.append(f"{client.name} at {client.ip} - {len(client.drives)} drives") return jsonify({ "message": "Brief Summary", "result": result }) # test route @app.route('/test', methods=['GET']) def test_route(): return jsonify({ "message": "Hello world!", "hostname": get_hostname(), "DriveHealthServer": f"{SummaryServer}" }) # test route 2 @app.route('/test_storage_summary', methods=['GET']) def test_storage_summary(): return jsonify({ "message": "Hello world!", "hostname": get_hostname(), "DriveHealthServer": f"{SummaryServer}" }) # Route Helpers # helper function for client_update route # handles the submission data from the flask route def client_update_helper(payload: dict): result = None required_keys = {"hostname", "API_KEY", "drives", "IP Address"} # check json structure and API key processed_payload = post_processor(payload, required_keys) # add or update the client result = client_processor(processed_payload) return result # handle submission from remove route def client_remove_helper(payload: dict): result = None required_keys = {"remove_hosts", "API_KEY"} # check the submission data processed_payload = post_processor(payload, required_keys) result = SummaryServer.remove_client(processed_payload["remove_hosts"]) return result # this function takes the raw POST input from client_update and makes sure it is valid and returns it if so def post_processor(client_dict: dict, required_keys: dict): payload_safe = False keys_present = False api_valid = False api_key = "deadbeef" # check for keys missing = required_keys - client_dict.keys() if not missing: keys_present = True else: return { "message": f"error - {missing} keys missing" } # check API if client_dict["API_KEY"] == api_key: api_valid = True # if both then safe if keys_present and api_valid: payload_safe = True # add a key to indicate this was processed client_dict["processed_at"] = time.time() return client_dict # Main functions # client processing function, add/update logic in Class Methods def client_processor(client_dict: dict): result = SummaryServer.process_client_data(client_dict) save_state(SummaryServer) return result def background_loop(): return True def run_main(): #if SummaryServer is none: #atexit.register(lambda: save_state(SummaryServer)) test # Flask scheduler for background loop, run if requested #scheduler.add_job(id='background_loop', # func=background_loop, # trigger='interval', # seconds=60) #scheduler.init_app(app) #scheduler.start() # Flask API background_loop() app.run(debug=False, host='0.0.0.0', port=5001)