fractal-server 2.16.5__py3-none-any.whl → 2.17.0a0__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/__main__.py +129 -22
- fractal_server/app/db/__init__.py +9 -11
- fractal_server/app/models/security.py +7 -3
- fractal_server/app/models/user_settings.py +0 -4
- fractal_server/app/models/v2/__init__.py +4 -0
- fractal_server/app/models/v2/job.py +3 -4
- fractal_server/app/models/v2/profile.py +16 -0
- fractal_server/app/models/v2/project.py +3 -0
- fractal_server/app/models/v2/resource.py +130 -0
- fractal_server/app/models/v2/task_group.py +3 -0
- fractal_server/app/routes/admin/v2/__init__.py +4 -0
- fractal_server/app/routes/admin/v2/_aux_functions.py +55 -0
- fractal_server/app/routes/admin/v2/profile.py +86 -0
- fractal_server/app/routes/admin/v2/resource.py +229 -0
- fractal_server/app/routes/admin/v2/task_group_lifecycle.py +48 -82
- fractal_server/app/routes/api/__init__.py +26 -7
- fractal_server/app/routes/api/v2/_aux_functions.py +27 -1
- fractal_server/app/routes/api/v2/_aux_functions_history.py +2 -2
- fractal_server/app/routes/api/v2/_aux_functions_task_lifecycle.py +3 -3
- fractal_server/app/routes/api/v2/_aux_functions_tasks.py +7 -7
- fractal_server/app/routes/api/v2/project.py +5 -1
- fractal_server/app/routes/api/v2/submit.py +32 -24
- fractal_server/app/routes/api/v2/task.py +5 -0
- fractal_server/app/routes/api/v2/task_collection.py +36 -47
- fractal_server/app/routes/api/v2/task_collection_custom.py +11 -5
- fractal_server/app/routes/api/v2/task_collection_pixi.py +34 -40
- fractal_server/app/routes/api/v2/task_group_lifecycle.py +39 -82
- fractal_server/app/routes/api/v2/workflow_import.py +4 -3
- fractal_server/app/routes/auth/_aux_auth.py +3 -3
- fractal_server/app/routes/auth/current_user.py +45 -7
- fractal_server/app/routes/auth/oauth.py +1 -1
- fractal_server/app/routes/auth/users.py +9 -0
- fractal_server/app/routes/aux/_runner.py +2 -1
- fractal_server/app/routes/aux/validate_user_profile.py +62 -0
- fractal_server/app/routes/aux/validate_user_settings.py +12 -9
- fractal_server/app/schemas/user.py +20 -13
- fractal_server/app/schemas/user_settings.py +0 -4
- fractal_server/app/schemas/v2/__init__.py +11 -0
- fractal_server/app/schemas/v2/profile.py +72 -0
- fractal_server/app/schemas/v2/resource.py +117 -0
- fractal_server/app/security/__init__.py +6 -13
- fractal_server/app/security/signup_email.py +2 -2
- fractal_server/app/user_settings.py +2 -12
- fractal_server/config/__init__.py +23 -0
- fractal_server/config/_database.py +58 -0
- fractal_server/config/_email.py +170 -0
- fractal_server/config/_init_data.py +27 -0
- fractal_server/config/_main.py +216 -0
- fractal_server/config/_settings_config.py +7 -0
- fractal_server/images/tools.py +3 -3
- fractal_server/logger.py +3 -3
- fractal_server/main.py +14 -21
- fractal_server/migrations/versions/90f6508c6379_drop_useroauth_username.py +36 -0
- fractal_server/migrations/versions/a80ac5a352bf_resource_profile.py +195 -0
- fractal_server/runner/config/__init__.py +2 -0
- fractal_server/runner/config/_local.py +21 -0
- fractal_server/runner/config/_slurm.py +128 -0
- fractal_server/runner/config/slurm_mem_to_MB.py +63 -0
- fractal_server/runner/exceptions.py +4 -0
- fractal_server/runner/executors/base_runner.py +17 -7
- fractal_server/runner/executors/local/get_local_config.py +21 -86
- fractal_server/runner/executors/local/runner.py +48 -5
- fractal_server/runner/executors/slurm_common/_batching.py +2 -2
- fractal_server/runner/executors/slurm_common/base_slurm_runner.py +59 -25
- fractal_server/runner/executors/slurm_common/get_slurm_config.py +38 -54
- fractal_server/runner/executors/slurm_common/remote.py +1 -1
- fractal_server/runner/executors/slurm_common/{_slurm_config.py → slurm_config.py} +3 -254
- fractal_server/runner/executors/slurm_common/slurm_job_task_models.py +1 -1
- fractal_server/runner/executors/slurm_ssh/runner.py +12 -14
- fractal_server/runner/executors/slurm_sudo/_subprocess_run_as_user.py +2 -2
- fractal_server/runner/executors/slurm_sudo/runner.py +12 -12
- fractal_server/runner/v2/_local.py +36 -21
- fractal_server/runner/v2/_slurm_ssh.py +40 -4
- fractal_server/runner/v2/_slurm_sudo.py +41 -11
- fractal_server/runner/v2/db_tools.py +1 -1
- fractal_server/runner/v2/runner.py +3 -11
- fractal_server/runner/v2/runner_functions.py +42 -28
- fractal_server/runner/v2/submit_workflow.py +87 -108
- fractal_server/runner/versions.py +8 -3
- fractal_server/ssh/_fabric.py +6 -6
- fractal_server/tasks/config/__init__.py +3 -0
- fractal_server/tasks/config/_pixi.py +127 -0
- fractal_server/tasks/config/_python.py +51 -0
- fractal_server/tasks/v2/local/_utils.py +7 -7
- fractal_server/tasks/v2/local/collect.py +13 -5
- fractal_server/tasks/v2/local/collect_pixi.py +26 -10
- fractal_server/tasks/v2/local/deactivate.py +7 -1
- fractal_server/tasks/v2/local/deactivate_pixi.py +5 -1
- fractal_server/tasks/v2/local/delete.py +4 -0
- fractal_server/tasks/v2/local/reactivate.py +13 -5
- fractal_server/tasks/v2/local/reactivate_pixi.py +27 -9
- fractal_server/tasks/v2/ssh/_pixi_slurm_ssh.py +11 -10
- fractal_server/tasks/v2/ssh/_utils.py +6 -7
- fractal_server/tasks/v2/ssh/collect.py +19 -12
- fractal_server/tasks/v2/ssh/collect_pixi.py +34 -16
- fractal_server/tasks/v2/ssh/deactivate.py +12 -8
- fractal_server/tasks/v2/ssh/deactivate_pixi.py +14 -10
- fractal_server/tasks/v2/ssh/delete.py +12 -9
- fractal_server/tasks/v2/ssh/reactivate.py +18 -12
- fractal_server/tasks/v2/ssh/reactivate_pixi.py +36 -17
- fractal_server/tasks/v2/templates/4_pip_show.sh +4 -6
- fractal_server/tasks/v2/utils_database.py +2 -2
- fractal_server/tasks/v2/utils_python_interpreter.py +8 -16
- fractal_server/tasks/v2/utils_templates.py +7 -10
- fractal_server/utils.py +1 -1
- {fractal_server-2.16.5.dist-info → fractal_server-2.17.0a0.dist-info}/METADATA +5 -5
- {fractal_server-2.16.5.dist-info → fractal_server-2.17.0a0.dist-info}/RECORD +112 -90
- {fractal_server-2.16.5.dist-info → fractal_server-2.17.0a0.dist-info}/WHEEL +1 -1
- fractal_server/config.py +0 -906
- /fractal_server/{runner → app}/shutdown.py +0 -0
- {fractal_server-2.16.5.dist-info → fractal_server-2.17.0a0.dist-info}/entry_points.txt +0 -0
- {fractal_server-2.16.5.dist-info → fractal_server-2.17.0a0.dist-info/licenses}/LICENSE +0 -0
|
@@ -10,6 +10,8 @@ from ._utils import _copy_wheel_file_ssh
|
|
|
10
10
|
from ._utils import _customize_and_run_template
|
|
11
11
|
from ._utils import check_ssh_or_fail_and_cleanup
|
|
12
12
|
from fractal_server.app.db import get_sync_db
|
|
13
|
+
from fractal_server.app.models import Profile
|
|
14
|
+
from fractal_server.app.models import Resource
|
|
13
15
|
from fractal_server.app.schemas.v2 import TaskGroupActivityActionV2
|
|
14
16
|
from fractal_server.app.schemas.v2 import TaskGroupV2OriginEnum
|
|
15
17
|
from fractal_server.app.schemas.v2.task_group import TaskGroupActivityStatusV2
|
|
@@ -28,8 +30,8 @@ def deactivate_ssh(
|
|
|
28
30
|
*,
|
|
29
31
|
task_group_activity_id: int,
|
|
30
32
|
task_group_id: int,
|
|
31
|
-
|
|
32
|
-
|
|
33
|
+
resource: Resource,
|
|
34
|
+
profile: Profile,
|
|
33
35
|
) -> None:
|
|
34
36
|
"""
|
|
35
37
|
Deactivate a task group venv.
|
|
@@ -37,13 +39,10 @@ def deactivate_ssh(
|
|
|
37
39
|
This function is run as a background task, therefore exceptions must be
|
|
38
40
|
handled.
|
|
39
41
|
|
|
40
|
-
|
|
42
|
+
Args:
|
|
41
43
|
task_group_id:
|
|
42
44
|
task_group_activity_id:
|
|
43
45
|
ssh_config:
|
|
44
|
-
tasks_base_dir:
|
|
45
|
-
Only used as a `safe_root` in `remove_dir`, and typically set to
|
|
46
|
-
`user_settings.ssh_tasks_dir`.
|
|
47
46
|
"""
|
|
48
47
|
|
|
49
48
|
LOGGER_NAME = f"{__name__}.ID{task_group_activity_id}"
|
|
@@ -66,7 +65,11 @@ def deactivate_ssh(
|
|
|
66
65
|
return
|
|
67
66
|
|
|
68
67
|
with SingleUseFractalSSH(
|
|
69
|
-
ssh_config=
|
|
68
|
+
ssh_config=SSHConfig(
|
|
69
|
+
user=profile.username,
|
|
70
|
+
host=resource.host,
|
|
71
|
+
key_path=profile.ssh_key_path,
|
|
72
|
+
),
|
|
70
73
|
logger_name=LOGGER_NAME,
|
|
71
74
|
) as fractal_ssh:
|
|
72
75
|
try:
|
|
@@ -110,6 +113,7 @@ def deactivate_ssh(
|
|
|
110
113
|
replacements = get_collection_replacements(
|
|
111
114
|
task_group=task_group,
|
|
112
115
|
python_bin="/not/applicable",
|
|
116
|
+
resource=resource,
|
|
113
117
|
)
|
|
114
118
|
|
|
115
119
|
# Define script_dir_remote and create it if missing
|
|
@@ -255,7 +259,7 @@ def deactivate_ssh(
|
|
|
255
259
|
logger.info(f"Now removing {task_group.venv_path}.")
|
|
256
260
|
fractal_ssh.remove_folder(
|
|
257
261
|
folder=task_group.venv_path,
|
|
258
|
-
safe_root=
|
|
262
|
+
safe_root=profile.tasks_remote_dir,
|
|
259
263
|
)
|
|
260
264
|
logger.info(f"All good, {task_group.venv_path} removed.")
|
|
261
265
|
activity.status = TaskGroupActivityStatusV2.OK
|
|
@@ -7,6 +7,8 @@ from ..utils_background import get_activity_and_task_group
|
|
|
7
7
|
from ..utils_pixi import SOURCE_DIR_NAME
|
|
8
8
|
from ._utils import check_ssh_or_fail_and_cleanup
|
|
9
9
|
from fractal_server.app.db import get_sync_db
|
|
10
|
+
from fractal_server.app.models import Profile
|
|
11
|
+
from fractal_server.app.models import Resource
|
|
10
12
|
from fractal_server.app.schemas.v2.task_group import TaskGroupActivityStatusV2
|
|
11
13
|
from fractal_server.logger import reset_logger_handlers
|
|
12
14
|
from fractal_server.logger import set_logger
|
|
@@ -21,8 +23,8 @@ def deactivate_ssh_pixi(
|
|
|
21
23
|
*,
|
|
22
24
|
task_group_activity_id: int,
|
|
23
25
|
task_group_id: int,
|
|
24
|
-
|
|
25
|
-
|
|
26
|
+
resource: Resource,
|
|
27
|
+
profile: Profile,
|
|
26
28
|
) -> None:
|
|
27
29
|
"""
|
|
28
30
|
Deactivate a pixi task group venv.
|
|
@@ -30,13 +32,11 @@ def deactivate_ssh_pixi(
|
|
|
30
32
|
This function is run as a background task, therefore exceptions must be
|
|
31
33
|
handled.
|
|
32
34
|
|
|
33
|
-
|
|
34
|
-
task_group_id:
|
|
35
|
+
Args:
|
|
35
36
|
task_group_activity_id:
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
`user_settings.ssh_tasks_dir`.
|
|
37
|
+
task_group_id:
|
|
38
|
+
resource:
|
|
39
|
+
profile:
|
|
40
40
|
"""
|
|
41
41
|
|
|
42
42
|
LOGGER_NAME = f"{__name__}.ID{task_group_activity_id}"
|
|
@@ -59,7 +59,11 @@ def deactivate_ssh_pixi(
|
|
|
59
59
|
return
|
|
60
60
|
|
|
61
61
|
with SingleUseFractalSSH(
|
|
62
|
-
ssh_config=
|
|
62
|
+
ssh_config=SSHConfig(
|
|
63
|
+
host=resource.host,
|
|
64
|
+
user=profile.username,
|
|
65
|
+
key_path=profile.ssh_key_path,
|
|
66
|
+
),
|
|
63
67
|
logger_name=LOGGER_NAME,
|
|
64
68
|
) as fractal_ssh:
|
|
65
69
|
try:
|
|
@@ -101,7 +105,7 @@ def deactivate_ssh_pixi(
|
|
|
101
105
|
logger.info(f"Now removing {source_dir}.")
|
|
102
106
|
fractal_ssh.remove_folder(
|
|
103
107
|
folder=source_dir,
|
|
104
|
-
safe_root=
|
|
108
|
+
safe_root=profile.tasks_remote_dir,
|
|
105
109
|
)
|
|
106
110
|
logger.info(f"All good, {source_dir} removed.")
|
|
107
111
|
activity.status = TaskGroupActivityStatusV2.OK
|
|
@@ -6,6 +6,8 @@ from ..utils_background import fail_and_cleanup
|
|
|
6
6
|
from ..utils_background import get_activity_and_task_group
|
|
7
7
|
from ._utils import check_ssh_or_fail_and_cleanup
|
|
8
8
|
from fractal_server.app.db import get_sync_db
|
|
9
|
+
from fractal_server.app.models import Profile
|
|
10
|
+
from fractal_server.app.models import Resource
|
|
9
11
|
from fractal_server.app.schemas.v2 import TaskGroupActivityStatusV2
|
|
10
12
|
from fractal_server.app.schemas.v2 import TaskGroupV2OriginEnum
|
|
11
13
|
from fractal_server.logger import reset_logger_handlers
|
|
@@ -21,8 +23,8 @@ def delete_ssh(
|
|
|
21
23
|
*,
|
|
22
24
|
task_group_activity_id: int,
|
|
23
25
|
task_group_id: int,
|
|
24
|
-
|
|
25
|
-
|
|
26
|
+
resource: Resource,
|
|
27
|
+
profile: Profile,
|
|
26
28
|
) -> None:
|
|
27
29
|
"""
|
|
28
30
|
Delete a task group.
|
|
@@ -30,13 +32,10 @@ def delete_ssh(
|
|
|
30
32
|
This function is run as a background task, therefore exceptions must be
|
|
31
33
|
handled.
|
|
32
34
|
|
|
33
|
-
|
|
35
|
+
Args:
|
|
34
36
|
task_group_id:
|
|
35
37
|
task_group_activity_id:
|
|
36
38
|
ssh_config:
|
|
37
|
-
tasks_base_dir:
|
|
38
|
-
Only used as a `safe_root` in `remove_dir`, and typically set to
|
|
39
|
-
`user_settings.ssh_tasks_dir`.
|
|
40
39
|
"""
|
|
41
40
|
|
|
42
41
|
LOGGER_NAME = f"{__name__}.ID{task_group_activity_id}"
|
|
@@ -59,7 +58,11 @@ def delete_ssh(
|
|
|
59
58
|
return
|
|
60
59
|
|
|
61
60
|
with SingleUseFractalSSH(
|
|
62
|
-
ssh_config=
|
|
61
|
+
ssh_config=SSHConfig(
|
|
62
|
+
host=resource.host,
|
|
63
|
+
user=profile.username,
|
|
64
|
+
key_path=profile.ssh_key_path,
|
|
65
|
+
),
|
|
63
66
|
logger_name=LOGGER_NAME,
|
|
64
67
|
) as fractal_ssh:
|
|
65
68
|
try:
|
|
@@ -86,11 +89,11 @@ def delete_ssh(
|
|
|
86
89
|
if task_group.origin != TaskGroupV2OriginEnum.OTHER:
|
|
87
90
|
logger.debug(
|
|
88
91
|
f"Removing remote {task_group.path=} "
|
|
89
|
-
f"(with {
|
|
92
|
+
f"(with {profile.tasks_remote_dir=})."
|
|
90
93
|
)
|
|
91
94
|
fractal_ssh.remove_folder(
|
|
92
95
|
folder=task_group.path,
|
|
93
|
-
safe_root=
|
|
96
|
+
safe_root=profile.tasks_remote_dir,
|
|
94
97
|
)
|
|
95
98
|
logger.debug(f"Remote {task_group.path=} removed.")
|
|
96
99
|
|
|
@@ -9,6 +9,8 @@ from ..utils_templates import get_collection_replacements
|
|
|
9
9
|
from ._utils import _customize_and_run_template
|
|
10
10
|
from ._utils import check_ssh_or_fail_and_cleanup
|
|
11
11
|
from fractal_server.app.db import get_sync_db
|
|
12
|
+
from fractal_server.app.models import Profile
|
|
13
|
+
from fractal_server.app.models import Resource
|
|
12
14
|
from fractal_server.app.schemas.v2 import TaskGroupActivityActionV2
|
|
13
15
|
from fractal_server.app.schemas.v2.task_group import TaskGroupActivityStatusV2
|
|
14
16
|
from fractal_server.logger import reset_logger_handlers
|
|
@@ -18,7 +20,7 @@ from fractal_server.ssh._fabric import SSHConfig
|
|
|
18
20
|
from fractal_server.tasks.utils import get_log_path
|
|
19
21
|
from fractal_server.tasks.v2.utils_background import get_current_log
|
|
20
22
|
from fractal_server.tasks.v2.utils_python_interpreter import (
|
|
21
|
-
|
|
23
|
+
get_python_interpreter,
|
|
22
24
|
)
|
|
23
25
|
from fractal_server.tasks.v2.utils_templates import SCRIPTS_SUBFOLDER
|
|
24
26
|
from fractal_server.utils import get_timestamp
|
|
@@ -28,8 +30,8 @@ def reactivate_ssh(
|
|
|
28
30
|
*,
|
|
29
31
|
task_group_activity_id: int,
|
|
30
32
|
task_group_id: int,
|
|
31
|
-
|
|
32
|
-
|
|
33
|
+
resource: Resource,
|
|
34
|
+
profile: Profile,
|
|
33
35
|
) -> None:
|
|
34
36
|
"""
|
|
35
37
|
Reactivate a task group venv.
|
|
@@ -37,13 +39,10 @@ def reactivate_ssh(
|
|
|
37
39
|
This function is run as a background task, therefore exceptions must be
|
|
38
40
|
handled.
|
|
39
41
|
|
|
40
|
-
|
|
42
|
+
Args:
|
|
41
43
|
task_group_id:
|
|
42
44
|
task_group_activity_id:
|
|
43
45
|
ssh_config:
|
|
44
|
-
tasks_base_dir:
|
|
45
|
-
Only used as a `safe_root` in `remove_dir`, and typically set to
|
|
46
|
-
`user_settings.ssh_tasks_dir`.
|
|
47
46
|
"""
|
|
48
47
|
|
|
49
48
|
LOGGER_NAME = f"{__name__}.ID{task_group_activity_id}"
|
|
@@ -67,7 +66,11 @@ def reactivate_ssh(
|
|
|
67
66
|
return
|
|
68
67
|
|
|
69
68
|
with SingleUseFractalSSH(
|
|
70
|
-
ssh_config=
|
|
69
|
+
ssh_config=SSHConfig(
|
|
70
|
+
host=resource.host,
|
|
71
|
+
user=profile.username,
|
|
72
|
+
key_path=profile.ssh_key_path,
|
|
73
|
+
),
|
|
71
74
|
logger_name=LOGGER_NAME,
|
|
72
75
|
) as fractal_ssh:
|
|
73
76
|
try:
|
|
@@ -102,11 +105,14 @@ def reactivate_ssh(
|
|
|
102
105
|
activity = add_commit_refresh(obj=activity, db=db)
|
|
103
106
|
|
|
104
107
|
# Prepare replacements for templates
|
|
108
|
+
python_bin = get_python_interpreter(
|
|
109
|
+
python_version=task_group.python_version,
|
|
110
|
+
resource=resource,
|
|
111
|
+
)
|
|
105
112
|
replacements = get_collection_replacements(
|
|
106
113
|
task_group=task_group,
|
|
107
|
-
python_bin=
|
|
108
|
-
|
|
109
|
-
),
|
|
114
|
+
python_bin=python_bin,
|
|
115
|
+
resource=resource,
|
|
110
116
|
)
|
|
111
117
|
|
|
112
118
|
# Prepare replacements for templates
|
|
@@ -181,7 +187,7 @@ def reactivate_ssh(
|
|
|
181
187
|
)
|
|
182
188
|
fractal_ssh.remove_folder(
|
|
183
189
|
folder=task_group.venv_path,
|
|
184
|
-
safe_root=
|
|
190
|
+
safe_root=profile.tasks_remote_dir,
|
|
185
191
|
)
|
|
186
192
|
logger.info(f"Deleted folder {task_group.venv_path}")
|
|
187
193
|
except Exception as rm_e:
|
|
@@ -9,14 +9,14 @@ from ._pixi_slurm_ssh import run_script_on_remote_slurm
|
|
|
9
9
|
from ._utils import check_ssh_or_fail_and_cleanup
|
|
10
10
|
from ._utils import edit_pyproject_toml_in_place_ssh
|
|
11
11
|
from fractal_server.app.db import get_sync_db
|
|
12
|
+
from fractal_server.app.models import Profile
|
|
13
|
+
from fractal_server.app.models import Resource
|
|
12
14
|
from fractal_server.app.schemas.v2 import TaskGroupActivityActionV2
|
|
13
15
|
from fractal_server.app.schemas.v2 import TaskGroupActivityStatusV2
|
|
14
|
-
from fractal_server.config import get_settings
|
|
15
16
|
from fractal_server.logger import reset_logger_handlers
|
|
16
17
|
from fractal_server.logger import set_logger
|
|
17
18
|
from fractal_server.ssh._fabric import SingleUseFractalSSH
|
|
18
19
|
from fractal_server.ssh._fabric import SSHConfig
|
|
19
|
-
from fractal_server.syringe import Inject
|
|
20
20
|
from fractal_server.tasks.utils import get_log_path
|
|
21
21
|
from fractal_server.tasks.v2.ssh._utils import _customize_and_run_template
|
|
22
22
|
from fractal_server.tasks.v2.ssh._utils import _customize_and_send_template
|
|
@@ -30,8 +30,8 @@ def reactivate_ssh_pixi(
|
|
|
30
30
|
*,
|
|
31
31
|
task_group_activity_id: int,
|
|
32
32
|
task_group_id: int,
|
|
33
|
-
|
|
34
|
-
|
|
33
|
+
resource: Resource,
|
|
34
|
+
profile: Profile,
|
|
35
35
|
) -> None:
|
|
36
36
|
"""
|
|
37
37
|
Reactivate a task group venv.
|
|
@@ -39,13 +39,11 @@ def reactivate_ssh_pixi(
|
|
|
39
39
|
This function is run as a background task, therefore exceptions must be
|
|
40
40
|
handled.
|
|
41
41
|
|
|
42
|
-
|
|
42
|
+
Args:
|
|
43
43
|
task_group_id:
|
|
44
44
|
task_group_activity_id:
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
Only used as a `safe_root` in `remove_dir`, and typically set to
|
|
48
|
-
`user_settings.ssh_tasks_dir`.
|
|
45
|
+
resource:
|
|
46
|
+
profile:
|
|
49
47
|
"""
|
|
50
48
|
|
|
51
49
|
LOGGER_NAME = f"{__name__}.ID{task_group_activity_id}"
|
|
@@ -69,7 +67,11 @@ def reactivate_ssh_pixi(
|
|
|
69
67
|
return
|
|
70
68
|
|
|
71
69
|
with SingleUseFractalSSH(
|
|
72
|
-
ssh_config=
|
|
70
|
+
ssh_config=SSHConfig(
|
|
71
|
+
host=resource.host,
|
|
72
|
+
user=profile.username,
|
|
73
|
+
key_path=profile.ssh_key_path,
|
|
74
|
+
),
|
|
73
75
|
logger_name=LOGGER_NAME,
|
|
74
76
|
) as fractal_ssh:
|
|
75
77
|
try:
|
|
@@ -103,11 +105,12 @@ def reactivate_ssh_pixi(
|
|
|
103
105
|
)
|
|
104
106
|
return
|
|
105
107
|
|
|
106
|
-
settings = Inject(get_settings)
|
|
107
108
|
replacements = {
|
|
108
109
|
(
|
|
109
110
|
"__PIXI_HOME__",
|
|
110
|
-
|
|
111
|
+
resource.tasks_pixi_config["versions"][
|
|
112
|
+
task_group.pixi_version
|
|
113
|
+
],
|
|
111
114
|
),
|
|
112
115
|
("__PACKAGE_DIR__", task_group.path),
|
|
113
116
|
("__TAR_GZ_PATH__", task_group.archive_path),
|
|
@@ -119,15 +122,27 @@ def reactivate_ssh_pixi(
|
|
|
119
122
|
("__FROZEN_OPTION__", "--frozen"),
|
|
120
123
|
(
|
|
121
124
|
"__TOKIO_WORKER_THREADS__",
|
|
122
|
-
str(
|
|
125
|
+
str(
|
|
126
|
+
resource.tasks_pixi_config[
|
|
127
|
+
"TOKIO_WORKER_THREADS"
|
|
128
|
+
]
|
|
129
|
+
),
|
|
123
130
|
),
|
|
124
131
|
(
|
|
125
132
|
"__PIXI_CONCURRENT_SOLVES__",
|
|
126
|
-
str(
|
|
133
|
+
str(
|
|
134
|
+
resource.tasks_pixi_config[
|
|
135
|
+
"PIXI_CONCURRENT_SOLVES"
|
|
136
|
+
]
|
|
137
|
+
),
|
|
127
138
|
),
|
|
128
139
|
(
|
|
129
140
|
"__PIXI_CONCURRENT_DOWNLOADS__",
|
|
130
|
-
str(
|
|
141
|
+
str(
|
|
142
|
+
resource.tasks_pixi_config[
|
|
143
|
+
"PIXI_CONCURRENT_DOWNLOADS"
|
|
144
|
+
]
|
|
145
|
+
),
|
|
131
146
|
),
|
|
132
147
|
}
|
|
133
148
|
|
|
@@ -172,6 +187,7 @@ def reactivate_ssh_pixi(
|
|
|
172
187
|
edit_pyproject_toml_in_place_ssh(
|
|
173
188
|
fractal_ssh=fractal_ssh,
|
|
174
189
|
pyproject_toml_path=pyproject_toml_path,
|
|
190
|
+
resource=resource,
|
|
175
191
|
)
|
|
176
192
|
# Write pixi.lock into `source_dir`
|
|
177
193
|
pixi_lock_local = Path(tmpdir, "pixi.lock").as_posix()
|
|
@@ -217,13 +233,16 @@ def reactivate_ssh_pixi(
|
|
|
217
233
|
remote_script3_path,
|
|
218
234
|
f"chmod -R 755 {source_dir}",
|
|
219
235
|
],
|
|
220
|
-
slurm_config=
|
|
236
|
+
slurm_config=resource.tasks_pixi_config[
|
|
237
|
+
"SLURM_CONFIG"
|
|
238
|
+
],
|
|
221
239
|
fractal_ssh=fractal_ssh,
|
|
222
240
|
logger_name=LOGGER_NAME,
|
|
223
241
|
prefix=common_args["prefix"],
|
|
224
242
|
db=db,
|
|
225
243
|
activity=activity,
|
|
226
244
|
log_file_path=log_file_path,
|
|
245
|
+
poll_interval=resource.jobs_poll_interval,
|
|
227
246
|
)
|
|
228
247
|
activity.log = get_current_log(log_file_path)
|
|
229
248
|
activity = add_commit_refresh(obj=activity, db=db)
|
|
@@ -244,7 +263,7 @@ def reactivate_ssh_pixi(
|
|
|
244
263
|
logger.info(f"Now delete folder {source_dir}")
|
|
245
264
|
fractal_ssh.remove_folder(
|
|
246
265
|
folder=source_dir,
|
|
247
|
-
safe_root=
|
|
266
|
+
safe_root=profile.tasks_remote_dir,
|
|
248
267
|
)
|
|
249
268
|
logger.info(f"Deleted folder {source_dir}")
|
|
250
269
|
except Exception as rm_e:
|
|
@@ -17,21 +17,19 @@ VENVPYTHON=${PACKAGE_ENV_DIR}/bin/python
|
|
|
17
17
|
write_log "Python interpreter: $VENVPYTHON"
|
|
18
18
|
echo
|
|
19
19
|
|
|
20
|
-
# FIXME: only run pip-show once!
|
|
21
|
-
|
|
22
20
|
# Extract information about paths
|
|
23
21
|
# WARNING: this block will fail for paths which include whitespace characters
|
|
24
22
|
write_log "START pip show"
|
|
25
|
-
$VENVPYTHON -m pip show ${PACKAGE_NAME}
|
|
23
|
+
PIP_SHOW_OUTPUT=$($VENVPYTHON -m pip show ${PACKAGE_NAME})
|
|
26
24
|
write_log "END pip show"
|
|
27
25
|
echo
|
|
28
|
-
PACKAGE_NAME=$(
|
|
26
|
+
PACKAGE_NAME=$(echo "$PIP_SHOW_OUTPUT" | grep "Name:" | cut -d ":" -f 2 | tr -d "[:space:]")
|
|
29
27
|
write_log "Package name: $PACKAGE_NAME"
|
|
30
28
|
echo
|
|
31
|
-
PACKAGE_VERSION=$(
|
|
29
|
+
PACKAGE_VERSION=$(echo "$PIP_SHOW_OUTPUT" | grep "Version:" | cut -d ":" -f 2 | tr -d "[:space:]")
|
|
32
30
|
write_log "Package version: $PACKAGE_VERSION"
|
|
33
31
|
echo
|
|
34
|
-
PACKAGE_PARENT_FOLDER=$(
|
|
32
|
+
PACKAGE_PARENT_FOLDER=$(echo "$PIP_SHOW_OUTPUT" | grep "Location:" | cut -d ":" -f 2 | tr -d "[:space:]")
|
|
35
33
|
write_log "Package parent folder: $PACKAGE_PARENT_FOLDER"
|
|
36
34
|
echo
|
|
37
35
|
MANIFEST_RELATIVE_PATH=$($VENVPYTHON -m pip show "$PACKAGE_NAME" --files | grep "__FRACTAL_MANIFEST__.json" | tr -d "[:space:]")
|
|
@@ -15,7 +15,7 @@ def create_db_tasks_and_update_task_group_sync(
|
|
|
15
15
|
"""
|
|
16
16
|
Create a `TaskGroupV2` with N `TaskV2`s, and insert them into the database.
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
Args:
|
|
19
19
|
task_group_id: ID of an existing `TaskGroupV2` object.
|
|
20
20
|
task_list: List of `TaskCreateV2` objects to be inserted into the db.
|
|
21
21
|
db: Synchronous database session
|
|
@@ -42,7 +42,7 @@ async def create_db_tasks_and_update_task_group_async(
|
|
|
42
42
|
"""
|
|
43
43
|
Create a `TaskGroupV2` with N `TaskV2`s, and insert them into the database.
|
|
44
44
|
|
|
45
|
-
|
|
45
|
+
Args:
|
|
46
46
|
task_group_id: ID of an existing `TaskGroupV2` object.
|
|
47
47
|
task_list: List of `TaskCreateV2` objects to be inserted into the db.
|
|
48
48
|
db: Synchronous database session
|
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
from
|
|
1
|
+
from fractal_server.app.models import Resource
|
|
2
2
|
|
|
3
|
-
from fractal_server.config import get_settings
|
|
4
|
-
from fractal_server.syringe import Inject
|
|
5
3
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
def get_python_interpreter(
|
|
5
|
+
python_version: str,
|
|
6
|
+
resource: Resource,
|
|
9
7
|
) -> str:
|
|
10
8
|
"""
|
|
11
9
|
Return the path to the Python interpreter
|
|
@@ -21,13 +19,7 @@ def get_python_interpreter_v2(
|
|
|
21
19
|
interpreter: string representing the python executable or its path
|
|
22
20
|
"""
|
|
23
21
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
version_underscore = python_version.replace(".", "_")
|
|
29
|
-
key = f"FRACTAL_TASKS_PYTHON_{version_underscore}"
|
|
30
|
-
value = getattr(settings, key)
|
|
31
|
-
if value is None:
|
|
32
|
-
raise ValueError(f"Requested {python_version=}, but {key}={value}.")
|
|
33
|
-
return value
|
|
22
|
+
python_path = resource.tasks_python_config["versions"].get(python_version)
|
|
23
|
+
if python_path is None:
|
|
24
|
+
raise ValueError(f"Requested {python_version=} is not available.")
|
|
25
|
+
return python_path
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
from pathlib import Path
|
|
2
2
|
|
|
3
|
+
from fractal_server.app.models import Resource
|
|
3
4
|
from fractal_server.app.models.v2 import TaskGroupV2
|
|
4
|
-
from fractal_server.config import get_settings
|
|
5
5
|
from fractal_server.logger import set_logger
|
|
6
|
-
from fractal_server.syringe import Inject
|
|
7
6
|
|
|
8
7
|
TEMPLATES_DIR = Path(__file__).parent / "templates"
|
|
9
8
|
|
|
@@ -12,7 +11,7 @@ SCRIPTS_SUBFOLDER = "scripts"
|
|
|
12
11
|
logger = set_logger(__name__)
|
|
13
12
|
|
|
14
13
|
|
|
15
|
-
def _check_pixi_frozen_option(replacements:
|
|
14
|
+
def _check_pixi_frozen_option(replacements: set[tuple[str, str]]):
|
|
16
15
|
try:
|
|
17
16
|
replacement = next(
|
|
18
17
|
rep for rep in replacements if rep[0] == "__FROZEN_OPTION__"
|
|
@@ -28,7 +27,7 @@ def customize_template(
|
|
|
28
27
|
template_name: str,
|
|
29
28
|
replacements: set[tuple[str, str]],
|
|
30
29
|
script_path: str,
|
|
31
|
-
) ->
|
|
30
|
+
) -> None:
|
|
32
31
|
"""
|
|
33
32
|
Customize a bash-script template and write it to disk.
|
|
34
33
|
|
|
@@ -84,16 +83,14 @@ def parse_script_pip_show_stdout(stdout: str) -> dict[str, str]:
|
|
|
84
83
|
|
|
85
84
|
|
|
86
85
|
def get_collection_replacements(
|
|
87
|
-
*, task_group: TaskGroupV2, python_bin: str
|
|
88
|
-
) ->
|
|
89
|
-
settings = Inject(get_settings)
|
|
90
|
-
|
|
86
|
+
*, task_group: TaskGroupV2, python_bin: str, resource: Resource
|
|
87
|
+
) -> list[tuple[str, str]]:
|
|
91
88
|
replacements = [
|
|
92
89
|
("__PACKAGE_NAME__", task_group.pkg_name),
|
|
93
90
|
("__PACKAGE_ENV_DIR__", task_group.venv_path),
|
|
94
91
|
("__PYTHON__", python_bin),
|
|
95
92
|
("__INSTALL_STRING__", task_group.pip_install_string),
|
|
96
|
-
("__FRACTAL_PIP_CACHE_DIR_ARG__",
|
|
93
|
+
("__FRACTAL_PIP_CACHE_DIR_ARG__", resource.pip_cache_dir_arg),
|
|
97
94
|
(
|
|
98
95
|
"__PINNED_PACKAGE_LIST_PRE__",
|
|
99
96
|
task_group.pinned_package_versions_pre_string,
|
|
@@ -104,6 +101,6 @@ def get_collection_replacements(
|
|
|
104
101
|
),
|
|
105
102
|
]
|
|
106
103
|
logger.info(
|
|
107
|
-
f"Cache-dir argument for `pip install`: {
|
|
104
|
+
f"Cache-dir argument for `pip install`: {resource.pip_cache_dir_arg}"
|
|
108
105
|
)
|
|
109
106
|
return replacements
|
fractal_server/utils.py
CHANGED
|
@@ -41,7 +41,7 @@ def execute_command_sync(
|
|
|
41
41
|
If the command returns a return code different from zero, a `RuntimeError`
|
|
42
42
|
is raised.
|
|
43
43
|
|
|
44
|
-
|
|
44
|
+
Args:
|
|
45
45
|
command: Command to be executed.
|
|
46
46
|
logger_name: Name of the logger.
|
|
47
47
|
allow_char: Argument propagated to `validate_cmd`.
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: fractal-server
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.17.0a0
|
|
4
4
|
Summary: Backend component of the Fractal analytics platform
|
|
5
|
-
License: BSD-3-Clause
|
|
5
|
+
License-Expression: BSD-3-Clause
|
|
6
|
+
License-File: LICENSE
|
|
6
7
|
Author: Tommaso Comparin
|
|
7
8
|
Author-email: tommaso.comparin@exact-lab.it
|
|
8
9
|
Requires-Python: >=3.11,<3.14
|
|
9
|
-
Classifier: License :: OSI Approved :: BSD License
|
|
10
10
|
Classifier: Programming Language :: Python :: 3
|
|
11
11
|
Classifier: Programming Language :: Python :: 3.11
|
|
12
12
|
Classifier: Programming Language :: Python :: 3.12
|
|
@@ -19,7 +19,7 @@ Requires-Dist: fastapi-users[oauth] (>=14,<15)
|
|
|
19
19
|
Requires-Dist: gunicorn (>=23.0,<24.0)
|
|
20
20
|
Requires-Dist: packaging (>=25.0.0,<26.0.0)
|
|
21
21
|
Requires-Dist: psycopg[binary] (>=3.1.0,<4.0.0)
|
|
22
|
-
Requires-Dist: pydantic (>=2.
|
|
22
|
+
Requires-Dist: pydantic (>=2.12.0,<2.13.0)
|
|
23
23
|
Requires-Dist: pydantic-settings (==2.11.0)
|
|
24
24
|
Requires-Dist: python-dotenv (>=1.1.0,<1.2.0)
|
|
25
25
|
Requires-Dist: sqlalchemy[asyncio] (>=2.0.23,<2.1)
|