From 6cf94af61a679d3159886ba6412a87e1ff284780 Mon Sep 17 00:00:00 2001 From: nsosio Date: Tue, 1 Aug 2023 21:06:35 +0200 Subject: [PATCH 1/8] first draft of update-available endpoint --- app/core/utils.py | 46 ++++++++++++++++++++++++++++++++++++++++++++++ app/routes.py | 12 ++++++++++++ app/schemas.py | 6 ++++++ requirements.txt | 1 + 4 files changed, 65 insertions(+) diff --git a/app/core/utils.py b/app/core/utils.py index 2aa0d1c..ae3ebd2 100644 --- a/app/core/utils.py +++ b/app/core/utils.py @@ -1,10 +1,12 @@ import logging +import re import subprocess import xml.etree.ElementTree as ET import docker import requests import torch +from bs4 import BeautifulSoup from app.core import config @@ -197,3 +199,47 @@ def get_gpu_info(): mem_percentage = (used_memory_value / total_memory_value) * 100 return gpu_name, total_memory_value, used_memory_value, mem_percentage + + +def extract_labels_from_html_file(html_content, class_names): + soup = BeautifulSoup(html_content, "html.parser") + labels = soup.select(class_names) + return [label.get_text() for label in labels] + + +def find_maximum_label(labels): + pattern = r"v(\d+)\.(\d+)\.(\d+)" + max_label = None + + for label in labels: + match = re.match(pattern, label) + if match: + version = f"v{match.group(1)}.{match.group(2)}.{match.group(3)}" + if max_label is None or version > max_label: + max_label = version + + return max_label + + +def get_premd_last_tag(owner, repository, package): + response = requests.get( + f"https://github.com/{owner}/{repository}/pkgs/container/{package}" + ) + class_names = ".Label.mr-1.mb-2.text-normal" + try: + labels = extract_labels_from_html_file(response.content, class_names) + if labels: + return find_maximum_label(labels) + except Exception as e: + logger.info(f"Unexpected error: {e}") + + +def get_local_docker_image_tags(owner, repository): + image_name = f"ghcr.io/{owner}/{repository}" + try: + client = get_docker_client() + image = client.images.get(image_name) + return image.tags + except Exception as e: + logger.info(f"Unexpected error: {e}") + return [] diff --git a/app/routes.py b/app/routes.py index eefbb9e..921e8a8 100644 --- a/app/routes.py +++ b/app/routes.py @@ -43,6 +43,18 @@ async def health(): return schemas.HealthResponse(status=True) +@router.get("/update-available/", response_model=schemas.UpdateAvailableResponse) +async def update_available(): + owner = "premAI-io" + remote_image = f"ghcr.io/premai-io/premd:{utils.get_premd_last_tag(owner, 'prem-daemon', 'premd')}" + local_tags = utils.get_local_docker_image_tags(owner.lower(), "premd") + return { + "remote_image": remote_image, + "local_images": local_tags, + "update": remote_image not in local_tags, + } + + @router.get("/interfaces/", response_model=list[schemas.InterfaceResponse]) async def interfaces(): return utils.get_interfaces() diff --git a/app/schemas.py b/app/schemas.py index dfae1de..e962e5f 100644 --- a/app/schemas.py +++ b/app/schemas.py @@ -17,6 +17,12 @@ class RunServiceInput(BaseModel): id: str +class UpdateAvailableResponse(BaseModel): + remote_image: str + local_images: list[str] + update: bool + + class ServiceInput(BaseModel): id: str name: str diff --git a/requirements.txt b/requirements.txt index ccaa674..2787568 100644 --- a/requirements.txt +++ b/requirements.txt @@ -15,3 +15,4 @@ torchvision==0.15.2 torchaudio==2.0.2 sentry-sdk==1.26.0 psutil==5.9.5 +beautifulsoup4==4.12.2 From e56ac7ca3c8f9b51fea803d843f57456b03164d2 Mon Sep 17 00:00:00 2001 From: nsosio Date: Wed, 2 Aug 2023 20:16:25 +0200 Subject: [PATCH 2/8] restart daemon with new image --- .env.example | 7 +++- app/core/config.py | 2 + app/core/events.py | 16 ++++++++ app/core/utils.py | 100 +++++++++++++++++++++++++++++++++++++++++++++ app/routes.py | 9 +++- 5 files changed, 132 insertions(+), 2 deletions(-) diff --git a/.env.example b/.env.example index b769901..efb6ac7 100644 --- a/.env.example +++ b/.env.example @@ -4,6 +4,11 @@ # For Dev Registry: https://raw.githubusercontent.com/premAI-io/prem-registry/dev/manifests.json PREM_REGISTRY_URL=https://raw.githubusercontent.com/premAI-io/prem-registry/main/manifests.json +# Prem Daemon +# ------------------------------------------------------------------------------------------ +DEFAULT_PORT='8000' +PREMD_IMAGE=ghcr.io/premai-io/premd + # Sentry # ------------------------------------------------------------------------------------------ -SENTRY_DSN=https://75592545ad6b472e9ad7c8ff51740b73@o1068608.ingest.sentry.io/4505244431941632 +#SENTRY_DSN=https://75592545ad6b472e9ad7c8ff51740b73@o1068608.ingest.sentry.io/4505244431941632 diff --git a/app/core/config.py b/app/core/config.py index 9086ab7..a0f152f 100644 --- a/app/core/config.py +++ b/app/core/config.py @@ -11,6 +11,8 @@ DEBUG: bool = os.getenv("DEBUG", False) SECRET_KEY: Secret = Secret(os.getenv("SECRET_KEY", "")) PROJECT_NAME: str = os.getenv("PROJECT_NAME", "Prem Daemon") +PREMD_IMAGE: str = os.getenv("PREMD_IMAGE", "ghcr.io/premai-io/premd") +DEFAULT_PORT: int = int(os.getenv("DEFAULT_PORT", "8000")) # APIs # ------------------------------------------------------------------------------ diff --git a/app/core/events.py b/app/core/events.py index 989d114..bc2ef1c 100644 --- a/app/core/events.py +++ b/app/core/events.py @@ -9,6 +9,22 @@ def create_start_app_handler(app: FastAPI): def start_app() -> None: + container_name, new_container_name = utils.generate_container_name("premd") + client = utils.get_docker_client() + container = client.containers.get(container_name) + host_port = container.ports.get(f"{utils.DEFAULT_PORT}/tcp", [None])[0][ + "HostPort" + ] + if host_port != f"{utils.DEFAULT_PORT}": + utils.check_host_port_availability(utils.DEFAULT_PORT) + _ = utils.create_new_container( + utils.PREMD_IMAGE, + "latest", + new_container_name, + container_name, + utils.DEFAULT_PORT, + ) + utils.update_and_remove_old_container(container_name) for registry in config.PREM_REGISTRY_URL.strip().split(): utils.add_services_from_registry(registry) diff --git a/app/core/utils.py b/app/core/utils.py index ae3ebd2..d97898d 100644 --- a/app/core/utils.py +++ b/app/core/utils.py @@ -1,6 +1,7 @@ import logging import re import subprocess +import time import xml.etree.ElementTree as ET import docker @@ -12,6 +13,8 @@ logger = logging.getLogger(__name__) +PREMD_IMAGE = config.PREMD_IMAGE +DEFAULT_PORT = config.DEFAULT_PORT SERVICES = [] REGISTRIES = config.PREM_REGISTRY_URL.strip().split() INTERFACES = [ @@ -243,3 +246,100 @@ def get_local_docker_image_tags(owner, repository): except Exception as e: logger.info(f"Unexpected error: {e}") return [] + + +def generate_container_name(prefix): + client = get_docker_client() + + containers = client.containers.list( + all=True, filters={"name": f"^{prefix}", "status": "running"} + ) + latest_suffix = -1 + for container in containers: + match = re.match(rf"{prefix}_(\d+)", container.name) + if match and container.status == "running": + suffix = int(match.group(1)) + if suffix > latest_suffix: + latest_suffix = suffix + + if latest_suffix == -1: + return prefix, f"{prefix}_1" + else: + return f"{prefix}_{latest_suffix}", f"{prefix}_{latest_suffix+1}" + + +def create_new_container( + image_name, image_tag, new_container_name, old_container_name, host_port +): + client = get_docker_client() + old_container = client.containers.get(old_container_name) + + if is_gpu_available(): + device_requests = [ + docker.types.DeviceRequest(device_ids=["all"], capabilities=[["gpu"]]) + ] + else: + device_requests = [] + + volumes = {} + for mount in old_container.attrs["Mounts"]: + source = mount["Source"] + target = mount["Destination"] + mode = mount["Mode"] + volumes[source] = {"bind": target, "mode": mode} + + current_ports = old_container.attrs["HostConfig"]["PortBindings"] + current_port_key = list(current_ports.keys())[0] + + logger.info( + f"Starting new container {new_container_name} with image {image_name}:{image_tag} at port {host_port}" + ) + new_container = client.containers.run( + image=f"{image_name}:{image_tag}", + name=new_container_name, + ports={f"{current_port_key}/tcp": [{"HostIp": "", "HostPort": host_port}]}, + volumes=volumes, + environment=old_container.attrs["Config"]["Env"], + device_requests=device_requests, + network_mode=old_container.attrs["HostConfig"]["NetworkMode"], + detach=True, + ) + return new_container + + +def update_and_remove_old_container(old_container_name): + client = get_docker_client() + logger.info(f"Stopping {old_container_name}") + old_container = client.containers.get(old_container_name) + old_container.stop() + old_container.remove(force=True) + client.system.prune() + + +def update_container(host_port): + container_name, new_container_name = generate_container_name("premd") + create_new_container( + PREMD_IMAGE, "latest", new_container_name, container_name, host_port + ) + update_and_remove_old_container(container_name) + + +def check_host_port_availability(host_port, timeout=30): + start_time = time.time() + client = docker.from_env() + + while True: + if time.time() - start_time > timeout: + return False + + containers = client.containers.list() + port_used = any( + f"{host_port}/tcp" in container.ports + for container in containers + if container.status == "running" + ) + + if not port_used: + return True + + time.sleep(1) diff --git a/app/routes.py b/app/routes.py index 921e8a8..8bf3791 100644 --- a/app/routes.py +++ b/app/routes.py @@ -46,7 +46,9 @@ async def health(): @router.get("/update-available/", response_model=schemas.UpdateAvailableResponse) async def update_available(): owner = "premAI-io" - remote_image = f"ghcr.io/premai-io/premd:{utils.get_premd_last_tag(owner, 'prem-daemon', 'premd')}" + remote_image = ( + f"{utils.PREMD_IMAGE}:{utils.get_premd_last_tag(owner, 'prem-daemon', 'premd')}" + ) local_tags = utils.get_local_docker_image_tags(owner.lower(), "premd") return { "remote_image": remote_image, @@ -55,6 +57,11 @@ async def update_available(): } +@router.get("/update-daemon/") +async def trigger_update(): + utils.update_container(utils.DEFAULT_PORT + 1) + + @router.get("/interfaces/", response_model=list[schemas.InterfaceResponse]) async def interfaces(): return utils.get_interfaces() From 3f2eca8aea8be96a43b0da3d528047a1aca95936 Mon Sep 17 00:00:00 2001 From: nsosio Date: Wed, 2 Aug 2023 20:21:55 +0200 Subject: [PATCH 3/8] updated endpoints --- app/core/utils.py | 2 +- app/routes.py | 56 ++++++++++++++++++++++++++++++++++++----------- 2 files changed, 44 insertions(+), 14 deletions(-) diff --git a/app/core/utils.py b/app/core/utils.py index d97898d..ececdbe 100644 --- a/app/core/utils.py +++ b/app/core/utils.py @@ -326,7 +326,7 @@ def update_container(host_port): def check_host_port_availability(host_port, timeout=30): start_time = time.time() - client = docker.from_env() + client = get_docker_client() while True: if time.time() - start_time > timeout: diff --git a/app/routes.py b/app/routes.py index 8bf3791..89d9283 100644 --- a/app/routes.py +++ b/app/routes.py @@ -43,23 +43,53 @@ async def health(): return schemas.HealthResponse(status=True) -@router.get("/update-available/", response_model=schemas.UpdateAvailableResponse) +@router.get( + "/update-available/", + responses={ + 400: { + "model": schemas.ErrorResponse, + "description": "Failed to check update available.", + } + }, + response_model=schemas.UpdateAvailableResponse, +) async def update_available(): - owner = "premAI-io" - remote_image = ( - f"{utils.PREMD_IMAGE}:{utils.get_premd_last_tag(owner, 'prem-daemon', 'premd')}" - ) - local_tags = utils.get_local_docker_image_tags(owner.lower(), "premd") - return { - "remote_image": remote_image, - "local_images": local_tags, - "update": remote_image not in local_tags, - } + try: + owner = "premAI-io" + remote_image = f"{utils.PREMD_IMAGE}:{utils.get_premd_last_tag(owner, 'prem-daemon', 'premd')}" + local_tags = utils.get_local_docker_image_tags(owner.lower(), "premd") + return { + "remote_image": remote_image, + "local_images": local_tags, + "update": remote_image not in local_tags, + } + except Exception as error: + logger.error(error) + raise HTTPException( + status_code=400, + detail={"message": f"Failed to check update available {error}."}, + ) from error -@router.get("/update-daemon/") +@router.get( + "/update-daemon/", + responses={ + 400: { + "model": schemas.ErrorResponse, + "description": "Failed to update.", + } + }, + response_model=schemas.UpdateAvailableResponse, +) async def trigger_update(): - utils.update_container(utils.DEFAULT_PORT + 1) + try: + utils.update_container(utils.DEFAULT_PORT + 1) + except Exception as error: + logger.error(error) + raise HTTPException( + status_code=400, + detail={"message": f"Failed to update {error}."}, + ) from error @router.get("/interfaces/", response_model=list[schemas.InterfaceResponse]) From b72b68fe42e79caa08bee749fed3cdde81c2e291 Mon Sep 17 00:00:00 2001 From: nsosio Date: Thu, 3 Aug 2023 09:17:44 +0200 Subject: [PATCH 4/8] bugfix in start up event and making changes based on feedback --- app/core/events.py | 29 +++++++++++++++-------------- app/core/utils.py | 31 ++++++++++--------------------- 2 files changed, 25 insertions(+), 35 deletions(-) diff --git a/app/core/events.py b/app/core/events.py index bc2ef1c..f53ba15 100644 --- a/app/core/events.py +++ b/app/core/events.py @@ -11,20 +11,21 @@ def create_start_app_handler(app: FastAPI): def start_app() -> None: container_name, new_container_name = utils.generate_container_name("premd") client = utils.get_docker_client() - container = client.containers.get(container_name) - host_port = container.ports.get(f"{utils.DEFAULT_PORT}/tcp", [None])[0][ - "HostPort" - ] - if host_port != f"{utils.DEFAULT_PORT}": - utils.check_host_port_availability(utils.DEFAULT_PORT) - _ = utils.create_new_container( - utils.PREMD_IMAGE, - "latest", - new_container_name, - container_name, - utils.DEFAULT_PORT, - ) - utils.update_and_remove_old_container(container_name) + if utils.container_exists(container_name): + container = client.containers.get(container_name) + host_port = container.ports.get(f"{utils.DEFAULT_PORT}/tcp", [None])[0][ + "HostPort" + ] + if host_port != f"{utils.DEFAULT_PORT}": + utils.check_host_port_availability(utils.DEFAULT_PORT) + _ = utils.create_new_container( + utils.PREMD_IMAGE, + "latest", + new_container_name, + container_name, + utils.DEFAULT_PORT, + ) + utils.update_and_remove_old_container(container_name) for registry in config.PREM_REGISTRY_URL.strip().split(): utils.add_services_from_registry(registry) diff --git a/app/core/utils.py b/app/core/utils.py index ececdbe..5dad6a5 100644 --- a/app/core/utils.py +++ b/app/core/utils.py @@ -207,41 +207,32 @@ def get_gpu_info(): def extract_labels_from_html_file(html_content, class_names): soup = BeautifulSoup(html_content, "html.parser") labels = soup.select(class_names) - return [label.get_text() for label in labels] + return (label.get_text() for label in labels) def find_maximum_label(labels): - pattern = r"v(\d+)\.(\d+)\.(\d+)" - max_label = None - - for label in labels: - match = re.match(pattern, label) - if match: - version = f"v{match.group(1)}.{match.group(2)}.{match.group(3)}" - if max_label is None or version > max_label: - max_label = version - - return max_label + pattern = re.compile(r"v\d+\.\d+\.\d+$") + return max(filter(pattern.match, labels), default=None) def get_premd_last_tag(owner, repository, package): response = requests.get( f"https://github.com/{owner}/{repository}/pkgs/container/{package}" ) - class_names = ".Label.mr-1.mb-2.text-normal" try: - labels = extract_labels_from_html_file(response.content, class_names) - if labels: - return find_maximum_label(labels) + labels = extract_labels_from_html_file( + response.content, ".Label.mr-1.mb-2.text-normal" + ) except Exception as e: logger.info(f"Unexpected error: {e}") + else: + return find_maximum_label(labels) def get_local_docker_image_tags(owner, repository): - image_name = f"ghcr.io/{owner}/{repository}" try: client = get_docker_client() - image = client.images.get(image_name) + image = client.images.get(f"ghcr.io/{owner}/{repository}") return image.tags except Exception as e: logger.info(f"Unexpected error: {e}") @@ -257,7 +248,7 @@ def generate_container_name(prefix): latest_suffix = -1 for container in containers: match = re.match(rf"{prefix}_(\d+)", container.name) - if match and container.status == "running": + if match: suffix = int(match.group(1)) if suffix > latest_suffix: latest_suffix = suffix @@ -312,8 +303,6 @@ def update_and_remove_old_container(old_container_name): logger.info(f"Stopping {old_container_name}") old_container = client.containers.get(old_container_name) old_container.stop() - old_container.remove(force=True) - client.system.prune() def update_container(host_port): From f9afaba7f547d7d481d8117d40acaf44397cd154 Mon Sep 17 00:00:00 2001 From: nsosio Date: Thu, 3 Aug 2023 09:24:38 +0200 Subject: [PATCH 5/8] wrongly deleted utils.container_exists --- app/core/utils.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/app/core/utils.py b/app/core/utils.py index 5dad6a5..a20d52a 100644 --- a/app/core/utils.py +++ b/app/core/utils.py @@ -332,3 +332,15 @@ def check_host_port_availability(host_port, timeout=30): return True time.sleep(1) + + +def container_exists(container_name): + try: + client = get_docker_client() + _ = client.containers.get(container_name) + return True + except docker.errors.NotFound: + return False + except docker.errors.APIError as e: + logging.error(f"Error checking container existence: {e}") + return False From b08d530745bcf023fa4e9e5632ec9a1adc166a7c Mon Sep 17 00:00:00 2001 From: nsosio Date: Thu, 3 Aug 2023 09:36:06 +0200 Subject: [PATCH 6/8] removed commentt in SENTRY_DNS --- .env.example | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.env.example b/.env.example index efb6ac7..98d42c2 100644 --- a/.env.example +++ b/.env.example @@ -11,4 +11,4 @@ PREMD_IMAGE=ghcr.io/premai-io/premd # Sentry # ------------------------------------------------------------------------------------------ -#SENTRY_DSN=https://75592545ad6b472e9ad7c8ff51740b73@o1068608.ingest.sentry.io/4505244431941632 +SENTRY_DSN=https://75592545ad6b472e9ad7c8ff51740b73@o1068608.ingest.sentry.io/4505244431941632 From 5c4668c9f02424b1e8bf739b0056f6a31228dd62 Mon Sep 17 00:00:00 2001 From: nicola Date: Sun, 3 Sep 2023 09:43:33 +0200 Subject: [PATCH 7/8] Apply suggestions from code review Co-authored-by: Casper da Costa-Luis --- app/core/events.py | 3 ++- app/core/utils.py | 41 ++++++++++++----------------------------- app/routes.py | 2 +- 3 files changed, 15 insertions(+), 31 deletions(-) diff --git a/app/core/events.py b/app/core/events.py index f53ba15..77f38e3 100644 --- a/app/core/events.py +++ b/app/core/events.py @@ -18,7 +18,7 @@ def start_app() -> None: ] if host_port != f"{utils.DEFAULT_PORT}": utils.check_host_port_availability(utils.DEFAULT_PORT) - _ = utils.create_new_container( + new_container = utils.create_new_container( utils.PREMD_IMAGE, "latest", new_container_name, @@ -26,6 +26,7 @@ def start_app() -> None: utils.DEFAULT_PORT, ) utils.update_and_remove_old_container(container_name) + new_container.start() for registry in config.PREM_REGISTRY_URL.strip().split(): utils.add_services_from_registry(registry) diff --git a/app/core/utils.py b/app/core/utils.py index a20d52a..7133297 100644 --- a/app/core/utils.py +++ b/app/core/utils.py @@ -8,6 +8,7 @@ import requests import torch from bs4 import BeautifulSoup +from packaging.version import parse as parse_version from app.core import config @@ -212,7 +213,7 @@ def extract_labels_from_html_file(html_content, class_names): def find_maximum_label(labels): pattern = re.compile(r"v\d+\.\d+\.\d+$") - return max(filter(pattern.match, labels), default=None) + return max(filter(pattern.match, labels), default=None, key=parse_version) def get_premd_last_tag(owner, repository, package): @@ -225,6 +226,7 @@ def get_premd_last_tag(owner, repository, package): ) except Exception as e: logger.info(f"Unexpected error: {e}") + return "latest" else: return find_maximum_label(labels) @@ -239,28 +241,8 @@ def get_local_docker_image_tags(owner, repository): return [] -def generate_container_name(prefix): - client = get_docker_client() - - containers = client.containers.list( - all=True, filters={"name": f"^{prefix}", "status": "running"} - ) - latest_suffix = -1 - for container in containers: - match = re.match(rf"{prefix}_(\d+)", container.name) - if match: - suffix = int(match.group(1)) - if suffix > latest_suffix: - latest_suffix = suffix - - if latest_suffix == -1: - return prefix, f"{prefix}_1" - else: - return f"{prefix}_{latest_suffix}", f"{prefix}_{latest_suffix+1}" - - def create_new_container( - image_name, image_tag, new_container_name, old_container_name, host_port + image_name, image_tag, new_container_name, old_container_name ): client = get_docker_client() old_container = client.containers.get(old_container_name) @@ -280,15 +262,15 @@ def create_new_container( volumes[source] = {"bind": target, "mode": mode} current_ports = old_container.attrs["HostConfig"]["PortBindings"] - current_port_key = list(current_ports.keys())[0] + current_port = list(current_ports.items())[0] logger.info( - f"Starting new container {new_container_name} with image {image_name}:{image_tag} at port {host_port}" + f"Starting new container {new_container_name} with image {image_name}:{image_tag} at port {current_port[0]}" ) - new_container = client.containers.run( + new_container = client.containers.create( image=f"{image_name}:{image_tag}", name=new_container_name, - ports={f"{current_port_key}/tcp": [{"HostIp": "", "HostPort": host_port}]}, + ports={f"{current_port[0]}/tcp": [{"HostIp": "", "HostPort": current_port[1]}]}, volumes=volumes, environment=old_container.attrs["Config"]["Env"], device_requests=device_requests, @@ -305,12 +287,13 @@ def update_and_remove_old_container(old_container_name): old_container.stop() -def update_container(host_port): +def update_container(): container_name, new_container_name = generate_container_name("premd") - create_new_container( - PREMD_IMAGE, "latest", new_container_name, container_name, host_port + new_container = create_new_container( + PREMD_IMAGE, "latest", new_container_name, container_name ) update_and_remove_old_container(container_name) + new_container.start() def check_host_port_availability(host_port, timeout=30): diff --git a/app/routes.py b/app/routes.py index 89d9283..12f5437 100644 --- a/app/routes.py +++ b/app/routes.py @@ -83,7 +83,7 @@ async def update_available(): ) async def trigger_update(): try: - utils.update_container(utils.DEFAULT_PORT + 1) + utils.update_container() except Exception as error: logger.error(error) raise HTTPException( From e4c03330b396bb2e73f8df54e72644968af5f147 Mon Sep 17 00:00:00 2001 From: nsosio Date: Sun, 3 Sep 2023 10:42:47 +0200 Subject: [PATCH 8/8] added requirement; removed reference to generate container name and replaced with new container; temporarily commented part of create_start_app_handler --- app/core/events.py | 35 +++++++++++++++++------------------ app/core/utils.py | 12 +++++------- requirements.txt | 1 + 3 files changed, 23 insertions(+), 25 deletions(-) diff --git a/app/core/events.py b/app/core/events.py index 77f38e3..6da383c 100644 --- a/app/core/events.py +++ b/app/core/events.py @@ -9,24 +9,23 @@ def create_start_app_handler(app: FastAPI): def start_app() -> None: - container_name, new_container_name = utils.generate_container_name("premd") - client = utils.get_docker_client() - if utils.container_exists(container_name): - container = client.containers.get(container_name) - host_port = container.ports.get(f"{utils.DEFAULT_PORT}/tcp", [None])[0][ - "HostPort" - ] - if host_port != f"{utils.DEFAULT_PORT}": - utils.check_host_port_availability(utils.DEFAULT_PORT) - new_container = utils.create_new_container( - utils.PREMD_IMAGE, - "latest", - new_container_name, - container_name, - utils.DEFAULT_PORT, - ) - utils.update_and_remove_old_container(container_name) - new_container.start() + # client = utils.get_docker_client() + # if utils.container_exists(container_name): + # container = client.containers.get(container_name) + # host_port = container.ports.get(f"{utils.DEFAULT_PORT}/tcp", [None])[0][ + # "HostPort" + # ] + # if host_port != f"{utils.DEFAULT_PORT}": + # utils.check_host_port_availability(utils.DEFAULT_PORT) + # new_container = utils.create_new_container( + # utils.PREMD_IMAGE, + # "latest", + # new_container_name, + # container_name, + # utils.DEFAULT_PORT, + # ) + # utils.update_and_remove_old_container(container_name) + # new_container.start() for registry in config.PREM_REGISTRY_URL.strip().split(): utils.add_services_from_registry(registry) diff --git a/app/core/utils.py b/app/core/utils.py index 6d7a4ee..77b2100 100644 --- a/app/core/utils.py +++ b/app/core/utils.py @@ -240,9 +240,7 @@ def get_local_docker_image_tags(owner, repository): return [] -def create_new_container( - image_name, image_tag, new_container_name, old_container_name -): +def create_new_container(image_name, image_tag, new_container_name, old_container_name): client = get_docker_client() old_container = client.containers.get(old_container_name) @@ -269,7 +267,7 @@ def create_new_container( new_container = client.containers.create( image=f"{image_name}:{image_tag}", name=new_container_name, - ports={f"{current_port[0]}/tcp": [{"HostIp": "", "HostPort": current_port[1]}]}, + ports={current_port[0]: current_port[1]}, volumes=volumes, environment=old_container.attrs["Config"]["Env"], device_requests=device_requests, @@ -287,12 +285,12 @@ def update_and_remove_old_container(old_container_name): def update_container(): - container_name, new_container_name = generate_container_name("premd") new_container = create_new_container( - PREMD_IMAGE, "latest", new_container_name, container_name + PREMD_IMAGE, "latest", "new_container", "premd" ) - update_and_remove_old_container(container_name) + update_and_remove_old_container("premd") new_container.start() + new_container.rename("premd") def check_host_port_availability(host_port, timeout=30): diff --git a/requirements.txt b/requirements.txt index 2787568..9d2548d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -16,3 +16,4 @@ torchaudio==2.0.2 sentry-sdk==1.26.0 psutil==5.9.5 beautifulsoup4==4.12.2 +packaging==23.1