fractal-server 2.16.0__tar.gz → 2.16.2__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.
Files changed (243) hide show
  1. {fractal_server-2.16.0 → fractal_server-2.16.2}/PKG-INFO +1 -1
  2. fractal_server-2.16.2/fractal_server/__init__.py +1 -0
  3. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/runner/v2/runner.py +2 -9
  4. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/config.py +55 -6
  5. fractal_server-2.16.2/fractal_server/tasks/v2/ssh/_pixi_slurm_ssh.py +214 -0
  6. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/tasks/v2/ssh/_utils.py +42 -9
  7. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/tasks/v2/ssh/collect_pixi.py +22 -3
  8. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/tasks/v2/ssh/reactivate_pixi.py +20 -3
  9. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/tasks/v2/utils_background.py +1 -1
  10. {fractal_server-2.16.0 → fractal_server-2.16.2}/pyproject.toml +2 -2
  11. fractal_server-2.16.0/fractal_server/__init__.py +0 -1
  12. {fractal_server-2.16.0 → fractal_server-2.16.2}/LICENSE +0 -0
  13. {fractal_server-2.16.0 → fractal_server-2.16.2}/README.md +0 -0
  14. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/__main__.py +0 -0
  15. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/alembic.ini +0 -0
  16. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/__init__.py +0 -0
  17. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/db/__init__.py +0 -0
  18. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/models/__init__.py +0 -0
  19. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/models/linkusergroup.py +0 -0
  20. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/models/linkuserproject.py +0 -0
  21. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/models/security.py +0 -0
  22. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/models/user_settings.py +0 -0
  23. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/models/v2/__init__.py +0 -0
  24. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/models/v2/accounting.py +0 -0
  25. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/models/v2/dataset.py +0 -0
  26. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/models/v2/history.py +0 -0
  27. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/models/v2/job.py +0 -0
  28. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/models/v2/project.py +0 -0
  29. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/models/v2/task.py +0 -0
  30. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/models/v2/task_group.py +0 -0
  31. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/models/v2/workflow.py +0 -0
  32. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/models/v2/workflowtask.py +0 -0
  33. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/routes/__init__.py +0 -0
  34. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/routes/admin/__init__.py +0 -0
  35. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/routes/admin/v2/__init__.py +0 -0
  36. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/routes/admin/v2/accounting.py +0 -0
  37. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/routes/admin/v2/impersonate.py +0 -0
  38. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/routes/admin/v2/job.py +0 -0
  39. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/routes/admin/v2/project.py +0 -0
  40. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/routes/admin/v2/task.py +0 -0
  41. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/routes/admin/v2/task_group.py +0 -0
  42. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/routes/admin/v2/task_group_lifecycle.py +0 -0
  43. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/routes/api/__init__.py +0 -0
  44. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/routes/api/v2/__init__.py +0 -0
  45. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/routes/api/v2/_aux_functions.py +0 -0
  46. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/routes/api/v2/_aux_functions_history.py +0 -0
  47. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/routes/api/v2/_aux_functions_task_lifecycle.py +0 -0
  48. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/routes/api/v2/_aux_functions_task_version_update.py +0 -0
  49. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/routes/api/v2/_aux_functions_tasks.py +0 -0
  50. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/routes/api/v2/_aux_task_group_disambiguation.py +0 -0
  51. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/routes/api/v2/dataset.py +0 -0
  52. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/routes/api/v2/history.py +0 -0
  53. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/routes/api/v2/images.py +0 -0
  54. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/routes/api/v2/job.py +0 -0
  55. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/routes/api/v2/pre_submission_checks.py +0 -0
  56. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/routes/api/v2/project.py +0 -0
  57. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/routes/api/v2/status_legacy.py +0 -0
  58. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/routes/api/v2/submit.py +0 -0
  59. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/routes/api/v2/task.py +0 -0
  60. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/routes/api/v2/task_collection.py +0 -0
  61. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/routes/api/v2/task_collection_custom.py +0 -0
  62. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/routes/api/v2/task_collection_pixi.py +0 -0
  63. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/routes/api/v2/task_group.py +0 -0
  64. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/routes/api/v2/task_group_lifecycle.py +0 -0
  65. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/routes/api/v2/task_version_update.py +0 -0
  66. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/routes/api/v2/workflow.py +0 -0
  67. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/routes/api/v2/workflow_import.py +0 -0
  68. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/routes/api/v2/workflowtask.py +0 -0
  69. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/routes/auth/__init__.py +0 -0
  70. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/routes/auth/_aux_auth.py +0 -0
  71. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/routes/auth/current_user.py +0 -0
  72. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/routes/auth/group.py +0 -0
  73. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/routes/auth/login.py +0 -0
  74. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/routes/auth/oauth.py +0 -0
  75. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/routes/auth/register.py +0 -0
  76. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/routes/auth/router.py +0 -0
  77. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/routes/auth/users.py +0 -0
  78. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/routes/aux/__init__.py +0 -0
  79. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/routes/aux/_job.py +0 -0
  80. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/routes/aux/_runner.py +0 -0
  81. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/routes/aux/validate_user_settings.py +0 -0
  82. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/routes/pagination.py +0 -0
  83. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/runner/__init__.py +0 -0
  84. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/runner/components.py +0 -0
  85. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/runner/exceptions.py +0 -0
  86. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/runner/executors/__init__.py +0 -0
  87. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/runner/executors/base_runner.py +0 -0
  88. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/runner/executors/call_command_wrapper.py +0 -0
  89. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/runner/executors/local/__init__.py +0 -0
  90. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/runner/executors/local/get_local_config.py +0 -0
  91. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/runner/executors/local/runner.py +0 -0
  92. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/runner/executors/slurm_common/__init__.py +0 -0
  93. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/runner/executors/slurm_common/_batching.py +0 -0
  94. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/runner/executors/slurm_common/_job_states.py +0 -0
  95. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/runner/executors/slurm_common/_slurm_config.py +0 -0
  96. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/runner/executors/slurm_common/base_slurm_runner.py +0 -0
  97. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/runner/executors/slurm_common/get_slurm_config.py +0 -0
  98. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/runner/executors/slurm_common/remote.py +0 -0
  99. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/runner/executors/slurm_common/slurm_job_task_models.py +0 -0
  100. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/runner/executors/slurm_ssh/__init__.py +0 -0
  101. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/runner/executors/slurm_ssh/run_subprocess.py +0 -0
  102. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/runner/executors/slurm_ssh/runner.py +0 -0
  103. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/runner/executors/slurm_ssh/tar_commands.py +0 -0
  104. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/runner/executors/slurm_sudo/__init__.py +0 -0
  105. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/runner/executors/slurm_sudo/_subprocess_run_as_user.py +0 -0
  106. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/runner/executors/slurm_sudo/runner.py +0 -0
  107. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/runner/filenames.py +0 -0
  108. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/runner/set_start_and_last_task_index.py +0 -0
  109. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/runner/shutdown.py +0 -0
  110. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/runner/task_files.py +0 -0
  111. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/runner/v2/__init__.py +0 -0
  112. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/runner/v2/_local.py +0 -0
  113. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/runner/v2/_slurm_ssh.py +0 -0
  114. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/runner/v2/_slurm_sudo.py +0 -0
  115. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/runner/v2/db_tools.py +0 -0
  116. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/runner/v2/deduplicate_list.py +0 -0
  117. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/runner/v2/merge_outputs.py +0 -0
  118. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/runner/v2/runner_functions.py +0 -0
  119. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/runner/v2/submit_workflow.py +0 -0
  120. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/runner/v2/task_interface.py +0 -0
  121. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/runner/versions.py +0 -0
  122. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/schemas/__init__.py +0 -0
  123. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/schemas/user.py +0 -0
  124. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/schemas/user_group.py +0 -0
  125. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/schemas/user_settings.py +0 -0
  126. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/schemas/v2/__init__.py +0 -0
  127. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/schemas/v2/accounting.py +0 -0
  128. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/schemas/v2/dataset.py +0 -0
  129. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/schemas/v2/dumps.py +0 -0
  130. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/schemas/v2/history.py +0 -0
  131. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/schemas/v2/job.py +0 -0
  132. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/schemas/v2/manifest.py +0 -0
  133. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/schemas/v2/project.py +0 -0
  134. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/schemas/v2/status_legacy.py +0 -0
  135. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/schemas/v2/task.py +0 -0
  136. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/schemas/v2/task_collection.py +0 -0
  137. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/schemas/v2/task_group.py +0 -0
  138. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/schemas/v2/workflow.py +0 -0
  139. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/schemas/v2/workflowtask.py +0 -0
  140. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/security/__init__.py +0 -0
  141. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/security/signup_email.py +0 -0
  142. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/app/user_settings.py +0 -0
  143. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/data_migrations/2_14_10.py +0 -0
  144. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/data_migrations/README.md +0 -0
  145. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/data_migrations/tools.py +0 -0
  146. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/exceptions.py +0 -0
  147. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/gunicorn_fractal.py +0 -0
  148. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/images/__init__.py +0 -0
  149. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/images/models.py +0 -0
  150. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/images/status_tools.py +0 -0
  151. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/images/tools.py +0 -0
  152. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/logger.py +0 -0
  153. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/main.py +0 -0
  154. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/migrations/env.py +0 -0
  155. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/migrations/naming_convention.py +0 -0
  156. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/migrations/versions/034a469ec2eb_task_groups.py +0 -0
  157. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/migrations/versions/091b01f51f88_add_usergroup_and_linkusergroup_table.py +0 -0
  158. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/migrations/versions/0f5f85bb2ae7_add_pre_pinned_packages.py +0 -0
  159. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/migrations/versions/19eca0dd47a9_user_settings_project_dir.py +0 -0
  160. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/migrations/versions/1a83a5260664_rename.py +0 -0
  161. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/migrations/versions/1eac13a26c83_drop_v1_tables.py +0 -0
  162. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/migrations/versions/316140ff7ee1_remove_usersettings_cache_dir.py +0 -0
  163. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/migrations/versions/47351f8c7ebc_drop_dataset_filters.py +0 -0
  164. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/migrations/versions/4c308bcaea2b_add_task_args_schema_and_task_args_.py +0 -0
  165. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/migrations/versions/4cedeb448a53_workflowtask_foreign_keys_not_nullables.py +0 -0
  166. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/migrations/versions/501961cfcd85_remove_link_between_v1_and_v2_tasks_.py +0 -0
  167. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/migrations/versions/50a13d6138fd_initial_schema.py +0 -0
  168. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/migrations/versions/5bf02391cfef_v2.py +0 -0
  169. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/migrations/versions/70e77f1c38b0_add_applyworkflow_first_task_index_and_.py +0 -0
  170. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/migrations/versions/71eefd1dd202_add_slurm_accounts.py +0 -0
  171. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/migrations/versions/791ce783d3d8_add_indices.py +0 -0
  172. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/migrations/versions/84bf0fffde30_add_dumps_to_applyworkflow.py +0 -0
  173. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/migrations/versions/8e8f227a3e36_update_taskv2_post_2_7_0.py +0 -0
  174. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/migrations/versions/8f79bd162e35_add_docs_info_and_docs_link_to_task_.py +0 -0
  175. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/migrations/versions/94a47ea2d3ff_remove_cache_dir_slurm_user_and_slurm_.py +0 -0
  176. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/migrations/versions/969d84257cac_add_historyrun_task_id.py +0 -0
  177. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/migrations/versions/97f444d47249_add_applyworkflow_project_dump.py +0 -0
  178. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/migrations/versions/981d588fe248_add_executor_error_log.py +0 -0
  179. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/migrations/versions/99ea79d9e5d2_add_dataset_history.py +0 -0
  180. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/migrations/versions/9c5ae74c9b98_add_user_settings_table.py +0 -0
  181. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/migrations/versions/9db60297b8b2_set_ondelete.py +0 -0
  182. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/migrations/versions/9fd26a2b0de4_add_workflow_timestamp_created.py +0 -0
  183. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/migrations/versions/a7f4d6137b53_add_workflow_dump_to_applyworkflow.py +0 -0
  184. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/migrations/versions/af1ef1c83c9b_add_accounting_tables.py +0 -0
  185. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/migrations/versions/af8673379a5c_drop_old_filter_columns.py +0 -0
  186. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/migrations/versions/b1e7f7a1ff71_task_group_for_pixi.py +0 -0
  187. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/migrations/versions/b3ffb095f973_json_to_jsonb.py +0 -0
  188. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/migrations/versions/c90a7c76e996_job_id_in_history_run.py +0 -0
  189. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/migrations/versions/d256a7379ab8_taskgroup_activity_and_venv_info_to_.py +0 -0
  190. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/migrations/versions/d4fe3708d309_make_applyworkflow_workflow_dump_non_.py +0 -0
  191. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/migrations/versions/da2cb2ac4255_user_group_viewer_paths.py +0 -0
  192. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/migrations/versions/db09233ad13a_split_filters_and_keep_old_columns.py +0 -0
  193. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/migrations/versions/e75cac726012_make_applyworkflow_start_timestamp_not_.py +0 -0
  194. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/migrations/versions/e81103413827_add_job_type_filters.py +0 -0
  195. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/migrations/versions/efa89c30e0a4_add_project_timestamp_created.py +0 -0
  196. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/migrations/versions/f37aceb45062_make_historyunit_logfile_required.py +0 -0
  197. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/migrations/versions/f384e1c0cf5d_drop_task_default_args_columns.py +0 -0
  198. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/migrations/versions/fbce16ff4e47_new_history_items.py +0 -0
  199. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/py.typed +0 -0
  200. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/ssh/__init__.py +0 -0
  201. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/ssh/_fabric.py +0 -0
  202. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/string_tools.py +0 -0
  203. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/syringe.py +0 -0
  204. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/tasks/__init__.py +0 -0
  205. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/tasks/utils.py +0 -0
  206. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/tasks/v2/__init__.py +0 -0
  207. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/tasks/v2/local/__init__.py +0 -0
  208. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/tasks/v2/local/_utils.py +0 -0
  209. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/tasks/v2/local/collect.py +0 -0
  210. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/tasks/v2/local/collect_pixi.py +0 -0
  211. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/tasks/v2/local/deactivate.py +0 -0
  212. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/tasks/v2/local/deactivate_pixi.py +0 -0
  213. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/tasks/v2/local/delete.py +0 -0
  214. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/tasks/v2/local/reactivate.py +0 -0
  215. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/tasks/v2/local/reactivate_pixi.py +0 -0
  216. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/tasks/v2/ssh/__init__.py +0 -0
  217. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/tasks/v2/ssh/collect.py +0 -0
  218. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/tasks/v2/ssh/deactivate.py +0 -0
  219. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/tasks/v2/ssh/deactivate_pixi.py +0 -0
  220. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/tasks/v2/ssh/delete.py +0 -0
  221. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/tasks/v2/ssh/reactivate.py +0 -0
  222. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/tasks/v2/templates/1_create_venv.sh +0 -0
  223. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/tasks/v2/templates/2_pip_install.sh +0 -0
  224. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/tasks/v2/templates/3_pip_freeze.sh +0 -0
  225. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/tasks/v2/templates/4_pip_show.sh +0 -0
  226. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/tasks/v2/templates/5_get_venv_size_and_file_number.sh +0 -0
  227. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/tasks/v2/templates/6_pip_install_from_freeze.sh +0 -0
  228. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/tasks/v2/templates/pixi_1_extract.sh +0 -0
  229. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/tasks/v2/templates/pixi_2_install.sh +0 -0
  230. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/tasks/v2/templates/pixi_3_post_install.sh +0 -0
  231. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/tasks/v2/utils_database.py +0 -0
  232. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/tasks/v2/utils_package_names.py +0 -0
  233. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/tasks/v2/utils_pixi.py +0 -0
  234. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/tasks/v2/utils_python_interpreter.py +0 -0
  235. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/tasks/v2/utils_templates.py +0 -0
  236. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/types/__init__.py +0 -0
  237. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/types/validators/__init__.py +0 -0
  238. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/types/validators/_common_validators.py +0 -0
  239. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/types/validators/_filter_validators.py +0 -0
  240. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/types/validators/_workflow_task_arguments_validators.py +0 -0
  241. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/urls.py +0 -0
  242. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/utils.py +0 -0
  243. {fractal_server-2.16.0 → fractal_server-2.16.2}/fractal_server/zip_tools.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: fractal-server
