fractal-server 2.15.0a0__py3-none-any.whl → 2.15.0a2__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/api/v2/task_collection_pixi.py +1 -1
- fractal_server/app/routes/api/v2/task_group_lifecycle.py +18 -4
- fractal_server/ssh/_fabric.py +26 -0
- fractal_server/tasks/v2/local/__init__.py +1 -0
- fractal_server/tasks/v2/local/collect.py +9 -12
- fractal_server/tasks/v2/local/collect_pixi.py +53 -41
- fractal_server/tasks/v2/local/deactivate.py +7 -14
- fractal_server/tasks/v2/local/deactivate_pixi.py +8 -16
- fractal_server/tasks/v2/local/reactivate.py +8 -15
- fractal_server/tasks/v2/local/reactivate_pixi.py +166 -0
- fractal_server/tasks/v2/ssh/__init__.py +2 -0
- fractal_server/tasks/v2/ssh/collect.py +7 -13
- fractal_server/tasks/v2/ssh/collect_pixi.py +44 -34
- fractal_server/tasks/v2/ssh/deactivate.py +7 -14
- fractal_server/tasks/v2/ssh/deactivate_pixi.py +128 -0
- fractal_server/tasks/v2/ssh/reactivate.py +7 -14
- fractal_server/tasks/v2/ssh/reactivate_pixi.py +108 -0
- fractal_server/tasks/v2/templates/pixi_1_extract.sh +40 -0
- fractal_server/tasks/v2/templates/pixi_2_install.sh +48 -0
- fractal_server/tasks/v2/templates/pixi_3_post_install.sh +80 -0
- fractal_server/tasks/v2/utils_background.py +35 -28
- fractal_server/tasks/v2/utils_pixi.py +2 -0
- {fractal_server-2.15.0a0.dist-info → fractal_server-2.15.0a2.dist-info}/METADATA +1 -1
- {fractal_server-2.15.0a0.dist-info → fractal_server-2.15.0a2.dist-info}/RECORD +28 -23
- fractal_server/tasks/v2/templates/pixi_1_collect.sh +0 -70
- {fractal_server-2.15.0a0.dist-info → fractal_server-2.15.0a2.dist-info}/LICENSE +0 -0
- {fractal_server-2.15.0a0.dist-info → fractal_server-2.15.0a2.dist-info}/WHEEL +0 -0
- {fractal_server-2.15.0a0.dist-info → fractal_server-2.15.0a2.dist-info}/entry_points.txt +0 -0
fractal_server/__init__.py
CHANGED
@@ -1 +1 @@
|
|
1
|
-
__VERSION__ = "2.15.
|
1
|
+
__VERSION__ = "2.15.0a2"
|
@@ -107,7 +107,7 @@ async def collect_task_pixi(
|
|
107
107
|
raise HTTPException(
|
108
108
|
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
109
109
|
detail=(
|
110
|
-
f"Pixi version {pixi_version} is not available. Available"
|
110
|
+
f"Pixi version {pixi_version} is not available. Available "
|
111
111
|
f"versions: {list(settings.pixi.versions.keys())}"
|
112
112
|
),
|
113
113
|
)
|
@@ -27,8 +27,11 @@ from fractal_server.syringe import Inject
|
|
27
27
|
from fractal_server.tasks.v2.local import deactivate_local
|
28
28
|
from fractal_server.tasks.v2.local import deactivate_local_pixi
|
29
29
|
from fractal_server.tasks.v2.local import reactivate_local
|
30
|
+
from fractal_server.tasks.v2.local import reactivate_local_pixi
|
30
31
|
from fractal_server.tasks.v2.ssh import deactivate_ssh
|
32
|
+
from fractal_server.tasks.v2.ssh import deactivate_ssh_pixi
|
31
33
|
from fractal_server.tasks.v2.ssh import reactivate_ssh
|
34
|
+
from fractal_server.tasks.v2.ssh import reactivate_ssh_pixi
|
32
35
|
from fractal_server.utils import get_timestamp
|
33
36
|
|
34
37
|
router = APIRouter()
|
@@ -126,9 +129,12 @@ async def deactivate_task_group(
|
|
126
129
|
host=user_settings.ssh_host,
|
127
130
|
key_path=user_settings.ssh_private_key_path,
|
128
131
|
)
|
129
|
-
|
132
|
+
if task_group.origin == TaskGroupV2OriginEnum.PIXI:
|
133
|
+
deactivate_function = deactivate_ssh_pixi
|
134
|
+
else:
|
135
|
+
deactivate_function = deactivate_ssh
|
130
136
|
background_tasks.add_task(
|
131
|
-
|
137
|
+
deactivate_function,
|
132
138
|
task_group_id=task_group.id,
|
133
139
|
task_group_activity_id=task_group_activity.id,
|
134
140
|
ssh_config=ssh_config,
|
@@ -252,8 +258,12 @@ async def reactivate_task_group(
|
|
252
258
|
key_path=user_settings.ssh_private_key_path,
|
253
259
|
)
|
254
260
|
|
261
|
+
if task_group.origin == TaskGroupV2OriginEnum.PIXI:
|
262
|
+
reactivate_function = reactivate_ssh_pixi
|
263
|
+
else:
|
264
|
+
reactivate_function = reactivate_ssh
|
255
265
|
background_tasks.add_task(
|
256
|
-
|
266
|
+
reactivate_function,
|
257
267
|
task_group_id=task_group.id,
|
258
268
|
task_group_activity_id=task_group_activity.id,
|
259
269
|
ssh_config=ssh_config,
|
@@ -261,8 +271,12 @@ async def reactivate_task_group(
|
|
261
271
|
)
|
262
272
|
|
263
273
|
else:
|
274
|
+
if task_group.origin == TaskGroupV2OriginEnum.PIXI:
|
275
|
+
reactivate_function = reactivate_local_pixi
|
276
|
+
else:
|
277
|
+
reactivate_function = reactivate_local
|
264
278
|
background_tasks.add_task(
|
265
|
-
|
279
|
+
reactivate_function,
|
266
280
|
task_group_id=task_group.id,
|
267
281
|
task_group_activity_id=task_group_activity.id,
|
268
282
|
)
|
fractal_server/ssh/_fabric.py
CHANGED
@@ -204,6 +204,32 @@ class FractalSSH:
|
|
204
204
|
self.logger.info(f"END reading remote JSON file {filepath}.")
|
205
205
|
return data
|
206
206
|
|
207
|
+
def read_remote_text_file(self, filepath: str) -> dict[str, Any]:
|
208
|
+
"""
|
209
|
+
Read a remote text file into a string.
|
210
|
+
|
211
|
+
Note from paramiko docs:
|
212
|
+
> The Python 'b' flag is ignored, since SSH treats all files as binary.
|
213
|
+
"""
|
214
|
+
self.logger.info(f"START reading remote text file {filepath}.")
|
215
|
+
with _acquire_lock_with_timeout(
|
216
|
+
lock=self._lock,
|
217
|
+
label="read_remote_text_file",
|
218
|
+
timeout=self.default_lock_timeout,
|
219
|
+
):
|
220
|
+
try:
|
221
|
+
with self._sftp_unsafe().open(filepath, "r") as f:
|
222
|
+
data = f.read().decode()
|
223
|
+
except Exception as e:
|
224
|
+
self.log_and_raise(
|
225
|
+
e=e,
|
226
|
+
message=(
|
227
|
+
f"Error in `read_remote_text_file`, for {filepath=}."
|
228
|
+
),
|
229
|
+
)
|
230
|
+
self.logger.info(f"END reading remote text file {filepath}.")
|
231
|
+
return data
|
232
|
+
|
207
233
|
def check_connection(self) -> None:
|
208
234
|
"""
|
209
235
|
Open the SSH connection and handle exceptions.
|
@@ -1,5 +1,4 @@
|
|
1
1
|
import json
|
2
|
-
import logging
|
3
2
|
import shutil
|
4
3
|
import time
|
5
4
|
from pathlib import Path
|
@@ -8,7 +7,6 @@ from tempfile import TemporaryDirectory
|
|
8
7
|
from ..utils_database import create_db_tasks_and_update_task_group_sync
|
9
8
|
from ._utils import _customize_and_run_template
|
10
9
|
from fractal_server.app.db import get_sync_db
|
11
|
-
from fractal_server.app.models.v2 import TaskGroupActivityV2
|
12
10
|
from fractal_server.app.models.v2 import TaskGroupV2
|
13
11
|
from fractal_server.app.schemas.v2 import FractalUploadedFile
|
14
12
|
from fractal_server.app.schemas.v2 import TaskGroupActivityActionV2
|
@@ -20,6 +18,9 @@ from fractal_server.tasks.utils import get_log_path
|
|
20
18
|
from fractal_server.tasks.v2.local._utils import check_task_files_exist
|
21
19
|
from fractal_server.tasks.v2.utils_background import add_commit_refresh
|
22
20
|
from fractal_server.tasks.v2.utils_background import fail_and_cleanup
|
21
|
+
from fractal_server.tasks.v2.utils_background import (
|
22
|
+
get_activity_and_task_group,
|
23
|
+
)
|
23
24
|
from fractal_server.tasks.v2.utils_background import get_current_log
|
24
25
|
from fractal_server.tasks.v2.utils_background import prepare_tasks_metadata
|
25
26
|
from fractal_server.tasks.v2.utils_package_names import compare_package_names
|
@@ -67,16 +68,12 @@ def collect_local(
|
|
67
68
|
)
|
68
69
|
|
69
70
|
with next(get_sync_db()) as db:
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
"Cannot find database rows with "
|
77
|
-
f"{task_group_id=} and {task_group_activity_id=}:\n"
|
78
|
-
f"{task_group=}\n{activity=}. Exit."
|
79
|
-
)
|
71
|
+
success, task_group, activity = get_activity_and_task_group(
|
72
|
+
task_group_activity_id=task_group_activity_id,
|
73
|
+
task_group_id=task_group_id,
|
74
|
+
db=db,
|
75
|
+
)
|
76
|
+
if not success:
|
80
77
|
return
|
81
78
|
|
82
79
|
# Log some info
|
@@ -1,5 +1,4 @@
|
|
1
1
|
import json
|
2
|
-
import logging
|
3
2
|
import shutil
|
4
3
|
import time
|
5
4
|
from pathlib import Path
|
@@ -9,8 +8,6 @@ from ..utils_database import create_db_tasks_and_update_task_group_sync
|
|
9
8
|
from ..utils_pixi import parse_collect_stdout
|
10
9
|
from ..utils_pixi import SOURCE_DIR_NAME
|
11
10
|
from fractal_server.app.db import get_sync_db
|
12
|
-
from fractal_server.app.models.v2 import TaskGroupActivityV2
|
13
|
-
from fractal_server.app.models.v2 import TaskGroupV2
|
14
11
|
from fractal_server.app.schemas.v2 import FractalUploadedFile
|
15
12
|
from fractal_server.app.schemas.v2 import TaskGroupActivityActionV2
|
16
13
|
from fractal_server.app.schemas.v2 import TaskGroupActivityStatusV2
|
@@ -24,6 +21,9 @@ from fractal_server.tasks.v2.local._utils import _customize_and_run_template
|
|
24
21
|
from fractal_server.tasks.v2.local._utils import check_task_files_exist
|
25
22
|
from fractal_server.tasks.v2.utils_background import add_commit_refresh
|
26
23
|
from fractal_server.tasks.v2.utils_background import fail_and_cleanup
|
24
|
+
from fractal_server.tasks.v2.utils_background import (
|
25
|
+
get_activity_and_task_group,
|
26
|
+
)
|
27
27
|
from fractal_server.tasks.v2.utils_background import get_current_log
|
28
28
|
from fractal_server.tasks.v2.utils_background import prepare_tasks_metadata
|
29
29
|
from fractal_server.tasks.v2.utils_templates import SCRIPTS_SUBFOLDER
|
@@ -48,14 +48,12 @@ def collect_local_pixi(
|
|
48
48
|
)
|
49
49
|
|
50
50
|
with next(get_sync_db()) as db:
|
51
|
-
activity =
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
f"{task_group=}\n{activity=}. Exit."
|
58
|
-
)
|
51
|
+
success, task_group, activity = get_activity_and_task_group(
|
52
|
+
task_group_activity_id=task_group_activity_id,
|
53
|
+
task_group_id=task_group_id,
|
54
|
+
db=db,
|
55
|
+
)
|
56
|
+
if not success:
|
59
57
|
return
|
60
58
|
|
61
59
|
logger.info("START")
|
@@ -75,10 +73,6 @@ def collect_local_pixi(
|
|
75
73
|
)
|
76
74
|
return
|
77
75
|
|
78
|
-
# Set `pixi_bin` and check that it exists
|
79
|
-
pixi_home = settings.pixi.versions[task_group.pixi_version]
|
80
|
-
pixi_bin = Path(pixi_home, "bin/pixi").as_posix()
|
81
|
-
|
82
76
|
try:
|
83
77
|
Path(task_group.path).mkdir(parents=True)
|
84
78
|
logger.info(f"Created {task_group.path}")
|
@@ -91,24 +85,20 @@ def collect_local_pixi(
|
|
91
85
|
task_group.archive_path = archive_path
|
92
86
|
task_group = add_commit_refresh(obj=task_group, db=db)
|
93
87
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
stdout = _customize_and_run_template(
|
110
|
-
template_filename="pixi_1_collect.sh",
|
111
|
-
replacements=replacements,
|
88
|
+
common_args = dict(
|
89
|
+
replacements={
|
90
|
+
(
|
91
|
+
"__PIXI_HOME__",
|
92
|
+
settings.pixi.versions[task_group.pixi_version],
|
93
|
+
),
|
94
|
+
("__PACKAGE_DIR__", task_group.path),
|
95
|
+
("__TAR_GZ_PATH__", archive_path),
|
96
|
+
(
|
97
|
+
"__IMPORT_PACKAGE_NAME__",
|
98
|
+
task_group.pkg_name.replace("-", "_"),
|
99
|
+
),
|
100
|
+
("__SOURCE_DIR_NAME__", SOURCE_DIR_NAME),
|
101
|
+
},
|
112
102
|
script_dir=Path(
|
113
103
|
task_group.path, SCRIPTS_SUBFOLDER
|
114
104
|
).as_posix(),
|
@@ -118,6 +108,32 @@ def collect_local_pixi(
|
|
118
108
|
),
|
119
109
|
logger_name=LOGGER_NAME,
|
120
110
|
)
|
111
|
+
|
112
|
+
activity.status = TaskGroupActivityStatusV2.ONGOING
|
113
|
+
activity.log = get_current_log(log_file_path)
|
114
|
+
activity = add_commit_refresh(obj=activity, db=db)
|
115
|
+
|
116
|
+
# Run script 1
|
117
|
+
_customize_and_run_template(
|
118
|
+
template_filename="pixi_1_extract.sh",
|
119
|
+
**common_args,
|
120
|
+
)
|
121
|
+
activity.log = get_current_log(log_file_path)
|
122
|
+
activity = add_commit_refresh(obj=activity, db=db)
|
123
|
+
|
124
|
+
# Run script 2
|
125
|
+
_customize_and_run_template(
|
126
|
+
template_filename="pixi_2_install.sh",
|
127
|
+
**common_args,
|
128
|
+
)
|
129
|
+
activity.log = get_current_log(log_file_path)
|
130
|
+
activity = add_commit_refresh(obj=activity, db=db)
|
131
|
+
|
132
|
+
# Run script 3
|
133
|
+
stdout = _customize_and_run_template(
|
134
|
+
template_filename="pixi_3_post_install.sh",
|
135
|
+
**common_args,
|
136
|
+
)
|
121
137
|
activity.log = get_current_log(log_file_path)
|
122
138
|
activity = add_commit_refresh(obj=activity, db=db)
|
123
139
|
|
@@ -126,6 +142,9 @@ def collect_local_pixi(
|
|
126
142
|
package_root = parsed_output["package_root"]
|
127
143
|
venv_size = parsed_output["venv_size"]
|
128
144
|
venv_file_number = parsed_output["venv_file_number"]
|
145
|
+
project_python_wrapper = parsed_output[
|
146
|
+
"project_python_wrapper"
|
147
|
+
]
|
129
148
|
|
130
149
|
# Read and validate manifest
|
131
150
|
# NOTE: we are only supporting the manifest path being relative
|
@@ -145,14 +164,7 @@ def collect_local_pixi(
|
|
145
164
|
package_manifest=pkg_manifest,
|
146
165
|
package_version=task_group.version,
|
147
166
|
package_root=Path(package_root),
|
148
|
-
|
149
|
-
pixi_manifest_path=(
|
150
|
-
Path(
|
151
|
-
task_group.path,
|
152
|
-
SOURCE_DIR_NAME,
|
153
|
-
"pyproject.toml",
|
154
|
-
).as_posix()
|
155
|
-
),
|
167
|
+
project_python_wrapper=Path(project_python_wrapper),
|
156
168
|
)
|
157
169
|
check_task_files_exist(task_list=task_list)
|
158
170
|
logger.info("_prepare_tasks_metadata - end")
|
@@ -1,4 +1,3 @@
|
|
1
|
-
import logging
|
2
1
|
import shutil
|
3
2
|
import time
|
4
3
|
from pathlib import Path
|
@@ -6,11 +5,10 @@ from tempfile import TemporaryDirectory
|
|
6
5
|
|
7
6
|
from ..utils_background import add_commit_refresh
|
8
7
|
from ..utils_background import fail_and_cleanup
|
8
|
+
from ..utils_background import get_activity_and_task_group
|
9
9
|
from ..utils_templates import get_collection_replacements
|
10
10
|
from ._utils import _customize_and_run_template
|
11
11
|
from fractal_server.app.db import get_sync_db
|
12
|
-
from fractal_server.app.models.v2 import TaskGroupActivityV2
|
13
|
-
from fractal_server.app.models.v2 import TaskGroupV2
|
14
12
|
from fractal_server.app.schemas.v2 import TaskGroupActivityActionV2
|
15
13
|
from fractal_server.app.schemas.v2 import TaskGroupV2OriginEnum
|
16
14
|
from fractal_server.app.schemas.v2.task_group import TaskGroupActivityStatusV2
|
@@ -49,17 +47,12 @@ def deactivate_local(
|
|
49
47
|
)
|
50
48
|
|
51
49
|
with next(get_sync_db()) as db:
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
logging.error(
|
59
|
-
"Cannot find database rows with "
|
60
|
-
f"{task_group_id=} and {task_group_activity_id=}:\n"
|
61
|
-
f"{task_group=}\n{activity=}. Exit."
|
62
|
-
)
|
50
|
+
success, task_group, activity = get_activity_and_task_group(
|
51
|
+
task_group_activity_id=task_group_activity_id,
|
52
|
+
task_group_id=task_group_id,
|
53
|
+
db=db,
|
54
|
+
)
|
55
|
+
if not success:
|
63
56
|
return
|
64
57
|
|
65
58
|
# Log some info
|
@@ -1,14 +1,12 @@
|
|
1
|
-
import logging
|
2
1
|
import shutil
|
3
2
|
from pathlib import Path
|
4
3
|
from tempfile import TemporaryDirectory
|
5
4
|
|
6
5
|
from ..utils_background import add_commit_refresh
|
7
6
|
from ..utils_background import fail_and_cleanup
|
7
|
+
from ..utils_background import get_activity_and_task_group
|
8
8
|
from ..utils_pixi import SOURCE_DIR_NAME
|
9
9
|
from fractal_server.app.db import get_sync_db
|
10
|
-
from fractal_server.app.models.v2 import TaskGroupActivityV2
|
11
|
-
from fractal_server.app.models.v2 import TaskGroupV2
|
12
10
|
from fractal_server.app.schemas.v2.task_group import TaskGroupActivityStatusV2
|
13
11
|
from fractal_server.logger import reset_logger_handlers
|
14
12
|
from fractal_server.logger import set_logger
|
@@ -23,7 +21,7 @@ def deactivate_local_pixi(
|
|
23
21
|
task_group_id: int,
|
24
22
|
) -> None:
|
25
23
|
"""
|
26
|
-
Deactivate a task group venv.
|
24
|
+
Deactivate a pixi task group venv.
|
27
25
|
|
28
26
|
This function is run as a background task, therefore exceptions must be
|
29
27
|
handled.
|
@@ -43,17 +41,12 @@ def deactivate_local_pixi(
|
|
43
41
|
)
|
44
42
|
|
45
43
|
with next(get_sync_db()) as db:
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
logging.error(
|
53
|
-
"Cannot find database rows with "
|
54
|
-
f"{task_group_id=} and {task_group_activity_id=}:\n"
|
55
|
-
f"{task_group=}\n{activity=}. Exit."
|
56
|
-
)
|
44
|
+
success, task_group, activity = get_activity_and_task_group(
|
45
|
+
task_group_activity_id=task_group_activity_id,
|
46
|
+
task_group_id=task_group_id,
|
47
|
+
db=db,
|
48
|
+
)
|
49
|
+
if not success:
|
57
50
|
return
|
58
51
|
|
59
52
|
# Log some info
|
@@ -63,7 +56,6 @@ def deactivate_local_pixi(
|
|
63
56
|
logger.debug(f"task_group.{key}: {value}")
|
64
57
|
|
65
58
|
source_dir = Path(task_group.path, SOURCE_DIR_NAME)
|
66
|
-
# Check that the (local) task_group venv_path does exist
|
67
59
|
if not source_dir.exists():
|
68
60
|
error_msg = f"'{source_dir.as_posix()}' does not exist."
|
69
61
|
logger.error(error_msg)
|
@@ -1,4 +1,3 @@
|
|
1
|
-
import logging
|
2
1
|
import shutil
|
3
2
|
import time
|
4
3
|
from pathlib import Path
|
@@ -6,11 +5,10 @@ from tempfile import TemporaryDirectory
|
|
6
5
|
|
7
6
|
from ..utils_background import add_commit_refresh
|
8
7
|
from ..utils_background import fail_and_cleanup
|
8
|
+
from ..utils_background import get_activity_and_task_group
|
9
9
|
from ..utils_templates import get_collection_replacements
|
10
10
|
from ._utils import _customize_and_run_template
|
11
11
|
from fractal_server.app.db import get_sync_db
|
12
|
-
from fractal_server.app.models.v2 import TaskGroupActivityV2
|
13
|
-
from fractal_server.app.models.v2 import TaskGroupV2
|
14
12
|
from fractal_server.app.schemas.v2 import TaskGroupActivityActionV2
|
15
13
|
from fractal_server.app.schemas.v2.task_group import TaskGroupActivityStatusV2
|
16
14
|
from fractal_server.logger import reset_logger_handlers
|
@@ -50,17 +48,12 @@ def reactivate_local(
|
|
50
48
|
)
|
51
49
|
|
52
50
|
with next(get_sync_db()) as db:
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
logging.error(
|
60
|
-
"Cannot find database rows with "
|
61
|
-
f"{task_group_id=} and {task_group_activity_id=}:\n"
|
62
|
-
f"{task_group=}\n{activity=}. Exit."
|
63
|
-
)
|
51
|
+
success, task_group, activity = get_activity_and_task_group(
|
52
|
+
task_group_activity_id=task_group_activity_id,
|
53
|
+
task_group_id=task_group_id,
|
54
|
+
db=db,
|
55
|
+
)
|
56
|
+
if not success:
|
64
57
|
return
|
65
58
|
|
66
59
|
# Log some info
|
@@ -99,7 +92,7 @@ def reactivate_local(
|
|
99
92
|
replacements.append(
|
100
93
|
("__PIP_FREEZE_FILE__", f"{tmpdir}/pip_freeze.txt")
|
101
94
|
)
|
102
|
-
# Prepare common arguments for `_customize_and_run_template
|
95
|
+
# Prepare common arguments for `_customize_and_run_template`
|
103
96
|
common_args = dict(
|
104
97
|
replacements=replacements,
|
105
98
|
script_dir=(
|
@@ -0,0 +1,166 @@
|
|
1
|
+
import shutil
|
2
|
+
import time
|
3
|
+
from pathlib import Path
|
4
|
+
from tempfile import TemporaryDirectory
|
5
|
+
|
6
|
+
from ..utils_background import add_commit_refresh
|
7
|
+
from ..utils_background import fail_and_cleanup
|
8
|
+
from ..utils_background import get_activity_and_task_group
|
9
|
+
from ..utils_pixi import SOURCE_DIR_NAME
|
10
|
+
from fractal_server.app.db import get_sync_db
|
11
|
+
from fractal_server.app.schemas.v2 import TaskGroupActivityActionV2
|
12
|
+
from fractal_server.app.schemas.v2.task_group import TaskGroupActivityStatusV2
|
13
|
+
from fractal_server.config import get_settings
|
14
|
+
from fractal_server.logger import reset_logger_handlers
|
15
|
+
from fractal_server.logger import set_logger
|
16
|
+
from fractal_server.syringe import Inject
|
17
|
+
from fractal_server.tasks.utils import get_log_path
|
18
|
+
from fractal_server.tasks.v2.local._utils import _customize_and_run_template
|
19
|
+
from fractal_server.tasks.v2.utils_background import get_current_log
|
20
|
+
from fractal_server.tasks.v2.utils_templates import SCRIPTS_SUBFOLDER
|
21
|
+
from fractal_server.utils import get_timestamp
|
22
|
+
|
23
|
+
|
24
|
+
def reactivate_local_pixi(
|
25
|
+
*,
|
26
|
+
task_group_activity_id: int,
|
27
|
+
task_group_id: int,
|
28
|
+
) -> None:
|
29
|
+
"""
|
30
|
+
Reactivate a task group venv.
|
31
|
+
|
32
|
+
This function is run as a background task, therefore exceptions must be
|
33
|
+
handled.
|
34
|
+
|
35
|
+
Arguments:
|
36
|
+
task_group_id:
|
37
|
+
task_group_activity_id:
|
38
|
+
"""
|
39
|
+
|
40
|
+
LOGGER_NAME = f"{__name__}.ID{task_group_activity_id}"
|
41
|
+
|
42
|
+
with TemporaryDirectory() as tmpdir:
|
43
|
+
log_file_path = get_log_path(Path(tmpdir))
|
44
|
+
logger = set_logger(
|
45
|
+
logger_name=LOGGER_NAME,
|
46
|
+
log_file_path=log_file_path,
|
47
|
+
)
|
48
|
+
with next(get_sync_db()) as db:
|
49
|
+
success, task_group, activity = get_activity_and_task_group(
|
50
|
+
task_group_activity_id=task_group_activity_id,
|
51
|
+
task_group_id=task_group_id,
|
52
|
+
db=db,
|
53
|
+
)
|
54
|
+
if not success:
|
55
|
+
return
|
56
|
+
|
57
|
+
# Log some info
|
58
|
+
logger.debug("START")
|
59
|
+
|
60
|
+
for key, value in task_group.model_dump().items():
|
61
|
+
logger.debug(f"task_group.{key}: {value}")
|
62
|
+
|
63
|
+
source_dir = Path(task_group.path, SOURCE_DIR_NAME).as_posix()
|
64
|
+
if Path(source_dir).exists():
|
65
|
+
error_msg = f"{source_dir} already exists."
|
66
|
+
logger.error(error_msg)
|
67
|
+
fail_and_cleanup(
|
68
|
+
task_group=task_group,
|
69
|
+
task_group_activity=activity,
|
70
|
+
logger_name=LOGGER_NAME,
|
71
|
+
log_file_path=log_file_path,
|
72
|
+
exception=FileExistsError(error_msg),
|
73
|
+
db=db,
|
74
|
+
)
|
75
|
+
return
|
76
|
+
|
77
|
+
try:
|
78
|
+
activity.status = TaskGroupActivityStatusV2.ONGOING
|
79
|
+
activity = add_commit_refresh(obj=activity, db=db)
|
80
|
+
|
81
|
+
logger.debug(f"start - writing {source_dir}/pixi.lock")
|
82
|
+
with Path(source_dir, "pixi.lock").open("w") as f:
|
83
|
+
f.write(task_group.env_info)
|
84
|
+
logger.debug(f"end - writing {source_dir}/pixi.lock")
|
85
|
+
|
86
|
+
settings = Inject(get_settings)
|
87
|
+
common_args = dict(
|
88
|
+
replacements={
|
89
|
+
(
|
90
|
+
"__PIXI_HOME__",
|
91
|
+
settings.pixi.versions[task_group.pixi_version],
|
92
|
+
),
|
93
|
+
("__PACKAGE_DIR__", task_group.path),
|
94
|
+
("__TAR_GZ_PATH__", task_group.archive_path),
|
95
|
+
(
|
96
|
+
"__IMPORT_PACKAGE_NAME__",
|
97
|
+
task_group.pkg_name.replace("-", "_"),
|
98
|
+
),
|
99
|
+
("__SOURCE_DIR_NAME__", SOURCE_DIR_NAME),
|
100
|
+
("__FROZEN_OPTION__", "true"),
|
101
|
+
},
|
102
|
+
script_dir=Path(
|
103
|
+
task_group.path, SCRIPTS_SUBFOLDER
|
104
|
+
).as_posix(),
|
105
|
+
prefix=(
|
106
|
+
f"{int(time.time())}_"
|
107
|
+
f"{TaskGroupActivityActionV2.REACTIVATE}"
|
108
|
+
),
|
109
|
+
logger_name=LOGGER_NAME,
|
110
|
+
)
|
111
|
+
|
112
|
+
# Run script 1
|
113
|
+
_customize_and_run_template(
|
114
|
+
template_filename="pixi_1_extract.sh",
|
115
|
+
**common_args,
|
116
|
+
)
|
117
|
+
activity.log = get_current_log(log_file_path)
|
118
|
+
activity = add_commit_refresh(obj=activity, db=db)
|
119
|
+
|
120
|
+
# Run script 2
|
121
|
+
_customize_and_run_template(
|
122
|
+
template_filename="pixi_2_install.sh",
|
123
|
+
**common_args,
|
124
|
+
)
|
125
|
+
activity.log = get_current_log(log_file_path)
|
126
|
+
activity = add_commit_refresh(obj=activity, db=db)
|
127
|
+
|
128
|
+
# Run script 3
|
129
|
+
_customize_and_run_template(
|
130
|
+
template_filename="pixi_3_post_install.sh",
|
131
|
+
**common_args,
|
132
|
+
)
|
133
|
+
activity.log = get_current_log(log_file_path)
|
134
|
+
activity = add_commit_refresh(obj=activity, db=db)
|
135
|
+
|
136
|
+
activity.log = get_current_log(log_file_path)
|
137
|
+
activity.status = TaskGroupActivityStatusV2.OK
|
138
|
+
activity.timestamp_ended = get_timestamp()
|
139
|
+
activity = add_commit_refresh(obj=activity, db=db)
|
140
|
+
task_group.active = True
|
141
|
+
task_group = add_commit_refresh(obj=task_group, db=db)
|
142
|
+
logger.debug("END")
|
143
|
+
|
144
|
+
reset_logger_handlers(logger)
|
145
|
+
|
146
|
+
except Exception as reactivate_e:
|
147
|
+
# Delete corrupted source_dir
|
148
|
+
try:
|
149
|
+
logger.info(f"Now delete folder {source_dir}")
|
150
|
+
shutil.rmtree(source_dir)
|
151
|
+
logger.info(f"Deleted folder {source_dir}")
|
152
|
+
except Exception as rm_e:
|
153
|
+
logger.error(
|
154
|
+
"Removing folder failed.\n"
|
155
|
+
f"Original error:\n{str(rm_e)}"
|
156
|
+
)
|
157
|
+
|
158
|
+
fail_and_cleanup(
|
159
|
+
task_group=task_group,
|
160
|
+
task_group_activity=activity,
|
161
|
+
logger_name=LOGGER_NAME,
|
162
|
+
log_file_path=log_file_path,
|
163
|
+
exception=reactivate_e,
|
164
|
+
db=db,
|
165
|
+
)
|
166
|
+
return
|
@@ -1,4 +1,6 @@
|
|
1
1
|
from .collect import collect_ssh # noqa
|
2
2
|
from .collect_pixi import collect_ssh_pixi # noqa
|
3
3
|
from .deactivate import deactivate_ssh # noqa
|
4
|
+
from .deactivate_pixi import deactivate_ssh_pixi # noqa
|
4
5
|
from .reactivate import reactivate_ssh # noqa
|
6
|
+
from .reactivate_pixi import reactivate_ssh_pixi # noqa
|
@@ -1,15 +1,13 @@
|
|
1
|
-
import logging
|
2
1
|
import time
|
3
2
|
from pathlib import Path
|
4
3
|
from tempfile import TemporaryDirectory
|
5
4
|
|
6
5
|
from ....ssh._fabric import SingleUseFractalSSH
|
7
6
|
from ..utils_background import fail_and_cleanup
|
7
|
+
from ..utils_background import get_activity_and_task_group
|
8
8
|
from ..utils_background import prepare_tasks_metadata
|
9
9
|
from ..utils_database import create_db_tasks_and_update_task_group_sync
|
10
10
|
from fractal_server.app.db import get_sync_db
|
11
|
-
from fractal_server.app.models.v2 import TaskGroupActivityV2
|
12
|
-
from fractal_server.app.models.v2 import TaskGroupV2
|
13
11
|
from fractal_server.app.schemas.v2 import FractalUploadedFile
|
14
12
|
from fractal_server.app.schemas.v2 import TaskGroupActivityActionV2
|
15
13
|
from fractal_server.app.schemas.v2 import TaskGroupActivityStatusV2
|
@@ -76,16 +74,12 @@ def collect_ssh(
|
|
76
74
|
) as fractal_ssh:
|
77
75
|
|
78
76
|
with next(get_sync_db()) as db:
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
"Cannot find database rows with "
|
86
|
-
f"{task_group_id=} and {task_group_activity_id=}:\n"
|
87
|
-
f"{task_group=}\n{activity=}. Exit."
|
88
|
-
)
|
77
|
+
success, task_group, activity = get_activity_and_task_group(
|
78
|
+
task_group_activity_id=task_group_activity_id,
|
79
|
+
task_group_id=task_group_id,
|
80
|
+
db=db,
|
81
|
+
)
|
82
|
+
if not success:
|
89
83
|
return
|
90
84
|
|
91
85
|
# Log some info
|