From 2d06ab81d59d9ac7131bccbc5e8f0fc25dfc3043 Mon Sep 17 00:00:00 2001 From: deepssin Date: Thu, 24 Jul 2025 07:01:45 -0400 Subject: [PATCH] Add WSGI handler to serve Teuthology logs Signed-off-by: deepssin --- run.py | 40 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/run.py b/run.py index 1a5e7fa..e73992a 100644 --- a/run.py +++ b/run.py @@ -3,6 +3,7 @@ from cheroot.wsgi import Server as WSGIServer, PathInfoDispatcher from pecan.deploy import deploy +from urllib.parse import unquote import prod @@ -16,6 +17,35 @@ class Root(object): pass +def teuthology_app(environ, start_response): + path = unquote(environ.get('PATH_INFO', '')).strip('/') + if not path.startswith('teuthology/'): + start_response('404 Not Found', [('Content-Type', 'text/plain')]) + return [b'Invalid request'] + + segments = path.split('/') + if len(segments) < 4: + start_response('404 Not Found', [('Content-Type', 'text/plain')]) + return [b'Invalid path structure'] + + _, run, job_id, filename = segments[:4] + archive_root = os.environ.get('PULPITO_ARCHIVE', '') + log_path = os.path.join(archive_root, run, job_id, filename) + + if not os.path.exists(log_path): + start_response('404 Not Found', [('Content-Type', 'text/plain')]) + return [b'Log not found'] + + try: + with open(log_path, 'rb') as f: + content = f.read() + start_response('200 OK', [('Content-Type', 'text/plain')]) + return [f"----------LOG START----------".encode() + content] + except Exception as e: + start_response('500 Internal Server Error', [('Content-Type', 'text/plain')]) + return [f'Error reading file: {e}'.encode()] + + def make_static_config(static_dir_name): """ All custom static configurations are set here, since most are common, it @@ -38,12 +68,18 @@ def make_static_config(static_dir_name): '/js': make_static_config('js'), '/images': make_static_config('images'), '/fonts': make_static_config('fonts'), - '/favicon.ico': make_static_config('images'), + '/favicon.ico': make_static_config('images'), + '/teuthology': teuthology_app, }) +def final_app(environ, start_response): + if environ.get('PATH_INFO', '').startswith('/teuthology/'): + return teuthology_app(environ, start_response) + return application(environ, start_response) + server = WSGIServer( (prod.server['host'], int(prod.server['port'])), - application + final_app ) try: