Skip to content

Commit 92aadcb

Browse files
authored
Merge pull request #53 from lsst-sqre/tickets/DM-45035
tickets/DM-45035: Conditionally add DAF_BUTLER_CACHE_DIRECTORY to env
2 parents ed68a68 + 06818a1 commit 92aadcb

File tree

3 files changed

+80
-0
lines changed

3 files changed

+80
-0
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<!-- Delete the sections that don't apply -->
2+
3+
### New features
4+
5+
- Conditionally set environment variable `DAF_BUTLER_CACHE_DIRECTORY`

src/lsst/rsp/startup/services/labrunner.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ def _configure_env(self) -> None:
120120
self._logger.debug("Configuring environment for JupyterLab process")
121121
self._set_user()
122122
self._set_tmpdir_if_scratch_available()
123+
self._set_butler_cache()
123124
self._set_cpu_variables()
124125
self._set_image_digest()
125126
self._expand_panda_tilde()
@@ -169,6 +170,38 @@ def _set_tmpdir_if_scratch_available(self) -> None:
169170
return
170171
self._env["TMPDIR"] = str(user_scratch)
171172

173+
def _set_butler_cache(self) -> None:
174+
# This should be called *after* _set_tmpdir_if_scratch_available()
175+
# at least for now. We may eventually want to force it to local
176+
# ephemeral storage and demand enough ephemeral storage to cover it
177+
# (currently about 500MB).
178+
#
179+
# For now, though, let's set it to `butler_cache` inside `TMPDIR`
180+
dbcd = self._env.get("DAF_BUTLER_CACHE_DIRECTORY", "")
181+
if dbcd:
182+
self._logger.debug(
183+
f"Not setting DAF_BUTLER_CACHE_DIRECTORY: already set to"
184+
f" {dbcd}"
185+
)
186+
return
187+
# Yes, we know that ruff doesn't like `/tmp`
188+
# In any sane RSP environment, either we will have set TMPDIR, or
189+
# /tmp will be on ephemeral storage.
190+
tmpdir = Path(self._env.get("TMPDIR", "/tmp")) # noqa: S108
191+
dbc = tmpdir / "butler_cache"
192+
try:
193+
dbc.mkdir(parents=True, exist_ok=True)
194+
except (OSError, FileExistsError) as exc:
195+
self._logger.warning(
196+
f"Could not create DAF_BUTLER_CACHE_DIRECTORY at"
197+
f" {dbc!s}: {exc}"
198+
)
199+
return
200+
if not os.access(dbc, os.W_OK):
201+
self._logger.warning(f"Unable to write to {dbc}")
202+
return
203+
self._env["DAF_BUTLER_CACHE_DIRECTORY"] = str(dbc)
204+
172205
def _set_cpu_variables(self) -> None:
173206
self._logger.debug("Setting CPU threading variables")
174207
try:

tests/startup_test.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,48 @@ def test_set_tmpdir(monkeypatch: pytest.MonkeyPatch) -> None:
7070
assert "TMPDIR" not in lr._env
7171

7272

73+
@pytest.mark.usefixtures("_rsp_env")
74+
def test_set_butler_cache(monkeypatch: pytest.MonkeyPatch) -> None:
75+
# Happy path.
76+
lr = LabRunner()
77+
lr._set_tmpdir_if_scratch_available()
78+
lr._set_butler_cache()
79+
assert lr._env["DAF_BUTLER_CACHE_DIRECTORY"].endswith(
80+
"/scratch/hambone/tmp/butler_cache"
81+
)
82+
# Exists, but it's not a directory
83+
dbc = Path(lr._env["DAF_BUTLER_CACHE_DIRECTORY"])
84+
dbc.rmdir()
85+
dbc.touch()
86+
lr = LabRunner()
87+
lr._set_tmpdir_if_scratch_available()
88+
lr._set_butler_cache()
89+
assert "DAF_BUTLER_CACHE_DIRECTORY" not in lr._env
90+
# Put it back the way it was
91+
dbc.unlink()
92+
# Pre-set DAF_BUTLER_CACHE_DIR.
93+
monkeypatch.setenv("DAF_BUTLER_CACHE_DIRECTORY", "/preset")
94+
lr = LabRunner()
95+
lr._set_butler_cache()
96+
assert lr._env["DAF_BUTLER_CACHE_DIRECTORY"] == "/preset"
97+
monkeypatch.delenv("DAF_BUTLER_CACHE_DIRECTORY")
98+
# Pre-set TMPDIR so cache is not writeable
99+
monkeypatch.setenv("TMPDIR", "/nonexistent")
100+
lr = LabRunner()
101+
lr._set_butler_cache()
102+
assert "DAF_BUTLER_CACHE_DIRECTORY" not in lr._env
103+
monkeypatch.delenv("TMPDIR")
104+
# No TMPDIR set: should go under `/tmp`
105+
lr = LabRunner()
106+
lr._set_butler_cache()
107+
e_dbcd = lr._env["DAF_BUTLER_CACHE_DIRECTORY"]
108+
# Yes, we know that ruff doesn't like `/tmp`
109+
# In any sane RSP environment, either we will have set TMPDIR, or
110+
# /tmp will be on ephemeral storage.
111+
assert e_dbcd == "/tmp/butler_cache" # noqa: S108
112+
Path(e_dbcd).rmdir()
113+
114+
73115
@pytest.mark.usefixtures("_rsp_env")
74116
def test_cpu_vars(monkeypatch: pytest.MonkeyPatch) -> None:
75117
lr = LabRunner()

0 commit comments

Comments
 (0)