fractal-server 2.17.0a4__py3-none-any.whl → 2.17.0a6__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 +22 -26
- fractal_server/app/models/security.py +19 -21
- fractal_server/app/models/user_settings.py +1 -0
- fractal_server/app/models/v2/task_group.py +1 -0
- fractal_server/app/routes/admin/v2/accounting.py +3 -3
- fractal_server/app/routes/admin/v2/impersonate.py +2 -2
- fractal_server/app/routes/admin/v2/job.py +6 -6
- fractal_server/app/routes/admin/v2/profile.py +18 -4
- fractal_server/app/routes/admin/v2/project.py +2 -2
- fractal_server/app/routes/admin/v2/resource.py +8 -8
- fractal_server/app/routes/admin/v2/task.py +11 -2
- fractal_server/app/routes/admin/v2/task_group.py +16 -12
- fractal_server/app/routes/admin/v2/task_group_lifecycle.py +4 -4
- fractal_server/app/routes/api/__init__.py +14 -5
- fractal_server/app/routes/api/v2/dataset.py +10 -19
- fractal_server/app/routes/api/v2/history.py +8 -8
- fractal_server/app/routes/api/v2/images.py +5 -5
- fractal_server/app/routes/api/v2/job.py +8 -8
- fractal_server/app/routes/api/v2/pre_submission_checks.py +3 -3
- fractal_server/app/routes/api/v2/project.py +6 -6
- fractal_server/app/routes/api/v2/status_legacy.py +2 -2
- fractal_server/app/routes/api/v2/submit.py +25 -29
- fractal_server/app/routes/api/v2/task.py +6 -7
- fractal_server/app/routes/api/v2/task_collection.py +4 -3
- fractal_server/app/routes/api/v2/task_collection_custom.py +4 -3
- fractal_server/app/routes/api/v2/task_collection_pixi.py +2 -2
- fractal_server/app/routes/api/v2/task_group.py +6 -6
- fractal_server/app/routes/api/v2/task_group_lifecycle.py +4 -4
- fractal_server/app/routes/api/v2/task_version_update.py +3 -3
- fractal_server/app/routes/api/v2/workflow.py +9 -9
- fractal_server/app/routes/api/v2/workflow_import.py +2 -2
- fractal_server/app/routes/api/v2/workflowtask.py +5 -5
- fractal_server/app/routes/auth/__init__.py +34 -5
- fractal_server/app/routes/auth/current_user.py +22 -72
- fractal_server/app/routes/auth/group.py +8 -35
- fractal_server/app/routes/auth/oauth.py +1 -1
- fractal_server/app/routes/auth/register.py +2 -2
- fractal_server/app/routes/auth/users.py +6 -48
- fractal_server/app/schemas/__init__.py +0 -1
- fractal_server/app/schemas/user.py +23 -0
- fractal_server/app/schemas/v2/__init__.py +1 -0
- fractal_server/app/schemas/v2/task_group.py +5 -0
- fractal_server/app/security/__init__.py +134 -46
- fractal_server/app/security/signup_email.py +52 -34
- fractal_server/config/__init__.py +6 -0
- fractal_server/config/_data.py +68 -0
- fractal_server/config/_email.py +10 -47
- fractal_server/config/_main.py +3 -56
- fractal_server/config/_oauth.py +2 -2
- fractal_server/main.py +3 -2
- fractal_server/migrations/versions/f65ee53991e3_user_settings_related.py +67 -0
- fractal_server/runner/executors/slurm_common/base_slurm_runner.py +1 -1
- fractal_server/runner/executors/slurm_common/slurm_config.py +5 -8
- fractal_server/runner/executors/slurm_ssh/runner.py +1 -1
- fractal_server/runner/executors/slurm_sudo/runner.py +1 -1
- fractal_server/runner/v2/_slurm_ssh.py +2 -1
- fractal_server/runner/v2/_slurm_sudo.py +1 -1
- fractal_server/runner/v2/submit_workflow.py +12 -12
- {fractal_server-2.17.0a4.dist-info → fractal_server-2.17.0a6.dist-info}/METADATA +4 -6
- {fractal_server-2.17.0a4.dist-info → fractal_server-2.17.0a6.dist-info}/RECORD +64 -65
- fractal_server/app/routes/aux/validate_user_settings.py +0 -76
- fractal_server/app/schemas/user_settings.py +0 -63
- fractal_server/app/user_settings.py +0 -32
- {fractal_server-2.17.0a4.dist-info → fractal_server-2.17.0a6.dist-info}/WHEEL +0 -0
- {fractal_server-2.17.0a4.dist-info → fractal_server-2.17.0a6.dist-info}/entry_points.txt +0 -0
- {fractal_server-2.17.0a4.dist-info → fractal_server-2.17.0a6.dist-info}/licenses/LICENSE +0 -0
fractal_server/config/_email.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from typing import Literal
|
|
2
|
+
from typing import Self
|
|
2
3
|
|
|
3
|
-
from cryptography.fernet import Fernet
|
|
4
4
|
from pydantic import BaseModel
|
|
5
5
|
from pydantic import EmailStr
|
|
6
6
|
from pydantic import Field
|
|
@@ -31,8 +31,7 @@ class PublicEmailSettings(BaseModel):
|
|
|
31
31
|
recipients: list[EmailStr] = Field(min_length=1)
|
|
32
32
|
smtp_server: str
|
|
33
33
|
port: int
|
|
34
|
-
|
|
35
|
-
encryption_key: SecretStr | None = None
|
|
34
|
+
password: SecretStr | None = None
|
|
36
35
|
instance_name: str
|
|
37
36
|
use_starttls: bool
|
|
38
37
|
use_login: bool
|
|
@@ -53,10 +52,6 @@ class EmailSettings(BaseSettings):
|
|
|
53
52
|
"""
|
|
54
53
|
Password for the OAuth-signup email sender.
|
|
55
54
|
"""
|
|
56
|
-
FRACTAL_EMAIL_PASSWORD_KEY: SecretStr | None = None
|
|
57
|
-
"""
|
|
58
|
-
Key value for `cryptography.fernet` decrypt
|
|
59
|
-
"""
|
|
60
55
|
FRACTAL_EMAIL_SMTP_SERVER: str | None = None
|
|
61
56
|
"""
|
|
62
57
|
SMTP server for the OAuth-signup emails.
|
|
@@ -81,8 +76,7 @@ class EmailSettings(BaseSettings):
|
|
|
81
76
|
FRACTAL_EMAIL_USE_LOGIN: Literal["true", "false"] = "true"
|
|
82
77
|
"""
|
|
83
78
|
Whether to use login when using the SMTP server.
|
|
84
|
-
If 'true', FRACTAL_EMAIL_PASSWORD
|
|
85
|
-
provided.
|
|
79
|
+
If 'true', FRACTAL_EMAIL_PASSWORD must be provided.
|
|
86
80
|
Accepted values: 'true', 'false'.
|
|
87
81
|
"""
|
|
88
82
|
|
|
@@ -93,7 +87,7 @@ class EmailSettings(BaseSettings):
|
|
|
93
87
|
"""
|
|
94
88
|
|
|
95
89
|
@model_validator(mode="after")
|
|
96
|
-
def validate_email_settings(self):
|
|
90
|
+
def validate_email_settings(self: Self) -> Self:
|
|
97
91
|
"""
|
|
98
92
|
Set `self.public`.
|
|
99
93
|
"""
|
|
@@ -119,49 +113,18 @@ class EmailSettings(BaseSettings):
|
|
|
119
113
|
use_starttls = self.FRACTAL_EMAIL_USE_STARTTLS == "true"
|
|
120
114
|
use_login = self.FRACTAL_EMAIL_USE_LOGIN == "true"
|
|
121
115
|
|
|
122
|
-
if use_login:
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
)
|
|
128
|
-
if self.FRACTAL_EMAIL_PASSWORD_KEY is None:
|
|
129
|
-
raise ValueError(
|
|
130
|
-
"'FRACTAL_EMAIL_USE_LOGIN' is 'true' but "
|
|
131
|
-
"'FRACTAL_EMAIL_PASSWORD_KEY' is not provided."
|
|
132
|
-
)
|
|
133
|
-
try:
|
|
134
|
-
(
|
|
135
|
-
Fernet(
|
|
136
|
-
self.FRACTAL_EMAIL_PASSWORD_KEY.get_secret_value()
|
|
137
|
-
)
|
|
138
|
-
.decrypt(
|
|
139
|
-
self.FRACTAL_EMAIL_PASSWORD.get_secret_value()
|
|
140
|
-
)
|
|
141
|
-
.decode("utf-8")
|
|
142
|
-
)
|
|
143
|
-
except Exception as e:
|
|
144
|
-
raise ValueError(
|
|
145
|
-
"Invalid pair (FRACTAL_EMAIL_PASSWORD, "
|
|
146
|
-
"FRACTAL_EMAIL_PASSWORD_KEY). "
|
|
147
|
-
f"Original error: {str(e)}."
|
|
148
|
-
)
|
|
149
|
-
password = self.FRACTAL_EMAIL_PASSWORD.get_secret_value()
|
|
150
|
-
else:
|
|
151
|
-
password = None
|
|
152
|
-
|
|
153
|
-
if self.FRACTAL_EMAIL_PASSWORD_KEY is not None:
|
|
154
|
-
key = self.FRACTAL_EMAIL_PASSWORD_KEY.get_secret_value()
|
|
155
|
-
else:
|
|
156
|
-
key = None
|
|
116
|
+
if use_login and self.FRACTAL_EMAIL_PASSWORD is None:
|
|
117
|
+
raise ValueError(
|
|
118
|
+
"'FRACTAL_EMAIL_USE_LOGIN' is 'true' but "
|
|
119
|
+
"'FRACTAL_EMAIL_PASSWORD' is not provided."
|
|
120
|
+
)
|
|
157
121
|
|
|
158
122
|
self.public = PublicEmailSettings(
|
|
159
123
|
sender=self.FRACTAL_EMAIL_SENDER,
|
|
160
124
|
recipients=self.FRACTAL_EMAIL_RECIPIENTS.split(","),
|
|
161
125
|
smtp_server=self.FRACTAL_EMAIL_SMTP_SERVER,
|
|
162
126
|
port=self.FRACTAL_EMAIL_SMTP_PORT,
|
|
163
|
-
|
|
164
|
-
encryption_key=key,
|
|
127
|
+
password=self.FRACTAL_EMAIL_PASSWORD,
|
|
165
128
|
instance_name=self.FRACTAL_EMAIL_INSTANCE_NAME,
|
|
166
129
|
use_starttls=use_starttls,
|
|
167
130
|
use_login=use_login,
|
fractal_server/config/_main.py
CHANGED
|
@@ -1,20 +1,12 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
from typing import Literal
|
|
3
|
-
from typing import TypeVar
|
|
4
3
|
|
|
4
|
+
from pydantic import HttpUrl
|
|
5
5
|
from pydantic import SecretStr
|
|
6
6
|
from pydantic_settings import BaseSettings
|
|
7
7
|
from pydantic_settings import SettingsConfigDict
|
|
8
8
|
|
|
9
9
|
from ._settings_config import SETTINGS_CONFIG_DICT
|
|
10
|
-
from fractal_server.types import AbsolutePathStr
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
class FractalConfigurationError(ValueError):
|
|
14
|
-
pass
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
T = TypeVar("T")
|
|
18
10
|
|
|
19
11
|
|
|
20
12
|
class Settings(BaseSettings):
|
|
@@ -26,7 +18,6 @@ class Settings(BaseSettings):
|
|
|
26
18
|
|
|
27
19
|
model_config = SettingsConfigDict(**SETTINGS_CONFIG_DICT)
|
|
28
20
|
|
|
29
|
-
# JWT TOKEN
|
|
30
21
|
JWT_EXPIRE_SECONDS: int = 180
|
|
31
22
|
"""
|
|
32
23
|
JWT token lifetime, in seconds.
|
|
@@ -40,7 +31,6 @@ class Settings(BaseSettings):
|
|
|
40
31
|
it.
|
|
41
32
|
"""
|
|
42
33
|
|
|
43
|
-
# COOKIE TOKEN
|
|
44
34
|
COOKIE_EXPIRE_SECONDS: int = 86400
|
|
45
35
|
"""
|
|
46
36
|
Cookie token lifetime, in seconds.
|
|
@@ -72,50 +62,7 @@ class Settings(BaseSettings):
|
|
|
72
62
|
Waiting time for the shutdown phase of executors
|
|
73
63
|
"""
|
|
74
64
|
|
|
75
|
-
|
|
76
|
-
"viewer-paths", "users-folders", "none"
|
|
77
|
-
] = "none"
|
|
78
|
-
"""
|
|
79
|
-
Defines how the list of allowed viewer paths is built.
|
|
80
|
-
|
|
81
|
-
This variable affects the `GET /auth/current-user/allowed-viewer-paths/`
|
|
82
|
-
response, which is then consumed by
|
|
83
|
-
[fractal-vizarr-viewer](https://github.com/fractal-analytics-platform/fractal-vizarr-viewer).
|
|
84
|
-
|
|
85
|
-
Options:
|
|
86
|
-
|
|
87
|
-
- "viewer-paths": The list of allowed viewer paths will include the user's
|
|
88
|
-
`project_dir` along with any path defined in user groups' `viewer_paths`
|
|
89
|
-
attributes.
|
|
90
|
-
- "users-folders": The list will consist of the user's `project_dir` and a
|
|
91
|
-
user-specific folder. The user folder is constructed by concatenating
|
|
92
|
-
the base folder `FRACTAL_VIEWER_BASE_FOLDER` with the user's
|
|
93
|
-
`slurm_user`.
|
|
94
|
-
- "none": An empty list will be returned, indicating no access to
|
|
95
|
-
viewer paths. Useful when vizarr viewer is not used.
|
|
96
|
-
"""
|
|
97
|
-
|
|
98
|
-
FRACTAL_VIEWER_BASE_FOLDER: AbsolutePathStr | None = None
|
|
65
|
+
FRACTAL_HELP_URL: HttpUrl | None = None
|
|
99
66
|
"""
|
|
100
|
-
|
|
101
|
-
This variable is required and used only when
|
|
102
|
-
FRACTAL_VIEWER_AUTHORIZATION_SCHEME is set to "users-folders".
|
|
67
|
+
The URL of an instance-specific Fractal help page.
|
|
103
68
|
"""
|
|
104
|
-
|
|
105
|
-
def check(self):
|
|
106
|
-
"""
|
|
107
|
-
Make sure that required variables are set
|
|
108
|
-
|
|
109
|
-
This method must be called before the server starts
|
|
110
|
-
"""
|
|
111
|
-
# FRACTAL_VIEWER_BASE_FOLDER is required when
|
|
112
|
-
# FRACTAL_VIEWER_AUTHORIZATION_SCHEME is set to "users-folders"
|
|
113
|
-
# and it must be an absolute path
|
|
114
|
-
if self.FRACTAL_VIEWER_AUTHORIZATION_SCHEME == "users-folders":
|
|
115
|
-
viewer_base_folder = self.FRACTAL_VIEWER_BASE_FOLDER
|
|
116
|
-
if viewer_base_folder is None:
|
|
117
|
-
raise FractalConfigurationError(
|
|
118
|
-
"FRACTAL_VIEWER_BASE_FOLDER is required when "
|
|
119
|
-
"FRACTAL_VIEWER_AUTHORIZATION_SCHEME is set to "
|
|
120
|
-
"users-folders"
|
|
121
|
-
)
|
fractal_server/config/_oauth.py
CHANGED
|
@@ -37,7 +37,7 @@ class OAuthSettings(BaseSettings):
|
|
|
37
37
|
"""
|
|
38
38
|
Secret to authorise against the identity provider.
|
|
39
39
|
"""
|
|
40
|
-
OAUTH_OIDC_CONFIG_ENDPOINT:
|
|
40
|
+
OAUTH_OIDC_CONFIG_ENDPOINT: SecretStr | None = None
|
|
41
41
|
"""
|
|
42
42
|
OpenID configuration endpoint, for autodiscovery of relevant endpoints.
|
|
43
43
|
"""
|
|
@@ -55,7 +55,7 @@ class OAuthSettings(BaseSettings):
|
|
|
55
55
|
and self.OAUTH_OIDC_CONFIG_ENDPOINT is None
|
|
56
56
|
):
|
|
57
57
|
raise ValueError(
|
|
58
|
-
f"
|
|
58
|
+
f"self.OAUTH_OIDC_CONFIG_ENDPOINT=None but "
|
|
59
59
|
f"{self.OAUTH_CLIENT_NAME=}"
|
|
60
60
|
)
|
|
61
61
|
return self
|
fractal_server/main.py
CHANGED
|
@@ -6,6 +6,7 @@ from fastapi import FastAPI
|
|
|
6
6
|
|
|
7
7
|
from .app.routes.aux._runner import _backend_supports_shutdown
|
|
8
8
|
from .app.shutdown import cleanup_after_shutdown
|
|
9
|
+
from .config import get_data_settings
|
|
9
10
|
from .config import get_db_settings
|
|
10
11
|
from .config import get_email_settings
|
|
11
12
|
from .config import get_settings
|
|
@@ -50,16 +51,16 @@ def check_settings() -> None:
|
|
|
50
51
|
ValidationError: If the configuration is invalid.
|
|
51
52
|
"""
|
|
52
53
|
settings = Inject(get_settings)
|
|
53
|
-
settings.check()
|
|
54
54
|
db_settings = Inject(get_db_settings)
|
|
55
55
|
email_settings = Inject(get_email_settings)
|
|
56
|
-
|
|
56
|
+
data_settings = Inject(get_data_settings)
|
|
57
57
|
logger = set_logger("fractal_server_settings")
|
|
58
58
|
logger.debug("Fractal Settings:")
|
|
59
59
|
for key, value in chain(
|
|
60
60
|
db_settings.model_dump().items(),
|
|
61
61
|
settings.model_dump().items(),
|
|
62
62
|
email_settings.model_dump().items(),
|
|
63
|
+
data_settings.model_dump().items(),
|
|
63
64
|
):
|
|
64
65
|
if any(s in key.upper() for s in ["PASSWORD", "SECRET", "KEY"]):
|
|
65
66
|
value = "*****"
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"""user-settings-related
|
|
2
|
+
|
|
3
|
+
Revision ID: f65ee53991e3
|
|
4
|
+
Revises: 90f6508c6379
|
|
5
|
+
Create Date: 2025-10-22 15:16:42.217910
|
|
6
|
+
|
|
7
|
+
"""
|
|
8
|
+
import sqlalchemy as sa
|
|
9
|
+
from alembic import op
|
|
10
|
+
from sqlalchemy.dialects import postgresql
|
|
11
|
+
|
|
12
|
+
# revision identifiers, used by Alembic.
|
|
13
|
+
revision = "f65ee53991e3"
|
|
14
|
+
down_revision = "90f6508c6379"
|
|
15
|
+
branch_labels = None
|
|
16
|
+
depends_on = None
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def upgrade() -> None:
|
|
20
|
+
# ### commands auto generated by Alembic - please adjust! ###
|
|
21
|
+
with op.batch_alter_table("user_oauth", schema=None) as batch_op:
|
|
22
|
+
batch_op.add_column(
|
|
23
|
+
sa.Column(
|
|
24
|
+
"project_dir",
|
|
25
|
+
sa.String(),
|
|
26
|
+
server_default="/PLACEHOLDER",
|
|
27
|
+
nullable=False,
|
|
28
|
+
)
|
|
29
|
+
)
|
|
30
|
+
batch_op.add_column(
|
|
31
|
+
sa.Column(
|
|
32
|
+
"slurm_accounts",
|
|
33
|
+
postgresql.ARRAY(sa.String()),
|
|
34
|
+
server_default="{}",
|
|
35
|
+
nullable=True,
|
|
36
|
+
)
|
|
37
|
+
)
|
|
38
|
+
batch_op.drop_constraint(
|
|
39
|
+
batch_op.f("fk_user_oauth_user_settings_id_user_settings"),
|
|
40
|
+
type_="foreignkey",
|
|
41
|
+
)
|
|
42
|
+
batch_op.drop_column("user_settings_id")
|
|
43
|
+
|
|
44
|
+
# ### end Alembic commands ###
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def downgrade() -> None:
|
|
48
|
+
# ### commands auto generated by Alembic - please adjust! ###
|
|
49
|
+
with op.batch_alter_table("user_oauth", schema=None) as batch_op:
|
|
50
|
+
batch_op.add_column(
|
|
51
|
+
sa.Column(
|
|
52
|
+
"user_settings_id",
|
|
53
|
+
sa.INTEGER(),
|
|
54
|
+
autoincrement=False,
|
|
55
|
+
nullable=True,
|
|
56
|
+
)
|
|
57
|
+
)
|
|
58
|
+
batch_op.create_foreign_key(
|
|
59
|
+
batch_op.f("fk_user_oauth_user_settings_id_user_settings"),
|
|
60
|
+
"user_settings",
|
|
61
|
+
["user_settings_id"],
|
|
62
|
+
["id"],
|
|
63
|
+
)
|
|
64
|
+
batch_op.drop_column("slurm_accounts")
|
|
65
|
+
batch_op.drop_column("project_dir")
|
|
66
|
+
|
|
67
|
+
# ### end Alembic commands ###
|
|
@@ -87,7 +87,7 @@ class BaseSlurmRunner(BaseRunner):
|
|
|
87
87
|
python_worker_interpreter: str,
|
|
88
88
|
poll_interval: int,
|
|
89
89
|
common_script_lines: list[str] | None = None,
|
|
90
|
-
user_cache_dir: str
|
|
90
|
+
user_cache_dir: str,
|
|
91
91
|
slurm_account: str | None = None,
|
|
92
92
|
):
|
|
93
93
|
self.slurm_runner_type = slurm_runner_type
|
|
@@ -136,7 +136,7 @@ class SlurmConfig(BaseModel):
|
|
|
136
136
|
|
|
137
137
|
def to_sbatch_preamble(
|
|
138
138
|
self,
|
|
139
|
-
remote_export_dir: str
|
|
139
|
+
remote_export_dir: str,
|
|
140
140
|
) -> list[str]:
|
|
141
141
|
"""
|
|
142
142
|
Compile `SlurmConfig` object into the preamble of a SLURM submission
|
|
@@ -189,13 +189,10 @@ class SlurmConfig(BaseModel):
|
|
|
189
189
|
for line in self._sorted_extra_lines():
|
|
190
190
|
lines.append(line)
|
|
191
191
|
|
|
192
|
-
if self.user_local_exports
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
for key, value in self.user_local_exports.items():
|
|
197
|
-
tmp_value = str(Path(remote_export_dir) / value)
|
|
198
|
-
lines.append(f"export {key}={tmp_value}")
|
|
192
|
+
if self.user_local_exports:
|
|
193
|
+
for key, value in self.user_local_exports.items():
|
|
194
|
+
tmp_value = str(Path(remote_export_dir) / value)
|
|
195
|
+
lines.append(f"export {key}={tmp_value}")
|
|
199
196
|
|
|
200
197
|
"""
|
|
201
198
|
FIXME export SRUN_CPUS_PER_TASK
|
|
@@ -50,7 +50,7 @@ def process_workflow(
|
|
|
50
50
|
fractal_ssh: FractalSSH | None = None,
|
|
51
51
|
slurm_account: str | None = None,
|
|
52
52
|
worker_init: str | None = None,
|
|
53
|
-
user_cache_dir: str
|
|
53
|
+
user_cache_dir: str,
|
|
54
54
|
) -> None:
|
|
55
55
|
"""
|
|
56
56
|
Run a workflow through a `slurm_ssh` backend.
|
|
@@ -105,6 +105,7 @@ def process_workflow(
|
|
|
105
105
|
resource=resource,
|
|
106
106
|
profile=profile,
|
|
107
107
|
common_script_lines=worker_init,
|
|
108
|
+
user_cache_dir=user_cache_dir,
|
|
108
109
|
) as runner:
|
|
109
110
|
execute_tasks_v2(
|
|
110
111
|
wf_task_list=workflow.task_list[
|
|
@@ -52,6 +52,7 @@ class ProcessWorkflowType(Protocol):
|
|
|
52
52
|
user_id: int,
|
|
53
53
|
resource: Resource,
|
|
54
54
|
profile: Profile,
|
|
55
|
+
user_cache_dir: str,
|
|
55
56
|
) -> None:
|
|
56
57
|
...
|
|
57
58
|
|
|
@@ -84,10 +85,10 @@ def submit_workflow(
|
|
|
84
85
|
dataset_id: int,
|
|
85
86
|
job_id: int,
|
|
86
87
|
user_id: int,
|
|
87
|
-
|
|
88
|
-
user_cache_dir: str | None = None, # FIXME: review this
|
|
88
|
+
user_cache_dir: str,
|
|
89
89
|
resource: Resource,
|
|
90
90
|
profile: Profile,
|
|
91
|
+
worker_init: str | None = None,
|
|
91
92
|
fractal_ssh: FractalSSH | None = None,
|
|
92
93
|
) -> None:
|
|
93
94
|
"""
|
|
@@ -110,8 +111,10 @@ def submit_workflow(
|
|
|
110
111
|
Custom executor parameters that get parsed before the execution of
|
|
111
112
|
each task.
|
|
112
113
|
user_cache_dir:
|
|
113
|
-
Cache directory (namely a path where the user can write)
|
|
114
|
-
|
|
114
|
+
Cache directory (namely a path where the user can write). For
|
|
115
|
+
`slurm_sudo` backend, this is both a base directory for
|
|
116
|
+
`job.working_dir_user`. For `slurm_sudo` and `slurm_ssh` backends,
|
|
117
|
+
this is used for `user_local_exports`.
|
|
115
118
|
resource:
|
|
116
119
|
Computational resource to be used for this job (e.g. a SLURM
|
|
117
120
|
cluster).
|
|
@@ -224,22 +227,18 @@ def submit_workflow(
|
|
|
224
227
|
job_working_dir = job.working_dir
|
|
225
228
|
|
|
226
229
|
try:
|
|
230
|
+
process_workflow: ProcessWorkflowType
|
|
227
231
|
match resource.type:
|
|
228
232
|
case ResourceType.LOCAL:
|
|
229
|
-
process_workflow
|
|
233
|
+
process_workflow = local_process_workflow
|
|
230
234
|
backend_specific_kwargs = {}
|
|
231
235
|
case ResourceType.SLURM_SUDO:
|
|
232
|
-
process_workflow
|
|
233
|
-
slurm_sudo_process_workflow
|
|
234
|
-
)
|
|
236
|
+
process_workflow = slurm_sudo_process_workflow
|
|
235
237
|
backend_specific_kwargs = dict(
|
|
236
238
|
slurm_account=job.slurm_account,
|
|
237
|
-
user_cache_dir=user_cache_dir,
|
|
238
239
|
)
|
|
239
240
|
case ResourceType.SLURM_SSH:
|
|
240
|
-
process_workflow
|
|
241
|
-
slurm_ssh_process_workflow
|
|
242
|
-
)
|
|
241
|
+
process_workflow = slurm_ssh_process_workflow
|
|
243
242
|
backend_specific_kwargs = dict(
|
|
244
243
|
fractal_ssh=fractal_ssh,
|
|
245
244
|
slurm_account=job.slurm_account,
|
|
@@ -260,6 +259,7 @@ def submit_workflow(
|
|
|
260
259
|
job_type_filters=job.type_filters,
|
|
261
260
|
resource=resource,
|
|
262
261
|
profile=profile,
|
|
262
|
+
user_cache_dir=user_cache_dir,
|
|
263
263
|
**backend_specific_kwargs,
|
|
264
264
|
)
|
|
265
265
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fractal-server
|
|
3
|
-
Version: 2.17.
|
|
3
|
+
Version: 2.17.0a6
|
|
4
4
|
Summary: Backend component of the Fractal analytics platform
|
|
5
5
|
License-Expression: BSD-3-Clause
|
|
6
6
|
License-File: LICENSE
|
|
@@ -12,20 +12,18 @@ 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 (>=46.0.0,<47.0.0)
|
|
16
15
|
Requires-Dist: fabric (>=3.2.2,<3.3.0)
|
|
17
|
-
Requires-Dist: fastapi (>=0.
|
|
18
|
-
Requires-Dist: fastapi-users[oauth] (>=
|
|
16
|
+
Requires-Dist: fastapi (>=0.120.0,<0.121.0)
|
|
17
|
+
Requires-Dist: fastapi-users[oauth] (>=15,<16)
|
|
19
18
|
Requires-Dist: gunicorn (>=23.0,<24.0)
|
|
20
19
|
Requires-Dist: packaging (>=25.0.0,<26.0.0)
|
|
21
20
|
Requires-Dist: psycopg[binary] (>=3.1.0,<4.0.0)
|
|
22
21
|
Requires-Dist: pydantic (>=2.12.0,<2.13.0)
|
|
23
22
|
Requires-Dist: pydantic-settings (==2.11.0)
|
|
24
|
-
Requires-Dist: python-dotenv (>=1.1.0,<1.2.0)
|
|
25
23
|
Requires-Dist: sqlalchemy[asyncio] (>=2.0.23,<2.1)
|
|
26
24
|
Requires-Dist: sqlmodel (==0.0.27)
|
|
27
25
|
Requires-Dist: tomli_w (>=1.2.0,<1.3.0)
|
|
28
|
-
Requires-Dist: uvicorn (>=0.
|
|
26
|
+
Requires-Dist: uvicorn (>=0.38.0,<0.39.0)
|
|
29
27
|
Requires-Dist: uvicorn-worker (==0.4.0)
|
|
30
28
|
Project-URL: Documentation, https://fractal-analytics-platform.github.io/fractal-server
|
|
31
29
|
Project-URL: Homepage, https://github.com/fractal-analytics-platform/fractal-server
|