3
- Version: 2.16.0
3
+ Version: 2.16.2
4
4
  Summary: Backend component of the Fractal analytics platform
5
5
  License: BSD-3-Clause
6
6
  Author: Tommaso Comparin
@@ -0,0 +1 @@
1
+ __VERSION__ = "2.16.2"
@@ -1,4 +1,3 @@
1
- import logging
2
1
  from collections.abc import Callable
3
2
  from copy import copy
4
3
  from copy import deepcopy
@@ -38,6 +37,7 @@ from fractal_server.images.status_tools import IMAGE_STATUS_KEY
38
37
  from fractal_server.images.tools import filter_image_list
39
38
  from fractal_server.images.tools import find_image_by_zarr_url
40
39
  from fractal_server.images.tools import merge_type_filters
40
+ from fractal_server.logger import get_logger
41
41
  from fractal_server.types import AttributeFilters
42
42
 
43
43
 
@@ -103,7 +103,7 @@ def execute_tasks_v2(
103
103
  job_type_filters: dict[str, bool],
104
104
  job_attribute_filters: AttributeFilters,
105
105
  ) -> None:
106
- logger = logging.getLogger(logger_name)
106
+ logger = get_logger(logger_name=logger_name)
107
107
 
108
108
  if not workflow_dir_local.exists():
