fractal-server 2.7.0a9__tar.gz → 2.7.0a10__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/PKG-INFO +1 -1
- fractal_server-2.7.0a10/fractal_server/__init__.py +1 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/runner/executors/slurm/ssh/executor.py +10 -12
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/ssh/_fabric.py +186 -73
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/tasks/v2/background_operations_ssh.py +15 -9
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/pyproject.toml +2 -2
- fractal_server-2.7.0a9/fractal_server/__init__.py +0 -1
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/LICENSE +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/README.md +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/__main__.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/alembic.ini +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/__init__.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/db/__init__.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/models/__init__.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/models/linkusergroup.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/models/linkuserproject.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/models/security.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/models/user_settings.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/models/v1/__init__.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/models/v1/dataset.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/models/v1/job.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/models/v1/project.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/models/v1/state.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/models/v1/task.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/models/v1/workflow.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/models/v2/__init__.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/models/v2/collection_state.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/models/v2/dataset.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/models/v2/job.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/models/v2/project.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/models/v2/task.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/models/v2/workflow.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/models/v2/workflowtask.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/routes/__init__.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/routes/admin/__init__.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/routes/admin/v1.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/routes/admin/v2/__init__.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/routes/admin/v2/job.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/routes/admin/v2/project.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/routes/admin/v2/task.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/routes/admin/v2/task_group.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/routes/api/__init__.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/routes/api/v1/__init__.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/routes/api/v1/_aux_functions.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/routes/api/v1/dataset.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/routes/api/v1/job.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/routes/api/v1/project.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/routes/api/v1/task.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/routes/api/v1/task_collection.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/routes/api/v1/workflow.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/routes/api/v1/workflowtask.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/routes/api/v2/__init__.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/routes/api/v2/_aux_functions.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/routes/api/v2/_aux_functions_tasks.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/routes/api/v2/dataset.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/routes/api/v2/images.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/routes/api/v2/job.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/routes/api/v2/project.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/routes/api/v2/status.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/routes/api/v2/submit.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/routes/api/v2/task.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/routes/api/v2/task_collection.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/routes/api/v2/task_collection_custom.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/routes/api/v2/task_group.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/routes/api/v2/workflow.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/routes/api/v2/workflow_import.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/routes/api/v2/workflowtask.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/routes/auth/__init__.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/routes/auth/_aux_auth.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/routes/auth/current_user.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/routes/auth/group.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/routes/auth/login.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/routes/auth/oauth.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/routes/auth/register.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/routes/auth/router.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/routes/auth/users.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/routes/aux/__init__.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/routes/aux/_job.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/routes/aux/_runner.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/routes/aux/validate_user_settings.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/runner/.gitignore +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/runner/__init__.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/runner/async_wrap.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/runner/components.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/runner/compress_folder.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/runner/exceptions.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/runner/executors/__init__.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/runner/executors/slurm/__init__.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/runner/executors/slurm/_batching.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/runner/executors/slurm/_slurm_config.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/runner/executors/slurm/remote.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/runner/executors/slurm/ssh/__init__.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/runner/executors/slurm/ssh/_executor_wait_thread.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/runner/executors/slurm/ssh/_slurm_job.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/runner/executors/slurm/sudo/__init__.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/runner/executors/slurm/sudo/_check_jobs_status.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/runner/executors/slurm/sudo/_executor_wait_thread.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/runner/executors/slurm/sudo/_subprocess_run_as_user.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/runner/executors/slurm/sudo/executor.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/runner/extract_archive.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/runner/filenames.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/runner/run_subprocess.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/runner/set_start_and_last_task_index.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/runner/shutdown.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/runner/task_files.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/runner/v1/__init__.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/runner/v1/_common.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/runner/v1/_local/__init__.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/runner/v1/_local/_local_config.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/runner/v1/_local/_submit_setup.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/runner/v1/_local/executor.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/runner/v1/_slurm/__init__.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/runner/v1/_slurm/_submit_setup.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/runner/v1/_slurm/get_slurm_config.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/runner/v1/common.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/runner/v1/handle_failed_job.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/runner/v2/__init__.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/runner/v2/_local/__init__.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/runner/v2/_local/_local_config.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/runner/v2/_local/_submit_setup.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/runner/v2/_local/executor.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/runner/v2/_local_experimental/__init__.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/runner/v2/_local_experimental/_local_config.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/runner/v2/_local_experimental/_submit_setup.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/runner/v2/_local_experimental/executor.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/runner/v2/_slurm_common/__init__.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/runner/v2/_slurm_common/get_slurm_config.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/runner/v2/_slurm_ssh/__init__.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/runner/v2/_slurm_ssh/_submit_setup.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/runner/v2/_slurm_sudo/__init__.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/runner/v2/_slurm_sudo/_submit_setup.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/runner/v2/deduplicate_list.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/runner/v2/handle_failed_job.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/runner/v2/merge_outputs.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/runner/v2/runner.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/runner/v2/runner_functions.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/runner/v2/runner_functions_low_level.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/runner/v2/task_interface.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/runner/versions.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/schemas/__init__.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/schemas/_validators.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/schemas/user.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/schemas/user_group.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/schemas/user_settings.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/schemas/v1/__init__.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/schemas/v1/applyworkflow.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/schemas/v1/dataset.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/schemas/v1/dumps.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/schemas/v1/manifest.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/schemas/v1/project.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/schemas/v1/state.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/schemas/v1/task.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/schemas/v1/task_collection.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/schemas/v1/workflow.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/schemas/v2/__init__.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/schemas/v2/dataset.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/schemas/v2/dumps.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/schemas/v2/job.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/schemas/v2/manifest.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/schemas/v2/project.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/schemas/v2/status.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/schemas/v2/task.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/schemas/v2/task_collection.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/schemas/v2/task_group.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/schemas/v2/workflow.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/schemas/v2/workflowtask.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/security/__init__.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/user_settings.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/config.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/data_migrations/2_7_0.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/data_migrations/README.md +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/data_migrations/tools.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/gunicorn_fractal.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/images/__init__.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/images/models.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/images/tools.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/logger.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/main.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/migrations/README +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/migrations/env.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/migrations/naming_convention.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/migrations/script.py.mako +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/migrations/versions/034a469ec2eb_task_groups.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/migrations/versions/091b01f51f88_add_usergroup_and_linkusergroup_table.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/migrations/versions/4c308bcaea2b_add_task_args_schema_and_task_args_.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/migrations/versions/4cedeb448a53_workflowtask_foreign_keys_not_nullables.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/migrations/versions/501961cfcd85_remove_link_between_v1_and_v2_tasks_.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/migrations/versions/50a13d6138fd_initial_schema.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/migrations/versions/5bf02391cfef_v2.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/migrations/versions/70e77f1c38b0_add_applyworkflow_first_task_index_and_.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/migrations/versions/71eefd1dd202_add_slurm_accounts.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/migrations/versions/84bf0fffde30_add_dumps_to_applyworkflow.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/migrations/versions/8f79bd162e35_add_docs_info_and_docs_link_to_task_.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/migrations/versions/94a47ea2d3ff_remove_cache_dir_slurm_user_and_slurm_.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/migrations/versions/97f444d47249_add_applyworkflow_project_dump.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/migrations/versions/99ea79d9e5d2_add_dataset_history.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/migrations/versions/9c5ae74c9b98_add_user_settings_table.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/migrations/versions/9fd26a2b0de4_add_workflow_timestamp_created.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/migrations/versions/a7f4d6137b53_add_workflow_dump_to_applyworkflow.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/migrations/versions/d4fe3708d309_make_applyworkflow_workflow_dump_non_.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/migrations/versions/da2cb2ac4255_user_group_viewer_paths.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/migrations/versions/e75cac726012_make_applyworkflow_start_timestamp_not_.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/migrations/versions/efa89c30e0a4_add_project_timestamp_created.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/migrations/versions/f384e1c0cf5d_drop_task_default_args_columns.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/py.typed +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/ssh/__init__.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/string_tools.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/syringe.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/tasks/__init__.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/tasks/utils.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/tasks/v1/_TaskCollectPip.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/tasks/v1/__init__.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/tasks/v1/background_operations.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/tasks/v1/endpoint_operations.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/tasks/v1/get_collection_data.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/tasks/v1/utils.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/tasks/v2/__init__.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/tasks/v2/_venv_pip.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/tasks/v2/background_operations.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/tasks/v2/database_operations.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/tasks/v2/endpoint_operations.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/tasks/v2/templates/_1_create_venv.sh +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/tasks/v2/templates/_2_upgrade_pip.sh +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/tasks/v2/templates/_3_pip_install.sh +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/tasks/v2/templates/_4_pip_freeze.sh +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/tasks/v2/templates/_5_pip_show.sh +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/tasks/v2/utils.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/urls.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/utils.py +0 -0
- {fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/zip_tools.py +0 -0
@@ -0,0 +1 @@
|
|
1
|
+
__VERSION__ = "2.7.0a10"
|
@@ -861,7 +861,7 @@ class FractalSlurmSSHExecutor(SlurmExecutor):
|
|
861
861
|
|
862
862
|
# Transfer archive
|
863
863
|
t_0_put = time.perf_counter()
|
864
|
-
self.fractal_ssh.
|
864
|
+
self.fractal_ssh.send_file(
|
865
865
|
local=tarfile_path_local,
|
866
866
|
remote=tarfile_path_remote,
|
867
867
|
)
|
@@ -1255,16 +1255,9 @@ class FractalSlurmSSHExecutor(SlurmExecutor):
|
|
1255
1255
|
self.workflow_dir_remote / f"{subfolder_name}.tar.gz"
|
1256
1256
|
).as_posix()
|
1257
1257
|
|
1258
|
-
# Remove
|
1259
|
-
|
1260
|
-
|
1261
|
-
|
1262
|
-
# Remove remote tarfile - FIXME SSH: is this needed?
|
1263
|
-
# rm_command = f"rm {tarfile_path_remote}"
|
1264
|
-
# _run_command_over_ssh(cmd=rm_command, fractal_ssh=self.fractal_ssh)
|
1265
|
-
logger.warning(f"Unlink {tarfile_path_remote=} - START")
|
1266
|
-
self.fractal_ssh.sftp().unlink(tarfile_path_remote)
|
1267
|
-
logger.warning(f"Unlink {tarfile_path_remote=} - STOP")
|
1258
|
+
# Remove remote tarfile
|
1259
|
+
rm_command = f"rm {tarfile_path_remote}"
|
1260
|
+
self.fractal_ssh.run_command(cmd=rm_command)
|
1268
1261
|
|
1269
1262
|
# Create remote tarfile
|
1270
1263
|
tar_command = (
|
@@ -1278,7 +1271,7 @@ class FractalSlurmSSHExecutor(SlurmExecutor):
|
|
1278
1271
|
|
1279
1272
|
# Fetch tarfile
|
1280
1273
|
t_0_get = time.perf_counter()
|
1281
|
-
self.fractal_ssh.
|
1274
|
+
self.fractal_ssh.fetch_file(
|
1282
1275
|
remote=tarfile_path_remote,
|
1283
1276
|
local=tarfile_path_local,
|
1284
1277
|
)
|
@@ -1291,6 +1284,11 @@ class FractalSlurmSSHExecutor(SlurmExecutor):
|
|
1291
1284
|
# Extract tarfile locally
|
1292
1285
|
extract_archive(Path(tarfile_path_local))
|
1293
1286
|
|
1287
|
+
# Remove local tarfile
|
1288
|
+
if Path(tarfile_path_local).exists():
|
1289
|
+
logger.warning(f"Remove existing file {tarfile_path_local}.")
|
1290
|
+
Path(tarfile_path_local).unlink()
|
1291
|
+
|
1294
1292
|
t_1 = time.perf_counter()
|
1295
1293
|
logger.info("[_get_subfolder_sftp] End - " f"elapsed: {t_1-t_0:.3f} s")
|
1296
1294
|
|
@@ -1,3 +1,4 @@
|
|
1
|
+
import json
|
1
2
|
import logging
|
2
3
|
import time
|
3
4
|
from contextlib import contextmanager
|
@@ -23,21 +24,58 @@ class FractalSSHTimeoutError(RuntimeError):
|
|
23
24
|
pass
|
24
25
|
|
25
26
|
|
26
|
-
|
27
|
-
pass
|
27
|
+
logger = set_logger(__name__)
|
28
28
|
|
29
29
|
|
30
|
-
|
30
|
+
@contextmanager
|
31
|
+
def _acquire_lock_with_timeout(
|
32
|
+
lock: Lock,
|
33
|
+
label: str,
|
34
|
+
timeout: float,
|
35
|
+
logger_name: str = __name__,
|
36
|
+
) -> Generator[Literal[True], Any, None]:
|
37
|
+
"""
|
38
|
+
Given a `threading.Lock` object, try to acquire it within a given timeout.
|
39
|
+
|
40
|
+
Arguments:
|
41
|
+
lock:
|
42
|
+
label:
|
43
|
+
timeout:
|
44
|
+
logger_name:
|
45
|
+
"""
|
46
|
+
logger = get_logger(logger_name)
|
47
|
+
logger.info(f"Trying to acquire lock for '{label}', with {timeout=}")
|
48
|
+
result = lock.acquire(timeout=timeout)
|
49
|
+
try:
|
50
|
+
if not result:
|
51
|
+
logger.error(f"Lock for '{label}' was *not* acquired.")
|
52
|
+
raise FractalSSHTimeoutError(
|
53
|
+
f"Failed to acquire lock for '{label}' within "
|
54
|
+
f"{timeout} seconds"
|
55
|
+
)
|
56
|
+
logger.info(f"Lock for '{label}' was acquired.")
|
57
|
+
yield result
|
58
|
+
finally:
|
59
|
+
if result:
|
60
|
+
lock.release()
|
61
|
+
logger.info(f"Lock for '{label}' was released.")
|
31
62
|
|
32
63
|
|
33
64
|
class FractalSSH(object):
|
34
65
|
"""
|
35
|
-
|
66
|
+
Wrapper of `fabric.Connection` object, enriched with locks.
|
67
|
+
|
68
|
+
Note: methods marked as `_unsafe` should not be used directly,
|
69
|
+
since they do not enforce locking.
|
36
70
|
|
37
71
|
Attributes:
|
38
72
|
_lock:
|
39
|
-
|
73
|
+
_connection:
|
40
74
|
default_lock_timeout:
|
75
|
+
default_max_attempts:
|
76
|
+
default_base_interval:
|
77
|
+
sftp_get_prefetch:
|
78
|
+
sftp_get_max_requests:
|
41
79
|
logger_name:
|
42
80
|
"""
|
43
81
|
|
@@ -46,6 +84,8 @@ class FractalSSH(object):
|
|
46
84
|
default_lock_timeout: float
|
47
85
|
default_max_attempts: int
|
48
86
|
default_base_interval: float
|
87
|
+
sftp_get_prefetch: bool
|
88
|
+
sftp_get_max_requests: int
|
49
89
|
logger_name: str
|
50
90
|
|
51
91
|
def __init__(
|
@@ -54,6 +94,8 @@ class FractalSSH(object):
|
|
54
94
|
default_timeout: float = 250,
|
55
95
|
default_max_attempts: int = 5,
|
56
96
|
default_base_interval: float = 3.0,
|
97
|
+
sftp_get_prefetch: bool = False,
|
98
|
+
sftp_get_max_requests: int = 64,
|
57
99
|
logger_name: str = __name__,
|
58
100
|
):
|
59
101
|
self._lock = Lock()
|
@@ -61,28 +103,11 @@ class FractalSSH(object):
|
|
61
103
|
self.default_lock_timeout = default_timeout
|
62
104
|
self.default_base_interval = default_base_interval
|
63
105
|
self.default_max_attempts = default_max_attempts
|
106
|
+
self.sftp_get_prefetch = sftp_get_prefetch
|
107
|
+
self.sftp_get_max_requests = sftp_get_max_requests
|
64
108
|
self.logger_name = logger_name
|
65
109
|
set_logger(self.logger_name)
|
66
110
|
|
67
|
-
@contextmanager
|
68
|
-
def acquire_timeout(
|
69
|
-
self, timeout: float
|
70
|
-
) -> Generator[Literal[True], Any, None]:
|
71
|
-
self.logger.debug(f"Trying to acquire lock, with {timeout=}")
|
72
|
-
result = self._lock.acquire(timeout=timeout)
|
73
|
-
try:
|
74
|
-
if not result:
|
75
|
-
self.logger.error("Lock was *NOT* acquired.")
|
76
|
-
raise FractalSSHTimeoutError(
|
77
|
-
f"Failed to acquire lock within {timeout} seconds"
|
78
|
-
)
|
79
|
-
self.logger.debug("Lock was acquired.")
|
80
|
-
yield result
|
81
|
-
finally:
|
82
|
-
if result:
|
83
|
-
self._lock.release()
|
84
|
-
self.logger.debug("Lock was released")
|
85
|
-
|
86
111
|
@property
|
87
112
|
def is_connected(self) -> bool:
|
88
113
|
return self._connection.is_connected
|
@@ -91,36 +116,82 @@ class FractalSSH(object):
|
|
91
116
|
def logger(self) -> logging.Logger:
|
92
117
|
return get_logger(self.logger_name)
|
93
118
|
|
94
|
-
def
|
95
|
-
self,
|
119
|
+
def _put(
|
120
|
+
self,
|
121
|
+
*,
|
122
|
+
local: str,
|
123
|
+
remote: str,
|
124
|
+
label: str,
|
125
|
+
lock_timeout: Optional[float] = None,
|
96
126
|
) -> Result:
|
127
|
+
"""
|
128
|
+
Transfer a local file to a remote path, via SFTP.
|
129
|
+
"""
|
97
130
|
actual_lock_timeout = self.default_lock_timeout
|
98
131
|
if lock_timeout is not None:
|
99
132
|
actual_lock_timeout = lock_timeout
|
100
|
-
with
|
101
|
-
|
133
|
+
with _acquire_lock_with_timeout(
|
134
|
+
lock=self._lock,
|
135
|
+
label=label,
|
136
|
+
timeout=actual_lock_timeout,
|
137
|
+
):
|
138
|
+
return self._sftp_unsafe().put(local, remote)
|
102
139
|
|
103
|
-
def
|
104
|
-
self,
|
140
|
+
def _get(
|
141
|
+
self,
|
142
|
+
*,
|
143
|
+
local: str,
|
144
|
+
remote: str,
|
145
|
+
label: str,
|
146
|
+
lock_timeout: Optional[float] = None,
|
105
147
|
) -> Result:
|
106
148
|
actual_lock_timeout = self.default_lock_timeout
|
107
149
|
if lock_timeout is not None:
|
108
150
|
actual_lock_timeout = lock_timeout
|
109
|
-
with
|
110
|
-
|
151
|
+
with _acquire_lock_with_timeout(
|
152
|
+
lock=self._lock,
|
153
|
+
label=label,
|
154
|
+
timeout=actual_lock_timeout,
|
155
|
+
):
|
156
|
+
return self._sftp_unsafe().get(
|
157
|
+
remote,
|
158
|
+
local,
|
159
|
+
prefetch=self.sftp_get_prefetch,
|
160
|
+
max_concurrent_prefetch_requests=self.sftp_get_max_requests,
|
161
|
+
)
|
111
162
|
|
112
|
-
def
|
113
|
-
self, *args, lock_timeout: Optional[float] = None, **kwargs
|
163
|
+
def _run(
|
164
|
+
self, *args, label: str, lock_timeout: Optional[float] = None, **kwargs
|
114
165
|
) -> Any:
|
115
166
|
actual_lock_timeout = self.default_lock_timeout
|
116
167
|
if lock_timeout is not None:
|
117
168
|
actual_lock_timeout = lock_timeout
|
118
|
-
with
|
169
|
+
with _acquire_lock_with_timeout(
|
170
|
+
lock=self._lock,
|
171
|
+
label=label,
|
172
|
+
timeout=actual_lock_timeout,
|
173
|
+
):
|
119
174
|
return self._connection.run(*args, **kwargs)
|
120
175
|
|
121
|
-
def
|
176
|
+
def _sftp_unsafe(self) -> paramiko.sftp_client.SFTPClient:
|
177
|
+
"""
|
178
|
+
This is marked as unsafe because you should only use its methods
|
179
|
+
after acquiring a lock.
|
180
|
+
"""
|
122
181
|
return self._connection.sftp()
|
123
182
|
|
183
|
+
def read_remote_json_file(self, filepath: str) -> dict[str, Any]:
|
184
|
+
self.logger.info(f"START reading remote JSON file {filepath}.")
|
185
|
+
with _acquire_lock_with_timeout(
|
186
|
+
lock=self._lock,
|
187
|
+
label="read_remote_json_file",
|
188
|
+
timeout=self.default_lock_timeout,
|
189
|
+
):
|
190
|
+
with self._sftp_unsafe().open(filepath, "r") as f:
|
191
|
+
data = json.load(f)
|
192
|
+
self.logger.info(f"END reading remote JSON file {filepath}.")
|
193
|
+
return data
|
194
|
+
|
124
195
|
def check_connection(self) -> None:
|
125
196
|
"""
|
126
197
|
Open the SSH connection and handle exceptions.
|
@@ -131,7 +202,12 @@ class FractalSSH(object):
|
|
131
202
|
"""
|
132
203
|
if not self._connection.is_connected:
|
133
204
|
try:
|
134
|
-
|
205
|
+
with _acquire_lock_with_timeout(
|
206
|
+
lock=self._lock,
|
207
|
+
label="_connection.open",
|
208
|
+
timeout=self.default_lock_timeout,
|
209
|
+
):
|
210
|
+
self._connection.open()
|
135
211
|
except Exception as e:
|
136
212
|
raise RuntimeError(
|
137
213
|
f"Cannot open SSH connection. Original error:\n{str(e)}"
|
@@ -146,8 +222,12 @@ class FractalSSH(object):
|
|
146
222
|
because we observed cases where `is_connected=False` but the underlying
|
147
223
|
`Transport` object was not closed.
|
148
224
|
"""
|
149
|
-
|
150
|
-
|
225
|
+
with _acquire_lock_with_timeout(
|
226
|
+
lock=self._lock,
|
227
|
+
label="_connection.close",
|
228
|
+
timeout=self.default_lock_timeout,
|
229
|
+
):
|
230
|
+
self._connection.close()
|
151
231
|
|
152
232
|
if self._connection.client is not None:
|
153
233
|
self._connection.client.close()
|
@@ -197,8 +277,11 @@ class FractalSSH(object):
|
|
197
277
|
self.logger.info(f"{prefix} START running '{cmd}' over SSH.")
|
198
278
|
try:
|
199
279
|
# Case 1: Command runs successfully
|
200
|
-
res = self.
|
201
|
-
cmd,
|
280
|
+
res = self._run(
|
281
|
+
cmd,
|
282
|
+
label=f"run {cmd}",
|
283
|
+
lock_timeout=actual_lock_timeout,
|
284
|
+
hide=True,
|
202
285
|
)
|
203
286
|
t_1 = time.perf_counter()
|
204
287
|
self.logger.info(
|
@@ -250,7 +333,6 @@ class FractalSSH(object):
|
|
250
333
|
*,
|
251
334
|
local: str,
|
252
335
|
remote: str,
|
253
|
-
logger_name: Optional[str] = None,
|
254
336
|
lock_timeout: Optional[float] = None,
|
255
337
|
) -> None:
|
256
338
|
"""
|
@@ -261,28 +343,65 @@ class FractalSSH(object):
|
|
261
343
|
remote: Target path on remote host
|
262
344
|
fractal_ssh: FractalSSH connection object with custom lock
|
263
345
|
logger_name: Name of the logger
|
264
|
-
|
265
346
|
"""
|
266
347
|
try:
|
267
|
-
|
348
|
+
prefix = "[send_file]"
|
349
|
+
self.logger.info(f"{prefix} START transfer of '{local}' over SSH.")
|
350
|
+
self._put(
|
351
|
+
local=local,
|
352
|
+
remote=remote,
|
353
|
+
lock_timeout=lock_timeout,
|
354
|
+
label=f"send_file {local=} {remote=}",
|
355
|
+
)
|
356
|
+
self.logger.info(f"{prefix} END transfer of '{local}' over SSH.")
|
268
357
|
except Exception as e:
|
269
|
-
logger
|
270
|
-
logger.error(
|
358
|
+
self.logger.error(
|
271
359
|
f"Transferring {local=} to {remote=} over SSH failed.\n"
|
272
360
|
f"Original Error:\n{str(e)}."
|
273
361
|
)
|
274
362
|
raise e
|
275
363
|
|
364
|
+
def fetch_file(
|
365
|
+
self,
|
366
|
+
*,
|
367
|
+
local: str,
|
368
|
+
remote: str,
|
369
|
+
lock_timeout: Optional[float] = None,
|
370
|
+
) -> None:
|
371
|
+
"""
|
372
|
+
Transfer a file via SSH
|
373
|
+
|
374
|
+
Args:
|
375
|
+
local: Local path to file
|
376
|
+
remote: Target path on remote host
|
377
|
+
logger_name: Name of the logger
|
378
|
+
lock_timeout:
|
379
|
+
"""
|
380
|
+
try:
|
381
|
+
prefix = "[fetch_file] "
|
382
|
+
self.logger.info(f"{prefix} START fetching '{remote}' over SSH.")
|
383
|
+
self._get(
|
384
|
+
local=local,
|
385
|
+
remote=remote,
|
386
|
+
lock_timeout=lock_timeout,
|
387
|
+
label=f"fetch_file {local=} {remote=}",
|
388
|
+
)
|
389
|
+
self.logger.info(f"{prefix} END fetching '{remote}' over SSH.")
|
390
|
+
except Exception as e:
|
391
|
+
self.logger.error(
|
392
|
+
f"Transferring {remote=} to {local=} over SSH failed.\n"
|
393
|
+
f"Original Error:\n{str(e)}."
|
394
|
+
)
|
395
|
+
raise e
|
396
|
+
|
276
397
|
def mkdir(self, *, folder: str, parents: bool = True) -> None:
|
277
398
|
"""
|
278
399
|
Create a folder remotely via SSH.
|
279
400
|
|
280
401
|
Args:
|
281
402
|
folder:
|
282
|
-
fractal_ssh:
|
283
403
|
parents:
|
284
404
|
"""
|
285
|
-
# FIXME SSH: try using `mkdir` method of `paramiko.SFTPClient`
|
286
405
|
if parents:
|
287
406
|
cmd = f"mkdir -p {folder}"
|
288
407
|
else:
|
@@ -339,12 +458,18 @@ class FractalSSH(object):
|
|
339
458
|
contents: File contents
|
340
459
|
lock_timeout:
|
341
460
|
"""
|
461
|
+
self.logger.info(f"START writing to remote file {path}.")
|
342
462
|
actual_lock_timeout = self.default_lock_timeout
|
343
463
|
if lock_timeout is not None:
|
344
464
|
actual_lock_timeout = lock_timeout
|
345
|
-
with
|
346
|
-
|
465
|
+
with _acquire_lock_with_timeout(
|
466
|
+
lock=self._lock,
|
467
|
+
label=f"write_remote_file {path=}",
|
468
|
+
timeout=actual_lock_timeout,
|
469
|
+
):
|
470
|
+
with self._sftp_unsafe().open(filename=path, mode="w") as f:
|
347
471
|
f.write(content)
|
472
|
+
self.logger.info(f"END writing to remote file {path}.")
|
348
473
|
|
349
474
|
|
350
475
|
class FractalSSHList(object):
|
@@ -425,7 +550,11 @@ class FractalSSHList(object):
|
|
425
550
|
"look_for_keys": False,
|
426
551
|
},
|
427
552
|
)
|
428
|
-
with
|
553
|
+
with _acquire_lock_with_timeout(
|
554
|
+
lock=self._lock,
|
555
|
+
label="FractalSSHList.get",
|
556
|
+
timeout=self._timeout,
|
557
|
+
):
|
429
558
|
self._data[key] = FractalSSH(connection=connection)
|
430
559
|
return self._data[key]
|
431
560
|
|
@@ -465,7 +594,11 @@ class FractalSSHList(object):
|
|
465
594
|
key_path:
|
466
595
|
"""
|
467
596
|
key = (host, user, key_path)
|
468
|
-
with
|
597
|
+
with _acquire_lock_with_timeout(
|
598
|
+
lock=self._lock,
|
599
|
+
timeout=self._timeout,
|
600
|
+
label="FractalSSHList.remove",
|
601
|
+
):
|
469
602
|
self.logger.info(
|
470
603
|
f"Removing FractalSSH object for {user}@{host} "
|
471
604
|
"from collection."
|
@@ -492,24 +625,4 @@ class FractalSSHList(object):
|
|
492
625
|
f"Closing FractalSSH object for {user}@{host} "
|
493
626
|
f"({fractal_ssh_obj.is_connected=})."
|
494
627
|
)
|
495
|
-
|
496
|
-
fractal_ssh_obj.close()
|
497
|
-
|
498
|
-
@contextmanager
|
499
|
-
def acquire_lock_with_timeout(self) -> Generator[Literal[True], Any, None]:
|
500
|
-
self.logger.debug(
|
501
|
-
f"Trying to acquire lock, with timeout {self._timeout} s"
|
502
|
-
)
|
503
|
-
result = self._lock.acquire(timeout=self._timeout)
|
504
|
-
try:
|
505
|
-
if not result:
|
506
|
-
self.logger.error("Lock was *NOT* acquired.")
|
507
|
-
raise FractalSSHListTimeoutError(
|
508
|
-
f"Failed to acquire lock within {self._timeout} ss"
|
509
|
-
)
|
510
|
-
self.logger.debug("Lock was acquired.")
|
511
|
-
yield result
|
512
|
-
finally:
|
513
|
-
if result:
|
514
|
-
self._lock.release()
|
515
|
-
self.logger.debug("Lock was released")
|
628
|
+
fractal_ssh_obj.close()
|
@@ -1,4 +1,3 @@
|
|
1
|
-
import json
|
2
1
|
import os
|
3
2
|
from pathlib import Path
|
4
3
|
from tempfile import TemporaryDirectory
|
@@ -144,6 +143,13 @@ def background_collect_pip_ssh(
|
|
144
143
|
for key, value in task_group.model_dump().items():
|
145
144
|
logger.debug(f"task_group.{key}: {value}")
|
146
145
|
|
146
|
+
# `remove_venv_folder_upon_failure` is set to True only if
|
147
|
+
# script 1 goes through, which means that the remote folder
|
148
|
+
# `package_env_dir` did not already exist. If this remote
|
149
|
+
# folder already existed, then script 1 fails and the boolean
|
150
|
+
# flag `remove_venv_folder_upon_failure` remains false.
|
151
|
+
remove_venv_folder_upon_failure = False
|
152
|
+
|
147
153
|
# Open a DB session soon, since it is needed for updating `state`
|
148
154
|
with next(get_sync_db()) as db:
|
149
155
|
try:
|
@@ -187,12 +193,11 @@ def background_collect_pip_ssh(
|
|
187
193
|
# long operations that do not use the db
|
188
194
|
db.close()
|
189
195
|
|
190
|
-
#
|
191
|
-
#
|
192
|
-
# `
|
193
|
-
|
194
|
-
|
195
|
-
remove_venv_folder_upon_failure = False
|
196
|
+
# Create remote folder (note that because of `parents=True` we
|
197
|
+
# are in the `no error if existing, make parent directories as
|
198
|
+
# needed` scenario)
|
199
|
+
fractal_ssh.mkdir(folder=tasks_base_dir, parents=True)
|
200
|
+
|
196
201
|
stdout = _customize_and_run_template(
|
197
202
|
script_filename="_1_create_venv.sh",
|
198
203
|
**common_args,
|
@@ -263,8 +268,9 @@ def background_collect_pip_ssh(
|
|
263
268
|
).as_posix()
|
264
269
|
|
265
270
|
# Read and validate remote manifest file
|
266
|
-
|
267
|
-
|
271
|
+
pkg_manifest_dict = fractal_ssh.read_remote_json_file(
|
272
|
+
manifest_path_remote
|
273
|
+
)
|
268
274
|
logger.info(f"collecting - loaded {manifest_path_remote=}")
|
269
275
|
pkg_manifest = ManifestV2(**pkg_manifest_dict)
|
270
276
|
logger.info("collecting - manifest is a valid ManifestV2")
|
@@ -1,6 +1,6 @@
|
|
1
1
|
[tool.poetry]
|
2
2
|
name = "fractal-server"
|
3
|
-
version = "2.7.
|
3
|
+
version = "2.7.0a10"
|
4
4
|
description = "Server component of the Fractal analytics platform"
|
5
5
|
authors = [
|
6
6
|
"Tommaso Comparin <tommaso.comparin@exact-lab.it>",
|
@@ -92,7 +92,7 @@ filterwarnings = [
|
|
92
92
|
]
|
93
93
|
|
94
94
|
[tool.bumpver]
|
95
|
-
current_version = "2.7.
|
95
|
+
current_version = "2.7.0a10"
|
96
96
|
version_pattern = "MAJOR.MINOR.PATCH[PYTAGNUM]"
|
97
97
|
commit_message = "bump version {old_version} -> {new_version}"
|
98
98
|
commit = true
|
@@ -1 +0,0 @@
|
|
1
|
-
__VERSION__ = "2.7.0a9"
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/models/linkusergroup.py
RENAMED
File without changes
|
{fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/models/linkuserproject.py
RENAMED
File without changes
|
File without changes
|
{fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/models/user_settings.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/models/v2/collection_state.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/models/v2/workflowtask.py
RENAMED
File without changes
|
File without changes
|
{fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/routes/admin/__init__.py
RENAMED
File without changes
|
File without changes
|
{fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/routes/admin/v2/__init__.py
RENAMED
File without changes
|
{fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/routes/admin/v2/job.py
RENAMED
File without changes
|
{fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/routes/admin/v2/project.py
RENAMED
File without changes
|
{fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/routes/admin/v2/task.py
RENAMED
File without changes
|
{fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/routes/admin/v2/task_group.py
RENAMED
File without changes
|
{fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/routes/api/__init__.py
RENAMED
File without changes
|
{fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/routes/api/v1/__init__.py
RENAMED
File without changes
|
File without changes
|
{fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/routes/api/v1/dataset.py
RENAMED
File without changes
|
File without changes
|
{fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/routes/api/v1/project.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
{fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/routes/api/v1/workflow.py
RENAMED
File without changes
|
{fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/routes/api/v1/workflowtask.py
RENAMED
File without changes
|
{fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/routes/api/v2/__init__.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
{fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/routes/api/v2/dataset.py
RENAMED
File without changes
|
{fractal_server-2.7.0a9 → fractal_server-2.7.0a10}/fractal_server/app/routes/api/v2/images.py
RENAMED
File without changes
|