Repository: radiocosmology/alpenhorn

Issue:
Parameterise HSM restore recheck-time
>The `yield 600` (which occurs in other places too) is the re-check time for things restored from HSM.  That might be worth an I/O config field.

_Originally posted by @ketiltrout in https://github.com/radiocosmology/alpenhorn/issues/218#issuecomment-2471363589_

Discussion:

Solution patch:
diff --git a/alpenhorn/io/lustrehsm.py b/alpenhorn/io/lustrehsm.py
index b51ba1973..5dfb504fa 100644
--- a/alpenhorn/io/lustrehsm.py
+++ b/alpenhorn/io/lustrehsm.py
@@ -84,6 +84,9 @@ class LustreHSMNodeIO(LustreQuotaNodeIO):
         * release_check_count : integer
             The number of files to check at a time when doing idle HSM status
             update (see idle_update()).  Default is 100.
+        * restore_wait : integer
+            The number of seconds to wait between checking if a restore request
+            has completed.  Default is 600 seconds (10 minutes).
     """
 
     remote_class = LustreHSMNodeRemote
@@ -106,8 +109,15 @@ def __init__(
         # For informational purposes.  Keys are elements in self._restoring.
         self._restore_start = {}
 
+        self._restore_wait_time = int(config.get("restore_wait", 600))
+        if self._restore_wait_time < 1:
+            raise ValueError(
+                "io_config key 'restore_wait' non-positive "
+                f"(={self._restore_wait_time})"
+            )
+
         # For idle-time HSM state updates
-        self._nrelease = config.get("release_check_count", 100)
+        self._nrelease = int(config.get("release_check_count", 100))
         if self._nrelease < 1:
             raise ValueError(
                 f"io_config key 'release_check_count' non-positive (={self._nrelease})"
@@ -411,7 +421,7 @@ def _async(task: Task, node_io: LustreHSMNodeIO, copy: ArchiveFileCopy) -> None:
             restore_wait = node_io._restore_wait(copy)
             while restore_wait:
                 # Wait for a bit
-                yield 600
+                yield self._restore_wait_time
 
                 # Now check again
                 restore_wait = node_io._restore_wait(copy)
@@ -581,7 +591,7 @@ def _async(task: Task, node_io: LustreHSMNodeIO, file_: ArchiveFile):
             restore_wait = node_io._restore_wait(copy)
             while restore_wait:
                 # Wait for a bit
-                yield 600
+                yield self._restore_wait_time
 
                 # Now check again
                 restore_wait = node_io._restore_wait(copy)


Test patch:
diff --git a/tests/io/test_lustrehsmnode.py b/tests/io/test_lustrehsmnode.py
index e0deabecd..bc4106b4a 100644
--- a/tests/io/test_lustrehsmnode.py
+++ b/tests/io/test_lustrehsmnode.py
@@ -59,7 +59,7 @@ def test_init_no_headroom(have_lfs, simplenode):
 
 
 def test_init_bad_release_count(simplenode, have_lfs):
-    """Check for bad realse_check_count."""
+    """Check for bad release_check_count."""
 
     simplenode.io_class = "LustreHSM"
     simplenode.io_config = (
@@ -70,6 +70,18 @@ def test_init_bad_release_count(simplenode, have_lfs):
         UpdateableNode(None, simplenode)
 
 
+def test_init_bad_restore_wait(simplenode, have_lfs):
+    """Check for bad restore_wait."""
+
+    simplenode.io_class = "LustreHSM"
+    simplenode.io_config = (
+        '{"quota_group": "qgroup", "headroom": 300000, "restore_wait": -1}'
+    )
+
+    with pytest.raises(ValueError):
+        UpdateableNode(None, simplenode)
+
+
 def test_release_files_okay(queue, node):
     """Test running release_files when we're under headroom"""