pybiolib 0.2.951__py3-none-any.whl → 1.2.1890__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.
- biolib/__init__.py +357 -11
- biolib/_data_record/data_record.py +380 -0
- biolib/_index/__init__.py +0 -0
- biolib/_index/index.py +55 -0
- biolib/_index/query_result.py +103 -0
- biolib/_internal/__init__.py +0 -0
- biolib/_internal/add_copilot_prompts.py +58 -0
- biolib/_internal/add_gui_files.py +81 -0
- biolib/_internal/data_record/__init__.py +1 -0
- biolib/_internal/data_record/data_record.py +85 -0
- biolib/_internal/data_record/push_data.py +116 -0
- biolib/_internal/data_record/remote_storage_endpoint.py +43 -0
- biolib/_internal/errors.py +5 -0
- biolib/_internal/file_utils.py +125 -0
- biolib/_internal/fuse_mount/__init__.py +1 -0
- biolib/_internal/fuse_mount/experiment_fuse_mount.py +209 -0
- biolib/_internal/http_client.py +159 -0
- biolib/_internal/lfs/__init__.py +1 -0
- biolib/_internal/lfs/cache.py +51 -0
- biolib/_internal/libs/__init__.py +1 -0
- biolib/_internal/libs/fusepy/__init__.py +1257 -0
- biolib/_internal/push_application.py +488 -0
- biolib/_internal/runtime.py +22 -0
- biolib/_internal/string_utils.py +13 -0
- biolib/_internal/templates/__init__.py +1 -0
- biolib/_internal/templates/copilot_template/.github/instructions/general-app-knowledge.instructions.md +10 -0
- biolib/_internal/templates/copilot_template/.github/instructions/style-general.instructions.md +20 -0
- biolib/_internal/templates/copilot_template/.github/instructions/style-python.instructions.md +16 -0
- biolib/_internal/templates/copilot_template/.github/instructions/style-react-ts.instructions.md +47 -0
- biolib/_internal/templates/copilot_template/.github/prompts/biolib_app_inputs.prompt.md +11 -0
- biolib/_internal/templates/copilot_template/.github/prompts/biolib_onboard_repo.prompt.md +19 -0
- biolib/_internal/templates/copilot_template/.github/prompts/biolib_run_apps.prompt.md +12 -0
- biolib/_internal/templates/dashboard_template/.biolib/config.yml +5 -0
- biolib/_internal/templates/github_workflow_template/.github/workflows/biolib.yml +21 -0
- biolib/_internal/templates/gitignore_template/.gitignore +10 -0
- biolib/_internal/templates/gui_template/.yarnrc.yml +1 -0
- biolib/_internal/templates/gui_template/App.tsx +53 -0
- biolib/_internal/templates/gui_template/Dockerfile +27 -0
- biolib/_internal/templates/gui_template/biolib-sdk.ts +82 -0
- biolib/_internal/templates/gui_template/dev-data/output.json +7 -0
- biolib/_internal/templates/gui_template/index.css +5 -0
- biolib/_internal/templates/gui_template/index.html +13 -0
- biolib/_internal/templates/gui_template/index.tsx +10 -0
- biolib/_internal/templates/gui_template/package.json +27 -0
- biolib/_internal/templates/gui_template/tsconfig.json +24 -0
- biolib/_internal/templates/gui_template/vite-plugin-dev-data.ts +50 -0
- biolib/_internal/templates/gui_template/vite.config.mts +10 -0
- biolib/_internal/templates/init_template/.biolib/config.yml +19 -0
- biolib/_internal/templates/init_template/Dockerfile +14 -0
- biolib/_internal/templates/init_template/requirements.txt +1 -0
- biolib/_internal/templates/init_template/run.py +12 -0
- biolib/_internal/templates/init_template/run.sh +4 -0
- biolib/_internal/templates/templates.py +25 -0
- biolib/_internal/tree_utils.py +106 -0
- biolib/_internal/utils/__init__.py +65 -0
- biolib/_internal/utils/auth.py +46 -0
- biolib/_internal/utils/job_url.py +33 -0
- biolib/_internal/utils/multinode.py +263 -0
- biolib/_runtime/runtime.py +157 -0
- biolib/_session/session.py +44 -0
- biolib/_shared/__init__.py +0 -0
- biolib/_shared/types/__init__.py +74 -0
- biolib/_shared/types/account.py +12 -0
- biolib/_shared/types/account_member.py +8 -0
- biolib/_shared/types/app.py +9 -0
- biolib/_shared/types/data_record.py +40 -0
- biolib/_shared/types/experiment.py +32 -0
- biolib/_shared/types/file_node.py +17 -0
- biolib/_shared/types/push.py +6 -0
- biolib/_shared/types/resource.py +37 -0
- biolib/_shared/types/resource_deploy_key.py +11 -0
- biolib/_shared/types/resource_permission.py +14 -0
- biolib/_shared/types/resource_version.py +19 -0
- biolib/_shared/types/result.py +14 -0
- biolib/_shared/types/typing.py +10 -0
- biolib/_shared/types/user.py +19 -0
- biolib/_shared/utils/__init__.py +7 -0
- biolib/_shared/utils/resource_uri.py +75 -0
- biolib/api/__init__.py +6 -0
- biolib/api/client.py +168 -0
- biolib/app/app.py +252 -49
- biolib/app/search_apps.py +45 -0
- biolib/biolib_api_client/api_client.py +126 -31
- biolib/biolib_api_client/app_types.py +24 -4
- biolib/biolib_api_client/auth.py +31 -8
- biolib/biolib_api_client/biolib_app_api.py +147 -52
- biolib/biolib_api_client/biolib_job_api.py +161 -141
- biolib/biolib_api_client/job_types.py +21 -5
- biolib/biolib_api_client/lfs_types.py +7 -23
- biolib/biolib_api_client/user_state.py +56 -0
- biolib/biolib_binary_format/__init__.py +1 -4
- biolib/biolib_binary_format/file_in_container.py +105 -0
- biolib/biolib_binary_format/module_input.py +24 -7
- biolib/biolib_binary_format/module_output_v2.py +149 -0
- biolib/biolib_binary_format/remote_endpoints.py +34 -0
- biolib/biolib_binary_format/remote_stream_seeker.py +59 -0
- biolib/biolib_binary_format/saved_job.py +3 -2
- biolib/biolib_binary_format/{attestation_document.py → stdout_and_stderr.py} +8 -8
- biolib/biolib_binary_format/system_status_update.py +3 -2
- biolib/biolib_binary_format/utils.py +175 -0
- biolib/biolib_docker_client/__init__.py +11 -2
- biolib/biolib_errors.py +36 -0
- biolib/biolib_logging.py +27 -10
- biolib/cli/__init__.py +38 -0
- biolib/cli/auth.py +46 -0
- biolib/cli/data_record.py +164 -0
- biolib/cli/index.py +32 -0
- biolib/cli/init.py +421 -0
- biolib/cli/lfs.py +101 -0
- biolib/cli/push.py +50 -0
- biolib/cli/run.py +63 -0
- biolib/cli/runtime.py +14 -0
- biolib/cli/sdk.py +16 -0
- biolib/cli/start.py +56 -0
- biolib/compute_node/cloud_utils/cloud_utils.py +110 -161
- biolib/compute_node/job_worker/cache_state.py +66 -88
- biolib/compute_node/job_worker/cache_types.py +1 -6
- biolib/compute_node/job_worker/docker_image_cache.py +112 -37
- biolib/compute_node/job_worker/executors/__init__.py +0 -3
- biolib/compute_node/job_worker/executors/docker_executor.py +532 -199
- biolib/compute_node/job_worker/executors/docker_types.py +9 -1
- biolib/compute_node/job_worker/executors/types.py +19 -9
- biolib/compute_node/job_worker/job_legacy_input_wait_timeout_thread.py +30 -0
- biolib/compute_node/job_worker/job_max_runtime_timer_thread.py +3 -5
- biolib/compute_node/job_worker/job_storage.py +108 -0
- biolib/compute_node/job_worker/job_worker.py +397 -212
- biolib/compute_node/job_worker/large_file_system.py +87 -38
- biolib/compute_node/job_worker/network_alloc.py +99 -0
- biolib/compute_node/job_worker/network_buffer.py +240 -0
- biolib/compute_node/job_worker/utilization_reporter_thread.py +197 -0
- biolib/compute_node/job_worker/utils.py +9 -24
- biolib/compute_node/remote_host_proxy.py +400 -98
- biolib/compute_node/utils.py +31 -9
- biolib/compute_node/webserver/compute_node_results_proxy.py +189 -0
- biolib/compute_node/webserver/proxy_utils.py +28 -0
- biolib/compute_node/webserver/webserver.py +130 -44
- biolib/compute_node/webserver/webserver_types.py +2 -6
- biolib/compute_node/webserver/webserver_utils.py +77 -12
- biolib/compute_node/webserver/worker_thread.py +183 -42
- biolib/experiments/__init__.py +0 -0
- biolib/experiments/experiment.py +356 -0
- biolib/jobs/__init__.py +1 -0
- biolib/jobs/job.py +741 -0
- biolib/jobs/job_result.py +185 -0
- biolib/jobs/types.py +50 -0
- biolib/py.typed +0 -0
- biolib/runtime/__init__.py +14 -0
- biolib/sdk/__init__.py +91 -0
- biolib/tables.py +34 -0
- biolib/typing_utils.py +2 -7
- biolib/user/__init__.py +1 -0
- biolib/user/sign_in.py +54 -0
- biolib/utils/__init__.py +162 -0
- biolib/utils/cache_state.py +94 -0
- biolib/utils/multipart_uploader.py +194 -0
- biolib/utils/seq_util.py +150 -0
- biolib/utils/zip/remote_zip.py +640 -0
- pybiolib-1.2.1890.dist-info/METADATA +41 -0
- pybiolib-1.2.1890.dist-info/RECORD +177 -0
- {pybiolib-0.2.951.dist-info → pybiolib-1.2.1890.dist-info}/WHEEL +1 -1
- pybiolib-1.2.1890.dist-info/entry_points.txt +2 -0
- README.md +0 -17
- biolib/app/app_result.py +0 -68
- biolib/app/utils.py +0 -62
- biolib/biolib-js/0-biolib.worker.js +0 -1
- biolib/biolib-js/1-biolib.worker.js +0 -1
- biolib/biolib-js/2-biolib.worker.js +0 -1
- biolib/biolib-js/3-biolib.worker.js +0 -1
- biolib/biolib-js/4-biolib.worker.js +0 -1
- biolib/biolib-js/5-biolib.worker.js +0 -1
- biolib/biolib-js/6-biolib.worker.js +0 -1
- biolib/biolib-js/index.html +0 -10
- biolib/biolib-js/main-biolib.js +0 -1
- biolib/biolib_api_client/biolib_account_api.py +0 -21
- biolib/biolib_api_client/biolib_large_file_system_api.py +0 -108
- biolib/biolib_binary_format/aes_encrypted_package.py +0 -42
- biolib/biolib_binary_format/module_output.py +0 -58
- biolib/biolib_binary_format/rsa_encrypted_aes_package.py +0 -57
- biolib/biolib_push.py +0 -114
- biolib/cli.py +0 -203
- biolib/cli_utils.py +0 -273
- biolib/compute_node/cloud_utils/enclave_parent_types.py +0 -7
- biolib/compute_node/enclave/__init__.py +0 -2
- biolib/compute_node/enclave/enclave_remote_hosts.py +0 -53
- biolib/compute_node/enclave/nitro_secure_module_utils.py +0 -64
- biolib/compute_node/job_worker/executors/base_executor.py +0 -18
- biolib/compute_node/job_worker/executors/pyppeteer_executor.py +0 -173
- biolib/compute_node/job_worker/executors/remote/__init__.py +0 -1
- biolib/compute_node/job_worker/executors/remote/nitro_enclave_utils.py +0 -81
- biolib/compute_node/job_worker/executors/remote/remote_executor.py +0 -51
- biolib/lfs.py +0 -196
- biolib/pyppeteer/.circleci/config.yml +0 -100
- biolib/pyppeteer/.coveragerc +0 -3
- biolib/pyppeteer/.gitignore +0 -89
- biolib/pyppeteer/.pre-commit-config.yaml +0 -28
- biolib/pyppeteer/CHANGES.md +0 -253
- biolib/pyppeteer/CONTRIBUTING.md +0 -26
- biolib/pyppeteer/LICENSE +0 -12
- biolib/pyppeteer/README.md +0 -137
- biolib/pyppeteer/docs/Makefile +0 -177
- biolib/pyppeteer/docs/_static/custom.css +0 -28
- biolib/pyppeteer/docs/_templates/layout.html +0 -10
- biolib/pyppeteer/docs/changes.md +0 -1
- biolib/pyppeteer/docs/conf.py +0 -299
- biolib/pyppeteer/docs/index.md +0 -21
- biolib/pyppeteer/docs/make.bat +0 -242
- biolib/pyppeteer/docs/reference.md +0 -211
- biolib/pyppeteer/docs/server.py +0 -60
- biolib/pyppeteer/poetry.lock +0 -1699
- biolib/pyppeteer/pyppeteer/__init__.py +0 -135
- biolib/pyppeteer/pyppeteer/accessibility.py +0 -286
- biolib/pyppeteer/pyppeteer/browser.py +0 -401
- biolib/pyppeteer/pyppeteer/browser_fetcher.py +0 -194
- biolib/pyppeteer/pyppeteer/command.py +0 -22
- biolib/pyppeteer/pyppeteer/connection/__init__.py +0 -242
- biolib/pyppeteer/pyppeteer/connection/cdpsession.py +0 -101
- biolib/pyppeteer/pyppeteer/coverage.py +0 -346
- biolib/pyppeteer/pyppeteer/device_descriptors.py +0 -787
- biolib/pyppeteer/pyppeteer/dialog.py +0 -79
- biolib/pyppeteer/pyppeteer/domworld.py +0 -597
- biolib/pyppeteer/pyppeteer/emulation_manager.py +0 -53
- biolib/pyppeteer/pyppeteer/errors.py +0 -48
- biolib/pyppeteer/pyppeteer/events.py +0 -63
- biolib/pyppeteer/pyppeteer/execution_context.py +0 -156
- biolib/pyppeteer/pyppeteer/frame/__init__.py +0 -299
- biolib/pyppeteer/pyppeteer/frame/frame_manager.py +0 -306
- biolib/pyppeteer/pyppeteer/helpers.py +0 -245
- biolib/pyppeteer/pyppeteer/input.py +0 -371
- biolib/pyppeteer/pyppeteer/jshandle.py +0 -598
- biolib/pyppeteer/pyppeteer/launcher.py +0 -683
- biolib/pyppeteer/pyppeteer/lifecycle_watcher.py +0 -169
- biolib/pyppeteer/pyppeteer/models/__init__.py +0 -103
- biolib/pyppeteer/pyppeteer/models/_protocol.py +0 -12460
- biolib/pyppeteer/pyppeteer/multimap.py +0 -82
- biolib/pyppeteer/pyppeteer/network_manager.py +0 -678
- biolib/pyppeteer/pyppeteer/options.py +0 -8
- biolib/pyppeteer/pyppeteer/page.py +0 -1728
- biolib/pyppeteer/pyppeteer/pipe_transport.py +0 -59
- biolib/pyppeteer/pyppeteer/target.py +0 -147
- biolib/pyppeteer/pyppeteer/task_queue.py +0 -24
- biolib/pyppeteer/pyppeteer/timeout_settings.py +0 -36
- biolib/pyppeteer/pyppeteer/tracing.py +0 -93
- biolib/pyppeteer/pyppeteer/us_keyboard_layout.py +0 -305
- biolib/pyppeteer/pyppeteer/util.py +0 -18
- biolib/pyppeteer/pyppeteer/websocket_transport.py +0 -47
- biolib/pyppeteer/pyppeteer/worker.py +0 -101
- biolib/pyppeteer/pyproject.toml +0 -97
- biolib/pyppeteer/spell.txt +0 -137
- biolib/pyppeteer/tox.ini +0 -72
- biolib/pyppeteer/utils/generate_protocol_types.py +0 -603
- biolib/start_cli.py +0 -7
- biolib/utils.py +0 -47
- biolib/validators/validate_app_version.py +0 -183
- biolib/validators/validate_argument.py +0 -134
- biolib/validators/validate_module.py +0 -323
- biolib/validators/validate_zip_file.py +0 -40
- biolib/validators/validator_utils.py +0 -103
- pybiolib-0.2.951.dist-info/LICENSE +0 -21
- pybiolib-0.2.951.dist-info/METADATA +0 -61
- pybiolib-0.2.951.dist-info/RECORD +0 -153
- pybiolib-0.2.951.dist-info/entry_points.txt +0 -3
- /LICENSE → /pybiolib-1.2.1890.dist-info/licenses/LICENSE +0 -0
|
@@ -4,51 +4,90 @@ import subprocess
|
|
|
4
4
|
from docker.errors import ImageNotFound, APIError # type: ignore
|
|
5
5
|
|
|
6
6
|
from biolib import utils
|
|
7
|
+
from biolib.typing_utils import TypedDict
|
|
7
8
|
from biolib.biolib_docker_client import BiolibDockerClient
|
|
8
|
-
from biolib.
|
|
9
|
+
from biolib.biolib_errors import BioLibError
|
|
10
|
+
from biolib.biolib_logging import logger_no_user_data
|
|
9
11
|
from biolib.compute_node.job_worker.cache_state import DockerImageCacheState, DockerCacheStateError
|
|
10
|
-
from biolib.compute_node.job_worker.cache_types import DockerImageInfo, DockerImageCacheStateDict,
|
|
12
|
+
from biolib.compute_node.job_worker.cache_types import DockerImageInfo, DockerImageCacheStateDict, UuidStr
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class DiskUsage(TypedDict):
|
|
16
|
+
image_storage_available_in_bytes: int
|
|
17
|
+
max_image_capacity_in_bytes: int
|
|
18
|
+
used_in_bytes: int
|
|
11
19
|
|
|
12
20
|
|
|
13
21
|
class DockerImageCache:
|
|
14
22
|
def __init__(self):
|
|
15
|
-
|
|
16
|
-
|
|
23
|
+
if not utils.IS_RUNNING_IN_CLOUD:
|
|
24
|
+
raise BioLibError('Using DockerImageCache outside Cloud is not supported')
|
|
25
|
+
|
|
17
26
|
self._docker_client = BiolibDockerClient().get_docker_client()
|
|
18
27
|
self._docker_data_dir = self._docker_client.info()['DockerRootDir']
|
|
19
28
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
# Need to use sudo outside of enclave
|
|
25
|
-
disk_usage_command.insert(0, "sudo")
|
|
26
|
-
|
|
27
|
-
du_output = subprocess.run(
|
|
29
|
+
def _get_current_disk_usage_stats(self) -> DiskUsage:
|
|
30
|
+
disk_usage_command = ['df', '--block-size=1', self._docker_data_dir]
|
|
31
|
+
logger_no_user_data.debug(f'Running {disk_usage_command}...')
|
|
32
|
+
df_output = subprocess.run(
|
|
28
33
|
disk_usage_command,
|
|
29
34
|
capture_output=True,
|
|
30
|
-
check=True
|
|
31
|
-
|
|
32
|
-
|
|
35
|
+
check=True,
|
|
36
|
+
timeout=3,
|
|
37
|
+
).stdout.decode()
|
|
38
|
+
logger_no_user_data.debug(df_output)
|
|
39
|
+
df_output_lines = [s.split() for s in df_output.splitlines()]
|
|
40
|
+
|
|
41
|
+
# Expect the filesystem to be row 1
|
|
42
|
+
disk = df_output_lines[1]
|
|
43
|
+
# Expect column 1 to be total disk size and column 2 to be disk space used
|
|
44
|
+
total_size_in_bytes = int(disk[1])
|
|
45
|
+
used_in_bytes = int(disk[2])
|
|
46
|
+
|
|
47
|
+
# Allow 80% to be used for images
|
|
48
|
+
max_image_capacity_in_bytes = total_size_in_bytes * 80 // 100
|
|
49
|
+
available_for_images_in_bytes = max(0, max_image_capacity_in_bytes - used_in_bytes)
|
|
50
|
+
|
|
51
|
+
disk_usage = DiskUsage(
|
|
52
|
+
image_storage_available_in_bytes=available_for_images_in_bytes,
|
|
53
|
+
max_image_capacity_in_bytes=max_image_capacity_in_bytes,
|
|
54
|
+
used_in_bytes=used_in_bytes,
|
|
55
|
+
)
|
|
56
|
+
logger_no_user_data.debug(f'Disk usage for Docker: {disk_usage}')
|
|
57
|
+
return disk_usage
|
|
33
58
|
|
|
34
59
|
def _clear_space_for_image(self, estimated_image_size_bytes: int, cache_state: DockerImageCacheStateDict):
|
|
35
|
-
|
|
36
|
-
self.
|
|
37
|
-
|
|
38
|
-
|
|
60
|
+
for _ in range(100):
|
|
61
|
+
if not self._has_space_to_pull_image(estimated_image_size_bytes, cache_state):
|
|
62
|
+
self._remove_least_recently_used_image(cache_state)
|
|
63
|
+
else:
|
|
64
|
+
return
|
|
65
|
+
|
|
66
|
+
raise DockerCacheStateError('Failed to free space for Docker image')
|
|
67
|
+
|
|
68
|
+
def get(
|
|
69
|
+
self,
|
|
70
|
+
image_uri: str,
|
|
71
|
+
estimated_image_size_bytes: int,
|
|
72
|
+
job_id: str,
|
|
73
|
+
) -> None:
|
|
39
74
|
try:
|
|
40
75
|
with DockerImageCacheState() as cache_state:
|
|
76
|
+
if image_uri not in cache_state:
|
|
77
|
+
raise ImageNotFound('Image not found in cache')
|
|
78
|
+
|
|
41
79
|
self._docker_client.images.get(image_uri)
|
|
42
80
|
cache_state[image_uri]['last_used_at'] = DockerImageCacheState.get_timestamp_now()
|
|
81
|
+
cache_state[image_uri]['active_jobs'].append(job_id)
|
|
43
82
|
|
|
44
83
|
except ImageNotFound:
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
84
|
+
disk_stats = self._get_current_disk_usage_stats()
|
|
85
|
+
if estimated_image_size_bytes > disk_stats['max_image_capacity_in_bytes']:
|
|
86
|
+
logger_no_user_data.error(
|
|
87
|
+
f'Image {image_uri} with size: {estimated_image_size_bytes} is bigger than the max cache size'
|
|
49
88
|
)
|
|
50
89
|
raise DockerCacheStateError( # pylint: disable=raise-missing-from
|
|
51
|
-
|
|
90
|
+
'Image is bigger than the max cache size'
|
|
52
91
|
)
|
|
53
92
|
|
|
54
93
|
with DockerImageCacheState() as cache_state:
|
|
@@ -59,26 +98,56 @@ class DockerImageCache:
|
|
|
59
98
|
last_used_at=DockerImageCacheState.get_timestamp_now(),
|
|
60
99
|
uri=image_uri,
|
|
61
100
|
state='pulling',
|
|
62
|
-
estimated_image_size_bytes=estimated_image_size_bytes
|
|
101
|
+
estimated_image_size_bytes=estimated_image_size_bytes,
|
|
102
|
+
active_jobs=[job_id]
|
|
63
103
|
)
|
|
64
104
|
|
|
65
|
-
|
|
66
|
-
|
|
105
|
+
logger_no_user_data.debug(f'Image {image_uri} not found in cache. Pulling...')
|
|
106
|
+
try:
|
|
107
|
+
self._docker_client.images.pull(image_uri)
|
|
108
|
+
except Exception as error:
|
|
109
|
+
logger_no_user_data.error(f'Could not pull image due to {error}')
|
|
110
|
+
|
|
111
|
+
# Remove image from cache_state
|
|
112
|
+
with DockerImageCacheState() as cache_state:
|
|
113
|
+
if image_uri in cache_state:
|
|
114
|
+
cache_state.pop(image_uri)
|
|
115
|
+
|
|
116
|
+
raise error
|
|
117
|
+
|
|
67
118
|
with DockerImageCacheState() as cache_state:
|
|
68
119
|
cache_state[image_uri]['state'] = 'ready'
|
|
69
120
|
|
|
121
|
+
@staticmethod
|
|
122
|
+
def detach_job(image_uri: str, job_id: UuidStr) -> None:
|
|
123
|
+
try:
|
|
124
|
+
with DockerImageCacheState() as cache_state:
|
|
125
|
+
if image_uri in cache_state and job_id in cache_state[image_uri]['active_jobs']:
|
|
126
|
+
cache_state[image_uri]['active_jobs'].remove(job_id)
|
|
127
|
+
|
|
128
|
+
except Exception as error: # pylint: disable=broad-except
|
|
129
|
+
logging.error('Could not remove job from image cache')
|
|
130
|
+
logging.error(error)
|
|
131
|
+
|
|
70
132
|
def _remove_least_recently_used_image(self, cache_state: DockerImageCacheStateDict) -> None:
|
|
71
133
|
cached_images = [image for image in cache_state.values() if image['state'] == 'ready']
|
|
72
134
|
images_sorted_by_least_recently_used = sorted(cached_images, key=lambda image: image['last_used_at'])
|
|
73
135
|
|
|
74
136
|
for image in images_sorted_by_least_recently_used:
|
|
75
|
-
|
|
137
|
+
logger_no_user_data.debug(f"Removing image: {image['uri']}")
|
|
138
|
+
|
|
139
|
+
# Only remove images that has no active jobs
|
|
140
|
+
if image['active_jobs']:
|
|
141
|
+
logger_no_user_data.debug(
|
|
142
|
+
f"Skipping removal of image {image['uri']} as it has the active jobs {image['active_jobs']}"
|
|
143
|
+
)
|
|
144
|
+
continue
|
|
145
|
+
|
|
76
146
|
try:
|
|
77
147
|
self._docker_client.api.remove_image(image=image['uri'])
|
|
78
148
|
except APIError as error:
|
|
79
|
-
|
|
80
|
-
f
|
|
81
|
-
logging.ERROR
|
|
149
|
+
logger_no_user_data.error(
|
|
150
|
+
f'Could not remove image due to {error}... Skipping removal of this image.'
|
|
82
151
|
)
|
|
83
152
|
continue # Image is in use or cannot be removed at this time
|
|
84
153
|
|
|
@@ -86,11 +155,17 @@ class DockerImageCache:
|
|
|
86
155
|
break
|
|
87
156
|
|
|
88
157
|
def _has_space_to_pull_image(self, estimated_image_size_bytes: int, cache_state: DockerImageCacheStateDict) -> bool:
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
158
|
+
logger_no_user_data.debug('Calculating cache metrics...')
|
|
159
|
+
size_of_images_being_pulled = sum(
|
|
160
|
+
[image['estimated_image_size_bytes'] for image in cache_state.values() if image['state'] == 'pulling']
|
|
161
|
+
)
|
|
162
|
+
disk_stats = self._get_current_disk_usage_stats()
|
|
163
|
+
cache_space_remaining = disk_stats['image_storage_available_in_bytes'] - size_of_images_being_pulled
|
|
164
|
+
|
|
165
|
+
logger_no_user_data.debug(
|
|
166
|
+
f'Needed current image: {estimated_image_size_bytes}. '
|
|
167
|
+
f'Cache remaining: {cache_space_remaining}. '
|
|
168
|
+
f'Total pulling: {size_of_images_being_pulled}. '
|
|
169
|
+
)
|
|
95
170
|
|
|
96
171
|
return bool(cache_space_remaining > estimated_image_size_bytes)
|
|
@@ -1,5 +1,2 @@
|
|
|
1
|
-
from biolib.compute_node.job_worker.executors.pyppeteer_executor import PyppeteerExecutor
|
|
2
1
|
from biolib.compute_node.job_worker.executors.docker_executor import DockerExecutor
|
|
3
|
-
from biolib.compute_node.job_worker.executors.remote import RemoteExecutor
|
|
4
|
-
|
|
5
2
|
from biolib.compute_node.job_worker.executors.types import *
|