From 26d634e64fe9b6a599dc63cd4abdcf2d213e55c7 Mon Sep 17 00:00:00 2001 From: Hilary James Oliver Date: Thu, 24 Jul 2025 05:32:36 +0000 Subject: [PATCH] Cylc Review: support alternate home dir. --- bin/cylc-review | 11 +++++++++-- lib/cylc/review.py | 19 +++++++++++++++++-- lib/cylc/review_dao.py | 31 +++++++++++++++++++------------ 3 files changed, 45 insertions(+), 16 deletions(-) diff --git a/bin/cylc-review b/bin/cylc-review index 9c779671883..2278e1fe23b 100755 --- a/bin/cylc-review +++ b/bin/cylc-review @@ -23,8 +23,15 @@ logs via an HTTP interface. With no arguments, the status of the ad-hoc web service server is printed. -For 'cylc review start', if 'PORT' is not specified, port 8080 is used.""" - +For 'cylc review start', if 'PORT' is not specified, port 8080 is used. + +If $CYLC_REVIEW_HOME is defined, look there for run directories instead of +in user home directories. This can be used to view symlinked run directories +directly when home directories are private. For example with symlinking as: + /home/USER/cylc-run/WORKFLOW -> /project/PROJECT/USER/cylc-run/WORKFLOW +set the environment variable as: + CYLC_REVIEW_HOME=/project/PROJECT +""" import sys diff --git a/lib/cylc/review.py b/lib/cylc/review.py index f3a20f82121..06407b9cb71 100644 --- a/lib/cylc/review.py +++ b/lib/cylc/review.py @@ -23,7 +23,15 @@ With no arguments, the status of the ad-hoc web service server is printed. -For 'cylc review start', if 'PORT' is not specified, port 8080 is used.""" +For 'cylc review start', if 'PORT' is not specified, port 8080 is used. + +If $CYLC_REVIEW_HOME is defined, look there for run directories instead of +in user home directories. This can be used to view symlinked run directories +directly when home directories are private. For example with symlinking as: + /home/USER/cylc-run/WORKFLOW -> /project/PROJECT/USER/cylc-run/WORKFLOW +set the environment variable as: + CYLC_REVIEW_HOME=/project/PROJECT +""" import cherrypy from fnmatch import fnmatch @@ -883,7 +891,9 @@ def _check_dir_access(cls, path): @staticmethod def _get_user_home(user): - """Return, e.g. ~/cylc-run/ for a cylc suite. + """Return user home dir. + + If $CYLC_REVIEW_HOME is defined, use that; else normal home dir. N.B. os.path.expanduser does not fail if ~user is invalid. @@ -891,6 +901,11 @@ def _get_user_home(user): cherrypy.HTTPError(404) """ + if os.environ.get('CYLC_REVIEW_HOME', False): + return os.path.join( + os.environ['CYLC_REVIEW_HOME'], + str(user) + ) try: return pwd.getpwnam(user).pw_dir except KeyError: diff --git a/lib/cylc/review_dao.py b/lib/cylc/review_dao.py index 9cb8337c259..e7db778e854 100644 --- a/lib/cylc/review_dao.py +++ b/lib/cylc/review_dao.py @@ -29,6 +29,20 @@ """Provide data access object to the suite runtime database for Cylc Review.""" +def get_prefix(user_name): + """Return user "home" dir under $CYLC_REVIEW_HOME, or else ~user_name.""" + if os.environ.get('CYLC_REVIEW_HOME', False) and user_name: + prefix = os.path.join( + os.environ['CYLC_REVIEW_HOME'], + str(user_name) + ) + else: + prefix = "~" + if user_name: + prefix += user_name + return prefix + + class CylcReviewDAO(object): """Cylc Review data access object to the suite runtime database.""" @@ -108,12 +122,11 @@ def _db_init(self, user_name, suite_name): """Initialise a named CylcSuiteDAO database connection.""" key = (user_name, suite_name) if key not in self.daos: - prefix = "~" - if user_name: - prefix += user_name for name in [os.path.join("log", "db"), "cylc-suite.db"]: db_f_name = os.path.expanduser(os.path.join( - prefix, os.path.join("cylc-run", suite_name, name))) + get_prefix(user_name), + os.path.join("cylc-run", + suite_name, name))) self.daos[key] = CylcSuiteDAO(db_f_name, is_public=True) if os.path.exists(db_f_name): break @@ -382,11 +395,8 @@ def _get_job_logs(self, user_name, suite_name, entries, entry_of): relevant entries of that cycle. Modify each entry in entries. """ - prefix = "~" - if user_name: - prefix += user_name user_suite_dir = os.path.expanduser(os.path.join( - prefix, os.path.join("cylc-run", suite_name))) + get_prefix(user_name), os.path.join("cylc-run", suite_name))) try: fs_log_cycles = os.listdir( os.path.join(user_suite_dir, "log", "job")) @@ -519,11 +529,8 @@ def get_suite_cycles_summary( integer_mode = row[0].isdigit() break - prefix = "~" - if user_name: - prefix += user_name user_suite_dir = os.path.expanduser(os.path.join( - prefix, os.path.join("cylc-run", suite_name))) + get_prefix(user_name), os.path.join("cylc-run", suite_name))) targzip_log_cycles = [] try: for item in os.listdir(os.path.join(user_suite_dir, "log")):