fractal-server 2.16.2a0__tar.gz → 2.16.3__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 (244) hide show
  1. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/PKG-INFO +2 -2
  2. fractal_server-2.16.3/fractal_server/__init__.py +1 -0
  3. fractal_server-2.16.3/fractal_server/tasks/v2/ssh/_pixi_slurm_ssh.py +255 -0
  4. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/tasks/v2/ssh/collect_pixi.py +20 -15
  5. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/tasks/v2/ssh/reactivate_pixi.py +20 -15
  6. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/tasks/v2/utils_background.py +1 -1
  7. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/pyproject.toml +3 -3
  8. fractal_server-2.16.2a0/fractal_server/__init__.py +0 -1
  9. fractal_server-2.16.2a0/fractal_server/tasks/v2/ssh/_pixi_slurm_ssh.py +0 -115
  10. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/LICENSE +0 -0
  11. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/README.md +0 -0
  12. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/__main__.py +0 -0
  13. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/alembic.ini +0 -0
  14. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/__init__.py +0 -0
  15. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/db/__init__.py +0 -0
  16. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/models/__init__.py +0 -0
  17. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/models/linkusergroup.py +0 -0
  18. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/models/linkuserproject.py +0 -0
  19. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/models/security.py +0 -0
  20. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/models/user_settings.py +0 -0
  21. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/models/v2/__init__.py +0 -0
  22. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/models/v2/accounting.py +0 -0
  23. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/models/v2/dataset.py +0 -0
  24. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/models/v2/history.py +0 -0
  25. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/models/v2/job.py +0 -0
  26. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/models/v2/project.py +0 -0
  27. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/models/v2/task.py +0 -0
  28. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/models/v2/task_group.py +0 -0
  29. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/models/v2/workflow.py +0 -0
  30. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/models/v2/workflowtask.py +0 -0
  31. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/routes/__init__.py +0 -0
  32. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/routes/admin/__init__.py +0 -0
  33. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/routes/admin/v2/__init__.py +0 -0
  34. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/routes/admin/v2/accounting.py +0 -0
  35. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/routes/admin/v2/impersonate.py +0 -0
  36. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/routes/admin/v2/job.py +0 -0
  37. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/routes/admin/v2/project.py +0 -0
  38. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/routes/admin/v2/task.py +0 -0
  39. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/routes/admin/v2/task_group.py +0 -0
  40. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/routes/admin/v2/task_group_lifecycle.py +0 -0
  41. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/routes/api/__init__.py +0 -0
  42. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/routes/api/v2/__init__.py +0 -0
  43. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/routes/api/v2/_aux_functions.py +0 -0
  44. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/routes/api/v2/_aux_functions_history.py +0 -0
  45. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/routes/api/v2/_aux_functions_task_lifecycle.py +0 -0
  46. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/routes/api/v2/_aux_functions_task_version_update.py +0 -0
  47. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/routes/api/v2/_aux_functions_tasks.py +0 -0
  48. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/routes/api/v2/_aux_task_group_disambiguation.py +0 -0
  49. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/routes/api/v2/dataset.py +0 -0
  50. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/routes/api/v2/history.py +0 -0
  51. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/routes/api/v2/images.py +0 -0
  52. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/routes/api/v2/job.py +0 -0
  53. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/routes/api/v2/pre_submission_checks.py +0 -0
  54. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/routes/api/v2/project.py +0 -0
  55. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/routes/api/v2/status_legacy.py +0 -0
  56. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/routes/api/v2/submit.py +0 -0
  57. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/routes/api/v2/task.py +0 -0
  58. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/routes/api/v2/task_collection.py +0 -0
  59. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/routes/api/v2/task_collection_custom.py +0 -0
  60. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/routes/api/v2/task_collection_pixi.py +0 -0
  61. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/routes/api/v2/task_group.py +0 -0
  62. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/routes/api/v2/task_group_lifecycle.py +0 -0
  63. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/routes/api/v2/task_version_update.py +0 -0
  64. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/routes/api/v2/workflow.py +0 -0
  65. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/routes/api/v2/workflow_import.py +0 -0
  66. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/routes/api/v2/workflowtask.py +0 -0
  67. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/routes/auth/__init__.py +0 -0
  68. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/routes/auth/_aux_auth.py +0 -0
  69. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/routes/auth/current_user.py +0 -0
  70. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/routes/auth/group.py +0 -0
  71. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/routes/auth/login.py +0 -0
  72. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/routes/auth/oauth.py +0 -0
  73. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/routes/auth/register.py +0 -0
  74. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/routes/auth/router.py +0 -0
  75. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/routes/auth/users.py +0 -0
  76. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/routes/aux/__init__.py +0 -0
  77. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/routes/aux/_job.py +0 -0
  78. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/routes/aux/_runner.py +0 -0
  79. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/routes/aux/validate_user_settings.py +0 -0
  80. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/routes/pagination.py +0 -0
  81. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/runner/__init__.py +0 -0
  82. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/runner/components.py +0 -0
  83. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/runner/exceptions.py +0 -0
  84. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/runner/executors/__init__.py +0 -0
  85. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/runner/executors/base_runner.py +0 -0
  86. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/runner/executors/call_command_wrapper.py +0 -0
  87. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/runner/executors/local/__init__.py +0 -0
  88. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/runner/executors/local/get_local_config.py +0 -0
  89. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/runner/executors/local/runner.py +0 -0
  90. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/runner/executors/slurm_common/__init__.py +0 -0
  91. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/runner/executors/slurm_common/_batching.py +0 -0
  92. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/runner/executors/slurm_common/_job_states.py +0 -0
  93. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/runner/executors/slurm_common/_slurm_config.py +0 -0
  94. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/runner/executors/slurm_common/base_slurm_runner.py +0 -0
  95. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/runner/executors/slurm_common/get_slurm_config.py +0 -0
  96. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/runner/executors/slurm_common/remote.py +0 -0
  97. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/runner/executors/slurm_common/slurm_job_task_models.py +0 -0
  98. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/runner/executors/slurm_ssh/__init__.py +0 -0
  99. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/runner/executors/slurm_ssh/run_subprocess.py +0 -0
  100. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/runner/executors/slurm_ssh/runner.py +0 -0
  101. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/runner/executors/slurm_ssh/tar_commands.py +0 -0
  102. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/runner/executors/slurm_sudo/__init__.py +0 -0
  103. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/runner/executors/slurm_sudo/_subprocess_run_as_user.py +0 -0
  104. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/runner/executors/slurm_sudo/runner.py +0 -0
  105. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/runner/filenames.py +0 -0
  106. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/runner/set_start_and_last_task_index.py +0 -0
  107. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/runner/shutdown.py +0 -0
  108. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/runner/task_files.py +0 -0
  109. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/runner/v2/__init__.py +0 -0
  110. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/runner/v2/_local.py +0 -0
  111. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/runner/v2/_slurm_ssh.py +0 -0
  112. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/runner/v2/_slurm_sudo.py +0 -0
  113. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/runner/v2/db_tools.py +0 -0
  114. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/runner/v2/deduplicate_list.py +0 -0
  115. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/runner/v2/merge_outputs.py +0 -0
  116. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/runner/v2/runner.py +0 -0
  117. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/runner/v2/runner_functions.py +0 -0
  118. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/runner/v2/submit_workflow.py +0 -0
  119. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/runner/v2/task_interface.py +0 -0
  120. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/runner/versions.py +0 -0
  121. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/schemas/__init__.py +0 -0
  122. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/schemas/user.py +0 -0
  123. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/schemas/user_group.py +0 -0
  124. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/schemas/user_settings.py +0 -0
  125. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/schemas/v2/__init__.py +0 -0
  126. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/schemas/v2/accounting.py +0 -0
  127. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/schemas/v2/dataset.py +0 -0
  128. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/schemas/v2/dumps.py +0 -0
  129. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/schemas/v2/history.py +0 -0
  130. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/schemas/v2/job.py +0 -0
  131. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/schemas/v2/manifest.py +0 -0
  132. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/schemas/v2/project.py +0 -0
  133. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/schemas/v2/status_legacy.py +0 -0
  134. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/schemas/v2/task.py +0 -0
  135. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/schemas/v2/task_collection.py +0 -0
  136. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/schemas/v2/task_group.py +0 -0
  137. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/schemas/v2/workflow.py +0 -0
  138. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/schemas/v2/workflowtask.py +0 -0
  139. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/security/__init__.py +0 -0
  140. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/security/signup_email.py +0 -0
  141. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/app/user_settings.py +0 -0
  142. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/config.py +0 -0
  143. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/data_migrations/2_14_10.py +0 -0
  144. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/data_migrations/README.md +0 -0
  145. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/data_migrations/tools.py +0 -0
  146. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/exceptions.py +0 -0
  147. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/gunicorn_fractal.py +0 -0
  148. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/images/__init__.py +0 -0
  149. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/images/models.py +0 -0
  150. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/images/status_tools.py +0 -0
  151. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/images/tools.py +0 -0
  152. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/logger.py +0 -0
  153. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/main.py +0 -0
  154. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/migrations/env.py +0 -0
  155. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/migrations/naming_convention.py +0 -0
  156. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/migrations/versions/034a469ec2eb_task_groups.py +0 -0
  157. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/migrations/versions/091b01f51f88_add_usergroup_and_linkusergroup_table.py +0 -0
  158. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/migrations/versions/0f5f85bb2ae7_add_pre_pinned_packages.py +0 -0
  159. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/migrations/versions/19eca0dd47a9_user_settings_project_dir.py +0 -0
  160. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/migrations/versions/1a83a5260664_rename.py +0 -0
  161. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/migrations/versions/1eac13a26c83_drop_v1_tables.py +0 -0
  162. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/migrations/versions/316140ff7ee1_remove_usersettings_cache_dir.py +0 -0
  163. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/migrations/versions/47351f8c7ebc_drop_dataset_filters.py +0 -0
  164. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/migrations/versions/4c308bcaea2b_add_task_args_schema_and_task_args_.py +0 -0
  165. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/migrations/versions/4cedeb448a53_workflowtask_foreign_keys_not_nullables.py +0 -0
  166. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/migrations/versions/501961cfcd85_remove_link_between_v1_and_v2_tasks_.py +0 -0
  167. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/migrations/versions/50a13d6138fd_initial_schema.py +0 -0
  168. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/migrations/versions/5bf02391cfef_v2.py +0 -0
  169. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/migrations/versions/70e77f1c38b0_add_applyworkflow_first_task_index_and_.py +0 -0
  170. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/migrations/versions/71eefd1dd202_add_slurm_accounts.py +0 -0
  171. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/migrations/versions/791ce783d3d8_add_indices.py +0 -0
  172. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/migrations/versions/84bf0fffde30_add_dumps_to_applyworkflow.py +0 -0
  173. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/migrations/versions/8e8f227a3e36_update_taskv2_post_2_7_0.py +0 -0
  174. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/migrations/versions/8f79bd162e35_add_docs_info_and_docs_link_to_task_.py +0 -0
  175. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/migrations/versions/94a47ea2d3ff_remove_cache_dir_slurm_user_and_slurm_.py +0 -0
  176. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/migrations/versions/969d84257cac_add_historyrun_task_id.py +0 -0
  177. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/migrations/versions/97f444d47249_add_applyworkflow_project_dump.py +0 -0
  178. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/migrations/versions/981d588fe248_add_executor_error_log.py +0 -0
  179. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/migrations/versions/99ea79d9e5d2_add_dataset_history.py +0 -0
  180. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/migrations/versions/9c5ae74c9b98_add_user_settings_table.py +0 -0
  181. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/migrations/versions/9db60297b8b2_set_ondelete.py +0 -0
  182. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/migrations/versions/9fd26a2b0de4_add_workflow_timestamp_created.py +0 -0
  183. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/migrations/versions/a7f4d6137b53_add_workflow_dump_to_applyworkflow.py +0 -0
  184. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/migrations/versions/af1ef1c83c9b_add_accounting_tables.py +0 -0
  185. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/migrations/versions/af8673379a5c_drop_old_filter_columns.py +0 -0
  186. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/migrations/versions/b1e7f7a1ff71_task_group_for_pixi.py +0 -0
  187. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/migrations/versions/b3ffb095f973_json_to_jsonb.py +0 -0
  188. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/migrations/versions/c90a7c76e996_job_id_in_history_run.py +0 -0
  189. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/migrations/versions/d256a7379ab8_taskgroup_activity_and_venv_info_to_.py +0 -0
  190. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/migrations/versions/d4fe3708d309_make_applyworkflow_workflow_dump_non_.py +0 -0
  191. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/migrations/versions/da2cb2ac4255_user_group_viewer_paths.py +0 -0
  192. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/migrations/versions/db09233ad13a_split_filters_and_keep_old_columns.py +0 -0
  193. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/migrations/versions/e75cac726012_make_applyworkflow_start_timestamp_not_.py +0 -0
  194. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/migrations/versions/e81103413827_add_job_type_filters.py +0 -0
  195. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/migrations/versions/efa89c30e0a4_add_project_timestamp_created.py +0 -0
  196. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/migrations/versions/f37aceb45062_make_historyunit_logfile_required.py +0 -0
  197. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/migrations/versions/f384e1c0cf5d_drop_task_default_args_columns.py +0 -0
  198. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/migrations/versions/fbce16ff4e47_new_history_items.py +0 -0
  199. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/py.typed +0 -0
  200. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/ssh/__init__.py +0 -0
  201. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/ssh/_fabric.py +0 -0
  202. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/string_tools.py +0 -0
  203. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/syringe.py +0 -0
  204. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/tasks/__init__.py +0 -0
  205. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/tasks/utils.py +0 -0
  206. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/tasks/v2/__init__.py +0 -0
  207. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/tasks/v2/local/__init__.py +0 -0
  208. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/tasks/v2/local/_utils.py +0 -0
  209. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/tasks/v2/local/collect.py +0 -0
  210. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/tasks/v2/local/collect_pixi.py +0 -0
  211. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/tasks/v2/local/deactivate.py +0 -0
  212. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/tasks/v2/local/deactivate_pixi.py +0 -0
  213. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/tasks/v2/local/delete.py +0 -0
  214. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/tasks/v2/local/reactivate.py +0 -0
  215. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/tasks/v2/local/reactivate_pixi.py +0 -0
  216. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/tasks/v2/ssh/__init__.py +0 -0
  217. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/tasks/v2/ssh/_utils.py +0 -0
  218. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/tasks/v2/ssh/collect.py +0 -0
  219. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/tasks/v2/ssh/deactivate.py +0 -0
  220. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/tasks/v2/ssh/deactivate_pixi.py +0 -0
  221. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/tasks/v2/ssh/delete.py +0 -0
  222. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/tasks/v2/ssh/reactivate.py +0 -0
  223. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/tasks/v2/templates/1_create_venv.sh +0 -0
  224. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/tasks/v2/templates/2_pip_install.sh +0 -0
  225. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/tasks/v2/templates/3_pip_freeze.sh +0 -0
  226. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/tasks/v2/templates/4_pip_show.sh +0 -0
  227. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/tasks/v2/templates/5_get_venv_size_and_file_number.sh +0 -0
  228. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/tasks/v2/templates/6_pip_install_from_freeze.sh +0 -0
  229. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/tasks/v2/templates/pixi_1_extract.sh +0 -0
  230. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/tasks/v2/templates/pixi_2_install.sh +0 -0
  231. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/tasks/v2/templates/pixi_3_post_install.sh +0 -0
  232. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/tasks/v2/utils_database.py +0 -0
  233. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/tasks/v2/utils_package_names.py +0 -0
  234. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/tasks/v2/utils_pixi.py +0 -0
  235. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/tasks/v2/utils_python_interpreter.py +0 -0
  236. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/tasks/v2/utils_templates.py +0 -0
  237. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/types/__init__.py +0 -0
  238. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/types/validators/__init__.py +0 -0
  239. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/types/validators/_common_validators.py +0 -0
  240. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/types/validators/_filter_validators.py +0 -0
  241. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/types/validators/_workflow_task_arguments_validators.py +0 -0
  242. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/urls.py +0 -0
  243. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/fractal_server/utils.py +0 -0
  244. {fractal_server-2.16.2a0 → fractal_server-2.16.3}/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.2a0
