fractal-server 2.5.1__py3-none-any.whl → 2.6.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 +24 -9
- fractal_server/app/models/__init__.py +1 -0
- fractal_server/app/models/security.py +8 -0
- fractal_server/app/models/user_settings.py +38 -0
- fractal_server/app/routes/api/v1/_aux_functions.py +6 -1
- fractal_server/app/routes/api/v1/project.py +11 -24
- fractal_server/app/routes/api/v1/task.py +12 -9
- fractal_server/app/routes/api/v2/_aux_functions.py +6 -1
- fractal_server/app/routes/api/v2/submit.py +29 -21
- fractal_server/app/routes/api/v2/task.py +12 -9
- fractal_server/app/routes/api/v2/task_collection.py +17 -2
- fractal_server/app/routes/api/v2/task_collection_custom.py +6 -1
- fractal_server/app/routes/auth/_aux_auth.py +5 -5
- fractal_server/app/routes/auth/current_user.py +41 -0
- fractal_server/app/routes/auth/users.py +42 -0
- fractal_server/app/routes/aux/validate_user_settings.py +74 -0
- fractal_server/app/runner/executors/slurm/ssh/executor.py +24 -4
- fractal_server/app/runner/executors/slurm/sudo/executor.py +6 -2
- fractal_server/app/runner/v2/__init__.py +5 -7
- fractal_server/app/schemas/__init__.py +2 -0
- fractal_server/app/schemas/user.py +1 -62
- fractal_server/app/schemas/user_settings.py +93 -0
- fractal_server/app/security/__init__.py +22 -9
- fractal_server/app/user_settings.py +42 -0
- fractal_server/config.py +0 -16
- fractal_server/data_migrations/2_6_0.py +49 -0
- fractal_server/data_migrations/tools.py +17 -0
- fractal_server/main.py +12 -10
- fractal_server/migrations/versions/9c5ae74c9b98_add_user_settings_table.py +74 -0
- fractal_server/ssh/_fabric.py +179 -34
- fractal_server/tasks/v2/background_operations_ssh.py +14 -5
- {fractal_server-2.5.1.dist-info → fractal_server-2.6.0a0.dist-info}/METADATA +1 -1
- {fractal_server-2.5.1.dist-info → fractal_server-2.6.0a0.dist-info}/RECORD +37 -31
- fractal_server/data_migrations/2_4_0.py +0 -61
- {fractal_server-2.5.1.dist-info → fractal_server-2.6.0a0.dist-info}/LICENSE +0 -0
- {fractal_server-2.5.1.dist-info → fractal_server-2.6.0a0.dist-info}/WHEEL +0 -0
- {fractal_server-2.5.1.dist-info → fractal_server-2.6.0a0.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,74 @@
|
|
1
|
+
"""Add user_settings table
|
2
|
+
|
3
|
+
Revision ID: 9c5ae74c9b98
|
4
|
+
Revises: d9a140db5d42
|
5
|
+
Create Date: 2024-09-24 12:01:13.393326
|
6
|
+
|
7
|
+
"""
|
8
|
+
import sqlalchemy as sa
|
9
|
+
import sqlmodel
|
10
|
+
from alembic import op
|
11
|
+
|
12
|
+
|
13
|
+
# revision identifiers, used by Alembic.
|
14
|
+
revision = "9c5ae74c9b98"
|
15
|
+
down_revision = "d9a140db5d42"
|
16
|
+
branch_labels = None
|
17
|
+
depends_on = None
|
18
|
+
|
19
|
+
# Manually define constraint name, see issue #1777
|
20
|
+
CONSTRAINT_NAME = "fk_user_oauth_user_settings_id_user_settings"
|
21
|
+
|
22
|
+
|
23
|
+
def upgrade() -> None:
|
24
|
+
# ### commands auto generated by Alembic - please adjust! ###
|
25
|
+
op.create_table(
|
26
|
+
"user_settings",
|
27
|
+
sa.Column("id", sa.Integer(), nullable=False),
|
28
|
+
sa.Column(
|
29
|
+
"slurm_accounts", sa.JSON(), server_default="[]", nullable=False
|
30
|
+
),
|
31
|
+
sa.Column(
|
32
|
+
"ssh_host", sqlmodel.sql.sqltypes.AutoString(), nullable=True
|
33
|
+
),
|
34
|
+
sa.Column(
|
35
|
+
"ssh_username", sqlmodel.sql.sqltypes.AutoString(), nullable=True
|
36
|
+
),
|
37
|
+
sa.Column(
|
38
|
+
"ssh_private_key_path",
|
39
|
+
sqlmodel.sql.sqltypes.AutoString(),
|
40
|
+
nullable=True,
|
41
|
+
),
|
42
|
+
sa.Column(
|
43
|
+
"ssh_tasks_dir", sqlmodel.sql.sqltypes.AutoString(), nullable=True
|
44
|
+
),
|
45
|
+
sa.Column(
|
46
|
+
"ssh_jobs_dir", sqlmodel.sql.sqltypes.AutoString(), nullable=True
|
47
|
+
),
|
48
|
+
sa.Column(
|
49
|
+
"slurm_user", sqlmodel.sql.sqltypes.AutoString(), nullable=True
|
50
|
+
),
|
51
|
+
sa.Column(
|
52
|
+
"cache_dir", sqlmodel.sql.sqltypes.AutoString(), nullable=True
|
53
|
+
),
|
54
|
+
sa.PrimaryKeyConstraint("id"),
|
55
|
+
)
|
56
|
+
with op.batch_alter_table("user_oauth", schema=None) as batch_op:
|
57
|
+
batch_op.add_column(
|
58
|
+
sa.Column("user_settings_id", sa.Integer(), nullable=True)
|
59
|
+
)
|
60
|
+
batch_op.create_foreign_key(
|
61
|
+
CONSTRAINT_NAME, "user_settings", ["user_settings_id"], ["id"]
|
62
|
+
)
|
63
|
+
|
64
|
+
# ### end Alembic commands ###
|
65
|
+
|
66
|
+
|
67
|
+
def downgrade() -> None:
|
68
|
+
# ### commands auto generated by Alembic - please adjust! ###
|
69
|
+
with op.batch_alter_table("user_oauth", schema=None) as batch_op:
|
70
|
+
batch_op.drop_constraint(CONSTRAINT_NAME, type_="foreignkey")
|
71
|
+
batch_op.drop_column("user_settings_id")
|
72
|
+
|
73
|
+
op.drop_table("user_settings")
|
74
|
+
# ### end Alembic commands ###
|
fractal_server/ssh/_fabric.py
CHANGED
@@ -16,20 +16,21 @@ from paramiko.ssh_exception import NoValidConnectionsError
|
|
16
16
|
|
17
17
|
from ..logger import get_logger
|
18
18
|
from ..logger import set_logger
|
19
|
-
from fractal_server.config import get_settings
|
20
19
|
from fractal_server.string_tools import validate_cmd
|
21
|
-
from fractal_server.syringe import Inject
|
22
20
|
|
23
21
|
|
24
22
|
class FractalSSHTimeoutError(RuntimeError):
|
25
23
|
pass
|
26
24
|
|
27
25
|
|
26
|
+
class FractalSSHListTimeoutError(RuntimeError):
|
27
|
+
pass
|
28
|
+
|
29
|
+
|
28
30
|
logger = set_logger(__name__)
|
29
31
|
|
30
32
|
|
31
33
|
class FractalSSH(object):
|
32
|
-
|
33
34
|
"""
|
34
35
|
FIXME SSH: Fix docstring
|
35
36
|
|
@@ -111,7 +112,6 @@ class FractalSSH(object):
|
|
111
112
|
def run(
|
112
113
|
self, *args, lock_timeout: Optional[float] = None, **kwargs
|
113
114
|
) -> Any:
|
114
|
-
|
115
115
|
actual_lock_timeout = self.default_lock_timeout
|
116
116
|
if lock_timeout is not None:
|
117
117
|
actual_lock_timeout = lock_timeout
|
@@ -138,7 +138,19 @@ class FractalSSH(object):
|
|
138
138
|
)
|
139
139
|
|
140
140
|
def close(self) -> None:
|
141
|
-
|
141
|
+
"""
|
142
|
+
Aggressively close `self._connection`.
|
143
|
+
|
144
|
+
When `Connection.is_connected` is `False`, `Connection.close()` does
|
145
|
+
not call `Connection.client.close()`. Thus we do this explicitly here,
|
146
|
+
because we observed cases where `is_connected=False` but the underlying
|
147
|
+
`Transport` object was not closed.
|
148
|
+
"""
|
149
|
+
|
150
|
+
self._connection.close()
|
151
|
+
|
152
|
+
if self._connection.client is not None:
|
153
|
+
self._connection.client.close()
|
142
154
|
|
143
155
|
def run_command(
|
144
156
|
self,
|
@@ -335,36 +347,169 @@ class FractalSSH(object):
|
|
335
347
|
f.write(content)
|
336
348
|
|
337
349
|
|
338
|
-
|
339
|
-
*,
|
340
|
-
host: Optional[str] = None,
|
341
|
-
user: Optional[str] = None,
|
342
|
-
key_filename: Optional[str] = None,
|
343
|
-
) -> Connection:
|
350
|
+
class FractalSSHList(object):
|
344
351
|
"""
|
345
|
-
|
346
|
-
or explicit arguments.
|
352
|
+
Collection of `FractalSSH` objects
|
347
353
|
|
348
|
-
|
349
|
-
|
350
|
-
user:
|
351
|
-
key_filename:
|
354
|
+
Attributes are all private, and access to this collection must be
|
355
|
+
through methods (mostly the `get` one).
|
352
356
|
|
353
|
-
|
354
|
-
|
357
|
+
Attributes:
|
358
|
+
_data:
|
359
|
+
Mapping of unique keys (the SSH-credentials tuples) to
|
360
|
+
`FractalSSH` objects.
|
361
|
+
_lock:
|
362
|
+
A `threading.Lock object`, to be acquired when changing `_data`.
|
363
|
+
_timeout: Timeout for `_lock` acquisition.
|
364
|
+
_logger_name: Logger name.
|
355
365
|
"""
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
366
|
+
|
367
|
+
_data: dict[tuple[str, str, str], FractalSSH]
|
368
|
+
_lock: Lock
|
369
|
+
_timeout: float
|
370
|
+
_logger_name: str
|
371
|
+
|
372
|
+
def __init__(
|
373
|
+
self,
|
374
|
+
*,
|
375
|
+
timeout: float = 5.0,
|
376
|
+
logger_name: str = "fractal_server.FractalSSHList",
|
377
|
+
):
|
378
|
+
self._lock = Lock()
|
379
|
+
self._data = {}
|
380
|
+
self._timeout = timeout
|
381
|
+
self._logger_name = logger_name
|
382
|
+
set_logger(self._logger_name)
|
383
|
+
|
384
|
+
@property
|
385
|
+
def logger(self) -> logging.Logger:
|
386
|
+
"""
|
387
|
+
This property exists so that we never have to propagate the
|
388
|
+
`Logger` object.
|
389
|
+
"""
|
390
|
+
return get_logger(self._logger_name)
|
391
|
+
|
392
|
+
@property
|
393
|
+
def size(self) -> int:
|
394
|
+
"""
|
395
|
+
Number of current key-value pairs in `self._data`.
|
396
|
+
"""
|
397
|
+
return len(self._data.values())
|
398
|
+
|
399
|
+
def get(self, *, host: str, user: str, key_path: str) -> FractalSSH:
|
400
|
+
"""
|
401
|
+
Get the `FractalSSH` for the current credentials, or create one.
|
402
|
+
|
403
|
+
Note: Changing `_data` requires acquiring `_lock`.
|
404
|
+
|
405
|
+
Arguments:
|
406
|
+
host:
|
407
|
+
user:
|
408
|
+
key_path:
|
409
|
+
"""
|
410
|
+
key = (host, user, key_path)
|
411
|
+
fractal_ssh = self._data.get(key, None)
|
412
|
+
if fractal_ssh is not None:
|
413
|
+
self.logger.info(
|
414
|
+
f"Return existing FractalSSH object for {user}@{host}"
|
415
|
+
)
|
416
|
+
return fractal_ssh
|
417
|
+
else:
|
418
|
+
self.logger.info(f"Add new FractalSSH object for {user}@{host}")
|
419
|
+
connection = Connection(
|
420
|
+
host=host,
|
421
|
+
user=user,
|
422
|
+
forward_agent=False,
|
423
|
+
connect_kwargs={
|
424
|
+
"key_filename": key_path,
|
425
|
+
"look_for_keys": False,
|
426
|
+
},
|
427
|
+
)
|
428
|
+
with self.acquire_lock_with_timeout():
|
429
|
+
self._data[key] = FractalSSH(connection=connection)
|
430
|
+
return self._data[key]
|
431
|
+
|
432
|
+
def contains(
|
433
|
+
self,
|
434
|
+
*,
|
435
|
+
host: str,
|
436
|
+
user: str,
|
437
|
+
key_path: str,
|
438
|
+
) -> bool:
|
439
|
+
"""
|
440
|
+
Return whether a given key is present in the collection.
|
441
|
+
|
442
|
+
Arguments:
|
443
|
+
host:
|
444
|
+
user:
|
445
|
+
key_path:
|
446
|
+
"""
|
447
|
+
key = (host, user, key_path)
|
448
|
+
return key in self._data.keys()
|
449
|
+
|
450
|
+
def remove(
|
451
|
+
self,
|
452
|
+
*,
|
453
|
+
host: str,
|
454
|
+
user: str,
|
455
|
+
key_path: str,
|
456
|
+
) -> None:
|
457
|
+
"""
|
458
|
+
Remove a key from `_data` and close the corresponding connection.
|
459
|
+
|
460
|
+
Note: Changing `_data` requires acquiring `_lock`.
|
461
|
+
|
462
|
+
Arguments:
|
463
|
+
host:
|
464
|
+
user:
|
465
|
+
key_path:
|
466
|
+
"""
|
467
|
+
key = (host, user, key_path)
|
468
|
+
with self.acquire_lock_with_timeout():
|
469
|
+
self.logger.info(
|
470
|
+
f"Removing FractalSSH object for {user}@{host} "
|
471
|
+
"from collection."
|
472
|
+
)
|
473
|
+
fractal_ssh_obj = self._data.pop(key)
|
474
|
+
self.logger.info(
|
475
|
+
f"Closing FractalSSH object for {user}@{host} "
|
476
|
+
f"({fractal_ssh_obj.is_connected=})."
|
477
|
+
)
|
478
|
+
fractal_ssh_obj.close()
|
479
|
+
|
480
|
+
def close_all(self, *, timeout: float = 5.0):
|
481
|
+
"""
|
482
|
+
Close all `FractalSSH` objects in the collection.
|
483
|
+
|
484
|
+
Arguments:
|
485
|
+
timeout:
|
486
|
+
Timeout for `FractalSSH._lock` acquisition, to be obtained
|
487
|
+
before closing.
|
488
|
+
"""
|
489
|
+
for key, fractal_ssh_obj in self._data.items():
|
490
|
+
host, user, _ = key[:]
|
491
|
+
self.logger.info(
|
492
|
+
f"Closing FractalSSH object for {user}@{host} "
|
493
|
+
f"({fractal_ssh_obj.is_connected=})."
|
494
|
+
)
|
495
|
+
with fractal_ssh_obj.acquire_timeout(timeout=timeout):
|
496
|
+
fractal_ssh_obj.close()
|
497
|
+
|
498
|
+
@contextmanager
|
499
|
+
def acquire_lock_with_timeout(self) -> Generator[Literal[True], Any, None]:
|
500
|
+
self.logger.debug(
|
501
|
+
f"Trying to acquire lock, with timeout {self._timeout} s"
|
502
|
+
)
|
503
|
+
result = self._lock.acquire(timeout=self._timeout)
|
504
|
+
try:
|
505
|
+
if not result:
|
506
|
+
self.logger.error("Lock was *NOT* acquired.")
|
507
|
+
raise FractalSSHListTimeoutError(
|
508
|
+
f"Failed to acquire lock within {self._timeout} ss"
|
509
|
+
)
|
510
|
+
self.logger.debug("Lock was acquired.")
|
511
|
+
yield result
|
512
|
+
finally:
|
513
|
+
if result:
|
514
|
+
self._lock.release()
|
515
|
+
self.logger.debug("Lock was released")
|
@@ -57,6 +57,7 @@ def _customize_and_run_template(
|
|
57
57
|
tmpdir: str,
|
58
58
|
logger_name: str,
|
59
59
|
fractal_ssh: FractalSSH,
|
60
|
+
tasks_base_dir: str,
|
60
61
|
) -> str:
|
61
62
|
"""
|
62
63
|
Customize one of the template bash scripts, transfer it to the remote host
|
@@ -72,7 +73,6 @@ def _customize_and_run_template(
|
|
72
73
|
"""
|
73
74
|
logger = get_logger(logger_name)
|
74
75
|
logger.debug(f"_customize_and_run_template {script_filename} - START")
|
75
|
-
settings = Inject(get_settings)
|
76
76
|
|
77
77
|
# Read template
|
78
78
|
template_path = templates_folder / script_filename
|
@@ -88,7 +88,7 @@ def _customize_and_run_template(
|
|
88
88
|
|
89
89
|
# Transfer script to remote host
|
90
90
|
script_path_remote = os.path.join(
|
91
|
-
|
91
|
+
tasks_base_dir,
|
92
92
|
f"script_{abs(hash(tmpdir))}{script_filename}",
|
93
93
|
)
|
94
94
|
logger.debug(f"Now transfer {script_path_local=} over SSH.")
|
@@ -111,6 +111,7 @@ def background_collect_pip_ssh(
|
|
111
111
|
state_id: int,
|
112
112
|
task_pkg: _TaskCollectPip,
|
113
113
|
fractal_ssh: FractalSSH,
|
114
|
+
tasks_base_dir: str,
|
114
115
|
) -> None:
|
115
116
|
"""
|
116
117
|
Collect a task package over SSH
|
@@ -121,6 +122,13 @@ def background_collect_pip_ssh(
|
|
121
122
|
NOTE: by making this function sync, it will run within a thread - due to
|
122
123
|
starlette/fastapi handling of background tasks (see
|
123
124
|
https://github.com/encode/starlette/blob/master/starlette/background.py).
|
125
|
+
|
126
|
+
|
127
|
+
Arguments:
|
128
|
+
state_id:
|
129
|
+
task_pkg:
|
130
|
+
fractal_ssh:
|
131
|
+
tasks_base_dir:
|
124
132
|
"""
|
125
133
|
|
126
134
|
# Work within a temporary folder, where also logs will be placed
|
@@ -140,7 +148,6 @@ def background_collect_pip_ssh(
|
|
140
148
|
with next(get_sync_db()) as db:
|
141
149
|
try:
|
142
150
|
# Prepare replacements for task-collection scripts
|
143
|
-
settings = Inject(get_settings)
|
144
151
|
python_bin = get_python_interpreter_v2(
|
145
152
|
python_version=task_pkg.python_version
|
146
153
|
)
|
@@ -163,11 +170,12 @@ def background_collect_pip_ssh(
|
|
163
170
|
f"{install_string}=={task_pkg.package_version}"
|
164
171
|
)
|
165
172
|
package_env_dir = (
|
166
|
-
Path(
|
173
|
+
Path(tasks_base_dir)
|
167
174
|
/ ".fractal"
|
168
175
|
/ f"{task_pkg.package_name}{package_version}"
|
169
176
|
).as_posix()
|
170
177
|
logger.debug(f"{package_env_dir=}")
|
178
|
+
settings = Inject(get_settings)
|
171
179
|
replacements = [
|
172
180
|
("__PACKAGE_NAME__", task_pkg.package_name),
|
173
181
|
("__PACKAGE_ENV_DIR__", package_env_dir),
|
@@ -186,6 +194,7 @@ def background_collect_pip_ssh(
|
|
186
194
|
tmpdir=tmpdir,
|
187
195
|
logger_name=LOGGER_NAME,
|
188
196
|
fractal_ssh=fractal_ssh,
|
197
|
+
tasks_base_dir=tasks_base_dir,
|
189
198
|
)
|
190
199
|
|
191
200
|
fractal_ssh.check_connection()
|
@@ -332,7 +341,7 @@ def background_collect_pip_ssh(
|
|
332
341
|
)
|
333
342
|
fractal_ssh.remove_folder(
|
334
343
|
folder=package_env_dir,
|
335
|
-
safe_root=
|
344
|
+
safe_root=tasks_base_dir,
|
336
345
|
)
|
337
346
|
logger.info(
|
338
347
|
f"Deleted remoted folder {package_env_dir}"
|
@@ -1,12 +1,13 @@
|
|
1
|
-
fractal_server/__init__.py,sha256=
|
2
|
-
fractal_server/__main__.py,sha256=
|
1
|
+
fractal_server/__init__.py,sha256=lk_fIGL_HoswrWAxf9d6JXNZnZqpaYWUlhLAW5EmVQE,24
|
2
|
+
fractal_server/__main__.py,sha256=WcBAkmVE9aH5mDI6wGkVmPAql2N5Vyk0A-7zuUl8WX0,6122
|
3
3
|
fractal_server/alembic.ini,sha256=MWwi7GzjzawI9cCAK1LW7NxIBQDUqD12-ptJoq5JpP0,3153
|
4
4
|
fractal_server/app/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
5
5
|
fractal_server/app/db/__init__.py,sha256=81rK9w1__Z6PJ5cEcChPVc-wI9YOK4fN--_5Opry0MQ,4119
|
6
|
-
fractal_server/app/models/__init__.py,sha256=
|
6
|
+
fractal_server/app/models/__init__.py,sha256=aG7mf1zZbsgzDSp7GHEcZhdjHfW3TGPOLCI8MrvYhPw,500
|
7
7
|
fractal_server/app/models/linkusergroup.py,sha256=ufthlbLFAWMU_dJmsVZzVlQa_D9C9SmgydxypQ2Xq1U,309
|
8
8
|
fractal_server/app/models/linkuserproject.py,sha256=eQaourbGRshvlMVlKzLYJKHEjfsW1CbWws9yW4eHXhA,567
|
9
|
-
fractal_server/app/models/security.py,sha256=
|
9
|
+
fractal_server/app/models/security.py,sha256=DY1JGS11pdlFXTValt86hNcL6a6kLRZ5xkOhhZJ8c1U,3831
|
10
|
+
fractal_server/app/models/user_settings.py,sha256=0YXCAwoAVGqI2irRLdXgr9-JS0STtHhSaoFENigAnrk,1312
|
10
11
|
fractal_server/app/models/v1/__init__.py,sha256=hUI7dEbPaiZGN0IbHW4RSmSicyvtn_xeuevoX7zvUwI,466
|
11
12
|
fractal_server/app/models/v1/dataset.py,sha256=99GDgt7njx8yYQApkImqp_7bHA5HH3ElvbR6Oyj9kVI,2017
|
12
13
|
fractal_server/app/models/v1/job.py,sha256=QLGXcWdVRHaUHQNDapYYlLpEfw4K7QyD8TmcwhrWw2o,3304
|
@@ -28,40 +29,41 @@ fractal_server/app/routes/admin/v1.py,sha256=GIpZlwAwwwLGDWkBqywhtmp9TGsKLhGmZAd
|
|
28
29
|
fractal_server/app/routes/admin/v2.py,sha256=hoEbH_sRJ-MaKMwhFp8c7SNObP0-Kmtgw1zbs_Z3nLY,12971
|
29
30
|
fractal_server/app/routes/api/__init__.py,sha256=2IDheFi0OFdsUg7nbUiyahqybvpgXqeHUXIL2QtWrQQ,641
|
30
31
|
fractal_server/app/routes/api/v1/__init__.py,sha256=Y2HQdG197J0a7DyQEE2jn53IfxD0EHGhzK1I2JZuEck,958
|
31
|
-
fractal_server/app/routes/api/v1/_aux_functions.py,sha256=
|
32
|
+
fractal_server/app/routes/api/v1/_aux_functions.py,sha256=P9Q48thGH95w0h5cacYoibxqgiiLW4oqZ8rNJ2LIISY,13219
|
32
33
|
fractal_server/app/routes/api/v1/dataset.py,sha256=KVfKdp-bT8eB14kCjTSmpji4a2IPIHxGID8L10h3Wac,17282
|
33
34
|
fractal_server/app/routes/api/v1/job.py,sha256=0jGxvu0xNQnWuov2qnoo9yE7Oat37XbcVn4Ute-UsiE,5370
|
34
|
-
fractal_server/app/routes/api/v1/project.py,sha256=
|
35
|
-
fractal_server/app/routes/api/v1/task.py,sha256=
|
35
|
+
fractal_server/app/routes/api/v1/project.py,sha256=V-oeLiLs3vhD6STKiI2_mOyeB7FDUAcEXevHZbCWQ10,15956
|
36
|
+
fractal_server/app/routes/api/v1/task.py,sha256=eW89nMCjpD4G6tHXDo2qGBKqWaPirjH6M3hpdJQhfa0,6528
|
36
37
|
fractal_server/app/routes/api/v1/task_collection.py,sha256=VYxhtd_idBppgJM7-FCHikI2OKMAIz05fhV_TsJpWI8,9060
|
37
38
|
fractal_server/app/routes/api/v1/workflow.py,sha256=2T93DuEnSshaDCue-JPmjuvGCtbk6lt9pFMuPt783t8,11217
|
38
39
|
fractal_server/app/routes/api/v1/workflowtask.py,sha256=OYYConwJbmNULDw5I3T-UbSJKrbbBiAHbbBeVcpoFKQ,5785
|
39
40
|
fractal_server/app/routes/api/v2/__init__.py,sha256=301enf_GsL27_CnG6lSbMIeoz9-rrb3R2iDSs5pk4q8,1650
|
40
|
-
fractal_server/app/routes/api/v2/_aux_functions.py,sha256=
|
41
|
+
fractal_server/app/routes/api/v2/_aux_functions.py,sha256=mAsJs3QeCrIYKmkXo5aqhrGCbyvbPg_fqZWQNJ-vI8o,13746
|
41
42
|
fractal_server/app/routes/api/v2/dataset.py,sha256=Eilf_BAGjicIhqUiVwI86jlW45ineA5sVzxXW4b2GoQ,8329
|
42
43
|
fractal_server/app/routes/api/v2/images.py,sha256=JR1rR6qEs81nacjriOXAOBQjAbCXF4Ew7M7mkWdxBU0,7920
|
43
44
|
fractal_server/app/routes/api/v2/job.py,sha256=Bga2Kz1OjvDIdxZObWaaXVhNIhC_5JKhKRjEH2_ayEE,5157
|
44
45
|
fractal_server/app/routes/api/v2/project.py,sha256=eWYFJ7F2ZYQcpi-_n-rhPF-Q4gJhzYBsVGYFhHZZXAE,6653
|
45
46
|
fractal_server/app/routes/api/v2/status.py,sha256=6N9DSZ4iFqbZImorWfEAPoyoFUgEruo4Hweqo0x0xXU,6435
|
46
|
-
fractal_server/app/routes/api/v2/submit.py,sha256=
|
47
|
-
fractal_server/app/routes/api/v2/task.py,sha256=
|
48
|
-
fractal_server/app/routes/api/v2/task_collection.py,sha256=
|
49
|
-
fractal_server/app/routes/api/v2/task_collection_custom.py,sha256=
|
47
|
+
fractal_server/app/routes/api/v2/submit.py,sha256=SVTV9wGC_mrKWHHxWtjvsdtiRzOeSRlw2PlDYLk66Ew,9006
|
48
|
+
fractal_server/app/routes/api/v2/task.py,sha256=XDKNmin-gyLpA6eVgh89OdrNq92Vkrtxjr8VI-PIV2E,8548
|
49
|
+
fractal_server/app/routes/api/v2/task_collection.py,sha256=3ugtkrlrFWvLSHXomF0oOg2Ayg2ige1gr5F51BCQEL4,12950
|
50
|
+
fractal_server/app/routes/api/v2/task_collection_custom.py,sha256=Q9vVicfY_VJKLu7yBox2KnBSiPBDZxAnoxykWmwD8X0,6291
|
50
51
|
fractal_server/app/routes/api/v2/workflow.py,sha256=rMCcclz9aJAMSVLncUdSDGrgkKbn4KOCZTqZtqs2HDY,10428
|
51
52
|
fractal_server/app/routes/api/v2/workflowtask.py,sha256=-3-c8DDnxGjMwWbX_h5V5OLaC_iCLXYzwWKBUaL-5wE,7060
|
52
53
|
fractal_server/app/routes/auth/__init__.py,sha256=fao6CS0WiAjHDTvBzgBVV_bSXFpEAeDBF6Z6q7rRkPc,1658
|
53
|
-
fractal_server/app/routes/auth/_aux_auth.py,sha256=
|
54
|
-
fractal_server/app/routes/auth/current_user.py,sha256=
|
54
|
+
fractal_server/app/routes/auth/_aux_auth.py,sha256=a3DCj6_tekf4Bfu8Kax9uxVGbTuVsONgki7E6AJUN_8,3269
|
55
|
+
fractal_server/app/routes/auth/current_user.py,sha256=kJk6bONS8bwPoJh40mpmVGM2bb5qRrJ6Rf_p1_flvgI,3480
|
55
56
|
fractal_server/app/routes/auth/group.py,sha256=az8kRJJU5rA0L8GCX5kvRNuQhrsoGWPuvQ26z7iFQ3E,5388
|
56
57
|
fractal_server/app/routes/auth/group_names.py,sha256=zvYDfhxKlDmbSr-oLXYy6WUVkPPTvzH6ZJtuoNdGZbE,960
|
57
58
|
fractal_server/app/routes/auth/login.py,sha256=tSu6OBLOieoBtMZB4JkBAdEgH2Y8KqPGSbwy7NIypIo,566
|
58
59
|
fractal_server/app/routes/auth/oauth.py,sha256=AnFHbjqL2AgBX3eksI931xD6RTtmbciHBEuGf9YJLjU,1895
|
59
60
|
fractal_server/app/routes/auth/register.py,sha256=DlHq79iOvGd_gt2v9uwtsqIKeO6i_GKaW59VIkllPqY,587
|
60
61
|
fractal_server/app/routes/auth/router.py,sha256=zWoZWiO69U48QFQf5tLRYQDWu8PUCj7GacnaFeW1n_I,618
|
61
|
-
fractal_server/app/routes/auth/users.py,sha256=
|
62
|
+
fractal_server/app/routes/auth/users.py,sha256=63gOBjGaQpUfakVmqb9RzBcKdIafiFlmaN_ctUOA0fg,8356
|
62
63
|
fractal_server/app/routes/aux/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
63
64
|
fractal_server/app/routes/aux/_job.py,sha256=q-RCiW17yXnZKAC_0La52RLvhqhxuvbgQJ2MlGXOj8A,702
|
64
65
|
fractal_server/app/routes/aux/_runner.py,sha256=FdCVla5DxGAZ__aB7Z8dEJzD_RIeh5tftjrPyqkr8N8,895
|
66
|
+
fractal_server/app/routes/aux/validate_user_settings.py,sha256=Y8eubau0julkwVYB5nA83nDtxh_7RU9Iq0zAhb_dXLA,2351
|
65
67
|
fractal_server/app/runner/.gitignore,sha256=ytzN_oyHWXrGU7iFAtoHSTUbM6Rn6kG0Zkddg0xZk6s,16
|
66
68
|
fractal_server/app/runner/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
67
69
|
fractal_server/app/runner/async_wrap.py,sha256=_O6f8jftKYXG_DozkmlrDBhoiK9QhE9MablOyECq2_M,829
|
@@ -76,12 +78,12 @@ fractal_server/app/runner/executors/slurm/remote.py,sha256=wLziIsGdSMiO-jIXM8x77
|
|
76
78
|
fractal_server/app/runner/executors/slurm/ssh/__init__.py,sha256=Cjn1rYvljddi96tAwS-qqGkNfOcfPzjChdaEZEObCcM,65
|
77
79
|
fractal_server/app/runner/executors/slurm/ssh/_executor_wait_thread.py,sha256=bKo5Ja0IGxJWpPWyh9dN0AG-PwzTDZzD5LyaEHB3YU4,3742
|
78
80
|
fractal_server/app/runner/executors/slurm/ssh/_slurm_job.py,sha256=rwlqZzoGo4SAb4nSlFjsQJdaCgfM1J6YGcjb8yYxlqc,4506
|
79
|
-
fractal_server/app/runner/executors/slurm/ssh/executor.py,sha256=
|
81
|
+
fractal_server/app/runner/executors/slurm/ssh/executor.py,sha256=K1lKsn40PqQb-GZKwJkzeJk2Q8OGqy6YR-IxcV0E0Pw,57705
|
80
82
|
fractal_server/app/runner/executors/slurm/sudo/__init__.py,sha256=Cjn1rYvljddi96tAwS-qqGkNfOcfPzjChdaEZEObCcM,65
|
81
83
|
fractal_server/app/runner/executors/slurm/sudo/_check_jobs_status.py,sha256=wAgwpVcr6JIslKHOuS0FhRa_6T1KCManyRJqA-fifzw,1909
|
82
84
|
fractal_server/app/runner/executors/slurm/sudo/_executor_wait_thread.py,sha256=z5LlhaiqAb8pHsF1WwdzXN39C5anQmwjo1rSQgtRAYE,4422
|
83
85
|
fractal_server/app/runner/executors/slurm/sudo/_subprocess_run_as_user.py,sha256=g8wqUjSicN17UZVXlfaMomYZ-xOIbBu1oE7HdJTzfvw,5218
|
84
|
-
fractal_server/app/runner/executors/slurm/sudo/executor.py,sha256=
|
86
|
+
fractal_server/app/runner/executors/slurm/sudo/executor.py,sha256=6OPe9t70gLyuC2JhWt2o1f0e7zhQPBtrbMHQkDd6RAQ,48725
|
85
87
|
fractal_server/app/runner/extract_archive.py,sha256=tLpjDrX47OjTNhhoWvm6iNukg8KoieWyTb7ZfvE9eWU,2483
|
86
88
|
fractal_server/app/runner/filenames.py,sha256=9lwu3yB4C67yiijYw8XIKaLFn3mJUt6_TCyVFM_aZUQ,206
|
87
89
|
fractal_server/app/runner/run_subprocess.py,sha256=c3JbYXq3hX2aaflQU19qJ5Xs6J6oXGNvnTEoAfv2bxc,959
|
@@ -99,7 +101,7 @@ fractal_server/app/runner/v1/_slurm/_submit_setup.py,sha256=KO9c694d318adoPQh9UG
|
|
99
101
|
fractal_server/app/runner/v1/_slurm/get_slurm_config.py,sha256=6pQNNx997bLIfLp0guF09t_O0ZYRXnbEGLktSAcKnic,5999
|
100
102
|
fractal_server/app/runner/v1/common.py,sha256=_L-vjLnWato80VdlB_BFN4G8P4jSM07u-5cnl1T3S34,3294
|
101
103
|
fractal_server/app/runner/v1/handle_failed_job.py,sha256=bHzScC_aIlU3q-bQxGW6rfWV4xbZ2tho_sktjsAs1no,4684
|
102
|
-
fractal_server/app/runner/v2/__init__.py,sha256=
|
104
|
+
fractal_server/app/runner/v2/__init__.py,sha256=BkmaVbhh6XMK_Y2Suzz3bXm3Ff2l0JKbHqs8zp0hi8A,16965
|
103
105
|
fractal_server/app/runner/v2/_local/__init__.py,sha256=KTj14K6jH8fXGUi5P7u5_RqEE1zF4aXtgPxCKzw46iw,5971
|
104
106
|
fractal_server/app/runner/v2/_local/_local_config.py,sha256=9oi209Dlp35ANfxb_DISqmMKKc6DPaMsmYVWbZLseME,3630
|
105
107
|
fractal_server/app/runner/v2/_local/_submit_setup.py,sha256=MucNOo8Er0F5ZIwH7CnTeXgnFMc6d3pKPkv563QNVi0,1630
|
@@ -122,10 +124,11 @@ fractal_server/app/runner/v2/runner_functions.py,sha256=BLREIcQaE6FSc2AEJyZuiYk6
|
|
122
124
|
fractal_server/app/runner/v2/runner_functions_low_level.py,sha256=1fWvQ6YZUUnDhO_mipXC5hnaT-zK-GHxg8ayoxZX82k,3648
|
123
125
|
fractal_server/app/runner/v2/task_interface.py,sha256=myS-kT0DsJ8xIJZBVEzgD8g54VbiwL6i7Im3e1zcVHQ,1866
|
124
126
|
fractal_server/app/runner/versions.py,sha256=dSaPRWqmFPHjg20kTCHmi_dmGNcCETflDtDLronNanU,852
|
125
|
-
fractal_server/app/schemas/__init__.py,sha256=
|
127
|
+
fractal_server/app/schemas/__init__.py,sha256=stURAU_t3AOBaH0HSUbV-GKhlPKngnnIMoqWc3orFyI,135
|
126
128
|
fractal_server/app/schemas/_validators.py,sha256=1dTOYr1IZykrxuQSV2-zuEMZbKe_nGwrfS7iUrsh-sE,3461
|
127
|
-
fractal_server/app/schemas/user.py,sha256=
|
129
|
+
fractal_server/app/schemas/user.py,sha256=VNnAPnAVK6X0PZlw7XehocAshVNuUHdDwiZVWCCor6Y,2156
|
128
130
|
fractal_server/app/schemas/user_group.py,sha256=2f9XQ6kIar6NMY4UCN0yOnve6ZDHUVZaHv1dna1Vfjg,1446
|
131
|
+
fractal_server/app/schemas/user_settings.py,sha256=wC_UbAjUgQI61aiX71Y-PWSPGtyOVwUVobjCLz__k9k,2840
|
129
132
|
fractal_server/app/schemas/v1/__init__.py,sha256=CrBGgBhoemCvmZ70ZUchM-jfVAICnoa7AjZBAtL2UB0,1852
|
130
133
|
fractal_server/app/schemas/v1/applyworkflow.py,sha256=uuIh7fHlHEL4yLqL-dePI6-nfCsqgBYATmht7w_KITw,4302
|
131
134
|
fractal_server/app/schemas/v1/dataset.py,sha256=n71lNUO3JLy2K3IM9BZM2Fk1EnKQOTU7pm2s2rJ1FGY,3444
|
@@ -147,16 +150,18 @@ fractal_server/app/schemas/v2/task.py,sha256=XsN8w1Szs8BrxxRtKyWCHKjN4Od-Kmlhi76
|
|
147
150
|
fractal_server/app/schemas/v2/task_collection.py,sha256=8PG1bOqkfQqORMN0brWf6mHDmijt0bBW-mZsF7cSxUs,6129
|
148
151
|
fractal_server/app/schemas/v2/workflow.py,sha256=Zzx3e-qgkH8le0FUmAx9UrV5PWd7bj14PPXUh_zgZXM,1827
|
149
152
|
fractal_server/app/schemas/v2/workflowtask.py,sha256=TN-mdkuE_EWet9Wk-xFrUwIt_tXYcw88WOKMnUcchKk,5665
|
150
|
-
fractal_server/app/security/__init__.py,sha256=
|
151
|
-
fractal_server/
|
152
|
-
fractal_server/
|
153
|
+
fractal_server/app/security/__init__.py,sha256=V1NOWlmaFZHMR6SrkMl62jyAuqYONyo8lyGvR6UZesM,12312
|
154
|
+
fractal_server/app/user_settings.py,sha256=aZgQ3i0JkHfgwLGW1ee6Gzr1ae3IioFfJKKSsSS8Svk,1312
|
155
|
+
fractal_server/config.py,sha256=NucdVswA4MJpgeePDqSsU01I893Bn_hqWUrxrax83Ls,24257
|
156
|
+
fractal_server/data_migrations/2_6_0.py,sha256=Vl17mFiOF5jQsktOnog5vnaXXcUXOJRa-ljas9kUX0E,1863
|
153
157
|
fractal_server/data_migrations/README.md,sha256=_3AEFvDg9YkybDqCLlFPdDmGJvr6Tw7HRI14aZ3LOIw,398
|
158
|
+
fractal_server/data_migrations/tools.py,sha256=LeMeASwYGtEqd-3wOLle6WARdTGAimoyMmRbbJl-hAM,572
|
154
159
|
fractal_server/gunicorn_fractal.py,sha256=u6U01TLGlXgq1v8QmEpLih3QnsInZD7CqphgJ_GrGzc,1230
|
155
160
|
fractal_server/images/__init__.py,sha256=xO6jTLE4EZKO6cTDdJsBmK9cdeh9hFTaSbSuWgQg7y4,196
|
156
161
|
fractal_server/images/models.py,sha256=9ipU5h4N6ogBChoB-2vHoqtL0TXOHCv6kRR-fER3mkM,4167
|
157
162
|
fractal_server/images/tools.py,sha256=gxeniYy4Z-cp_ToK2LHPJUTVVUUrdpogYdcBUvBuLiY,2209
|
158
163
|
fractal_server/logger.py,sha256=56wfka6fHaa3Rx5qO009nEs_y8gx5wZ2NUNZZ1I-uvc,5130
|
159
|
-
fractal_server/main.py,sha256=
|
164
|
+
fractal_server/main.py,sha256=68rVybnviF28yFgRhfHZXwnf6LyzkcmeYYZZppboU4M,4925
|
160
165
|
fractal_server/migrations/README,sha256=4rQvyDfqodGhpJw74VYijRmgFP49ji5chyEemWGHsuw,59
|
161
166
|
fractal_server/migrations/env.py,sha256=mEiX0TRa_8KAYBrUGJTx1cFJ5YAq_oNHHsFCp1raegk,2543
|
162
167
|
fractal_server/migrations/naming_convention.py,sha256=htbKrVdetx3pklowb_9Cdo5RqeF0fJ740DNecY5de_M,265
|
@@ -173,6 +178,7 @@ fractal_server/migrations/versions/84bf0fffde30_add_dumps_to_applyworkflow.py,sh
|
|
173
178
|
fractal_server/migrations/versions/8f79bd162e35_add_docs_info_and_docs_link_to_task_.py,sha256=6pgODDtyAxevZvAJBj9IJ41inhV1RpwbpZr_qfPPu1A,1115
|
174
179
|
fractal_server/migrations/versions/97f444d47249_add_applyworkflow_project_dump.py,sha256=eKTZm3EgUgapXBxO0RuHkEfTKic-TZG3ADaMpGLuc0k,1057
|
175
180
|
fractal_server/migrations/versions/99ea79d9e5d2_add_dataset_history.py,sha256=0im6TxDr53sKKcjiPgeH4ftVRGnRXZSh2lPbRQ1Ir9w,883
|
181
|
+
fractal_server/migrations/versions/9c5ae74c9b98_add_user_settings_table.py,sha256=syONdZNf4-OnAcWIsbzXpYwpXPsXZ4SsmjwVvmVG0PU,2256
|
176
182
|
fractal_server/migrations/versions/9fd26a2b0de4_add_workflow_timestamp_created.py,sha256=4l1AHGUsa0ONoJVZlr3fTXw_xbbQ8O7wlD92Az2aRfM,1849
|
177
183
|
fractal_server/migrations/versions/a7f4d6137b53_add_workflow_dump_to_applyworkflow.py,sha256=ekDUML7ILpmdoqEclKbEUdyLi4uw9HSG_sTjG2hp_JE,867
|
178
184
|
fractal_server/migrations/versions/d4fe3708d309_make_applyworkflow_workflow_dump_non_.py,sha256=6cHEZFuTXiQg9yu32Y3RH1XAl71av141WQ6UMbiITIg,949
|
@@ -181,7 +187,7 @@ fractal_server/migrations/versions/efa89c30e0a4_add_project_timestamp_created.py
|
|
181
187
|
fractal_server/migrations/versions/f384e1c0cf5d_drop_task_default_args_columns.py,sha256=9BwqUS9Gf7UW_KjrzHbtViC880qhD452KAytkHWWZyk,746
|
182
188
|
fractal_server/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
183
189
|
fractal_server/ssh/__init__.py,sha256=sVUmzxf7_DuXG1xoLQ1_00fo5NPhi2LJipSmU5EAkPs,124
|
184
|
-
fractal_server/ssh/_fabric.py,sha256=
|
190
|
+
fractal_server/ssh/_fabric.py,sha256=B9C7Cj9ibrT1_OGlu38Jz94elNofLvkP1pxf0Tv8Eic,16140
|
185
191
|
fractal_server/string_tools.py,sha256=YyopB2ZZ8iL9JLDXUA8PI0hahivqLiohir2HsAlEzqE,2170
|
186
192
|
fractal_server/syringe.py,sha256=3qSMW3YaMKKnLdgnooAINOPxnCOxP7y2jeAQYB21Gdo,2786
|
187
193
|
fractal_server/tasks/__init__.py,sha256=kadmVUoIghl8s190_Tt-8f-WBqMi8u8oU4Pvw39NHE8,23
|
@@ -196,7 +202,7 @@ fractal_server/tasks/v2/_TaskCollectPip.py,sha256=kWQNMNZ8OEddkYhmhsk3E6ArcaD7qe
|
|
196
202
|
fractal_server/tasks/v2/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
197
203
|
fractal_server/tasks/v2/_venv_pip.py,sha256=6NCItfeWgO9BDnlfhoCfiUG5UCGGz_SJz4Mfn4Jg_nk,6489
|
198
204
|
fractal_server/tasks/v2/background_operations.py,sha256=CQwQon5RKAXrjsN255Okh5dcT0R45axgqoPW3EB-v_Q,11527
|
199
|
-
fractal_server/tasks/v2/background_operations_ssh.py,sha256=
|
205
|
+
fractal_server/tasks/v2/background_operations_ssh.py,sha256=K2_MLmHaYBIyT9PfeLsA5JpNH6V1SHczNdQI6hH71GM,14112
|
200
206
|
fractal_server/tasks/v2/endpoint_operations.py,sha256=gT38pl5TEH6WNWOtg4Itegt2lTJJI6YRa7fEj9Y4x2s,4226
|
201
207
|
fractal_server/tasks/v2/templates/_1_create_venv.sh,sha256=5uW0ETYxl5xiQEXP107zgq8V_-vf3k5NzMMj1hSLjas,1015
|
202
208
|
fractal_server/tasks/v2/templates/_2_upgrade_pip.sh,sha256=ca5Yng6JgJYu-a4QrsIsatwUmrLdRWBKw7_VJrY7WLY,555
|
@@ -207,8 +213,8 @@ fractal_server/tasks/v2/utils.py,sha256=JOyCacb6MNvrwfLNTyLwcz8y79J29YuJeJ2MK5kq
|
|
207
213
|
fractal_server/urls.py,sha256=5o_qq7PzKKbwq12NHSQZDmDitn5RAOeQ4xufu-2v9Zk,448
|
208
214
|
fractal_server/utils.py,sha256=b7WwFdcFZ8unyT65mloFToYuEDXpQoHRcmRNqrhd_dQ,2115
|
209
215
|
fractal_server/zip_tools.py,sha256=xYpzBshysD2nmxkD5WLYqMzPYUcCRM3kYy-7n9bJL-U,4426
|
210
|
-
fractal_server-2.
|
211
|
-
fractal_server-2.
|
212
|
-
fractal_server-2.
|
213
|
-
fractal_server-2.
|
214
|
-
fractal_server-2.
|
216
|
+
fractal_server-2.6.0a0.dist-info/LICENSE,sha256=QKAharUuhxL58kSoLizKJeZE3mTCBnX6ucmz8W0lxlk,1576
|
217
|
+
fractal_server-2.6.0a0.dist-info/METADATA,sha256=9N03OeHxGpun6VcE0goQQIFPG5WNhOy-r5bR5vuZxb0,4630
|
218
|
+
fractal_server-2.6.0a0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
219
|
+
fractal_server-2.6.0a0.dist-info/entry_points.txt,sha256=8tV2kynvFkjnhbtDnxAqImL6HMVKsopgGfew0DOp5UY,58
|
220
|
+
fractal_server-2.6.0a0.dist-info/RECORD,,
|
@@ -1,61 +0,0 @@
|
|
1
|
-
import logging
|
2
|
-
|
3
|
-
from packaging.version import parse
|
4
|
-
from sqlalchemy import select
|
5
|
-
|
6
|
-
import fractal_server
|
7
|
-
from fractal_server.app.db import get_sync_db
|
8
|
-
from fractal_server.app.models import LinkUserGroup
|
9
|
-
from fractal_server.app.models import UserGroup
|
10
|
-
from fractal_server.app.models import UserOAuth
|
11
|
-
from fractal_server.app.security import FRACTAL_DEFAULT_GROUP_NAME
|
12
|
-
|
13
|
-
|
14
|
-
def _check_current_version(*, expected_version: str):
|
15
|
-
# Check that this module matches with the current version
|
16
|
-
module_version = parse(expected_version)
|
17
|
-
current_version = parse(fractal_server.__VERSION__)
|
18
|
-
if (
|
19
|
-
current_version.major != module_version.major
|
20
|
-
or current_version.minor != module_version.minor
|
21
|
-
or current_version.micro != module_version.micro
|
22
|
-
):
|
23
|
-
raise RuntimeError(
|
24
|
-
f"{fractal_server.__VERSION__=} not matching with {__file__=}"
|
25
|
-
)
|
26
|
-
|
27
|
-
|
28
|
-
def fix_db():
|
29
|
-
logger = logging.getLogger("fix_db")
|
30
|
-
logger.warning("START execution of fix_db function")
|
31
|
-
_check_current_version(expected_version="2.4.0")
|
32
|
-
|
33
|
-
with next(get_sync_db()) as db:
|
34
|
-
# Find default group
|
35
|
-
stm = select(UserGroup).where(
|
36
|
-
UserGroup.name == FRACTAL_DEFAULT_GROUP_NAME
|
37
|
-
)
|
38
|
-
res = db.execute(stm)
|
39
|
-
default_group = res.scalar_one_or_none()
|
40
|
-
if default_group is None:
|
41
|
-
raise RuntimeError("Default group not found, exit.")
|
42
|
-
logger.warning(
|
43
|
-
"Default user group exists: "
|
44
|
-
f"{default_group.id=}, {default_group.name=}."
|
45
|
-
)
|
46
|
-
|
47
|
-
# Find
|
48
|
-
stm = select(UserOAuth)
|
49
|
-
users = db.execute(stm).scalars().unique().all()
|
50
|
-
for user in sorted(users, key=lambda x: x.id):
|
51
|
-
logger.warning(
|
52
|
-
f"START adding {user.id=} ({user.email=}) to default group."
|
53
|
-
)
|
54
|
-
link = LinkUserGroup(user_id=user.id, group_id=default_group.id)
|
55
|
-
db.add(link)
|
56
|
-
db.commit()
|
57
|
-
logger.warning(
|
58
|
-
f"END adding {user.id=} ({user.email=}) to default group."
|
59
|
-
)
|
60
|
-
|
61
|
-
logger.warning("END of execution of fix_db function")
|
File without changes
|
File without changes
|