fractal-server 2.14.5__py3-none-any.whl → 2.14.6__py3-none-any.whl

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 (108) hide show
  1. fractal_server/__init__.py +1 -1
  2. fractal_server/app/db/__init__.py +2 -2
  3. fractal_server/app/models/security.py +8 -8
  4. fractal_server/app/models/user_settings.py +8 -10
  5. fractal_server/app/models/v2/accounting.py +2 -3
  6. fractal_server/app/models/v2/dataset.py +1 -2
  7. fractal_server/app/models/v2/history.py +3 -4
  8. fractal_server/app/models/v2/job.py +10 -11
  9. fractal_server/app/models/v2/project.py +1 -2
  10. fractal_server/app/models/v2/task.py +13 -14
  11. fractal_server/app/models/v2/task_group.py +15 -16
  12. fractal_server/app/models/v2/workflow.py +1 -2
  13. fractal_server/app/models/v2/workflowtask.py +6 -7
  14. fractal_server/app/routes/admin/v2/accounting.py +3 -4
  15. fractal_server/app/routes/admin/v2/job.py +13 -14
  16. fractal_server/app/routes/admin/v2/project.py +2 -4
  17. fractal_server/app/routes/admin/v2/task.py +11 -13
  18. fractal_server/app/routes/admin/v2/task_group.py +15 -17
  19. fractal_server/app/routes/admin/v2/task_group_lifecycle.py +5 -8
  20. fractal_server/app/routes/api/v2/__init__.py +2 -0
  21. fractal_server/app/routes/api/v2/_aux_functions.py +7 -9
  22. fractal_server/app/routes/api/v2/_aux_functions_history.py +1 -1
  23. fractal_server/app/routes/api/v2/_aux_functions_task_lifecycle.py +1 -3
  24. fractal_server/app/routes/api/v2/_aux_functions_tasks.py +5 -6
  25. fractal_server/app/routes/api/v2/dataset.py +6 -8
  26. fractal_server/app/routes/api/v2/history.py +5 -8
  27. fractal_server/app/routes/api/v2/images.py +2 -3
  28. fractal_server/app/routes/api/v2/job.py +5 -6
  29. fractal_server/app/routes/api/v2/pre_submission_checks.py +1 -3
  30. fractal_server/app/routes/api/v2/project.py +2 -4
  31. fractal_server/app/routes/api/v2/status_legacy.py +2 -4
  32. fractal_server/app/routes/api/v2/submit.py +3 -4
  33. fractal_server/app/routes/api/v2/task.py +6 -7
  34. fractal_server/app/routes/api/v2/task_collection.py +11 -13
  35. fractal_server/app/routes/api/v2/task_collection_custom.py +4 -4
  36. fractal_server/app/routes/api/v2/task_group.py +6 -8
  37. fractal_server/app/routes/api/v2/task_group_lifecycle.py +6 -9
  38. fractal_server/app/routes/api/v2/task_version_update.py +270 -0
  39. fractal_server/app/routes/api/v2/workflow.py +5 -6
  40. fractal_server/app/routes/api/v2/workflow_import.py +3 -5
  41. fractal_server/app/routes/api/v2/workflowtask.py +2 -114
  42. fractal_server/app/routes/auth/current_user.py +2 -2
  43. fractal_server/app/routes/pagination.py +2 -3
  44. fractal_server/app/runner/exceptions.py +15 -16
  45. fractal_server/app/runner/executors/base_runner.py +3 -3
  46. fractal_server/app/runner/executors/call_command_wrapper.py +1 -1
  47. fractal_server/app/runner/executors/local/get_local_config.py +2 -3
  48. fractal_server/app/runner/executors/local/runner.py +1 -1
  49. fractal_server/app/runner/executors/slurm_common/_batching.py +2 -3
  50. fractal_server/app/runner/executors/slurm_common/_slurm_config.py +27 -29
  51. fractal_server/app/runner/executors/slurm_common/base_slurm_runner.py +11 -14
  52. fractal_server/app/runner/executors/slurm_common/get_slurm_config.py +2 -3
  53. fractal_server/app/runner/executors/slurm_common/remote.py +2 -2
  54. fractal_server/app/runner/executors/slurm_common/slurm_job_task_models.py +2 -3
  55. fractal_server/app/runner/executors/slurm_ssh/run_subprocess.py +2 -3
  56. fractal_server/app/runner/executors/slurm_ssh/runner.py +3 -4
  57. fractal_server/app/runner/executors/slurm_sudo/_subprocess_run_as_user.py +1 -2
  58. fractal_server/app/runner/executors/slurm_sudo/runner.py +6 -7
  59. fractal_server/app/runner/set_start_and_last_task_index.py +2 -5
  60. fractal_server/app/runner/shutdown.py +5 -11
  61. fractal_server/app/runner/task_files.py +3 -5
  62. fractal_server/app/runner/v2/_local.py +3 -4
  63. fractal_server/app/runner/v2/_slurm_ssh.py +4 -5
  64. fractal_server/app/runner/v2/_slurm_sudo.py +7 -8
  65. fractal_server/app/runner/v2/runner.py +4 -5
  66. fractal_server/app/runner/v2/runner_functions.py +4 -5
  67. fractal_server/app/runner/v2/submit_workflow.py +7 -10
  68. fractal_server/app/runner/v2/task_interface.py +2 -3
  69. fractal_server/app/runner/versions.py +1 -2
  70. fractal_server/app/schemas/user.py +2 -4
  71. fractal_server/app/schemas/user_group.py +1 -2
  72. fractal_server/app/schemas/user_settings.py +19 -21
  73. fractal_server/app/schemas/v2/dataset.py +2 -3
  74. fractal_server/app/schemas/v2/dumps.py +13 -15
  75. fractal_server/app/schemas/v2/history.py +6 -7
  76. fractal_server/app/schemas/v2/job.py +17 -18
  77. fractal_server/app/schemas/v2/manifest.py +12 -13
  78. fractal_server/app/schemas/v2/status_legacy.py +2 -2
  79. fractal_server/app/schemas/v2/task.py +29 -30
  80. fractal_server/app/schemas/v2/task_collection.py +8 -9
  81. fractal_server/app/schemas/v2/task_group.py +22 -23
  82. fractal_server/app/schemas/v2/workflow.py +1 -2
  83. fractal_server/app/schemas/v2/workflowtask.py +27 -29
  84. fractal_server/app/security/__init__.py +10 -12
  85. fractal_server/config.py +32 -33
  86. fractal_server/images/models.py +2 -4
  87. fractal_server/images/tools.py +4 -7
  88. fractal_server/logger.py +3 -5
  89. fractal_server/ssh/_fabric.py +37 -12
  90. fractal_server/string_tools.py +2 -2
  91. fractal_server/syringe.py +1 -1
  92. fractal_server/tasks/v2/local/collect.py +2 -3
  93. fractal_server/tasks/v2/local/deactivate.py +1 -1
  94. fractal_server/tasks/v2/local/reactivate.py +1 -1
  95. fractal_server/tasks/v2/ssh/collect.py +256 -245
  96. fractal_server/tasks/v2/ssh/deactivate.py +210 -187
  97. fractal_server/tasks/v2/ssh/reactivate.py +154 -146
  98. fractal_server/tasks/v2/utils_background.py +2 -3
  99. fractal_server/types/__init__.py +1 -2
  100. fractal_server/types/validators/_filter_validators.py +1 -2
  101. fractal_server/utils.py +4 -5
  102. fractal_server/zip_tools.py +1 -1
  103. {fractal_server-2.14.5.dist-info → fractal_server-2.14.6.dist-info}/METADATA +2 -3
  104. {fractal_server-2.14.5.dist-info → fractal_server-2.14.6.dist-info}/RECORD +107 -107
  105. fractal_server/app/history/__init__.py +0 -0
  106. {fractal_server-2.14.5.dist-info → fractal_server-2.14.6.dist-info}/LICENSE +0 -0
  107. {fractal_server-2.14.5.dist-info → fractal_server-2.14.6.dist-info}/WHEEL +0 -0
  108. {fractal_server-2.14.5.dist-info → fractal_server-2.14.6.dist-info}/entry_points.txt +0 -0
