From 48fb864094748bcbc07a712d6454eb670deea100 Mon Sep 17 00:00:00 2001 From: yoshifuminakamura Date: Wed, 17 Sep 2025 17:37:25 +0900 Subject: [PATCH 1/5] fixing estimated_results.html --- result_server/utils/results_loader.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/result_server/utils/results_loader.py b/result_server/utils/results_loader.py index a89b014..b645706 100644 --- a/result_server/utils/results_loader.py +++ b/result_server/utils/results_loader.py @@ -131,8 +131,8 @@ def load_estimated_results_table(public_only=True, session_email=None, authentic if data is None: continue - current = data.get("current system", {}) - future = data.get("future system", {}) + current = data.get("current_system", {}) + future = data.get("future_system", {}) row = { # "timestamp": timestamp, @@ -142,11 +142,13 @@ def load_estimated_results_table(public_only=True, session_email=None, authentic "benchmark_fom": data.get("benchmark_fom", ""), "benchmark_nodes": data.get("benchmark_nodes", ""), "systemA_fom": current.get("fom", ""), - "systemA_method": current.get("method", ""), + "systemA_system": current.get("system", ""), "systemA_nodes": current.get("nodes", ""), + "systemA_method": current.get("method", ""), "systemB_fom": future.get("fom", ""), - "systemB_method": future.get("method", ""), + "systemB_system": future.get("system", ""), "systemB_nodes": future.get("nodes", ""), + "systemB_method": future.get("method", ""), "performance_ratio": data.get("performance_ratio", ""), "json_link": json_file, } @@ -160,11 +162,11 @@ def load_estimated_results_table(public_only=True, session_email=None, authentic ("Benchmark FOM", "benchmark_fom"), ("Benchmark Nodes", "benchmark_nodes"), ("System A FOM", "systemA_fom"), - ("System A Method", "systemA_method"), ("System A Nodes", "systemA_nodes"), + ("System A Method", "systemA_method"), ("System B FOM", "systemB_fom"), - ("System B Method", "systemB_method"), ("System B Nodes", "systemB_nodes"), + ("System B Method", "systemB_method"), ("Performance Ratio", "performance_ratio"), ("JSON", "json_link"), ] From 0525649f30b81173adbf03655d0cfa2a25567a1d Mon Sep 17 00:00:00 2001 From: yoshifuminakamura Date: Wed, 17 Sep 2025 17:50:09 +0900 Subject: [PATCH 2/5] fixing estimated_results.html(missing more file to be added) --- .../templates/estimated_results.html | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/result_server/templates/estimated_results.html b/result_server/templates/estimated_results.html index 7aee3c9..6930165 100644 --- a/result_server/templates/estimated_results.html +++ b/result_server/templates/estimated_results.html @@ -21,21 +21,24 @@

Estimated Results

Code Exp - System A - System B - Benchmark + System A + System B + Benchmark JSON Ratio FOM - Method + System Nodes - FOM Method + FOM + System Nodes + Method FOM System + Nodes @@ -44,13 +47,16 @@

Estimated Results

{{ r.code }} {{ r.exp }} {{ r.systemA_fom }} - {{ r.systemA_method }} + {{ r.systemA_system }} {{ r.systemA_nodes }} + {{ r.systemA_method }} {{ r.systemB_fom }} - {{ r.systemB_method }} + {{ r.systemB_system }} {{ r.systemB_nodes }} + {{ r.systemB_method }} {{ r.benchmark_fom }} {{ r.benchmark_system }} + {{ r.benchmark_nodes }} json From 04f9db587b48a0cf88b6713690f30dcfaee6bd52 Mon Sep 17 00:00:00 2001 From: yoshifuminakamura Date: Thu, 18 Sep 2025 11:14:05 +0900 Subject: [PATCH 3/5] merging from benchest, more standardized --- result_server/routes/receive.py | 91 ++++++++++++++++--- .../templates/estimated_results.html | 2 + result_server/utils/results_loader.py | 18 +++- 3 files changed, 97 insertions(+), 14 deletions(-) diff --git a/result_server/routes/receive.py b/result_server/routes/receive.py index 9b38ac2..c532736 100644 --- a/result_server/routes/receive.py +++ b/result_server/routes/receive.py @@ -7,31 +7,98 @@ EXPECTED_API_KEY = os.environ.get("RESULT_SERVER_KEY") SAVE_DIR = "received" +ESTIMATED_RESULT_DIR = "estimated_results" -@receive_bp.route("write-api", methods=["POST"]) -def receive(): +def require_api_key(): api_key = request.headers.get("X-API-Key") if api_key != EXPECTED_API_KEY: abort(401, description="Invalid API Key") - data = request.data +def save_json_file(data, prefix, out_dir, given_uuid=None): timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") - unique_id = str(uuid.uuid4()) + unique_id = given_uuid or str(uuid.uuid4()) + filename = f"{prefix}_{timestamp}_{unique_id}.json" + path = os.path.join(out_dir, filename) + tmp_path = path + ".tmp" - json_filename = f"result_{timestamp}_{unique_id}.json" - json_path = os.path.join(SAVE_DIR, json_filename) - # rename (atomic)を使って確実にflushする - tmp_path = json_path + ".tmp" + #------------------------------This is for + #data = request.data + #------------------------------ with open(tmp_path, "wb") as f: f.write(data) f.flush() os.fsync(f.fileno()) - os.rename(tmp_path, json_path) - print(f"Saved: {json_path}", flush=True) + #-----------------------------This is for + #data = request.get_json() + #----------------------------- + #with open(tmp_path, "w", encoding="utf-8") as f: + # json.dump(data, f, indent=2, ensure_ascii=False) + # f.flush() + # os.fsync(f.fileno()) + + os.rename(tmp_path, path) + print(f"Saved {prefix}: {path}", flush=True) + return { "status": "ok", "id": unique_id, "timestamp": timestamp, - "json_file": json_filename, - }, 200 + "json_file": filename, + } + + +@receive_bp.route("write-api", methods=["POST"]) +def receive_result(): + require_api_key() + data = request.data + #data = request.get_json() + return save_json_file( + data=data, + prefix="result", + out_dir=SAVE_DIR + ), 200 + +@receive_bp.route("write-est", methods=["POST"]) +def upload_estimate(): + require_api_key() + data = request.data + #data = request.get_json() + return save_json_file( + data=data, + prefix="estimate", + out_dir=ESTIMATED_RESULT_DIR, + given_uuid=request.headers.get("X-UUID") + ), 200 + + + + + +#@receive_bp.route("write-api", methods=["POST"]) +#def receive(): +# api_key = request.headers.get("X-API-Key") +# if api_key != EXPECTED_API_KEY: +# abort(401, description="Invalid API Key") +# +# data = request.data +# timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") +# unique_id = str(uuid.uuid4()) +# +# json_filename = f"result_{timestamp}_{unique_id}.json" +# json_path = os.path.join(SAVE_DIR, json_filename) +# # rename (atomic)を使って確実にflushする +# tmp_path = json_path + ".tmp" +# with open(tmp_path, "wb") as f: +# f.write(data) +# f.flush() +# os.fsync(f.fileno()) +# os.rename(tmp_path, json_path) +# +# print(f"Saved: {json_path}", flush=True) +# return { +# "status": "ok", +# "id": unique_id, +# "timestamp": timestamp, +# "json_file": json_filename, +# }, 200 diff --git a/result_server/templates/estimated_results.html b/result_server/templates/estimated_results.html index 6930165..13408d7 100644 --- a/result_server/templates/estimated_results.html +++ b/result_server/templates/estimated_results.html @@ -19,6 +19,7 @@

Estimated Results

+ @@ -44,6 +45,7 @@

Estimated Results

{% for r in rows %} + diff --git a/result_server/utils/results_loader.py b/result_server/utils/results_loader.py index b645706..37a4cb6 100644 --- a/result_server/utils/results_loader.py +++ b/result_server/utils/results_loader.py @@ -70,6 +70,7 @@ def load_results_table(public_only=True, session_email=None, authenticated=False gpus = data.get("gpus_per_node", "N/A") cpu_cores = data.get("cpu_cores", "N/A") + # get timestamp and uuid match = re.search(r"\d{8}_\d{6}", json_file) timestamp = "Unknown" if match: @@ -134,8 +135,21 @@ def load_estimated_results_table(public_only=True, session_email=None, authentic current = data.get("current_system", {}) future = data.get("future_system", {}) + # get timestamp and uuid + match = re.search(r"\d{8}_\d{6}", json_file) + timestamp = "Unknown" + if match: + try: + ts = datetime.strptime(match.group(), "%Y%m%d_%H%M%S") + timestamp = ts.strftime("%Y-%m-%d %H:%M:%S") + except: + pass + + uuid_match = re.search(r"[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}", json_file, re.IGNORECASE) + uid = uuid_match.group(0) if uuid_match else None + row = { -# "timestamp": timestamp, + "timestamp": timestamp, "code": data.get("code", ""), "exp": data.get("exp", ""), "benchmark_system": data.get("benchmark_system", ""), @@ -155,7 +169,7 @@ def load_estimated_results_table(public_only=True, session_email=None, authentic rows.append(row) columns = [ - #("Timestamp", "timestamp"), + ("Timestamp", "timestamp"), ("CODE", "code"), ("Exp", "exp"), ("Benchmark System", "benchmark_system"), From fc82d9886f099d43cd2e0a56f25f7c9aced51136 Mon Sep 17 00:00:00 2001 From: yoshifuminakamura Date: Thu, 18 Sep 2025 12:24:35 +0900 Subject: [PATCH 4/5] fixed link generation --- result_server/templates/_results_table.html | 2 +- result_server/utils/results_loader.py | 10 ++++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/result_server/templates/_results_table.html b/result_server/templates/_results_table.html index 0fb83eb..0a87f8f 100644 --- a/result_server/templates/_results_table.html +++ b/result_server/templates/_results_table.html @@ -16,7 +16,7 @@ {% if key in ["json_link", "data_link"] %}
Timestamp Code Exp System A
{{ r.timestamp }} {{ r.code }} {{ r.exp }} {{ r.systemA_fom }} {% if row[key] %} - + {{ "json" if key == "json_link" else "data" }} {% else %} diff --git a/result_server/utils/results_loader.py b/result_server/utils/results_loader.py index 37a4cb6..f1f1978 100644 --- a/result_server/utils/results_loader.py +++ b/result_server/utils/results_loader.py @@ -4,6 +4,7 @@ from datetime import datetime from utils.result_file import get_file_confidential_tags from utils.otp_manager import get_affiliations +from flask import url_for #-------------------------------------------------------------------------------------------------------------- def load_json_with_confidential_filter(json_file, directory, affs=None, public_only=True, authenticated=False): @@ -97,8 +98,13 @@ def load_results_table(public_only=True, session_email=None, authenticated=False "cpus": cpus, "gpus": gpus, "cpu_cores": cpu_cores, - "json_link": json_file, - "data_link": tgz_file, + # error handling to avoid strange link generation such as ../resuts//dev/results/result_...json + #"json_link": url_for("results.show_result", filename=json_file.split("results/")[-1].lstrip("/")), + #"data_link": url_for("results.show_result", filename=tgz_file.split("results/")[-1].lstrip("/")) if tgz_file else None, + "json_link": url_for("results.show_result", filename=json_file), + "data_link": url_for("results.show_result", filename=tgz_file) if tgz_file else None, + #"json_link": json_file, + #"data_link": tgz_file, } rows.append(row) From 0bd1ca4680666b3acef88c23a01c63111ebf6ef0 Mon Sep 17 00:00:00 2001 From: yoshifuminakamura Date: Thu, 18 Sep 2025 16:13:25 +0900 Subject: [PATCH 5/5] fixed session and key --- result_server/app.py | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/result_server/app.py b/result_server/app.py index b56ba5f..36bd37c 100644 --- a/result_server/app.py +++ b/result_server/app.py @@ -1,5 +1,6 @@ import os import sys +from datetime import timedelta # Retrieve the API key from environment variable (needed in receive.py) EXPECTED_API_KEY = os.environ.get("RESULT_SERVER_KEY") @@ -32,7 +33,24 @@ def create_app(prefix="", base_dir=None): # Set a secret key for session management (required for flash and OTP sessions) # In production, use a secure random key, e.g., os.urandom(24) - app.secret_key = os.environ.get("FLASK_SECRET_KEY", "dev_secret_key") + #app.secret_key = os.environ.get("FLASK_SECRET_KEY", "dev_secret_key") + + # --- Secret Key --- + secret_key = os.environ.get("FLASK_SECRET_KEY") + if not secret_key: + raise RuntimeError("FLASK_SECRET_KEY must be set in production") + app.secret_key = secret_key + + # --- セッションCookieのセキュリティ設定 --- + app.config.update( + SESSION_COOKIE_SECURE=True, # HTTPS必須 + SESSION_COOKIE_HTTPONLY=True, # JSからのアクセス禁止 + SESSION_COOKIE_SAMESITE="Strict", # もしくは "Lax" + PERMANENT_SESSION_LIFETIME=timedelta(minutes=30), # セッション寿命を短めに + ) + + + # make dir, !!!!!!!! received & estimated_results received_dir = os.path.join(base_dir, "received")