diff --git a/webservice/serve_overview.py b/webservice/serve_overview.py index 919d48c153aa102b3dc0dfed40e5b0d5b7f8bd6a..ded99ef5897692c578cd24974e8564d1ebc94810 100644 --- a/webservice/serve_overview.py +++ b/webservice/serve_overview.py @@ -2,10 +2,10 @@ import argparse import glob import os import sqlite3 -from collections import OrderedDict from datetime import datetime, timezone from http.server import BaseHTTPRequestHandler, HTTPServer from pathlib import Path +from shutil import copyfileobj from subprocess import check_output from typing import Optional @@ -20,34 +20,11 @@ except: from config import serve_overview as config - -class LimitedSizeDict(OrderedDict): - def __init__(self, *args, **kwds): - self.size_limit = kwds.pop("size_limit", None) - OrderedDict.__init__(self, *args, **kwds) - self._check_size_limit() - - def __setitem__(self, key, value): - OrderedDict.__setitem__(self, key, value) - self._check_size_limit() - - def _check_size_limit(self): - if self.size_limit is not None: - while len(self) > self.size_limit: - self.popitem(last=False) - - -pdf_queue = LimitedSizeDict(size_limit=50) - - # HTTPRequestHandler class class RequestHandler(BaseHTTPRequestHandler): conf_was_init = False def init_config(self): - - global cal_config - self.total_jobs_cmd = config["shell-commands"]["total-jobs"] self.tail_log_cmd = config["shell-commands"]["tail-log"] self.cat_log_cmd = config["shell-commands"]["cat-log"] @@ -57,98 +34,94 @@ class RequestHandler(BaseHTTPRequestHandler): for template, tfile in config["templates"].items(): with open(tfile, "r") as tf: self.templates[template] = tf.read() - global pdf_queue - self.pdf_queue = pdf_queue + self.conf_was_init = True + def serve_css(self): + """Serve /serve_overview.css""" + self.send_response(200) + self.send_header('Content-type', 'text/css') + self.end_headers() + self.wfile.write(self.templates["css"].encode('utf-8')) + + def serve_dark_overview(self): + # Send headers + self.send_response(200) + self.send_header('Content-type', 'text/html') + self.end_headers() + host = config["server-config"]["host"] + port = config["server-config"]["port"] + reports = {} + for instrument, detectors in cal_config['dark'].items(): + reports[instrument] = {} + for detector in detectors: + tmpl = f'/gpfs/exfel/d/cal/caldb_store/xfel/reports/{instrument}/{detector}/dark/*pdf' + files = glob.glob(tmpl) + files.sort(key=os.path.getmtime, reverse=True) + file_info = [] + for i, file in enumerate(files): + if (len(file_info) % 2) == 0: + bgcolor = 'EEEEEE' + else: + bgcolor = 'FFFFFF' + time = os.stat(file).st_mtime + d_time = datetime.fromtimestamp(time).replace( + tzinfo=timezone.utc) + s_time = d_time.strftime('%y-%m-%d %H:%M') + file_info.append([file, s_time, bgcolor]) + + reports[instrument][detector] = file_info + + tmpl = Template(self.templates["dark-overview"]) + message = tmpl.render(reports=reports, host=host, port=port) + + self.wfile.write(bytes(message, "utf8")) + + def serve_file_from_gpfs(self): + """Serve a file from a path starting with /gpfs""" + if self.path.endswith(".html"): + mimetype = 'text/html' + elif self.path.endswith(".jpg"): + mimetype = 'image/jpg' + elif self.path.endswith(".gif"): + mimetype = 'image/gif' + elif self.path.endswith(".png"): + mimetype = 'image/png' + elif self.path.endswith(".pdf"): + mimetype = 'application/pdf' + elif self.path.endswith(".js"): + mimetype = 'application/javascript' + elif self.path.endswith(".css"): + mimetype = 'text/css' + else: + return self.send_error(404) + + if os.path.isfile(self.path): + self.send_response(200) + self.send_header('Content-Length', str(os.stat(self.path).st_size)) + self.send_header('Content-type', mimetype) + self.end_headers() + with open(self.path, "rb") as f: + copyfileobj(f, self.wfile) + else: + self.send_error(404) + def do_GET(self): if not self.conf_was_init: self.init_config() - # Send response status code - self.send_response(200) + if "/serve_overview.css" in self.path: - self.send_header('Content-type', 'text/css') - self.end_headers() - for s in self.templates["css"].split("\n"): - self.wfile.write(s.encode()) - return - - if "pdf?" in self.path: - puuid = self.path.split("?")[1] - fpath = self.pdf_queue.get(puuid, None) - if fpath is None: - return - self.send_header('Content-type', 'application/pdf') - self.end_headers() - with open(fpath, "rb") as f: - self.wfile.write(f.read()) - return + return self.serve_css() if "dark?" in self.path: - # Send headers - self.send_header('Content-type', 'text/html') - self.end_headers() - host = config["server-config"]["host"] - port = config["server-config"]["port"] - reports = {} - for instrument, detectors in cal_config['dark'].items(): - reports[instrument] = {} - for detector in detectors: - tmpl = f'/gpfs/exfel/d/cal/caldb_store/xfel/reports/{instrument}/{detector}/dark/*pdf' - files = glob.glob(tmpl) - files.sort(key=os.path.getmtime, reverse=True) - file_info = [] - for i, file in enumerate(files): - if (len(file_info) % 2) == 0: - bgcolor = 'EEEEEE' - else: - bgcolor = 'FFFFFF' - time = os.stat(file).st_mtime - d_time = datetime.fromtimestamp(time).replace( - tzinfo=timezone.utc) - s_time = d_time.strftime('%y-%m-%d %H:%M') - file_info.append([file, s_time, bgcolor]) - - reports[instrument][detector] = file_info - - tmpl = Template(self.templates["dark-overview"]) - message = tmpl.render(reports=reports, host=host, port=port) - - self.wfile.write(bytes(message, "utf8")) - return + return self.serve_dark_overview() if "/gpfs" in self.path: - sendReply = False - if self.path.endswith(".html"): - mimetype = 'text/html' - sendReply = True - if self.path.endswith(".jpg"): - mimetype = 'image/jpg' - sendReply = True - if self.path.endswith(".gif"): - mimetype = 'image/gif' - sendReply = True - if self.path.endswith(".png"): - mimetype = 'image/png' - sendReply = True - if self.path.endswith(".pdf"): - mimetype = 'application/pdf' - sendReply = True - if self.path.endswith(".js"): - mimetype = 'application/javascript' - sendReply = True - if self.path.endswith(".css"): - mimetype = 'text/css' - sendReply = True - - if sendReply == True and os.path.isfile(self.path): - with open(self.path, "rb") as f: - self.send_header('Content-type', mimetype) - self.end_headers() - self.wfile.write(f.read()) - return + return self.serve_file_from_gpfs() + # Send response status code + self.send_response(200) # Send headers self.send_header('Content-type', 'text/html')