3
+ Version: 2.16.3
4
4
  Summary: Backend component of the Fractal analytics platform
5
5
  License: BSD-3-Clause
6
6
  Author: Tommaso Comparin
@@ -12,7 +12,7 @@ Classifier: Programming Language :: Python :: 3.11
12
12
  Classifier: Programming Language :: Python :: 3.12
13
13
  Classifier: Programming Language :: Python :: 3.13
14
14
  Requires-Dist: alembic (>=1.13.1,<2.0.0)
15
- Requires-Dist: cryptography (>=45.0.3,<45.1.0)
15
+ Requires-Dist: cryptography (>=46.0.0,<47.0.0)
16
16
  Requires-Dist: fabric (>=3.2.2,<3.3.0)
17
17
  Requires-Dist: fastapi (>=0.116.0,<0.117.0)
18
18
  Requires-Dist: fastapi-users[oauth] (>=14,<15)
@@ -0,0 +1 @@
1
+ __VERSION__ = "2.16.3"
@@ -0,0 +1,255 @@
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 _get_workdir_remote(script_paths: list[str]) -> str:
35
+ """
36
+ Check that there is one and only one `workdir`, and return it.
37
+
38
+ Note: The `is_absolute` check is to filter out a `chmod` command.
39
+ """
40
+ workdirs = [
41
+ Path(script_path).parent.as_posix()
42
+ for script_path in script_paths
43
+ if Path(script_path).is_absolute()
44
+ ]
45
+ if not len(set(workdirs)) == 1:
46
+ raise ValueError(f"Invalid {script_paths=}.")
47
+ return workdirs[0]
48
+
49
+
50
+ def _read_file_if_exists(
51
+ *,
52
+ fractal_ssh: FractalSSH,
53
+ path: str,
54
+ ) -> str:
55
+ """
56
+ Read a remote file if it exists, or return an empty string.
57
+ """
58
+ if fractal_ssh.remote_exists(path=path):
59
+ return fractal_ssh.read_remote_text_file(path)
60
+ else:
61
+ return ""
62
+
63
+
64
+ def _log_change_of_job_state(
65
+ *,
66
+ old_state: str | None,
67
+ new_state: str,
68
+ logger_name: str,
69
+ ) -> None:
70
+ """
71
+ Emit a log for state changes.
72
+
73
+ Args:
74
+ old_state:
75
+ new_state:
76
+ logger_name:
77
+ """
78
+ if new_state != old_state:
79
+ logger = get_logger(logger_name=logger_name)
80
+ logger.debug(
81
+ f"SLURM-job state changed from {old_state=} to {new_state=}."
82
+ )
83
+
84
+
85
+ def _run_squeue(
86
+ *,
87
+ fractal_ssh: FractalSSH,
88
+ squeue_cmd: str,
89
+ logger_name: str,
90
+ ) -> str:
91
+ """
92
+ Run a `squeue` command and handle exceptions.
93
+
94
+ Args:
95
+ fractal_ssh:
96
+ logger_name:
97
+ squeue_cmd:
98
+
99
+ Return:
100
+ state: The SLURM-job state.
101
+ """
102
+ try:
103
+ cmd_stdout = fractal_ssh.run_command(cmd=squeue_cmd)
104
+ state = cmd_stdout.strip().split()[1]
105
+ return state
106
+ except Exception as e:
107
+ logger = get_logger(logger_name=logger_name)
108
+ logger.info(f"`squeue` command failed (original error: {e})")
109
+ return FRACTAL_SQUEUE_ERROR_STATE
110
+
111
+
112
+ def _verify_success_file_exists(
113
+ *,
114
+ fractal_ssh: FractalSSH,
115
+ success_file_remote: str,
116
+ logger_name: str,
117
+ stderr_remote: str,
118
+ ) -> None:
119
+ """
120
+ Fail if the success sentinel file does not exist remotely.
121
+
122
+ Note: the `FractalSSH` methods in this function may fail, and such failures
123
+ are not handled in this function. Any such failure, however, will lead to
124
+ a "failed" task-group lifecycle activity (because it will raise an
125
+ exception from within `run_script_on_remote_slurm`, which will then be
126
+ handled at the calling-function level.
127
+ """
128
+ if not fractal_ssh.remote_exists(path=success_file_remote):
129
+ logger = get_logger(logger_name=logger_name)
130
+ error_msg = f"{success_file_remote=} missing."
131
+ logger.info(error_msg)
132
+
133
+ stderr = _read_file_if_exists(
134
+ fractal_ssh=fractal_ssh, path=stderr_remote
135
+ )
136
+ if stderr:
137
+ logger.info(f"SLURM-job stderr:\n{stderr}")
138
+ raise RuntimeError(error_msg)
139
+
140
+
141
+ def run_script_on_remote_slurm(
142
+ *,
143
+ script_paths: list[str],
144
+ slurm_config: PixiSLURMConfig,
145
+ fractal_ssh: FractalSSH,
146
+ logger_name: str,
147
+ log_file_path: Path,
148
+ prefix: str,
149
+ db: Session,
150
+ activity: TaskGroupActivityV2,
151
+ ):
152
+ """
153
+ Run a `pixi install` script as a SLURM job.
154
+
155
+ NOTE: This is called from within a try/except, thus we can use exceptions
156
+ as a mechanism to propagate failure/errors.
157
+ """
158
+
159
+ logger = get_logger(logger_name=logger_name)
160
+ settings = Inject(get_settings)
161
+
162
+ # (1) Prepare remote submission script
163
+ workdir_remote = _get_workdir_remote(script_paths)
164
+ submission_script_remote = os.path.join(
165
+ workdir_remote, f"{prefix}-submit.sh"
166
+ )
167
+ stderr_remote = os.path.join(workdir_remote, f"{prefix}-err.txt")
168
+ stdout_remote = os.path.join(workdir_remote, f"{prefix}-out.txt")
169
+ success_file_remote = os.path.join(workdir_remote, f"{prefix}-success.txt")
170
+ script_lines = [
171
+ "#!/bin/bash",
172
+ f"#SBATCH --partition={slurm_config.partition}",
173
+ f"#SBATCH --cpus-per-task={slurm_config.cpus}",
174
+ f"#SBATCH --mem={slurm_config.mem}",
175
+ f"#SBATCH --time={slurm_config.time}",
176
+ f"#SBATCH --err={stderr_remote}",
177
+ f"#SBATCH --out={stdout_remote}",
178
+ f"#SBATCH -D {workdir_remote}",
179
+ "",
180
+ ]
181
+ for script_path in script_paths:
182
+ script_lines.append(f"bash {script_path}")
183
+ script_lines.append(f"touch {success_file_remote}")
184
+
185
+ script_contents = "\n".join(script_lines)
186
+ fractal_ssh.write_remote_file(
187
+ path=submission_script_remote,
188
+ content=script_contents,
189
+ )
190
+ logger.debug(f"Written {submission_script_remote=}.")
191
+
192
+ activity.log = get_current_log(log_file_path)
193
+ activity = add_commit_refresh(obj=activity, db=db)
194
+
195
+ # (2) Submit SLURM job
196
+ logger.debug("Now submit SLURM job.")
197
+ sbatch_cmd = f"sbatch --parsable {submission_script_remote}"
198
+ try:
199
+ stdout = fractal_ssh.run_command(cmd=sbatch_cmd)
200
+ job_id = int(stdout)
201
+ logger.debug(f"SLURM-job submission successful ({job_id=}).")
202
+ except Exception as e:
203
+ logger.error(
204
+ (
205
+ f"Submission of {submission_script_remote} failed. "
206
+ f"Original error: {str(e)}"
207
+ )
208
+ )
209
+ raise e
210
+ finally:
211
+ activity.log = get_current_log(log_file_path)
212
+ activity = add_commit_refresh(obj=activity, db=db)
213
+
214
+ # (3) Monitor job
215
+ squeue_cmd = (
216
+ f"squeue --noheader --format='%i %T' --states=all --jobs={job_id}"
217
+ )
218
+ logger.debug(f"Start monitoring job with {squeue_cmd=}.")
219
+ old_state = None
220
+ while True:
221
+ new_state = _run_squeue(
222
+ fractal_ssh=fractal_ssh,
223
+ squeue_cmd=squeue_cmd,
224
+ logger_name=logger_name,
225
+ )
226
+ _log_change_of_job_state(
227
+ old_state=old_state,
228
+ new_state=new_state,
229
+ logger_name=logger_name,
230
+ )
231
+ activity.log = get_current_log(log_file_path)
232
+ activity = add_commit_refresh(obj=activity, db=db)
233
+ if new_state in STATES_FINISHED:
234
+ logger.debug(f"Exit retrieval loop (state={new_state}).")
235
+ break
236
+ old_state = new_state
237
+ time.sleep(settings.FRACTAL_SLURM_POLL_INTERVAL)
238
+
239
+ _verify_success_file_exists(
240
+ fractal_ssh=fractal_ssh,
241
+ logger_name=logger_name,
242
+ success_file_remote=success_file_remote,
243
+ stderr_remote=stderr_remote,
244
+ )
245
+
246
+ stdout = _read_file_if_exists(
247
+ fractal_ssh=fractal_ssh,
248
+ path=stdout_remote,
249
+ )
250
+
251
+ logger.info("SLURM-job execution completed successfully, continue.")
252
+ activity.log = get_current_log(log_file_path)
253
+ activity = add_commit_refresh(obj=activity, db=db)
254
+
255
+ return stdout
@@ -203,12 +203,21 @@ def collect_ssh_pixi(
203
203
  pyproject_toml_path=pyproject_toml_path,
204
204
  )
