diff --git a/src/murfey/client/multigrid_control.py b/src/murfey/client/multigrid_control.py index de47ddee..dae0e7fb 100644 --- a/src/murfey/client/multigrid_control.py +++ b/src/murfey/client/multigrid_control.py @@ -378,6 +378,7 @@ def _start_rsyncer( stop_callback=self._rsyncer_stopped, do_transfer=self.do_transfer, remove_files=remove_files, + chmod=self._machine_config.get("rsync_chmod", "D0750,F0750"), substrings_blacklist=self._machine_config.get( "substrings_blacklist", {"directories": [], "files": []} ), diff --git a/src/murfey/client/rsync.py b/src/murfey/client/rsync.py index 5d27dc0d..475d3157 100644 --- a/src/murfey/client/rsync.py +++ b/src/murfey/client/rsync.py @@ -61,6 +61,7 @@ def __init__( local: bool = False, do_transfer: bool = True, remove_files: bool = False, + chmod: str = "D0750,F0750", required_substrings_for_removal: List[str] = [], substrings_blacklist: dict[str, list[str]] = {}, notify: bool = True, @@ -75,6 +76,7 @@ def __init__( self._local = local self._do_transfer = do_transfer self._remove_files = remove_files + self._chmod = chmod self._required_substrings_for_removal = required_substrings_for_removal self._substrings_blacklist = substrings_blacklist self._notify = notify @@ -501,7 +503,7 @@ def parse_stderr(line: str): # Needed as a pair to trigger permission modifications # Ref: https://serverfault.com/a/796341 "-p", - "--chmod=D0750,F0750", # Use extended chmod format + f"--chmod={self._chmod}", # Set permissions for transferred files and folders ] # Add file locations rsync_cmd.extend([".", self._remote]) diff --git a/src/murfey/server/api/file_io_instrument.py b/src/murfey/server/api/file_io_instrument.py index bbe12f1b..6346fc32 100644 --- a/src/murfey/server/api/file_io_instrument.py +++ b/src/murfey/server/api/file_io_instrument.py @@ -86,9 +86,11 @@ def suggest_path( count = count + 1 if count else 2 check_path = check_path.parent / f"{check_path_name}{count}" if params.touch: - check_path.mkdir(mode=0o750) + check_path.mkdir(mode=machine_config.mkdir_chmod) if params.extra_directory: - (check_path / secure_filename(params.extra_directory)).mkdir(mode=0o750) + (check_path / secure_filename(params.extra_directory)).mkdir( + mode=machine_config.mkdir_chmod + ) return {"suggested_path": check_path.relative_to(rsync_basepath)} @@ -112,7 +114,7 @@ def make_rsyncer_destination(session_id: int, destination: Dest, db=murfey_db): machine_config.rsync_basepath or Path("") ).resolve() / destination_path for parent_path in full_destination_path.parents: - parent_path.mkdir(mode=0o750, exist_ok=True) + parent_path.mkdir(mode=machine_config.mkdir_chmod, exist_ok=True) return destination diff --git a/src/murfey/util/config.py b/src/murfey/util/config.py index 5e50d7c2..580f423a 100644 --- a/src/murfey/util/config.py +++ b/src/murfey/util/config.py @@ -58,11 +58,13 @@ class MachineConfig(BaseModel): # type: ignore "directories": [], "files": [], } + mkdir_chmod: int = 0o750 # Rsync setup rsync_url: str = "" rsync_module: str = "" rsync_basepath: Optional[Path] = None + rsync_chmod: str = "D0750,F0750" allow_removal: bool = False # Upstream data download setup @@ -151,6 +153,15 @@ def validate_software_versions(cls, v: dict[str, Any]) -> dict[str, str]: # Let it validate and fail as-is return v + @field_validator("mkdir_chmod", mode="before") + @classmethod + def parse_octal_int(cls, value): + # Attempt to parse the string as an octal int + if isinstance(value, str): + return int(value, 8) + # Return value as-is otherwise + return value + @lru_cache(maxsize=1) def machine_config_from_file(