fractal-server 2.16.3__py3-none-any.whl → 2.16.4__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.
- fractal_server/__init__.py +1 -1
- fractal_server/app/routes/admin/v2/job.py +3 -3
- fractal_server/app/routes/admin/v2/task.py +1 -1
- fractal_server/app/routes/admin/v2/task_group.py +1 -1
- fractal_server/app/routes/admin/v2/task_group_lifecycle.py +3 -3
- fractal_server/app/routes/api/v2/_aux_functions.py +7 -7
- fractal_server/app/routes/api/v2/_aux_functions_history.py +2 -2
- fractal_server/app/routes/api/v2/_aux_functions_task_lifecycle.py +37 -13
- fractal_server/app/routes/api/v2/_aux_functions_tasks.py +8 -8
- fractal_server/app/routes/api/v2/dataset.py +4 -4
- fractal_server/app/routes/api/v2/history.py +2 -2
- fractal_server/app/routes/api/v2/images.py +3 -3
- fractal_server/app/routes/api/v2/job.py +1 -1
- fractal_server/app/routes/api/v2/project.py +1 -1
- fractal_server/app/routes/api/v2/status_legacy.py +1 -1
- fractal_server/app/routes/api/v2/submit.py +9 -9
- fractal_server/app/routes/api/v2/task.py +4 -4
- fractal_server/app/routes/api/v2/task_collection.py +5 -5
- fractal_server/app/routes/api/v2/task_collection_custom.py +6 -6
- fractal_server/app/routes/api/v2/task_collection_pixi.py +5 -5
- fractal_server/app/routes/api/v2/task_group_lifecycle.py +3 -3
- fractal_server/app/routes/api/v2/task_version_update.py +3 -3
- fractal_server/app/routes/api/v2/workflow.py +4 -4
- fractal_server/app/routes/api/v2/workflow_import.py +1 -1
- fractal_server/app/routes/api/v2/workflowtask.py +6 -6
- fractal_server/app/routes/auth/group.py +2 -2
- fractal_server/app/routes/auth/users.py +1 -1
- fractal_server/app/routes/aux/_job.py +1 -1
- fractal_server/app/routes/aux/_runner.py +2 -2
- fractal_server/app/routes/aux/validate_user_settings.py +2 -2
- fractal_server/config.py +2 -2
- fractal_server/main.py +1 -1
- fractal_server/{app/runner → runner}/executors/base_runner.py +1 -1
- fractal_server/{app/runner → runner}/executors/call_command_wrapper.py +1 -1
- fractal_server/{app/runner → runner}/executors/local/runner.py +9 -9
- fractal_server/{app/runner → runner}/executors/slurm_common/_slurm_config.py +1 -1
- fractal_server/{app/runner → runner}/executors/slurm_common/base_slurm_runner.py +13 -13
- fractal_server/{app/runner → runner}/executors/slurm_common/slurm_job_task_models.py +1 -1
- fractal_server/{app/runner → runner}/executors/slurm_sudo/runner.py +1 -1
- fractal_server/{app/runner → runner}/task_files.py +1 -1
- fractal_server/{app/runner → runner}/v2/_local.py +2 -2
- fractal_server/{app/runner → runner}/v2/_slurm_ssh.py +3 -3
- fractal_server/{app/runner → runner}/v2/_slurm_sudo.py +2 -2
- fractal_server/{app/runner → runner}/v2/deduplicate_list.py +2 -2
- fractal_server/{app/runner → runner}/v2/merge_outputs.py +2 -2
- fractal_server/{app/runner → runner}/v2/runner.py +3 -3
- fractal_server/{app/runner → runner}/v2/runner_functions.py +12 -12
- fractal_server/{app/runner → runner}/v2/submit_workflow.py +13 -13
- fractal_server/{app/runner → runner}/v2/task_interface.py +2 -2
- fractal_server/ssh/_fabric.py +61 -18
- {fractal_server-2.16.3.dist-info → fractal_server-2.16.4.dist-info}/METADATA +5 -5
- {fractal_server-2.16.3.dist-info → fractal_server-2.16.4.dist-info}/RECORD +78 -78
- /fractal_server/{app/runner → runner}/__init__.py +0 -0
- /fractal_server/{app/runner → runner}/components.py +0 -0
- /fractal_server/{app/runner → runner}/exceptions.py +0 -0
- /fractal_server/{app/runner → runner}/executors/__init__.py +0 -0
- /fractal_server/{app/runner → runner}/executors/local/__init__.py +0 -0
- /fractal_server/{app/runner → runner}/executors/local/get_local_config.py +0 -0
- /fractal_server/{app/runner → runner}/executors/slurm_common/__init__.py +0 -0
- /fractal_server/{app/runner → runner}/executors/slurm_common/_batching.py +0 -0
- /fractal_server/{app/runner → runner}/executors/slurm_common/_job_states.py +0 -0
- /fractal_server/{app/runner → runner}/executors/slurm_common/get_slurm_config.py +0 -0
- /fractal_server/{app/runner → runner}/executors/slurm_common/remote.py +0 -0
- /fractal_server/{app/runner → runner}/executors/slurm_ssh/__init__.py +0 -0
- /fractal_server/{app/runner → runner}/executors/slurm_ssh/run_subprocess.py +0 -0
- /fractal_server/{app/runner → runner}/executors/slurm_ssh/runner.py +0 -0
- /fractal_server/{app/runner → runner}/executors/slurm_ssh/tar_commands.py +0 -0
- /fractal_server/{app/runner → runner}/executors/slurm_sudo/__init__.py +0 -0
- /fractal_server/{app/runner → runner}/executors/slurm_sudo/_subprocess_run_as_user.py +0 -0
- /fractal_server/{app/runner → runner}/filenames.py +0 -0
- /fractal_server/{app/runner → runner}/set_start_and_last_task_index.py +0 -0
- /fractal_server/{app/runner → runner}/shutdown.py +0 -0
- /fractal_server/{app/runner → runner}/v2/__init__.py +0 -0
- /fractal_server/{app/runner → runner}/v2/db_tools.py +0 -0
- /fractal_server/{app/runner → runner}/versions.py +0 -0
- {fractal_server-2.16.3.dist-info → fractal_server-2.16.4.dist-info}/LICENSE +0 -0
- {fractal_server-2.16.3.dist-info → fractal_server-2.16.4.dist-info}/WHEEL +0 -0
- {fractal_server-2.16.3.dist-info → fractal_server-2.16.4.dist-info}/entry_points.txt +0 -0
|
@@ -60,7 +60,7 @@ async def collect_task_custom(
|
|
|
60
60
|
if settings.FRACTAL_RUNNER_BACKEND == "slurm_ssh":
|
|
61
61
|
if task_collect.package_root is None:
|
|
62
62
|
raise HTTPException(
|
|
63
|
-
status_code=status.
|
|
63
|
+
status_code=status.HTTP_422_UNPROCESSABLE_CONTENT,
|
|
64
64
|
detail="Cannot infer 'package_root' with 'slurm_ssh' backend.",
|
|
65
65
|
)
|
|
66
66
|
else:
|
|
@@ -68,7 +68,7 @@ async def collect_task_custom(
|
|
|
68
68
|
task_collect.python_interpreter, os.X_OK
|
|
69
69
|
) or not os.access(task_collect.python_interpreter, os.R_OK):
|
|
70
70
|
raise HTTPException(
|
|
71
|
-
status_code=status.
|
|
71
|
+
status_code=status.HTTP_422_UNPROCESSABLE_CONTENT,
|
|
72
72
|
detail=(
|
|
73
73
|
f"{task_collect.python_interpreter=} "
|
|
74
74
|
"is not accessible to the Fractal user "
|
|
@@ -77,13 +77,13 @@ async def collect_task_custom(
|
|
|
77
77
|
)
|
|
78
78
|
if not Path(task_collect.python_interpreter).is_file():
|
|
79
79
|
raise HTTPException(
|
|
80
|
-
status_code=status.
|
|
80
|
+
status_code=status.HTTP_422_UNPROCESSABLE_CONTENT,
|
|
81
81
|
detail=f"{task_collect.python_interpreter=} is not a file.",
|
|
82
82
|
)
|
|
83
83
|
if task_collect.package_root is not None:
|
|
84
84
|
if not os.access(task_collect.package_root, os.R_OK):
|
|
85
85
|
raise HTTPException(
|
|
86
|
-
status_code=status.
|
|
86
|
+
status_code=status.HTTP_422_UNPROCESSABLE_CONTENT,
|
|
87
87
|
detail=(
|
|
88
88
|
f"{task_collect.package_root=} "
|
|
89
89
|
"is not accessible to the Fractal user."
|
|
@@ -91,7 +91,7 @@ async def collect_task_custom(
|
|
|
91
91
|
)
|
|
92
92
|
if not Path(task_collect.package_root).is_dir():
|
|
93
93
|
raise HTTPException(
|
|
94
|
-
status_code=status.
|
|
94
|
+
status_code=status.HTTP_422_UNPROCESSABLE_CONTENT,
|
|
95
95
|
detail=f"{task_collect.package_root=} is not a directory.",
|
|
96
96
|
)
|
|
97
97
|
|
|
@@ -125,7 +125,7 @@ async def collect_task_custom(
|
|
|
125
125
|
or ("\n" in res.stdout.strip("\n"))
|
|
126
126
|
):
|
|
127
127
|
raise HTTPException(
|
|
128
|
-
status_code=status.
|
|
128
|
+
status_code=status.HTTP_422_UNPROCESSABLE_CONTENT,
|
|
129
129
|
detail=(
|
|
130
130
|
"Cannot determine 'package_root'.\n"
|
|
131
131
|
f"Original output: {res.stdout}\n"
|
|
@@ -54,13 +54,13 @@ logger = set_logger(__name__)
|
|
|
54
54
|
def validate_pkgname_and_version(filename: str) -> tuple[str, str]:
|
|
55
55
|
if not filename.endswith(".tar.gz"):
|
|
56
56
|
raise HTTPException(
|
|
57
|
-
status_code=status.
|
|
57
|
+
status_code=status.HTTP_422_UNPROCESSABLE_CONTENT,
|
|
58
58
|
detail=f"{filename=} does not end with '.tar.gz'.",
|
|
59
59
|
)
|
|
60
60
|
filename_splitted = filename.split("-")
|
|
61
61
|
if len(filename_splitted) != 2:
|
|
62
62
|
raise HTTPException(
|
|
63
|
-
status_code=status.
|
|
63
|
+
status_code=status.HTTP_422_UNPROCESSABLE_CONTENT,
|
|
64
64
|
detail=(
|
|
65
65
|
f"Invalid filename: '{filename}' must contain a single `-` "
|
|
66
66
|
"character, separating the package name from the version "
|
|
@@ -93,7 +93,7 @@ async def collect_task_pixi(
|
|
|
93
93
|
# Check if Pixi is available
|
|
94
94
|
if settings.pixi is None:
|
|
95
95
|
raise HTTPException(
|
|
96
|
-
status_code=status.
|
|
96
|
+
status_code=status.HTTP_422_UNPROCESSABLE_CONTENT,
|
|
97
97
|
detail="Pixi task collection is not available.",
|
|
98
98
|
)
|
|
99
99
|
# Check if provided Pixi version is available. Use default if not provided
|
|
@@ -102,7 +102,7 @@ async def collect_task_pixi(
|
|
|
102
102
|
else:
|
|
103
103
|
if pixi_version not in settings.pixi.versions:
|
|
104
104
|
raise HTTPException(
|
|
105
|
-
status_code=status.
|
|
105
|
+
status_code=status.HTTP_422_UNPROCESSABLE_CONTENT,
|
|
106
106
|
detail=(
|
|
107
107
|
f"Pixi version {pixi_version} is not available. Available "
|
|
108
108
|
f"versions: {list(settings.pixi.versions.keys())}"
|
|
@@ -165,7 +165,7 @@ async def collect_task_pixi(
|
|
|
165
165
|
if settings.FRACTAL_RUNNER_BACKEND != "slurm_ssh":
|
|
166
166
|
if Path(task_group_path).exists():
|
|
167
167
|
raise HTTPException(
|
|
168
|
-
status_code=status.
|
|
168
|
+
status_code=status.HTTP_422_UNPROCESSABLE_CONTENT,
|
|
169
169
|
detail=f"{task_group_path} already exists.",
|
|
170
170
|
)
|
|
171
171
|
|
|
@@ -72,7 +72,7 @@ async def deactivate_task_group(
|
|
|
72
72
|
# Check that task-group is active
|
|
73
73
|
if not task_group.active:
|
|
74
74
|
raise HTTPException(
|
|
75
|
-
status_code=status.
|
|
75
|
+
status_code=status.HTTP_422_UNPROCESSABLE_CONTENT,
|
|
76
76
|
detail=(
|
|
77
77
|
f"Cannot deactivate a task group with {task_group.active=}."
|
|
78
78
|
),
|
|
@@ -185,7 +185,7 @@ async def reactivate_task_group(
|
|
|
185
185
|
# Check that task-group is not active
|
|
186
186
|
if task_group.active:
|
|
187
187
|
raise HTTPException(
|
|
188
|
-
status_code=status.
|
|
188
|
+
status_code=status.HTTP_422_UNPROCESSABLE_CONTENT,
|
|
189
189
|
detail=(
|
|
190
190
|
f"Cannot reactivate a task group with {task_group.active=}."
|
|
191
191
|
),
|
|
@@ -222,7 +222,7 @@ async def reactivate_task_group(
|
|
|
222
222
|
|
|
223
223
|
if task_group.env_info is None:
|
|
224
224
|
raise HTTPException(
|
|
225
|
-
status_code=status.
|
|
225
|
+
status_code=status.HTTP_422_UNPROCESSABLE_CONTENT,
|
|
226
226
|
detail=(
|
|
227
227
|
"Cannot reactivate a task group with "
|
|
228
228
|
f"{task_group.env_info=}."
|
|
@@ -201,7 +201,7 @@ async def replace_workflowtask(
|
|
|
201
201
|
new_type=new_task.type,
|
|
202
202
|
):
|
|
203
203
|
raise HTTPException(
|
|
204
|
-
status_code=status.
|
|
204
|
+
status_code=status.HTTP_422_UNPROCESSABLE_CONTENT,
|
|
205
205
|
detail=(
|
|
206
206
|
"Cannot change task type from "
|
|
207
207
|
f"{workflow_task.task_type} to {new_task.type}."
|
|
@@ -213,7 +213,7 @@ async def replace_workflowtask(
|
|
|
213
213
|
and new_task.type == TaskType.PARALLEL
|
|
214
214
|
):
|
|
215
215
|
raise HTTPException(
|
|
216
|
-
status_code=status.
|
|
216
|
+
status_code=status.HTTP_422_UNPROCESSABLE_CONTENT,
|
|
217
217
|
detail="Cannot set 'args_non_parallel' for parallel task.",
|
|
218
218
|
)
|
|
219
219
|
if (
|
|
@@ -221,7 +221,7 @@ async def replace_workflowtask(
|
|
|
221
221
|
and new_task.type == TaskType.NON_PARALLEL
|
|
222
222
|
):
|
|
223
223
|
raise HTTPException(
|
|
224
|
-
status_code=status.
|
|
224
|
+
status_code=status.HTTP_422_UNPROCESSABLE_CONTENT,
|
|
225
225
|
detail="Cannot set 'args_parallel' for non-parallel task.",
|
|
226
226
|
)
|
|
227
227
|
_check_type_filters_compatibility(
|
|
@@ -151,7 +151,7 @@ async def update_workflow(
|
|
|
151
151
|
workflow_id=workflow_id, db=db
|
|
152
152
|
):
|
|
153
153
|
raise HTTPException(
|
|
154
|
-
status_code=status.
|
|
154
|
+
status_code=status.HTTP_422_UNPROCESSABLE_CONTENT,
|
|
155
155
|
detail=(
|
|
156
156
|
"Cannot re-order WorkflowTasks while a Job is running "
|
|
157
157
|
"for this Workflow."
|
|
@@ -166,7 +166,7 @@ async def update_workflow(
|
|
|
166
166
|
current_workflowtask_ids
|
|
167
167
|
):
|
|
168
168
|
raise HTTPException(
|
|
169
|
-
status_code=status.
|
|
169
|
+
status_code=status.HTTP_422_UNPROCESSABLE_CONTENT,
|
|
170
170
|
detail=(
|
|
171
171
|
"`reordered_workflowtask_ids` must be a permutation of"
|
|
172
172
|
f" {current_workflowtask_ids} (given {value})"
|
|
@@ -225,7 +225,7 @@ async def delete_workflow(
|
|
|
225
225
|
if jobs:
|
|
226
226
|
string_ids = str([job.id for job in jobs])[1:-1]
|
|
227
227
|
raise HTTPException(
|
|
228
|
-
status_code=status.
|
|
228
|
+
status_code=status.HTTP_422_UNPROCESSABLE_CONTENT,
|
|
229
229
|
detail=(
|
|
230
230
|
f"Cannot delete workflow {workflow.id} because it "
|
|
231
231
|
f"is linked to active job(s) {string_ids}."
|
|
@@ -320,7 +320,7 @@ async def get_workflow_type_filters(
|
|
|
320
320
|
num_tasks = len(workflow.task_list)
|
|
321
321
|
if num_tasks == 0:
|
|
322
322
|
raise HTTPException(
|
|
323
|
-
status_code=status.
|
|
323
|
+
status_code=status.HTTP_422_UNPROCESSABLE_CONTENT,
|
|
324
324
|
detail="Workflow has no tasks.",
|
|
325
325
|
)
|
|
326
326
|
|
|
@@ -248,7 +248,7 @@ async def import_workflow(
|
|
|
248
248
|
)
|
|
249
249
|
if task_id is None:
|
|
250
250
|
raise HTTPException(
|
|
251
|
-
status_code=status.
|
|
251
|
+
status_code=status.HTTP_422_UNPROCESSABLE_CONTENT,
|
|
252
252
|
detail=f"Could not find a task matching with {wf_task.task}.",
|
|
253
253
|
)
|
|
254
254
|
new_wf_task = WorkflowTaskCreateV2(
|
|
@@ -55,7 +55,7 @@ async def create_workflowtask(
|
|
|
55
55
|
or wftask.args_non_parallel is not None
|
|
56
56
|
):
|
|
57
57
|
raise HTTPException(
|
|
58
|
-
status_code=status.
|
|
58
|
+
status_code=status.HTTP_422_UNPROCESSABLE_CONTENT,
|
|
59
59
|
detail=(
|
|
60
60
|
"Cannot set `WorkflowTaskV2.meta_non_parallel` or "
|
|
61
61
|
"`WorkflowTask.args_non_parallel` if the associated Task "
|
|
@@ -68,7 +68,7 @@ async def create_workflowtask(
|
|
|
68
68
|
or wftask.args_parallel is not None
|
|
69
69
|
):
|
|
70
70
|
raise HTTPException(
|
|
71
|
-
status_code=status.
|
|
71
|
+
status_code=status.HTTP_422_UNPROCESSABLE_CONTENT,
|
|
72
72
|
detail=(
|
|
73
73
|
"Cannot set `WorkflowTaskV2.meta_parallel` or "
|
|
74
74
|
"`WorkflowTask.args_parallel` if the associated Task "
|
|
@@ -150,7 +150,7 @@ async def update_workflowtask(
|
|
|
150
150
|
or workflow_task_update.meta_non_parallel is not None
|
|
151
151
|
):
|
|
152
152
|
raise HTTPException(
|
|
153
|
-
status_code=status.
|
|
153
|
+
status_code=status.HTTP_422_UNPROCESSABLE_CONTENT,
|
|
154
154
|
detail=(
|
|
155
155
|
"Cannot patch `WorkflowTaskV2.args_non_parallel` or "
|
|
156
156
|
"`WorkflowTask.meta_non_parallel` if the associated Task is "
|
|
@@ -165,7 +165,7 @@ async def update_workflowtask(
|
|
|
165
165
|
or workflow_task_update.meta_parallel is not None
|
|
166
166
|
):
|
|
167
167
|
raise HTTPException(
|
|
168
|
-
status_code=status.
|
|
168
|
+
status_code=status.HTTP_422_UNPROCESSABLE_CONTENT,
|
|
169
169
|
detail=(
|
|
170
170
|
"Cannot patch `WorkflowTaskV2.args_parallel` or "
|
|
171
171
|
"`WorkflowTask.meta_parallel` if the associated Task is "
|
|
@@ -191,7 +191,7 @@ async def update_workflowtask(
|
|
|
191
191
|
setattr(db_wf_task, key, value)
|
|
192
192
|
else:
|
|
193
193
|
raise HTTPException(
|
|
194
|
-
status_code=status.
|
|
194
|
+
status_code=status.HTTP_422_UNPROCESSABLE_CONTENT,
|
|
195
195
|
detail=f"patch_workflow_task endpoint cannot set {key=}",
|
|
196
196
|
)
|
|
197
197
|
|
|
@@ -227,7 +227,7 @@ async def delete_workflowtask(
|
|
|
227
227
|
|
|
228
228
|
if await _workflow_has_submitted_job(workflow_id=workflow_id, db=db):
|
|
229
229
|
raise HTTPException(
|
|
230
|
-
status_code=status.
|
|
230
|
+
status_code=status.HTTP_422_UNPROCESSABLE_CONTENT,
|
|
231
231
|
detail=(
|
|
232
232
|
"Cannot delete a WorkflowTask while a Job is running for this "
|
|
233
233
|
"Workflow."
|
|
@@ -144,7 +144,7 @@ async def delete_single_group(
|
|
|
144
144
|
|
|
145
145
|
if group.name == FRACTAL_DEFAULT_GROUP_NAME:
|
|
146
146
|
raise HTTPException(
|
|
147
|
-
status_code=status.
|
|
147
|
+
status_code=status.HTTP_422_UNPROCESSABLE_CONTENT,
|
|
148
148
|
detail=(
|
|
149
149
|
"Cannot delete default UserGroup "
|
|
150
150
|
f"'{FRACTAL_DEFAULT_GROUP_NAME}'."
|
|
@@ -223,7 +223,7 @@ async def remove_user_from_group(
|
|
|
223
223
|
default_user_group_id = await _get_default_usergroup_id(db=db)
|
|
224
224
|
if default_user_group_id == group_id:
|
|
225
225
|
raise HTTPException(
|
|
226
|
-
status_code=status.
|
|
226
|
+
status_code=status.HTTP_422_UNPROCESSABLE_CONTENT,
|
|
227
227
|
detail=(
|
|
228
228
|
f"Cannot remove user from '{FRACTAL_DEFAULT_GROUP_NAME}' "
|
|
229
229
|
"group.",
|
|
@@ -157,7 +157,7 @@ async def set_user_groups(
|
|
|
157
157
|
default_group_id = await _get_default_usergroup_id(db=db)
|
|
158
158
|
if default_group_id not in target_group_ids:
|
|
159
159
|
raise HTTPException(
|
|
160
|
-
status_code=status.
|
|
160
|
+
status_code=status.HTTP_422_UNPROCESSABLE_CONTENT,
|
|
161
161
|
detail=(
|
|
162
162
|
f"Cannot remove user from "
|
|
163
163
|
f"'{FRACTAL_DEFAULT_GROUP_NAME}' group.",
|
|
@@ -15,7 +15,7 @@ def _backend_supports_shutdown(backend: str) -> bool:
|
|
|
15
15
|
def _check_shutdown_is_supported():
|
|
16
16
|
"""
|
|
17
17
|
Raises:
|
|
18
|
-
HTTPException(status_code=
|
|
18
|
+
HTTPException(status_code=HTTP_422_UNPROCESSABLE_CONTENT):
|
|
19
19
|
If FRACTAL_RUNNER_BACKEND is the thread-based 'local' backend.
|
|
20
20
|
"""
|
|
21
21
|
settings = Inject(get_settings)
|
|
@@ -23,7 +23,7 @@ def _check_shutdown_is_supported():
|
|
|
23
23
|
|
|
24
24
|
if not _backend_supports_shutdown(backend):
|
|
25
25
|
raise HTTPException(
|
|
26
|
-
status_code=status.
|
|
26
|
+
status_code=status.HTTP_422_UNPROCESSABLE_CONTENT,
|
|
27
27
|
detail=(
|
|
28
28
|
"Stopping a job execution is not implemented for "
|
|
29
29
|
f"FRACTAL_RUNNER_BACKEND={backend}."
|
|
@@ -24,7 +24,7 @@ def verify_user_has_settings(user: UserOAuth) -> None:
|
|
|
24
24
|
"""
|
|
25
25
|
if user.user_settings_id is None:
|
|
26
26
|
raise HTTPException(
|
|
27
|
-
status_code=status.
|
|
27
|
+
status_code=status.HTTP_422_UNPROCESSABLE_CONTENT,
|
|
28
28
|
detail=f"Error: user '{user.email}' has no settings.",
|
|
29
29
|
)
|
|
30
30
|
|
|
@@ -66,7 +66,7 @@ async def validate_user_settings(
|
|
|
66
66
|
)
|
|
67
67
|
logger.warning(error_msg)
|
|
68
68
|
raise HTTPException(
|
|
69
|
-
status_code=status.
|
|
69
|
+
status_code=status.HTTP_422_UNPROCESSABLE_CONTENT,
|
|
70
70
|
detail=error_msg,
|
|
71
71
|
)
|
|
72
72
|
|
fractal_server/config.py
CHANGED
|
@@ -806,7 +806,7 @@ class Settings(BaseSettings):
|
|
|
806
806
|
|
|
807
807
|
info = f"FRACTAL_RUNNER_BACKEND={self.FRACTAL_RUNNER_BACKEND}"
|
|
808
808
|
if self.FRACTAL_RUNNER_BACKEND == "slurm":
|
|
809
|
-
from fractal_server.
|
|
809
|
+
from fractal_server.runner.executors.slurm_common._slurm_config import ( # noqa: E501
|
|
810
810
|
load_slurm_config_file,
|
|
811
811
|
)
|
|
812
812
|
|
|
@@ -840,7 +840,7 @@ class Settings(BaseSettings):
|
|
|
840
840
|
"Pixi config must include SLURM_CONFIG."
|
|
841
841
|
)
|
|
842
842
|
|
|
843
|
-
from fractal_server.
|
|
843
|
+
from fractal_server.runner.executors.slurm_common._slurm_config import ( # noqa: E501
|
|
844
844
|
load_slurm_config_file,
|
|
845
845
|
)
|
|
846
846
|
|
fractal_server/main.py
CHANGED
|
@@ -21,12 +21,12 @@ from contextlib import asynccontextmanager
|
|
|
21
21
|
from fastapi import FastAPI
|
|
22
22
|
|
|
23
23
|
from .app.routes.aux._runner import _backend_supports_shutdown
|
|
24
|
-
from .app.runner.shutdown import cleanup_after_shutdown
|
|
25
24
|
from .config import get_settings
|
|
26
25
|
from .logger import config_uvicorn_loggers
|
|
27
26
|
from .logger import get_logger
|
|
28
27
|
from .logger import reset_logger_handlers
|
|
29
28
|
from .logger import set_logger
|
|
29
|
+
from .runner.shutdown import cleanup_after_shutdown
|
|
30
30
|
from .syringe import Inject
|
|
31
31
|
from fractal_server import __VERSION__
|
|
32
32
|
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
from enum import StrEnum
|
|
2
2
|
from typing import Any
|
|
3
3
|
|
|
4
|
-
from fractal_server.app.runner.task_files import TaskFiles
|
|
5
4
|
from fractal_server.app.schemas.v2.task import TaskType
|
|
6
5
|
from fractal_server.logger import set_logger
|
|
6
|
+
from fractal_server.runner.task_files import TaskFiles
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
class SubmitTaskType(StrEnum):
|
|
@@ -7,18 +7,18 @@ from typing import Any
|
|
|
7
7
|
from ..call_command_wrapper import call_command_wrapper
|
|
8
8
|
from .get_local_config import LocalBackendConfig
|
|
9
9
|
from fractal_server.app.db import get_sync_db
|
|
10
|
-
from fractal_server.app.runner.exceptions import TaskExecutionError
|
|
11
|
-
from fractal_server.app.runner.executors.base_runner import BaseRunner
|
|
12
|
-
from fractal_server.app.runner.executors.base_runner import MultisubmitTaskType
|
|
13
|
-
from fractal_server.app.runner.executors.base_runner import SubmitTaskType
|
|
14
|
-
from fractal_server.app.runner.task_files import TaskFiles
|
|
15
|
-
from fractal_server.app.runner.v2.db_tools import (
|
|
16
|
-
bulk_update_status_of_history_unit,
|
|
17
|
-
)
|
|
18
|
-
from fractal_server.app.runner.v2.db_tools import update_status_of_history_unit
|
|
19
10
|
from fractal_server.app.schemas.v2 import HistoryUnitStatus
|
|
20
11
|
from fractal_server.app.schemas.v2 import TaskType
|
|
21
12
|
from fractal_server.logger import set_logger
|
|
13
|
+
from fractal_server.runner.exceptions import TaskExecutionError
|
|
14
|
+
from fractal_server.runner.executors.base_runner import BaseRunner
|
|
15
|
+
from fractal_server.runner.executors.base_runner import MultisubmitTaskType
|
|
16
|
+
from fractal_server.runner.executors.base_runner import SubmitTaskType
|
|
17
|
+
from fractal_server.runner.task_files import TaskFiles
|
|
18
|
+
from fractal_server.runner.v2.db_tools import (
|
|
19
|
+
bulk_update_status_of_history_unit,
|
|
20
|
+
)
|
|
21
|
+
from fractal_server.runner.v2.db_tools import update_status_of_history_unit
|
|
22
22
|
|
|
23
23
|
logger = set_logger(__name__)
|
|
24
24
|
|
|
@@ -212,7 +212,7 @@ class SlurmConfig(BaseModel):
|
|
|
212
212
|
`SlurmConfig` attributes (e.g. `mem_per_task_MB`), which are not meant to
|
|
213
213
|
be part of the `FRACTAL_SLURM_CONFIG_FILE` JSON file (details on the
|
|
214
214
|
expected file content are defined in
|
|
215
|
-
[`SlurmConfigFile`](#fractal_server.
|
|
215
|
+
[`SlurmConfigFile`](#fractal_server.runner._slurm._slurm_config.SlurmConfigFile)).
|
|
216
216
|
|
|
217
217
|
Part of the attributes map directly to some of the SLURM attributes (see
|
|
218
218
|
https://slurm.schedmd.com/sbatch.html), e.g. `partition`. Other attributes
|
|
@@ -16,21 +16,21 @@ from ._job_states import STATES_FINISHED
|
|
|
16
16
|
from fractal_server import __VERSION__
|
|
17
17
|
from fractal_server.app.db import get_sync_db
|
|
18
18
|
from fractal_server.app.models.v2 import AccountingRecordSlurm
|
|
19
|
-
from fractal_server.app.runner.exceptions import JobExecutionError
|
|
20
|
-
from fractal_server.app.runner.exceptions import TaskExecutionError
|
|
21
|
-
from fractal_server.app.runner.executors.base_runner import BaseRunner
|
|
22
|
-
from fractal_server.app.runner.executors.base_runner import MultisubmitTaskType
|
|
23
|
-
from fractal_server.app.runner.executors.base_runner import SubmitTaskType
|
|
24
|
-
from fractal_server.app.runner.filenames import SHUTDOWN_FILENAME
|
|
25
|
-
from fractal_server.app.runner.task_files import TaskFiles
|
|
26
|
-
from fractal_server.app.runner.v2.db_tools import (
|
|
27
|
-
bulk_update_status_of_history_unit,
|
|
28
|
-
)
|
|
29
|
-
from fractal_server.app.runner.v2.db_tools import update_status_of_history_unit
|
|
30
19
|
from fractal_server.app.schemas.v2 import HistoryUnitStatus
|
|
31
20
|
from fractal_server.app.schemas.v2 import TaskType
|
|
32
21
|
from fractal_server.config import get_settings
|
|
33
22
|
from fractal_server.logger import set_logger
|
|
23
|
+
from fractal_server.runner.exceptions import JobExecutionError
|
|
24
|
+
from fractal_server.runner.exceptions import TaskExecutionError
|
|
25
|
+
from fractal_server.runner.executors.base_runner import BaseRunner
|
|
26
|
+
from fractal_server.runner.executors.base_runner import MultisubmitTaskType
|
|
27
|
+
from fractal_server.runner.executors.base_runner import SubmitTaskType
|
|
28
|
+
from fractal_server.runner.filenames import SHUTDOWN_FILENAME
|
|
29
|
+
from fractal_server.runner.task_files import TaskFiles
|
|
30
|
+
from fractal_server.runner.v2.db_tools import (
|
|
31
|
+
bulk_update_status_of_history_unit,
|
|
32
|
+
)
|
|
33
|
+
from fractal_server.runner.v2.db_tools import update_status_of_history_unit
|
|
34
34
|
from fractal_server.syringe import Inject
|
|
35
35
|
|
|
36
36
|
SHUTDOWN_ERROR_MESSAGE = "Failed due to job-execution shutdown."
|
|
@@ -326,7 +326,7 @@ class BaseSlurmRunner(BaseRunner):
|
|
|
326
326
|
output_file = task.output_file_remote
|
|
327
327
|
cmdlines.append(
|
|
328
328
|
f"{self.python_worker_interpreter}"
|
|
329
|
-
" -m fractal_server.
|
|
329
|
+
" -m fractal_server.runner."
|
|
330
330
|
"executors.slurm_common.remote "
|
|
331
331
|
f"--input-file {input_file} "
|
|
332
332
|
f"--output-file {output_file}"
|
|
@@ -1008,7 +1008,7 @@ class BaseSlurmRunner(BaseRunner):
|
|
|
1008
1008
|
# Fetch remote fractal-server version
|
|
1009
1009
|
cmd = (
|
|
1010
1010
|
f"{self.python_worker_interpreter} "
|
|
1011
|
-
"-m fractal_server.
|
|
1011
|
+
"-m fractal_server.runner.versions"
|
|
1012
1012
|
)
|
|
1013
1013
|
stdout = self._run_remote_cmd(cmd)
|
|
1014
1014
|
remote_version = json.loads(stdout.strip("\n"))["fractal_server"]
|
|
@@ -10,9 +10,9 @@ from ..slurm_common.base_slurm_runner import BaseSlurmRunner
|
|
|
10
10
|
from ..slurm_common.slurm_job_task_models import SlurmJob
|
|
11
11
|
from ._subprocess_run_as_user import _mkdir_as_user
|
|
12
12
|
from ._subprocess_run_as_user import _run_command_as_user
|
|
13
|
-
from fractal_server.app.runner.exceptions import JobExecutionError
|
|
14
13
|
from fractal_server.config import get_settings
|
|
15
14
|
from fractal_server.logger import set_logger
|
|
15
|
+
from fractal_server.runner.exceptions import JobExecutionError
|
|
16
16
|
from fractal_server.syringe import Inject
|
|
17
17
|
|
|
18
18
|
logger = set_logger(__name__)
|
|
@@ -2,7 +2,7 @@ from pathlib import Path
|
|
|
2
2
|
|
|
3
3
|
from pydantic import BaseModel
|
|
4
4
|
|
|
5
|
-
from fractal_server.
|
|
5
|
+
from fractal_server.runner.components import _index_to_component
|
|
6
6
|
from fractal_server.string_tools import sanitize_string
|
|
7
7
|
|
|
8
8
|
SUBMIT_PREFIX = "non_par"
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
from pathlib import Path
|
|
2
2
|
|
|
3
|
-
from ...models.v2 import DatasetV2
|
|
4
|
-
from ...models.v2 import WorkflowV2
|
|
5
3
|
from ..executors.local.get_local_config import get_local_backend_config
|
|
6
4
|
from ..executors.local.runner import LocalRunner
|
|
7
5
|
from ..set_start_and_last_task_index import set_start_and_last_task_index
|
|
8
6
|
from .runner import execute_tasks_v2
|
|
7
|
+
from fractal_server.app.models.v2 import DatasetV2
|
|
8
|
+
from fractal_server.app.models.v2 import WorkflowV2
|
|
9
9
|
from fractal_server.types import AttributeFilters
|
|
10
10
|
|
|
11
11
|
|
|
@@ -17,13 +17,13 @@ This backend runs fractal workflows in a SLURM cluster.
|
|
|
17
17
|
"""
|
|
18
18
|
from pathlib import Path
|
|
19
19
|
|
|
20
|
-
from
|
|
21
|
-
from ...models.v2 import DatasetV2
|
|
22
|
-
from ...models.v2 import WorkflowV2
|
|
20
|
+
from ...ssh._fabric import FractalSSH
|
|
23
21
|
from ..executors.slurm_common.get_slurm_config import get_slurm_config
|
|
24
22
|
from ..executors.slurm_ssh.runner import SlurmSSHRunner
|
|
25
23
|
from ..set_start_and_last_task_index import set_start_and_last_task_index
|
|
26
24
|
from .runner import execute_tasks_v2
|
|
25
|
+
from fractal_server.app.models.v2 import DatasetV2
|
|
26
|
+
from fractal_server.app.models.v2 import WorkflowV2
|
|
27
27
|
from fractal_server.logger import set_logger
|
|
28
28
|
from fractal_server.types import AttributeFilters
|
|
29
29
|
|
|
@@ -17,12 +17,12 @@ This backend runs fractal workflows in a SLURM cluster.
|
|
|
17
17
|
"""
|
|
18
18
|
from pathlib import Path
|
|
19
19
|
|
|
20
|
-
from ...models.v2 import DatasetV2
|
|
21
|
-
from ...models.v2 import WorkflowV2
|
|
22
20
|
from ..executors.slurm_common.get_slurm_config import get_slurm_config
|
|
23
21
|
from ..executors.slurm_sudo.runner import SudoSlurmRunner
|
|
24
22
|
from ..set_start_and_last_task_index import set_start_and_last_task_index
|
|
25
23
|
from .runner import execute_tasks_v2
|
|
24
|
+
from fractal_server.app.models.v2 import DatasetV2
|
|
25
|
+
from fractal_server.app.models.v2 import WorkflowV2
|
|
26
26
|
from fractal_server.types import AttributeFilters
|
|
27
27
|
|
|
28
28
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
from typing import TypeVar
|
|
2
2
|
|
|
3
|
-
from ....images import SingleImage
|
|
4
|
-
from ....images import SingleImageTaskOutput
|
|
5
3
|
from .task_interface import InitArgsModel
|
|
4
|
+
from fractal_server.images import SingleImage
|
|
5
|
+
from fractal_server.images import SingleImageTaskOutput
|
|
6
6
|
|
|
7
7
|
T = TypeVar("T", SingleImage, SingleImageTaskOutput, InitArgsModel)
|
|
8
8
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
from fractal_server.
|
|
2
|
-
from fractal_server.
|
|
1
|
+
from fractal_server.runner.v2.deduplicate_list import deduplicate_list
|
|
2
|
+
from fractal_server.runner.v2.task_interface import TaskOutput
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
def merge_outputs(task_outputs: list[TaskOutput]) -> TaskOutput:
|
|
@@ -24,9 +24,6 @@ from fractal_server.app.models.v2 import HistoryUnit
|
|
|
24
24
|
from fractal_server.app.models.v2 import JobV2
|
|
25
25
|
from fractal_server.app.models.v2 import TaskGroupV2
|
|
26
26
|
from fractal_server.app.models.v2 import WorkflowTaskV2
|
|
27
|
-
from fractal_server.app.runner.exceptions import JobExecutionError
|
|
28
|
-
from fractal_server.app.runner.executors.base_runner import BaseRunner
|
|
29
|
-
from fractal_server.app.runner.v2.db_tools import update_status_of_history_run
|
|
30
27
|
from fractal_server.app.schemas.v2 import HistoryUnitStatus
|
|
31
28
|
from fractal_server.app.schemas.v2 import TaskDumpV2
|
|
32
29
|
from fractal_server.app.schemas.v2 import TaskGroupDumpV2
|
|
@@ -38,6 +35,9 @@ from fractal_server.images.tools import filter_image_list
|
|
|
38
35
|
from fractal_server.images.tools import find_image_by_zarr_url
|
|
39
36
|
from fractal_server.images.tools import merge_type_filters
|
|
40
37
|
from fractal_server.logger import get_logger
|
|
38
|
+
from fractal_server.runner.exceptions import JobExecutionError
|
|
39
|
+
from fractal_server.runner.executors.base_runner import BaseRunner
|
|
40
|
+
from fractal_server.runner.v2.db_tools import update_status_of_history_run
|
|
41
41
|
from fractal_server.types import AttributeFilters
|
|
42
42
|
|
|
43
43
|
|
|
@@ -16,24 +16,24 @@ from fractal_server.app.db import get_sync_db
|
|
|
16
16
|
from fractal_server.app.models.v2 import HistoryUnit
|
|
17
17
|
from fractal_server.app.models.v2 import TaskV2
|
|
18
18
|
from fractal_server.app.models.v2 import WorkflowTaskV2
|
|
19
|
-
from fractal_server.app.
|
|
20
|
-
from fractal_server.app.
|
|
21
|
-
from fractal_server.
|
|
22
|
-
from fractal_server.
|
|
23
|
-
from fractal_server.
|
|
19
|
+
from fractal_server.app.schemas.v2 import HistoryUnitStatus
|
|
20
|
+
from fractal_server.app.schemas.v2 import TaskType
|
|
21
|
+
from fractal_server.exceptions import UnreachableBranchError
|
|
22
|
+
from fractal_server.logger import set_logger
|
|
23
|
+
from fractal_server.runner.executors.base_runner import BaseRunner
|
|
24
|
+
from fractal_server.runner.task_files import enrich_task_files_multisubmit
|
|
25
|
+
from fractal_server.runner.task_files import SUBMIT_PREFIX
|
|
26
|
+
from fractal_server.runner.task_files import TaskFiles
|
|
27
|
+
from fractal_server.runner.v2.db_tools import (
|
|
24
28
|
bulk_update_status_of_history_unit,
|
|
25
29
|
)
|
|
26
|
-
from fractal_server.
|
|
27
|
-
from fractal_server.
|
|
30
|
+
from fractal_server.runner.v2.db_tools import bulk_upsert_image_cache_fast
|
|
31
|
+
from fractal_server.runner.v2.task_interface import (
|
|
28
32
|
_cast_and_validate_InitTaskOutput,
|
|
29
33
|
)
|
|
30
|
-
from fractal_server.
|
|
34
|
+
from fractal_server.runner.v2.task_interface import (
|
|
31
35
|
_cast_and_validate_TaskOutput,
|
|
32
36
|
)
|
|
33
|
-
from fractal_server.app.schemas.v2 import HistoryUnitStatus
|
|
34
|
-
from fractal_server.app.schemas.v2 import TaskType
|
|
35
|
-
from fractal_server.exceptions import UnreachableBranchError
|
|
36
|
-
from fractal_server.logger import set_logger
|
|
37
37
|
|
|
38
38
|
__all__ = [
|
|
39
39
|
"run_v2_task_parallel",
|