205
205
 
206
- # Run script 2 - run pixi-install command
206
+ # Prepare scripts 2 and 3
207
207
  remote_script2_path = _customize_and_send_template(
208
208
  template_filename="pixi_2_install.sh",
209
209
  replacements=replacements,
210
210
  **common_args,
211
211
  )
212
+ remote_script3_path = _customize_and_send_template(
213
+ template_filename="pixi_3_post_install.sh",
214
+ replacements=replacements,
215
+ **common_args,
216
+ )
217
+ logger.debug(
218
+ "Post-installation script written to "
219
+ f"{remote_script3_path=}."
220
+ )
212
221
  logger.debug(
213
222
  "Installation script written to "
214
223
  f"{remote_script2_path=}."
@@ -216,26 +225,24 @@ def collect_ssh_pixi(
216
225
  activity.log = get_current_log(log_file_path)
217
226
  activity = add_commit_refresh(obj=activity, db=db)
218
227
 
219
- run_script_on_remote_slurm(
220
- script_path=remote_script2_path,
228
+ # Run scripts 2 and 3
229
+ stdout = run_script_on_remote_slurm(
230
+ script_paths=[
231
+ remote_script2_path,
232
+ remote_script3_path,
233
+ f"chmod -R 755 {source_dir}",
234
+ ],
221
235
  slurm_config=settings.pixi.SLURM_CONFIG,
222
236
  fractal_ssh=fractal_ssh,
223
237
  logger_name=LOGGER_NAME,
224
238
  prefix=common_args["prefix"],
239
+ db=db,
240
+ activity=activity,
241
+ log_file_path=log_file_path,
225
242
  )
226
243
  activity.log = get_current_log(log_file_path)
227
244
  activity = add_commit_refresh(obj=activity, db=db)
228
245
 
229
- # Run script 3 - post-install
230
- stdout = _customize_and_run_template(
231
- template_filename="pixi_3_post_install.sh",
232
- replacements=replacements,
233
- **common_args,
234
- )
235
- logger.debug(f"STDOUT: {stdout}")
236
- activity.log = get_current_log(log_file_path)
237
- activity = add_commit_refresh(obj=activity, db=db)
238
-
239
246
  # Parse stdout
240
247
  parsed_output = parse_collect_stdout(stdout)
241
248
  package_root_remote = parsed_output["package_root"]
@@ -245,8 +252,6 @@ def collect_ssh_pixi(
245
252
  "project_python_wrapper"
246
253
  ]
247
254
 
248
- fractal_ssh.run_command(cmd=f"chmod -R 755 {source_dir}")
249
-
250
255
  # Read and validate remote manifest file
251
256
  manifest_path_remote = (
252
257
  f"{package_root_remote}/__FRACTAL_MANIFEST__.json"
@@ -188,12 +188,21 @@ def reactivate_ssh_pixi(
188
188
  remote=pixi_lock_remote,
189
189
  )
190
190
 
191
- # Run script 2 - run pixi-install command
191
+ # Prepare scripts 2 and 3
192
192
  remote_script2_path = _customize_and_send_template(
193
193
  template_filename="pixi_2_install.sh",
194
194
  replacements=replacements,
195
195
  **common_args,
196
196
  )
197
+ remote_script3_path = _customize_and_send_template(
198
+ template_filename="pixi_3_post_install.sh",
199
+ replacements=replacements,
200
+ **common_args,
201
+ )
202
+ logger.debug(
203
+ "Post-installation script written to "
204
+ f"{remote_script3_path=}."
205
+ )
197
206
  logger.debug(
198
207
  "Installation script written to "
199
208
  f"{remote_script2_path=}."
@@ -201,28 +210,24 @@ def reactivate_ssh_pixi(
201
210
  activity.log = get_current_log(log_file_path)
202
211
  activity = add_commit_refresh(obj=activity, db=db)
203
212
 
204
- run_script_on_remote_slurm(
205
- script_path=remote_script2_path,
213
+ # Run scripts 2 and 3
214
+ stdout = run_script_on_remote_slurm(
215
+ script_paths=[
216
+ remote_script2_path,
217
+ remote_script3_path,
218
+ f"chmod -R 755 {source_dir}",
219
+ ],
206
220
  slurm_config=settings.pixi.SLURM_CONFIG,
207
221
  fractal_ssh=fractal_ssh,
208
222
  logger_name=LOGGER_NAME,
209
223
  prefix=common_args["prefix"],
224
+ db=db,
225
+ activity=activity,
226
+ log_file_path=log_file_path,
210
227
  )
211
228
  activity.log = get_current_log(log_file_path)
212
229
  activity = add_commit_refresh(obj=activity, db=db)
213
230
 
214
- # Run script 3 - post-install
215
- stdout = _customize_and_run_template(
216
- template_filename="pixi_3_post_install.sh",
217
- replacements=replacements,
218
- **common_args,
219
- )
220
- logger.debug(f"STDOUT: {stdout}")
221
- activity.log = get_current_log(log_file_path)
222
- activity = add_commit_refresh(obj=activity, db=db)
223
-
224
- fractal_ssh.run_command(cmd=f"chmod -R 755 {source_dir}")
225
-
226
231
  # Finalize (write metadata to DB)
227
232
  activity.status = TaskGroupActivityStatusV2.OK
228
233
  activity.timestamp_ended = get_timestamp()
@@ -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.2a0"
3
+ version = "2.16.3"
4
4
  description = "Backend component of the Fractal analytics platform"
5
5
  authors = [
6
6
  { name="Tommaso Comparin", email="tommaso.comparin@exact-lab.it" },
@@ -26,7 +26,7 @@ dependencies = [
26
26
  "fabric >= 3.2.2, <3.3.0",
27
27
  "gunicorn >=23.0,<24.0",
28
28
  "psycopg[binary] >= 3.1.0, <4.0.0",
29
- "cryptography >=45.0.3,<45.1.0",
29
+ "cryptography >=46.0.0,<47.0.0",
30
30
  "tomli_w >=1.2.0, <1.3.0 "
31
31
  ]
32
32
 
@@ -95,7 +95,7 @@ filterwarnings = [
95
95
  markers = ["container", "ssh", "fails_on_macos"]
96
96
 
97
97
  [tool.bumpver]
98
- current_version = "2.16.2a0"
98
+ current_version = "2.16.3"
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.2a0"
@@ -1,115 +0,0 @@
1
- import os
2
- import time
3
- from pathlib import Path
4
-
5
- from fractal_server.config import get_settings
6
- from fractal_server.config import PixiSLURMConfig
7
- from fractal_server.logger import get_logger
8
- from fractal_server.ssh._fabric import FractalSSH
9
- from fractal_server.syringe import Inject
10
-
11
-
12
- # https://slurm.schedmd.com/squeue.html#lbAG
13
- STATES_FINISHED = {
14
- "BOOT_FAIL",
15
- "CANCELLED",
16
- "COMPLETED",
17
- "DEADLINE",
18
- "FAILED",
19
- "NODE_FAIL",
20
- "OUT_OF_MEMORY",
21
- "PREEMPTED",
22
- "SPECIAL_EXIT",
23
- "TIMEOUT",
24
- }
25
-
26
-
27
- def run_script_on_remote_slurm(
28
- *,
29
- script_path: str,
30
- slurm_config: PixiSLURMConfig,
31
- fractal_ssh: FractalSSH,
32
- logger_name: str,
33
- prefix: str,
34
- ):
35
- """
36
- FIXME
37
-
38
-
39
- NOTE: This is called from within a try/except, thus we can use exceptions
40
- as a mechanism to propagate failure/errors.
41
- """
42
-
43
- logger = get_logger(logger_name=logger_name)
44
- settings = Inject(get_settings)
45
-
46
- # (1) Prepare remote submission script
47
- workdir_remote = Path(script_path).parent.as_posix()
48
- submission_script_remote = os.path.join(
49
- workdir_remote, f"{prefix}-submit.sh"
50
- )
51
- stderr_remote = os.path.join(workdir_remote, f"{prefix}-err.txt")
52
- stdout_remote = os.path.join(workdir_remote, f"{prefix}-out.txt")
53
- success_file_remote = os.path.join(workdir_remote, f"{prefix}-success.txt")
54
- script_lines = [
55
- "#!/bin/bash",
56
- f"#SBATCH --partition={slurm_config.partition}",
57
- f"#SBATCH --cpus-per-task={slurm_config.cpus}",
58
- f"#SBATCH --mem={slurm_config.mem}",
59
- f"#SBATCH --time={slurm_config.time}",
60
- f"#SBATCH --err={stderr_remote}",
61
- f"#SBATCH --out={stdout_remote}",
62
- f"#SBATCH -D {workdir_remote}",
63
- "",
64
- f"bash {script_path}",
65
- f"touch {success_file_remote}",
66
- "",
67
- ]
68
- script_contents = "\n".join(script_lines)
69
- fractal_ssh.write_remote_file(
70
- path=submission_script_remote,
71
- content=script_contents,
72
- )
73
-
74
- # (2) Submit SLURM job
75
- sbatch_cmd = f"sbatch --parsable {submission_script_remote} "
76
- try:
77
- stdout = fractal_ssh.run_command(cmd=sbatch_cmd)
78
- except Exception as e:
79
- logger.error(
80
- f"Submission of {submission_script_remote} failed. "
81
- f"Original error: {str(e)}"
82
- )
83
- raise e
84
- logger.debug(f"Now submit job {submission_script_remote} to SLURM.")
85
- job_id = int(stdout)
86
- logger.debug(f"SLURM-job submission successful ({job_id=}).")
87
-
88
- # (3) Monitor job
89
- squeue_cmd = (
90
- f"squeue --noheader --format='%i %T' --states=all --jobs={job_id}"
91
- )
92
- while True:
93
- try:
94
- stdout = fractal_ssh.run_command(cmd=squeue_cmd)
95
- except Exception as e:
96
- # FIXME: review this logic
97
- logger.info(
98
- f"`squeue` command failed (original error: {e}), "
99
- "consider the job as complete."
100
- )
101
- break
102
- state = stdout.strip().split()[1]
103
- logger.debug(f"Status of SLURM job {job_id}: {state}")
104
- if state in STATES_FINISHED:
105
- logger.debug(f"Exit retrieval loop ({state=}).")
106
- break
107
- time.sleep(settings.FRACTAL_SLURM_POLL_INTERVAL)
108
-
109
- if fractal_ssh.remote_exists(path=success_file_remote):
110
- logger.info(f"{success_file_remote=} exists.")
111
- else:
112
- raise RuntimeError(
113
- "SLURM job did not complete correctly "
114
- f"({success_file_remote=} missing)."
115
- )