@@ -2,8 +2,8 @@ import logging
2
2
  import time
3
3
  from pathlib import Path
4
4
  from tempfile import TemporaryDirectory
5
- from typing import Optional
6
5
 
6
+ from ....ssh._fabric import SingleUseFractalSSH
7
7
  from ..utils_background import _prepare_tasks_metadata
8
8
  from ..utils_background import fail_and_cleanup
9
9
  from ..utils_database import create_db_tasks_and_update_task_group_sync
@@ -16,7 +16,7 @@ from fractal_server.app.schemas.v2 import WheelFile
16
16
  from fractal_server.app.schemas.v2.manifest import ManifestV2
17
17
  from fractal_server.logger import reset_logger_handlers
18
18
  from fractal_server.logger import set_logger
19
- from fractal_server.ssh._fabric import FractalSSH
19
+ from fractal_server.ssh._fabric import SSHConfig
20
20
  from fractal_server.tasks.v2.ssh._utils import _customize_and_run_template
21
21
  from fractal_server.tasks.v2.utils_background import add_commit_refresh
22
22
  from fractal_server.tasks.v2.utils_background import get_current_log
@@ -36,9 +36,9 @@ def collect_ssh(
36
36
  *,
37
37
  task_group_id: int,
38
38
  task_group_activity_id: int,
39
- fractal_ssh: FractalSSH,
39
+ ssh_config: SSHConfig,
40
40
  tasks_base_dir: str,
41
- wheel_file: Optional[WheelFile] = None,
41
+ wheel_file: WheelFile | None = None,
42
42
  ) -> None:
43
43
  """
44
44
  Collect a task package over SSH
@@ -54,7 +54,7 @@ def collect_ssh(
54
54
  Arguments:
55
55
  task_group_id:
56
56
  task_group_activity_id:
57
- fractal_ssh:
57
+ ssh_config:
58
58
  tasks_base_dir:
59
59
  Only used as a `safe_root` in `remove_dir`, and typically set to
60
60
  `user_settings.ssh_tasks_dir`.
@@ -65,256 +65,267 @@ def collect_ssh(
65
65
 
66
66
  # Work within a temporary folder, where also logs will be placed
67
67
  with TemporaryDirectory() as tmpdir:
68
- LOGGER_NAME = "task_collection_ssh"
69
68
  log_file_path = Path(tmpdir) / "log"
70
69
  logger = set_logger(
71
70
  logger_name=LOGGER_NAME,
72
71
  log_file_path=log_file_path,
73
72
  )
73
+ with SingleUseFractalSSH(
74
+ ssh_config=ssh_config,
75
+ logger_name=LOGGER_NAME,
76
+ ) as fractal_ssh:
77
+
78
+ with next(get_sync_db()) as db:
79
+ # Get main objects from db
80
+ activity = db.get(TaskGroupActivityV2, task_group_activity_id)
81
+ task_group = db.get(TaskGroupV2, task_group_id)
82
+ if activity is None or task_group is None:
83
+ # Use `logging` directly
84
+ logging.error(
85
+ "Cannot find database rows with "
86
+ f"{task_group_id=} and {task_group_activity_id=}:\n"
87
+ f"{task_group=}\n{activity=}. Exit."
88
+ )
89
+ return
90
+
91
+ # Log some info
92
+ logger.info("START")
93
+ for key, value in task_group.model_dump().items():
94
+ logger.debug(f"task_group.{key}: {value}")
95
+
96
+ # Check that SSH connection works
97
+ try:
98
+ fractal_ssh.check_connection()
99
+ except Exception as e:
100
+ logger.error("Cannot establish SSH connection.")
101
+ fail_and_cleanup(
102
+ task_group=task_group,
103
+ task_group_activity=activity,
104
+ logger_name=LOGGER_NAME,
105
+ log_file_path=log_file_path,
106
+ exception=e,
107
+ db=db,
108
+ )
109
+ return
110
+
111
+ # Check that the (remote) task_group path does not exist
112
+ if fractal_ssh.remote_exists(task_group.path):
113
+ error_msg = f"{task_group.path} already exists."
114
+ logger.error(error_msg)
115
+ fail_and_cleanup(
116
+ task_group=task_group,
117
+ task_group_activity=activity,
118
+ logger_name=LOGGER_NAME,
119
+ log_file_path=log_file_path,
120
+ exception=FileExistsError(error_msg),
121
+ db=db,
122
+ )
123
+ return
124
+
125
+ try:
126
+ # Create remote `task_group.path` and `script_dir_remote`
127
+ # folders (note that because of `parents=True` we are in
128
+ # the `no error if existing, make parent directories as
129
+ # needed` scenario for `mkdir`)
130
+ script_dir_remote = (
131
+ Path(task_group.path) / SCRIPTS_SUBFOLDER
132
+ ).as_posix()
133
+ fractal_ssh.mkdir(folder=task_group.path, parents=True)
134
+ fractal_ssh.mkdir(folder=script_dir_remote, parents=True)
135
+
136
+ # Write wheel file locally and send it to remote path,
137
+ # and set task_group.wheel_path
138
+ if wheel_file is not None:
139
+ wheel_filename = wheel_file.filename
140
+ wheel_path = (
141
+ Path(task_group.path) / wheel_filename
142
+ ).as_posix()
143
+ tmp_wheel_path = (
144
+ Path(tmpdir) / wheel_filename
145
+ ).as_posix()
146
+ logger.info(
147
+ f"Write wheel-file contents into {tmp_wheel_path}"
148
+ )
149
+ with open(tmp_wheel_path, "wb") as f:
150
+ f.write(wheel_file.contents)
151
+ fractal_ssh.send_file(
152
+ local=tmp_wheel_path,
153
+ remote=wheel_path,
154
+ )
155
+ task_group.wheel_path = wheel_path
156
+ task_group = add_commit_refresh(obj=task_group, db=db)
157
+
158
+ replacements = get_collection_replacements(
159
+ task_group=task_group,
160
+ python_bin=get_python_interpreter_v2(
161
+ python_version=task_group.python_version
162
+ ),
163
+ )
164
+
165
+ # Prepare common arguments for _customize_and_run_template
166
+ common_args = dict(
167
+ replacements=replacements,
168
+ script_dir_local=(
169
+ Path(tmpdir) / SCRIPTS_SUBFOLDER
170
+ ).as_posix(),
171
+ script_dir_remote=script_dir_remote,
172
+ prefix=(
173
+ f"{int(time.time())}_"
174
+ f"{TaskGroupActivityActionV2.COLLECT}"
175
+ ),
176
+ fractal_ssh=fractal_ssh,
177
+ logger_name=LOGGER_NAME,
178
+ )
179
+
180
+ logger.info("installing - START")
181
+
182
+ # Set status to ONGOING and refresh logs
183
+ activity.status = TaskGroupActivityStatusV2.ONGOING
184
+ activity.log = get_current_log(log_file_path)
185
+ activity = add_commit_refresh(obj=activity, db=db)
186
+
187
+ # Run script 1
188
+ stdout = _customize_and_run_template(
189
+ template_filename="1_create_venv.sh",
190
+ **common_args,
191
+ )
192
+ activity.log = get_current_log(log_file_path)
193
+ activity = add_commit_refresh(obj=activity, db=db)
194
+ # Run script 2
195
+ stdout = _customize_and_run_template(
196
+ template_filename="2_pip_install.sh",
197
+ **common_args,
198
+ )
199
+ activity.log = get_current_log(log_file_path)
200
+ activity = add_commit_refresh(obj=activity, db=db)
74
201
 
75
- with next(get_sync_db()) as db:
76
- # Get main objects from db
77
- activity = db.get(TaskGroupActivityV2, task_group_activity_id)
78
- task_group = db.get(TaskGroupV2, task_group_id)
79
- if activity is None or task_group is None:
80
- # Use `logging` directly
81
- logging.error(
82
- "Cannot find database rows with "
83
- f"{task_group_id=} and {task_group_activity_id=}:\n"
84
- f"{task_group=}\n{activity=}. Exit."
85
- )
86
- return
87
-
88
- # Log some info
89
- logger.info("START")
90
- for key, value in task_group.model_dump().items():
91
- logger.debug(f"task_group.{key}: {value}")
92
-
93
- # Check that SSH connection works
94
- try:
95
- fractal_ssh.check_connection()
96
- except Exception as e:
97
- logger.error("Cannot establish SSH connection.")
98
- fail_and_cleanup(
99
- task_group=task_group,
100
- task_group_activity=activity,
101
- logger_name=LOGGER_NAME,
102
- log_file_path=log_file_path,
103
- exception=e,
104
- db=db,
105
- )
106
- return
107
-
108
- # Check that the (remote) task_group path does not exist
109
- if fractal_ssh.remote_exists(task_group.path):
110
- error_msg = f"{task_group.path} already exists."
111
- logger.error(error_msg)
112
- fail_and_cleanup(
113
- task_group=task_group,
114
- task_group_activity=activity,
115
- logger_name=LOGGER_NAME,
116
- log_file_path=log_file_path,
117
- exception=FileExistsError(error_msg),
118
- db=db,
119
- )
120
- return
121
-
122
- try:
123
- # Create remote `task_group.path` and `script_dir_remote`
124
- # folders (note that because of `parents=True` we are in
125
- # the `no error if existing, make parent directories as
126
- # needed` scenario for `mkdir`)
127
- script_dir_remote = (
128
- Path(task_group.path) / SCRIPTS_SUBFOLDER
129
- ).as_posix()
130
- fractal_ssh.mkdir(folder=task_group.path, parents=True)
131
- fractal_ssh.mkdir(folder=script_dir_remote, parents=True)
132
-
133
- # Write wheel file locally and send it to remote path,
134
- # and set task_group.wheel_path
135
- if wheel_file is not None:
136
- wheel_filename = wheel_file.filename
137
- wheel_path = (
138
- Path(task_group.path) / wheel_filename
202
+ # Run script 3
203
+ pip_freeze_stdout = _customize_and_run_template(
204
+ template_filename="3_pip_freeze.sh",
205
+ **common_args,
206
+ )
207
+ activity.log = get_current_log(log_file_path)
208
+ activity = add_commit_refresh(obj=activity, db=db)
209
+
210
+ # Run script 4
211
+ stdout = _customize_and_run_template(
212
+ template_filename="4_pip_show.sh",
213
+ **common_args,
214
+ )
215
+ activity.log = get_current_log(log_file_path)
216
+ activity = add_commit_refresh(obj=activity, db=db)
217
+
218
+ # Run script 5
219
+ venv_info = _customize_and_run_template(
220
+ template_filename="5_get_venv_size_and_file_number.sh",
221
+ **common_args,
222
+ )
223
+ venv_size, venv_file_number = venv_info.split()
224
+ activity.log = get_current_log(log_file_path)
225
+ activity = add_commit_refresh(obj=activity, db=db)
226
+
227
+ pkg_attrs = parse_script_pip_show_stdout(stdout)
228
+
229
+ for key, value in pkg_attrs.items():
230
+ logger.debug(f"parsed from pip-show: {key}={value}")
231
+ # Check package_name match between pip show and task-group
232
+ package_name_pip_show = pkg_attrs.get("package_name")
233
+ package_name_task_group = task_group.pkg_name
234
+ compare_package_names(
235
+ pkg_name_pip_show=package_name_pip_show,
236
+ pkg_name_task_group=package_name_task_group,
237
+ logger_name=LOGGER_NAME,
238
+ )
239
+ # Extract/drop parsed attributes
240
+ package_name = package_name_task_group
241
+ python_bin = pkg_attrs.pop("python_bin")
242
+ package_root_parent_remote = pkg_attrs.pop(
243
+ "package_root_parent"
244
+ )
245
+ manifest_path_remote = pkg_attrs.pop("manifest_path")
246
+
247
+ # TODO SSH: Use more robust logic to determine
248
+ # `package_root`. Examples: use `importlib.util.find_spec`
249
+ # or parse the output of `pip show --files {package_name}`.
250
+ package_name_underscore = package_name.replace("-", "_")
251
+ package_root_remote = (
252
+ Path(package_root_parent_remote)
253
+ / package_name_underscore
139
254
  ).as_posix()
140
- tmp_wheel_path = (Path(tmpdir) / wheel_filename).as_posix()
255
+
256
+ # Read and validate remote manifest file
257
+ pkg_manifest_dict = fractal_ssh.read_remote_json_file(
258
+ manifest_path_remote
259
+ )
260
+ logger.info(f"Loaded {manifest_path_remote=}")
261
+ pkg_manifest = ManifestV2(**pkg_manifest_dict)
262
+ logger.info("Manifest is a valid ManifestV2")
263
+
264
+ logger.info("_prepare_tasks_metadata - start")
265
+ task_list = _prepare_tasks_metadata(
266
+ package_manifest=pkg_manifest,
267
+ package_version=task_group.version,
268
+ package_root=Path(package_root_remote),
269
+ python_bin=Path(python_bin),
270
+ )
271
+ logger.info("_prepare_tasks_metadata - end")
272
+
141
273
  logger.info(
142
- f"Write wheel-file contents into {tmp_wheel_path}"
274
+ "create_db_tasks_and_update_task_group - " "start"
143
275
  )
144
- with open(tmp_wheel_path, "wb") as f:
145
- f.write(wheel_file.contents)
146
- fractal_ssh.send_file(
147
- local=tmp_wheel_path,
148
- remote=wheel_path,
276
+ create_db_tasks_and_update_task_group_sync(
277
+ task_list=task_list,
278
+ task_group_id=task_group.id,
279
+ db=db,
149
280
  )
150
- task_group.wheel_path = wheel_path
151
- task_group = add_commit_refresh(obj=task_group, db=db)
281
+ logger.info("create_db_tasks_and_update_task_group - end")
152
282
 
153
- replacements = get_collection_replacements(
154
- task_group=task_group,
155
- python_bin=get_python_interpreter_v2(
156
- python_version=task_group.python_version
157
- ),
158
- )
159
-
160
- # Prepare common arguments for `_customize_and_run_template``
161
- common_args = dict(
162
- replacements=replacements,
163
- script_dir_local=(
164
- Path(tmpdir) / SCRIPTS_SUBFOLDER
165
- ).as_posix(),
166
- script_dir_remote=script_dir_remote,
167
- prefix=(
168
- f"{int(time.time())}_"
169
- f"{TaskGroupActivityActionV2.COLLECT.value}"
170
- ),
171
- fractal_ssh=fractal_ssh,
172
- logger_name=LOGGER_NAME,
173
- )
174
-
175
- logger.info("installing - START")
176
-
177
- # Set status to ONGOING and refresh logs
178
- activity.status = TaskGroupActivityStatusV2.ONGOING
179
- activity.log = get_current_log(log_file_path)
180
- activity = add_commit_refresh(obj=activity, db=db)
181
-
182
- # Run script 1
183
- stdout = _customize_and_run_template(
184
- template_filename="1_create_venv.sh",
185
- **common_args,
186
- )
187
- activity.log = get_current_log(log_file_path)
188
- activity = add_commit_refresh(obj=activity, db=db)
189
- # Run script 2
190
- stdout = _customize_and_run_template(
191
- template_filename="2_pip_install.sh",
192
- **common_args,
193
- )
194
- activity.log = get_current_log(log_file_path)
195
- activity = add_commit_refresh(obj=activity, db=db)
196
-
197
- # Run script 3
198
- pip_freeze_stdout = _customize_and_run_template(
199
- template_filename="3_pip_freeze.sh",
200
- **common_args,
201
- )
202
- activity.log = get_current_log(log_file_path)
203
- activity = add_commit_refresh(obj=activity, db=db)
204
-
205
- # Run script 4
206
- stdout = _customize_and_run_template(
207
- template_filename="4_pip_show.sh",
208
- **common_args,
209
- )
210
- activity.log = get_current_log(log_file_path)
211
- activity = add_commit_refresh(obj=activity, db=db)
212
-
213
- # Run script 5
214
- venv_info = _customize_and_run_template(
215
- template_filename="5_get_venv_size_and_file_number.sh",
216
- **common_args,
217
- )
218
- venv_size, venv_file_number = venv_info.split()
219
- activity.log = get_current_log(log_file_path)
220
- activity = add_commit_refresh(obj=activity, db=db)
221
-
222
- pkg_attrs = parse_script_pip_show_stdout(stdout)
223
-
224
- for key, value in pkg_attrs.items():
225
- logger.debug(f"parsed from pip-show: {key}={value}")
226
- # Check package_name match between pip show and task-group
227
- package_name_pip_show = pkg_attrs.get("package_name")
228
- package_name_task_group = task_group.pkg_name
229
- compare_package_names(
230
- pkg_name_pip_show=package_name_pip_show,
231
- pkg_name_task_group=package_name_task_group,
232
- logger_name=LOGGER_NAME,
233
- )
234
- # Extract/drop parsed attributes
235
- package_name = package_name_task_group
236
- python_bin = pkg_attrs.pop("python_bin")
237
- package_root_parent_remote = pkg_attrs.pop(
238
- "package_root_parent"
239
- )
240
- manifest_path_remote = pkg_attrs.pop("manifest_path")
241
-
242
- # TODO SSH: Use more robust logic to determine `package_root`.
243
- # Examples: use `importlib.util.find_spec`, or parse the output
244
- # of `pip show --files {package_name}`.
245
- package_name_underscore = package_name.replace("-", "_")
246
- package_root_remote = (
247
- Path(package_root_parent_remote) / package_name_underscore
248
- ).as_posix()
249
-
250
- # Read and validate remote manifest file
251
- pkg_manifest_dict = fractal_ssh.read_remote_json_file(
252
- manifest_path_remote
253
- )
254
- logger.info(f"Loaded {manifest_path_remote=}")
255
- pkg_manifest = ManifestV2(**pkg_manifest_dict)
256
- logger.info("Manifest is a valid ManifestV2")
257
-
258
- logger.info("_prepare_tasks_metadata - start")
259
- task_list = _prepare_tasks_metadata(
260
- package_manifest=pkg_manifest,
261
- package_version=task_group.version,
262
- package_root=Path(package_root_remote),
263
- python_bin=Path(python_bin),
264
- )
265
- logger.info("_prepare_tasks_metadata - end")
266
-
267
- logger.info("create_db_tasks_and_update_task_group - " "start")
268
- create_db_tasks_and_update_task_group_sync(
269
- task_list=task_list,
270
- task_group_id=task_group.id,
271
- db=db,
272
- )
273
- logger.info("create_db_tasks_and_update_task_group - end")
274
-
275
- # Update task_group data
276
- logger.info(
277
- "Add pip_freeze, venv_size and venv_file_number "
278
- "to TaskGroupV2 - start"
279
- )
280
- task_group.pip_freeze = pip_freeze_stdout
281
- task_group.venv_size_in_kB = int(venv_size)
282
- task_group.venv_file_number = int(venv_file_number)
283
- task_group = add_commit_refresh(obj=task_group, db=db)
284
- logger.info(
285
- "Add pip_freeze, venv_size and venv_file_number "
286
- "to TaskGroupV2 - end"
287
- )
288
-
289
- # Finalize (write metadata to DB)
290
- logger.info("finalising - START")
291
- activity.status = TaskGroupActivityStatusV2.OK
292
- activity.timestamp_ended = get_timestamp()
293
- activity = add_commit_refresh(obj=activity, db=db)
294
- logger.info("finalising - END")
295
- logger.info("END")
296
- reset_logger_handlers(logger)
297
-
298
- except Exception as collection_e:
299
- # Delete corrupted package dir
300
- try:
301
- logger.info(f"Now delete remote folder {task_group.path}")
302
- fractal_ssh.remove_folder(
303
- folder=task_group.path,
304
- safe_root=tasks_base_dir,
283
+ # Update task_group data
284
+ logger.info(
285
+ "Add pip_freeze, venv_size and venv_file_number "
286
+ "to TaskGroupV2 - start"
305
287
  )
306
- logger.info(f"Deleted remoted folder {task_group.path}")
307
- except Exception as e_rm:
308
- logger.error(
309
- "Removing folder failed. "
310
- f"Original error:\n{str(e_rm)}"
288
+ task_group.pip_freeze = pip_freeze_stdout
289
+ task_group.venv_size_in_kB = int(venv_size)
290
+ task_group.venv_file_number = int(venv_file_number)
291
+ task_group = add_commit_refresh(obj=task_group, db=db)
292
+ logger.info(
293
+ "Add pip_freeze, venv_size and venv_file_number "
294
+ "to TaskGroupV2 - end"
295
+ )
296
+
297
+ # Finalize (write metadata to DB)
298
+ logger.info("finalising - START")
299
+ activity.status = TaskGroupActivityStatusV2.OK
300
+ activity.timestamp_ended = get_timestamp()
301
+ activity = add_commit_refresh(obj=activity, db=db)
302
+ logger.info("finalising - END")
303
+ logger.info("END")
304
+ reset_logger_handlers(logger)
305
+
306
+ except Exception as collection_e:
307
+ # Delete corrupted package dir
308
+ try:
309
+ logger.info(
310
+ f"Now delete remote folder {task_group.path}"
311
+ )
312
+ fractal_ssh.remove_folder(
313
+ folder=task_group.path,
314
+ safe_root=tasks_base_dir,
315
+ )
316
+ logger.info(
317
+ f"Deleted remoted folder {task_group.path}"
318
+ )
319
+ except Exception as e_rm:
320
+ logger.error(
321
+ "Removing folder failed. "
322
+ f"Original error:\n{str(e_rm)}"
323
+ )
324
+ fail_and_cleanup(
325
+ task_group=task_group,
326
+ task_group_activity=activity,
327
+ log_file_path=log_file_path,
328
+ logger_name=LOGGER_NAME,
329
+ exception=collection_e,
330
+ db=db,
311
331
  )
312
- fail_and_cleanup(
313
- task_group=task_group,
314
- task_group_activity=activity,
315
- log_file_path=log_file_path,
316
- logger_name=LOGGER_NAME,
317
- exception=collection_e,
318
- db=db,
319
- )
320
- return