109
109
  logger.warning(
@@ -198,9 +198,6 @@ def execute_tasks_v2(
198
198
  # over from a previous task
199
199
  job_db = db.get(JobV2, job_id)
200
200
  job_db.executor_error_log = None
201
- logger.debug(
202
- f"Resetting `JobV2[{job_id}].executor_error_log` to None."
203
- )
204
201
  db.merge(job_db)
205
202
  db.commit()
206
203
 
@@ -449,10 +446,6 @@ def execute_tasks_v2(
449
446
  # Store the SLURM error in the job database
450
447
  job_db = db.get(JobV2, job_id)
451
448
  job_db.executor_error_log = runner.executor_error_log
452
- logger.debug(
453
- f"Setting JobV2[{job_id}].executor_error_log "
454
- f"to '{job_db.executor_error_log}'."
455
- )
456
449
  db.merge(job_db)
457
450
  db.commit()
458
451
 
@@ -18,16 +18,19 @@ import sys
18
18
  from os import environ
19
19
  from os import getenv
20
20
  from pathlib import Path
21
+ from typing import Annotated
21
22
  from typing import Literal
22
23
  from typing import TypeVar
23
24
 
24
25
  from cryptography.fernet import Fernet
25
26
  from dotenv import load_dotenv
27
+ from pydantic import AfterValidator
26
28
  from pydantic import BaseModel
27
29
  from pydantic import EmailStr
28
30
  from pydantic import Field
29
31
  from pydantic import field_validator
30
32
  from pydantic import model_validator
33
+ from pydantic import PositiveInt
31
34
  from pydantic import SecretStr
32
35
  from pydantic_settings import BaseSettings
33
36
  from pydantic_settings import SettingsConfigDict
@@ -36,6 +39,7 @@ from sqlalchemy.engine import URL
36
39
  import fractal_server
37
40
  from fractal_server.types import AbsolutePathStr
38
41
  from fractal_server.types import DictStrStr
42
+ from fractal_server.types import NonEmptyStr
39
43
 
40
44
 
41
45
  class MailSettings(BaseModel):
@@ -64,6 +68,47 @@ class MailSettings(BaseModel):
64
68
  use_login: bool
65
69
 
66
70
 
71
+ def _check_pixi_slurm_memory(mem: str) -> str:
72
+ if mem[-1] not in ["K", "M", "G", "T"]:
73
+ raise ValueError(
74
+ f"Invalid memory requirement {mem=} for `pixi`, "
75
+ "please set a K/M/G/T units suffix."
76
+ )
77
+ return mem
78
+
79
+
80
+ class PixiSLURMConfig(BaseModel):
81
+ """
82
+ Parameters that are passed directly to a `sbatch` command.
83
+
84
+ See https://slurm.schedmd.com/sbatch.html.
85
+ """
86
+
87
+ partition: NonEmptyStr
88
+ """
89
+ `-p, --partition=<partition_names>`
90
+ """
91
+ cpus: PositiveInt
92
+ """
93
+ `-c, --cpus-per-task=<ncpus>
94
+ """
95
+ mem: Annotated[NonEmptyStr, AfterValidator(_check_pixi_slurm_memory)]
96
+ """
97
+ `--mem=<size>[units]` (examples: `"10M"`, `"10G"`).
98
+ From `sbatch` docs: Specify the real memory required per node. Default
99
+ units are megabytes. Different units can be specified using the suffix
100
+ [K|M|G|T].
101
+ """
102
+ time: NonEmptyStr
103
+ """
104
+ `-t, --time=<time>`.
105
+ From `sbatch` docs: "A time limit of zero requests that no time limit be
106
+ imposed. Acceptable time formats include "minutes", "minutes:seconds",
107
+ "hours:minutes:seconds", "days-hours", "days-hours:minutes" and
108
+ "days-hours:minutes:seconds".
109
+ """
110
+
111
+
67
112
  class PixiSettings(BaseModel):
68
113
  """
69
114
  Configuration for Pixi Task collection.
@@ -130,9 +175,15 @@ class PixiSettings(BaseModel):
130
175
  """
131
176
  DEFAULT_ENVIRONMENT: str = "default"
132
177
  """
178
+ Default pixi environment name.
133
179
  """
134
180
  DEFAULT_PLATFORM: str = "linux-64"
135
181
  """
182
+ Default platform for pixi.
183
+ """
184
+ SLURM_CONFIG: PixiSLURMConfig | None = None
185
+ """
186
+ Required when using pixi in a SSH/SLURM deployment.
136
187
  """
137
188
 
138
189
  @model_validator(mode="after")
@@ -554,12 +605,6 @@ class Settings(BaseSettings):
554
605
  still running on SLURM.
555
606
  """
556
607
 
557
- FRACTAL_SLURM_SBATCH_SLEEP: float = 0
558
- """
559
- Interval to wait (in seconds) between two subsequent `sbatch` calls, when
560
- running a task that produces multiple SLURM jobs.
561
- """
562
-
563
608
  FRACTAL_PIP_CACHE_DIR: AbsolutePathStr | None = None
564
609
  """
565
610
  Absolute path to the cache directory for `pip`; if unset,
@@ -790,6 +835,10 @@ class Settings(BaseSettings):
790
835
  raise FractalConfigurationError(
791
836
  f"Must set FRACTAL_SLURM_WORKER_PYTHON when {info}"
792
837
  )
838
+ if self.pixi and self.pixi.SLURM_CONFIG is None:
839
+ raise FractalConfigurationError(
840
+ "Pixi config must include SLURM_CONFIG."
841
+ )
793
842
 
794
843
  from fractal_server.app.runner.executors.slurm_common._slurm_config import ( # noqa: E501
795
844
  load_slurm_config_file,
@@ -0,0 +1,214 @@
1
+ import os
2
+ import time
3
+ from pathlib import Path
4
+
5
+ from sqlalchemy.orm import Session
6
+
7
+ from fractal_server.app.models.v2 import TaskGroupActivityV2
8
+ from fractal_server.config import get_settings
9
+ from fractal_server.config import PixiSLURMConfig
10
+ from fractal_server.logger import get_logger
11
+ from fractal_server.ssh._fabric import FractalSSH
12
+ from fractal_server.syringe import Inject
13
+ from fractal_server.tasks.v2.utils_background import add_commit_refresh
14
+ from fractal_server.tasks.v2.utils_background import get_current_log
15
+
16
+ FRACTAL_SQUEUE_ERROR_STATE = "__FRACTAL_SQUEUE_ERROR__"
17
+
18
+ # https://slurm.schedmd.com/squeue.html#lbAG
19
+ STATES_FINISHED = {
20
+ "BOOT_FAIL",
21
+ "CANCELLED",
22
+ "COMPLETED",
23
+ "DEADLINE",
24
+ "FAILED",
25
+ "NODE_FAIL",
26
+ "OUT_OF_MEMORY",
27
+ "PREEMPTED",
28
+ "SPECIAL_EXIT",
29
+ "TIMEOUT",
30
+ FRACTAL_SQUEUE_ERROR_STATE,
31
+ }
32
+
33
+
34
+ def _log_change_of_job_state(
35
+ *,
36
+ old_state: str | None,
37
+ new_state: str,
38
+ logger_name: str,
39
+ ) -> None:
40
+ """
41
+ Emit a log for state changes.
42
+
43
+ Args:
44
+ old_state:
45
+ new_state:
46
+ logger_name:
47
+ """
48
+ if new_state != old_state:
49
+ logger = get_logger(logger_name=logger_name)
50
+ logger.debug(
51
+ f"SLURM-job state changed from {old_state=} to {new_state=}."
52
+ )
53
+
54
+
55
+ def _run_squeue(
56
+ *,
57
+ fractal_ssh: FractalSSH,
58
+ squeue_cmd: str,
59
+ logger_name: str,
60
+ ) -> str:
61
+ """
62
+ Run a `squeue` command and handle exceptions.
63
+
64
+ Args:
65
+ fractal_ssh:
66
+ logger_name:
67
+ squeue_cmd:
68
+
69
+ Return:
70
+ state: The SLURM-job state.
71
+ """
72
+ try:
73
+ cmd_stdout = fractal_ssh.run_command(cmd=squeue_cmd)
74
+ state = cmd_stdout.strip().split()[1]
75
+ return state
76
+ except Exception as e:
77
+ logger = get_logger(logger_name=logger_name)
78
+ logger.info(f"`squeue` command failed (original error: {e})")
79
+ return FRACTAL_SQUEUE_ERROR_STATE
80
+
81
+
82
+ def _verify_success_file_exists(
83
+ *,
84
+ fractal_ssh: FractalSSH,
85
+ success_file_remote: str,
86
+ logger_name: str,
87
+ stderr_remote: str,
88
+ ) -> None:
89
+ """
90
+ Fail if the success sentinel file does not exist remotely.
91
+
92
+ Note: the `FractalSSH` methods in this function may fail, and such failures
93
+ are not handled in this function. Any such failure, however, will lead to
94
+ a "failed" task-group lifecycle activity (because it will raise an
95
+ exception from within `run_script_on_remote_slurm`, which will then be
96
+ handled at the calling-function level.
97
+ """
98
+ if not fractal_ssh.remote_exists(path=success_file_remote):
99
+ logger = get_logger(logger_name=logger_name)
100
+ error_msg = f"{success_file_remote=} missing."
101
+ logger.info(error_msg)
102
+ if fractal_ssh.remote_exists(stderr_remote):
103
+ stderr = fractal_ssh.read_remote_text_file(stderr_remote)
104
+ logger.info(f"SLURM-job stderr:\n{stderr}")
105
+ raise RuntimeError(error_msg)
106
+
107
+
108
+ def run_script_on_remote_slurm(
109
+ *,
110
+ script_path: str,
111
+ slurm_config: PixiSLURMConfig,
112
+ fractal_ssh: FractalSSH,
113
+ logger_name: str,
114
+ log_file_path: Path,
115
+ prefix: str,
116
+ db: Session,
117
+ activity: TaskGroupActivityV2,
118
+ ):
119
+ """
120
+ Run a `pixi install` script as a SLURM job.
121
+
122
+ NOTE: This is called from within a try/except, thus we can use exceptions
123
+ as a mechanism to propagate failure/errors.
124
+ """
125
+
126
+ logger = get_logger(logger_name=logger_name)
127
+ settings = Inject(get_settings)
128
+
129
+ # (1) Prepare remote submission script
130
+ workdir_remote = Path(script_path).parent.as_posix()
131
+ submission_script_remote = os.path.join(
132
+ workdir_remote, f"{prefix}-submit.sh"
133
+ )
134
+ stderr_remote = os.path.join(workdir_remote, f"{prefix}-err.txt")
135
+ stdout_remote = os.path.join(workdir_remote, f"{prefix}-out.txt")
136
+ success_file_remote = os.path.join(workdir_remote, f"{prefix}-success.txt")
137
+ script_lines = [
138
+ "#!/bin/bash",
139
+ f"#SBATCH --partition={slurm_config.partition}",
140
+ f"#SBATCH --cpus-per-task={slurm_config.cpus}",
141
+ f"#SBATCH --mem={slurm_config.mem}",
142
+ f"#SBATCH --time={slurm_config.time}",
143
+ f"#SBATCH --err={stderr_remote}",
144
+ f"#SBATCH --out={stdout_remote}",
145
+ f"#SBATCH -D {workdir_remote}",
146
+ "",
147
+ f"bash {script_path}",
148
+ f"touch {success_file_remote}",
149
+ "",
150
+ ]
151
+ script_contents = "\n".join(script_lines)
152
+ fractal_ssh.write_remote_file(
153
+ path=submission_script_remote,
154
+ content=script_contents,
155
+ )
156
+ logger.debug(f"Written {submission_script_remote=}.")
157
+
158
+ activity.log = get_current_log(log_file_path)
159
+ activity = add_commit_refresh(obj=activity, db=db)
160
+
161
+ # (2) Submit SLURM job
162
+ logger.debug("Now submit SLURM job.")
163
+ sbatch_cmd = f"sbatch --parsable {submission_script_remote}"
164
+ try:
165
+ stdout = fractal_ssh.run_command(cmd=sbatch_cmd)
166
+ job_id = int(stdout)
167
+ logger.debug(f"SLURM-job submission successful ({job_id=}).")
168
+ except Exception as e:
169
+ logger.error(
170
+ (
171
+ f"Submission of {submission_script_remote} failed. "
172
+ f"Original error: {str(e)}"
173
+ )
174
+ )
175
+ raise e
176
+ finally:
177
+ activity.log = get_current_log(log_file_path)
178
+ activity = add_commit_refresh(obj=activity, db=db)
179
+
180
+ # (3) Monitor job
181
+ squeue_cmd = (
182
+ f"squeue --noheader --format='%i %T' --states=all --jobs={job_id}"
183
+ )
184
+ logger.debug(f"Start monitoring job with {squeue_cmd=}.")
185
+ old_state = None
186
+ while True:
187
+ new_state = _run_squeue(
188
+ fractal_ssh=fractal_ssh,
189
+ squeue_cmd=squeue_cmd,
190
+ logger_name=logger_name,
191
+ )
192
+ _log_change_of_job_state(
193
+ old_state=old_state,
194
+ new_state=new_state,
195
+ logger_name=logger_name,
196
+ )
197
+ activity.log = get_current_log(log_file_path)
198
+ activity = add_commit_refresh(obj=activity, db=db)
199
+ if new_state in STATES_FINISHED:
200
+ logger.debug(f"Exit retrieval loop (state={new_state}).")
201
+ break
202
+ old_state = new_state
203
+ time.sleep(settings.FRACTAL_SLURM_POLL_INTERVAL)
204
+
205
+ _verify_success_file_exists(
206
+ fractal_ssh=fractal_ssh,
207
+ logger_name=logger_name,
208
+ success_file_remote=success_file_remote,
209
+ stderr_remote=stderr_remote,
210
+ )
211
+
212
+ logger.info("SLURM-job execution completed successfully, continue.")
213
+ activity.log = get_current_log(log_file_path)
214
+ activity = add_commit_refresh(obj=activity, db=db)
@@ -17,29 +17,26 @@ from fractal_server.tasks.v2.utils_templates import customize_template
17
17
  logger = set_logger(__name__)
18
18
 
19
19
 
20
- def _customize_and_run_template(
20
+ def _customize_and_send_template(
21
21
  *,
22
22
  template_filename: str,
23
23
  replacements: set[tuple[str, str]],
24
24
  script_dir_local: str,
25
+ script_dir_remote: str,
25
26
  prefix: str,
26
27
  fractal_ssh: FractalSSH,
27
- script_dir_remote: str,
28
28
  logger_name: str,
29
- login_shell: bool = False,
30
29
  ) -> str:
31
30
  """
32
- Customize one of the template bash scripts, transfer it to the remote host
33
- via SFTP and then run it via SSH.
31
+ Customize a template bash scripts and transfer it to the remote host.
34
32
 
35
33
  Args:
36
34
  template_filename: Filename of the template file (ends with ".sh").
37
35
  replacements: Dictionary of replacements.
38
36
  script_dir_local: Local folder where the script will be placed.
37
+ script_dir_remote: Remote scripts directory
39
38
  prefix: Prefix for the script filename.
40
39
  fractal_ssh: FractalSSH object
41
- script_dir_remote: Remote scripts directory
42
- login_shell: If `True`, use `bash --login` for remote script execution.
43
40
  """
44
41
  logger = get_logger(logger_name=logger_name)
45
42
  logger.debug(f"_customize_and_run_template {template_filename} - START")
@@ -67,10 +64,46 @@ def _customize_and_run_template(
67
64
  local=script_path_local,
68
65
  remote=script_path_remote,
69
66
  )
67
+ return script_path_remote
68
+
69
+
70
+ def _customize_and_run_template(
71
+ *,
72
+ template_filename: str,
73
+ replacements: set[tuple[str, str]],
74
+ script_dir_local: str,
75
+ script_dir_remote: str,
76
+ prefix: str,
77
+ fractal_ssh: FractalSSH,
78
+ logger_name: str,
79
+ ) -> str:
80
+ """
81
+ Customize one of the template bash scripts, transfer it to the remote host
82
+ via SFTP and then run it via SSH.
83
+
84
+ Args:
85
+ template_filename: Filename of the template file (ends with ".sh").
86
+ replacements: Dictionary of replacements.
87
+ script_dir_remote: Remote scripts directory
88
+ script_dir_local: Local folder where the script will be placed.
89
+ prefix: Prefix for the script filename.
90
+ fractal_ssh: FractalSSH object
91
+ """
92
+ logger = get_logger(logger_name=logger_name)
93
+ logger.debug(f"_customize_and_run_template {template_filename} - START")
94
+
95
+ script_path_remote = _customize_and_send_template(
96
+ template_filename=template_filename,
97
+ replacements=replacements,
98
+ script_dir_local=script_dir_local,
99
+ script_dir_remote=script_dir_remote,
100
+ prefix=prefix,
101
+ fractal_ssh=fractal_ssh,
102
+ logger_name=logger_name,
103
+ )
70
104
 
71
105
  # Execute script remotely
72
- bash = "bash --login" if login_shell else "bash"
73
- cmd = f"{bash} {script_path_remote}"
106
+ cmd = f"bash {script_path_remote}"
74
107
  logger.debug(f"Now run '{cmd}' over SSH.")
75
108
  stdout = fractal_ssh.run_command(cmd=cmd)
76
109
 
@@ -8,6 +8,7 @@ from ..utils_background import prepare_tasks_metadata
8
8
  from ..utils_database import create_db_tasks_and_update_task_group_sync
9
9
  from ..utils_pixi import parse_collect_stdout
10
10
  from ..utils_pixi import SOURCE_DIR_NAME
11
+ from ._pixi_slurm_ssh import run_script_on_remote_slurm
11
12
  from ._utils import check_ssh_or_fail_and_cleanup
12
13
  from ._utils import edit_pyproject_toml_in_place_ssh
13
14
  from fractal_server.app.db import get_sync_db
@@ -22,6 +23,7 @@ from fractal_server.ssh._fabric import SingleUseFractalSSH
22
23
  from fractal_server.ssh._fabric import SSHConfig
23
24
  from fractal_server.syringe import Inject
24
25
  from fractal_server.tasks.v2.ssh._utils import _customize_and_run_template
26
+ from fractal_server.tasks.v2.ssh._utils import _customize_and_send_template
25
27
  from fractal_server.tasks.v2.utils_background import add_commit_refresh
26
28
  from fractal_server.tasks.v2.utils_background import get_current_log
27
29
  from fractal_server.tasks.v2.utils_templates import SCRIPTS_SUBFOLDER
@@ -201,16 +203,33 @@ def collect_ssh_pixi(
201
203
  pyproject_toml_path=pyproject_toml_path,
202
204
  )
203
205
 
204
- stdout = _customize_and_run_template(
206
+ # Run script 2 - run pixi-install command
207
+ remote_script2_path = _customize_and_send_template(
205
208
  template_filename="pixi_2_install.sh",
206
209
  replacements=replacements,
207
- login_shell=True,
208
210
  **common_args,
209
211
  )
210
- logger.debug(f"STDOUT: {stdout}")
212
+ logger.debug(
213
+ "Installation script written to "
214
+ f"{remote_script2_path=}."
215
+ )
216
+ activity.log = get_current_log(log_file_path)
217
+ activity = add_commit_refresh(obj=activity, db=db)
218
+
219
+ run_script_on_remote_slurm(
220
+ script_path=remote_script2_path,
221
+ slurm_config=settings.pixi.SLURM_CONFIG,
222
+ fractal_ssh=fractal_ssh,
223
+ logger_name=LOGGER_NAME,
224
+ prefix=common_args["prefix"],
225
+ db=db,
226
+ activity=activity,
227
+ log_file_path=log_file_path,
228
+ )
211
229
  activity.log = get_current_log(log_file_path)
212
230
  activity = add_commit_refresh(obj=activity, db=db)
213
231
 
232
+ # Run script 3 - post-install
214
233
  stdout = _customize_and_run_template(
215
234
  template_filename="pixi_3_post_install.sh",
216
235
  replacements=replacements,
@@ -5,6 +5,7 @@ from tempfile import TemporaryDirectory
5
5
  from ..utils_background import fail_and_cleanup
6
6
  from ..utils_background import get_activity_and_task_group
7
7
  from ..utils_pixi import SOURCE_DIR_NAME
8
+ from ._pixi_slurm_ssh import run_script_on_remote_slurm
8
9
  from ._utils import check_ssh_or_fail_and_cleanup
9
10
  from ._utils import edit_pyproject_toml_in_place_ssh
10
11
  from fractal_server.app.db import get_sync_db
@@ -18,6 +19,7 @@ from fractal_server.ssh._fabric import SSHConfig
18
19
  from fractal_server.syringe import Inject
19
20
  from fractal_server.tasks.utils import get_log_path
20
21
  from fractal_server.tasks.v2.ssh._utils import _customize_and_run_template
22
+ from fractal_server.tasks.v2.ssh._utils import _customize_and_send_template
21
23
  from fractal_server.tasks.v2.utils_background import add_commit_refresh
22
24
  from fractal_server.tasks.v2.utils_background import get_current_log
23
25
  from fractal_server.tasks.v2.utils_templates import SCRIPTS_SUBFOLDER
@@ -187,13 +189,28 @@ def reactivate_ssh_pixi(
187
189
  )
188
190
 
189
191
  # Run script 2 - run pixi-install command
190
- stdout = _customize_and_run_template(
192
+ remote_script2_path = _customize_and_send_template(
191
193
  template_filename="pixi_2_install.sh",
192
194
  replacements=replacements,
193
- login_shell=True,
194
195
  **common_args,
195
196
  )
196
- logger.debug(f"STDOUT: {stdout}")
197
+ logger.debug(
198
+ "Installation script written to "
199
+ f"{remote_script2_path=}."
200
+ )
201
+ activity.log = get_current_log(log_file_path)
202
+ activity = add_commit_refresh(obj=activity, db=db)
203
+
204
+ run_script_on_remote_slurm(
205
+ script_path=remote_script2_path,
206
+ slurm_config=settings.pixi.SLURM_CONFIG,
207
+ fractal_ssh=fractal_ssh,
208
+ logger_name=LOGGER_NAME,
209
+ prefix=common_args["prefix"],
210
+ db=db,
211
+ activity=activity,
212
+ log_file_path=log_file_path,
213
+ )
197
214
  activity.log = get_current_log(log_file_path)
198
215
  activity = add_commit_refresh(obj=activity, db=db)
199
216
 
@@ -143,6 +143,6 @@ def prepare_tasks_metadata(
143
143
  return task_list
144
144
 
145
145
 
146
- def get_current_log(logger_file_path: str) -> str:
146
+ def get_current_log(logger_file_path: str | Path) -> str:
147
147
  with open(logger_file_path) as f:
148
148
  return f.read()
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "fractal-server"
3
- version = "2.16.0"
3
+ version = "2.16.2"
4
4
  description = "Backend component of the Fractal analytics platform"
5
5
  authors = [
6
6
  { name="Tommaso Comparin", email="tommaso.comparin@exact-lab.it" },
@@ -95,7 +95,7 @@ filterwarnings = [
95
95
  markers = ["container", "ssh", "fails_on_macos"]
96
96
 
97
97
  [tool.bumpver]
98
- current_version = "2.16.0"
98
+ current_version = "2.16.2"
99
99
  version_pattern = "MAJOR.MINOR.PATCH[PYTAGNUM]"
100
100
  commit_message = "bump version {old_version} -> {new_version}"
101
101
  commit = true
@@ -1 +0,0 @@
1
- __VERSION__ = "2.16.0"
File without changes