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.
@@ -1 +1 @@
1
- __VERSION__ = "2.9.0a3"
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
@@ -138,7 +138,7 @@ def collect_ssh(
138
138
  script_dir_remote=script_dir_remote,
139
139
  prefix=(
140
140
  f"{int(time.time())}_"
141
- f"{TaskGroupActivityActionV2.COLLECT}_"
141
+ f"{TaskGroupActivityActionV2.COLLECT}"
142
142
  ),
143
143
  fractal_ssh=fractal_ssh,
144
144
  logger_name=LOGGER_NAME,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: fractal-server
3
- Version: 2.9.0a3
3
+ Version: 2.9.0a4
4
4
  Summary: Server component of the Fractal analytics platform
5
5
  Home-page: https://github.com/fractal-analytics-platform/fractal-server
6
6
  License: BSD-3-Clause
@@ -1,4 +1,4 @@
1
- fractal_server/__init__.py,sha256=8LdiYD77VYwRKrVoavHTgYHkexYzgn-F5OpNKKf-WMU,24
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=zkdrk3mSQWfgTJugS8Sc_Q_xCAwfmHUfdRe0DTaYT80,521
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=U8f6-dgtAI9Pr-gWPeDMeYdOkxYSqfsrYcSPDYEqz4I,12942
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.0a3.dist-info/LICENSE,sha256=QKAharUuhxL58kSoLizKJeZE3mTCBnX6ucmz8W0lxlk,1576
242
- fractal_server-2.9.0a3.dist-info/METADATA,sha256=W92NgqXaqh1eO8X_o9XPN8chROYn0ZyszQCjkBo_BIg,4585
243
- fractal_server-2.9.0a3.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
244
- fractal_server-2.9.0a3.dist-info/entry_points.txt,sha256=8tV2kynvFkjnhbtDnxAqImL6HMVKsopgGfew0DOp5UY,58
245
- fractal_server-2.9.0a3.dist-info/RECORD,,
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,,