177 lines
4.9 KiB
Python
177 lines
4.9 KiB
Python
# 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)
|
|
|