cosmostat has working drive health dashboard

This commit is contained in:
2026-04-19 14:23:32 -07:00
parent c6007d9c33
commit 46d9f86d55
48 changed files with 4295 additions and 257 deletions

View File

@ -0,0 +1,176 @@
# 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)