fractal-server 2.9.0a3__py3-none-any.whl → 2.9.0a4__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/__init__.py +4 -0
- fractal_server/app/routes/admin/v2/task_group_lifecycle.py +260 -0
- fractal_server/tasks/v2/ssh/collect.py +1 -1
- {fractal_server-2.9.0a3.dist-info → fractal_server-2.9.0a4.dist-info}/METADATA +1 -1
- {fractal_server-2.9.0a3.dist-info → fractal_server-2.9.0a4.dist-info}/RECORD +9 -8
- {fractal_server-2.9.0a3.dist-info → fractal_server-2.9.0a4.dist-info}/LICENSE +0 -0
- {fractal_server-2.9.0a3.dist-info → fractal_server-2.9.0a4.dist-info}/WHEEL +0 -0
- {fractal_server-2.9.0a3.dist-info → fractal_server-2.9.0a4.dist-info}/entry_points.txt +0 -0
fractal_server/__init__.py
CHANGED
@@ -1 +1 @@
|
|
1
|
-
__VERSION__ = "2.9.
|
1
|
+
__VERSION__ = "2.9.0a4"
|
@@ -7,6 +7,7 @@ from .job import router as job_router
|
|
7
7
|
from .project import router as project_router
|
8
8
|
from .task import router as task_router
|
9
9
|
from .task_group import router as task_group_router
|
10
|
+
from .task_group_lifecycle import router as task_group_lifecycle_router
|
10
11
|
|
11
12
|
router_admin_v2 = APIRouter()
|
12
13
|
|
@@ -14,3 +15,6 @@ router_admin_v2.include_router(job_router, prefix="/job")
|
|
14
15
|
router_admin_v2.include_router(project_router, prefix="/project")
|
15
16
|
router_admin_v2.include_router(task_router, prefix="/task")
|
16
17
|
router_admin_v2.include_router(task_group_router, prefix="/task-group")
|
18
|
+
router_admin_v2.include_router(
|
19
|
+
task_group_lifecycle_router, prefix="/task-group"
|
20
|
+
)
|
@@ -0,0 +1,260 @@
|
|
1
|
+
from fastapi import APIRouter
|
2
|
+
from fastapi import BackgroundTasks
|
3
|
+
from fastapi import Depends
|
4
|
+
from fastapi import HTTPException
|
5
|
+
from fastapi import Request
|
6
|
+
from fastapi import Response
|
7
|
+
from fastapi import status
|
8
|
+
|
9
|
+
from fractal_server.app.db import AsyncSession
|
10
|
+
from fractal_server.app.db import get_async_db
|
11
|
+
from fractal_server.app.models import UserOAuth
|
12
|
+
from fractal_server.app.models.v2 import TaskGroupActivityV2
|
13
|
+
from fractal_server.app.routes.api.v2._aux_functions_task_lifecycle import (
|
14
|
+
check_no_ongoing_activity,
|
15
|
+
)
|
16
|
+
from fractal_server.app.routes.api.v2._aux_functions_tasks import (
|
17
|
+
_get_task_group_or_404,
|
18
|
+
)
|
19
|
+
from fractal_server.app.routes.auth import current_active_superuser
|
20
|
+
from fractal_server.app.routes.aux.validate_user_settings import (
|
21
|
+
validate_user_settings,
|
22
|
+
)
|
23
|
+
from fractal_server.app.schemas.v2 import TaskGroupActivityActionV2
|
24
|
+
from fractal_server.app.schemas.v2 import TaskGroupActivityStatusV2
|
25
|
+
from fractal_server.app.schemas.v2 import TaskGroupActivityV2Read
|
26
|
+
from fractal_server.app.schemas.v2 import TaskGroupReadV2
|
27
|
+
from fractal_server.app.schemas.v2 import TaskGroupV2OriginEnum
|
28
|
+
from fractal_server.config import get_settings
|
29
|
+
from fractal_server.logger import set_logger
|
30
|
+
from fractal_server.syringe import Inject
|
31
|
+
from fractal_server.tasks.v2.local import deactivate_local
|
32
|
+
from fractal_server.tasks.v2.local import reactivate_local
|
33
|
+
from fractal_server.tasks.v2.ssh import deactivate_ssh
|
34
|
+
from fractal_server.tasks.v2.ssh import reactivate_ssh
|
35
|
+
from fractal_server.utils import get_timestamp
|
36
|
+
|
37
|
+
router = APIRouter()
|
38
|
+
|
39
|
+
logger = set_logger(__name__)
|
40
|
+
|
41
|
+
|
42
|
+
@router.post(
|
43
|
+
"/{task_group_id}/deactivate/",
|
44
|
+
response_model=TaskGroupActivityV2Read,
|
45
|
+
)
|
46
|
+
async def deactivate_task_group(
|
47
|
+
task_group_id: int,
|
48
|
+
background_tasks: BackgroundTasks,
|
49
|
+
response: Response,
|
50
|
+
request: Request,
|
51
|
+
superuser: UserOAuth = Depends(current_active_superuser),
|
52
|
+
db: AsyncSession = Depends(get_async_db),
|
53
|
+
) -> TaskGroupReadV2:
|
54
|
+
"""
|
55
|
+
Deactivate task-group venv
|
56
|
+
"""
|
57
|
+
task_group = await _get_task_group_or_404(
|
58
|
+
task_group_id=task_group_id, db=db
|
59
|
+
)
|
60
|
+
|
61
|
+
# Check no other activity is ongoing
|
62
|
+
await check_no_ongoing_activity(task_group_id=task_group_id, db=db)
|
63
|
+
|
64
|
+
# Check that task-group is active
|
65
|
+
if not task_group.active:
|
66
|
+
raise HTTPException(
|
67
|
+
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
68
|
+
detail=(
|
69
|
+
f"Cannot deactivate a task group with {task_group.active=}."
|
70
|
+
),
|
71
|
+
)
|
72
|
+
|
73
|
+
# Shortcut for task-group with origin="other"
|
74
|
+
if task_group.origin == TaskGroupV2OriginEnum.OTHER:
|
75
|
+
task_group.active = False
|
76
|
+
task_group_activity = TaskGroupActivityV2(
|
77
|
+
user_id=task_group.user_id,
|
78
|
+
taskgroupv2_id=task_group.id,
|
79
|
+
status=TaskGroupActivityStatusV2.OK,
|
80
|
+
action=TaskGroupActivityActionV2.DEACTIVATE,
|
81
|
+
pkg_name=task_group.pkg_name,
|
82
|
+
version=(task_group.version or "N/A"),
|
83
|
+
log=(
|
84
|
+
f"Task group has {task_group.origin=}, set "
|
85
|
+
"task_group.active to False and exit."
|
86
|
+
),
|
87
|
+
timestamp_started=get_timestamp(),
|
88
|
+
timestamp_ended=get_timestamp(),
|
89
|
+
)
|
90
|
+
db.add(task_group)
|
91
|
+
db.add(task_group_activity)
|
92
|
+
await db.commit()
|
93
|
+
response.status_code = status.HTTP_202_ACCEPTED
|
94
|
+
return task_group_activity
|
95
|
+
|
96
|
+
task_group_activity = TaskGroupActivityV2(
|
97
|
+
user_id=task_group.user_id,
|
98
|
+
taskgroupv2_id=task_group.id,
|
99
|
+
status=TaskGroupActivityStatusV2.PENDING,
|
100
|
+
action=TaskGroupActivityActionV2.DEACTIVATE,
|
101
|
+
pkg_name=task_group.pkg_name,
|
102
|
+
version=task_group.version,
|
103
|
+
timestamp_started=get_timestamp(),
|
104
|
+
)
|
105
|
+
task_group.active = False
|
106
|
+
db.add(task_group)
|
107
|
+
db.add(task_group_activity)
|
108
|
+
await db.commit()
|
109
|
+
|
110
|
+
# Submit background task
|
111
|
+
settings = Inject(get_settings)
|
112
|
+
if settings.FRACTAL_RUNNER_BACKEND == "slurm_ssh":
|
113
|
+
# Validate user settings (backend-specific)
|
114
|
+
user = await db.get(UserOAuth, task_group.user_id)
|
115
|
+
user_settings = await validate_user_settings(
|
116
|
+
user=user, backend=settings.FRACTAL_RUNNER_BACKEND, db=db
|
117
|
+
)
|
118
|
+
# User appropriate FractalSSH object
|
119
|
+
ssh_credentials = dict(
|
120
|
+
user=user_settings.ssh_username,
|
121
|
+
host=user_settings.ssh_host,
|
122
|
+
key_path=user_settings.ssh_private_key_path,
|
123
|
+
)
|
124
|
+
fractal_ssh_list = request.app.state.fractal_ssh_list
|
125
|
+
fractal_ssh = fractal_ssh_list.get(**ssh_credentials)
|
126
|
+
|
127
|
+
background_tasks.add_task(
|
128
|
+
deactivate_ssh,
|
129
|
+
task_group_id=task_group.id,
|
130
|
+
task_group_activity_id=task_group_activity.id,
|
131
|
+
fractal_ssh=fractal_ssh,
|
132
|
+
tasks_base_dir=user_settings.ssh_tasks_dir,
|
133
|
+
)
|
134
|
+
else:
|
135
|
+
background_tasks.add_task(
|
136
|
+
deactivate_local,
|
137
|
+
task_group_id=task_group.id,
|
138
|
+
task_group_activity_id=task_group_activity.id,
|
139
|
+
)
|
140
|
+
|
141
|
+
logger.debug(
|
142
|
+
"Admin task group deactivation endpoint: start deactivate "
|
143
|
+
"and return task_group_activity"
|
144
|
+
)
|
145
|
+
response.status_code = status.HTTP_202_ACCEPTED
|
146
|
+
return task_group_activity
|
147
|
+
|
148
|
+
|
149
|
+
@router.post(
|
150
|
+
"/{task_group_id}/reactivate/",
|
151
|
+
response_model=TaskGroupActivityV2Read,
|
152
|
+
)
|
153
|
+
async def reactivate_task_group(
|
154
|
+
task_group_id: int,
|
155
|
+
background_tasks: BackgroundTasks,
|
156
|
+
response: Response,
|
157
|
+
request: Request,
|
158
|
+
superuser: UserOAuth = Depends(current_active_superuser),
|
159
|
+
db: AsyncSession = Depends(get_async_db),
|
160
|
+
) -> TaskGroupReadV2:
|
161
|
+
"""
|
162
|
+
Deactivate task-group venv
|
163
|
+
"""
|
164
|
+
|
165
|
+
task_group = await _get_task_group_or_404(
|
166
|
+
task_group_id=task_group_id, db=db
|
167
|
+
)
|
168
|
+
|
169
|
+
# Check that task-group is not active
|
170
|
+
if task_group.active:
|
171
|
+
raise HTTPException(
|
172
|
+
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
173
|
+
detail=(
|
174
|
+
f"Cannot reactivate a task group with {task_group.active=}."
|
175
|
+
),
|
176
|
+
)
|
177
|
+
|
178
|
+
# Check no other activity is ongoing
|
179
|
+
await check_no_ongoing_activity(task_group_id=task_group_id, db=db)
|
180
|
+
|
181
|
+
# Shortcut for task-group with origin="other"
|
182
|
+
if task_group.origin == TaskGroupV2OriginEnum.OTHER:
|
183
|
+
task_group.active = True
|
184
|
+
task_group_activity = TaskGroupActivityV2(
|
185
|
+
user_id=task_group.user_id,
|
186
|
+
taskgroupv2_id=task_group.id,
|
187
|
+
status=TaskGroupActivityStatusV2.OK,
|
188
|
+
action=TaskGroupActivityActionV2.REACTIVATE,
|
189
|
+
pkg_name=task_group.pkg_name,
|
190
|
+
version=(task_group.version or "N/A"),
|
191
|
+
log=(
|
192
|
+
f"Task group has {task_group.origin=}, set "
|
193
|
+
"task_group.active to True and exit."
|
194
|
+
),
|
195
|
+
timestamp_started=get_timestamp(),
|
196
|
+
timestamp_ended=get_timestamp(),
|
197
|
+
)
|
198
|
+
db.add(task_group)
|
199
|
+
db.add(task_group_activity)
|
200
|
+
await db.commit()
|
201
|
+
response.status_code = status.HTTP_202_ACCEPTED
|
202
|
+
return task_group_activity
|
203
|
+
|
204
|
+
if task_group.pip_freeze is None:
|
205
|
+
raise HTTPException(
|
206
|
+
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
207
|
+
detail=(
|
208
|
+
"Cannot reactivate a task group with "
|
209
|
+
f"{task_group.pip_freeze=}."
|
210
|
+
),
|
211
|
+
)
|
212
|
+
|
213
|
+
task_group_activity = TaskGroupActivityV2(
|
214
|
+
user_id=task_group.user_id,
|
215
|
+
taskgroupv2_id=task_group.id,
|
216
|
+
status=TaskGroupActivityStatusV2.PENDING,
|
217
|
+
action=TaskGroupActivityActionV2.REACTIVATE,
|
218
|
+
pkg_name=task_group.pkg_name,
|
219
|
+
version=task_group.version,
|
220
|
+
timestamp_started=get_timestamp(),
|
221
|
+
)
|
222
|
+
db.add(task_group_activity)
|
223
|
+
await db.commit()
|
224
|
+
|
225
|
+
# Submit background task
|
226
|
+
settings = Inject(get_settings)
|
227
|
+
if settings.FRACTAL_RUNNER_BACKEND == "slurm_ssh":
|
228
|
+
# Validate user settings (backend-specific)
|
229
|
+
user = await db.get(UserOAuth, task_group.user_id)
|
230
|
+
user_settings = await validate_user_settings(
|
231
|
+
user=user, backend=settings.FRACTAL_RUNNER_BACKEND, db=db
|
232
|
+
)
|
233
|
+
# Use appropriate FractalSSH object
|
234
|
+
ssh_credentials = dict(
|
235
|
+
user=user_settings.ssh_username,
|
236
|
+
host=user_settings.ssh_host,
|
237
|
+
key_path=user_settings.ssh_private_key_path,
|
238
|
+
)
|
239
|
+
fractal_ssh_list = request.app.state.fractal_ssh_list
|
240
|
+
fractal_ssh = fractal_ssh_list.get(**ssh_credentials)
|
241
|
+
|
242
|
+
background_tasks.add_task(
|
243
|
+
reactivate_ssh,
|
244
|
+
task_group_id=task_group.id,
|
245
|
+
task_group_activity_id=task_group_activity.id,
|
246
|
+
fractal_ssh=fractal_ssh,
|
247
|
+
tasks_base_dir=user_settings.ssh_tasks_dir,
|
248
|
+
)
|
249
|
+
else:
|
250
|
+
background_tasks.add_task(
|
251
|
+
reactivate_local,
|
252
|
+
task_group_id=task_group.id,
|
253
|
+
task_group_activity_id=task_group_activity.id,
|
254
|
+
)
|
255
|
+
logger.debug(
|
256
|
+
"Admin task group reactivation endpoint: start reactivate "
|
257
|
+
"and return task_group_activity"
|
258
|
+
)
|
259
|
+
response.status_code = status.HTTP_202_ACCEPTED
|
260
|
+
return task_group_activity
|
@@ -1,4 +1,4 @@
|
|
1
|
-
fractal_server/__init__.py,sha256=
|
1
|
+
fractal_server/__init__.py,sha256=Y1rSgqglVGXD4u5k97z-tPhXn-XoXu0yguIqzQ4j9Os,24
|
2
2
|
fractal_server/__main__.py,sha256=dEkCfzLLQrIlxsGC-HBfoR-RBMWnJDgNrxYTyzmE9c0,6146
|
3
3
|
fractal_server/alembic.ini,sha256=MWwi7GzjzawI9cCAK1LW7NxIBQDUqD12-ptJoq5JpP0,3153
|
4
4
|
fractal_server/app/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -26,11 +26,12 @@ fractal_server/app/models/v2/workflowtask.py,sha256=iDuJYk8kp4PNqGmbKRtGI7y-Qsbj
|
|
26
26
|
fractal_server/app/routes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
27
27
|
fractal_server/app/routes/admin/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
28
28
|
fractal_server/app/routes/admin/v1.py,sha256=5YxfWz2QK2spUKomnAteaMsWF9Ql-oHwMs1jhSjHznk,13319
|
29
|
-
fractal_server/app/routes/admin/v2/__init__.py,sha256=
|
29
|
+
fractal_server/app/routes/admin/v2/__init__.py,sha256=KYrw0COmmMuIMp7c6YcYRXah4tEYplCWeROnPK1VTeg,681
|
30
30
|
fractal_server/app/routes/admin/v2/job.py,sha256=DbkPmUk7V2iEGIlKa_xgC07cc3G8oNsONGDZ_aKq5zE,7589
|
31
31
|
fractal_server/app/routes/admin/v2/project.py,sha256=luy-yiGX1JYTdPm1hpIdDUUqPm8xHuipLy9k2X6zu74,1223
|
32
32
|
fractal_server/app/routes/admin/v2/task.py,sha256=Y0eujBgGhVapNXfW9azDxw4EBzLmEmCdh70y1RNQcb0,3895
|
33
33
|
fractal_server/app/routes/admin/v2/task_group.py,sha256=ldMQ8OIUKEhr1a_BXiwgh4K3d1T299ZaDNJjbn_zAxc,7411
|
34
|
+
fractal_server/app/routes/admin/v2/task_group_lifecycle.py,sha256=vDaTRX8AD8ESd-2CmT2rJPDDl4WxazxvSMdaUqcUPOY,9113
|
34
35
|
fractal_server/app/routes/api/__init__.py,sha256=2IDheFi0OFdsUg7nbUiyahqybvpgXqeHUXIL2QtWrQQ,641
|
35
36
|
fractal_server/app/routes/api/v1/__init__.py,sha256=Y2HQdG197J0a7DyQEE2jn53IfxD0EHGhzK1I2JZuEck,958
|
36
37
|
fractal_server/app/routes/api/v1/_aux_functions.py,sha256=P9Q48thGH95w0h5cacYoibxqgiiLW4oqZ8rNJ2LIISY,13219
|
@@ -221,7 +222,7 @@ fractal_server/tasks/v2/local/deactivate.py,sha256=Tjooode2oXfaSLiJz7iSu-qC1OkeI
|
|
221
222
|
fractal_server/tasks/v2/local/reactivate.py,sha256=R3rArAzUpMGf6xa3dGVwwXHW9WVDi5ia28AFisZsqNc,6112
|
222
223
|
fractal_server/tasks/v2/ssh/__init__.py,sha256=aSQbVi6Ummt9QzcSLWNmSqYjfdxrn9ROmqgH6bDpI7k,135
|
223
224
|
fractal_server/tasks/v2/ssh/_utils.py,sha256=2E-F_862zM6FZA-im-E8t8kjptWRIhBj1IDHC6QD1H8,2818
|
224
|
-
fractal_server/tasks/v2/ssh/collect.py,sha256=
|
225
|
+
fractal_server/tasks/v2/ssh/collect.py,sha256=ZOpz-v2t2kOAbbpdlsH_P_XjNtEh2TaC1dIZ1bBHwxw,12941
|
225
226
|
fractal_server/tasks/v2/ssh/deactivate.py,sha256=YNJEcUPNuQ7H3I9EtWn84es2AY9Dnij388w6PQra4wc,10186
|
226
227
|
fractal_server/tasks/v2/ssh/reactivate.py,sha256=brIa3XuoD7g9m9vIB7CSgog6KC9w8e45phLT-vSSXlI,7754
|
227
228
|
fractal_server/tasks/v2/templates/1_create_venv.sh,sha256=PK0jdHKtQpda1zULebBaVPORt4t6V17wa4N1ohcj5ac,548
|
@@ -238,8 +239,8 @@ fractal_server/tasks/v2/utils_templates.py,sha256=C5WLuY3uGG2s53OEL-__H35-fmSlgu
|
|
238
239
|
fractal_server/urls.py,sha256=5o_qq7PzKKbwq12NHSQZDmDitn5RAOeQ4xufu-2v9Zk,448
|
239
240
|
fractal_server/utils.py,sha256=utvmBx8K9I8hRWFquxna2pBaOqe0JifDL_NVPmihEJI,3525
|
240
241
|
fractal_server/zip_tools.py,sha256=GjDgo_sf6V_DDg6wWeBlZu5zypIxycn_l257p_YVKGc,4876
|
241
|
-
fractal_server-2.9.
|
242
|
-
fractal_server-2.9.
|
243
|
-
fractal_server-2.9.
|
244
|
-
fractal_server-2.9.
|
245
|
-
fractal_server-2.9.
|
242
|
+
fractal_server-2.9.0a4.dist-info/LICENSE,sha256=QKAharUuhxL58kSoLizKJeZE3mTCBnX6ucmz8W0lxlk,1576
|
243
|
+
fractal_server-2.9.0a4.dist-info/METADATA,sha256=9-4cLdLtEDXeXgb_z6i_czY2VnfpFxlaHGe54WU5YGY,4585
|
244
|
+
fractal_server-2.9.0a4.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
245
|
+
fractal_server-2.9.0a4.dist-info/entry_points.txt,sha256=8tV2kynvFkjnhbtDnxAqImL6HMVKsopgGfew0DOp5UY,58
|
246
|
+
fractal_server-2.9.0a4.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|