-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: share images backend to backend
Signed-off-by: SdgJlbl <[email protected]>
- Loading branch information
Showing
13 changed files
with
166 additions
and
29 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,34 +1,76 @@ | ||
import os | ||
import pathlib | ||
import time | ||
from tempfile import TemporaryDirectory | ||
|
||
import structlog | ||
from django.conf import settings | ||
|
||
import orchestrator | ||
|
||
import substrapp.clients.organization as organization_client | ||
from builder import exceptions | ||
from image_transfer import push_payload | ||
from substrapp.compute_tasks import utils | ||
from substrapp.docker_registry import container_image_exists | ||
from substrapp.exceptions import OrganizationHttpError | ||
from substrapp.utils import get_owner | ||
|
||
logger = structlog.get_logger(__name__) | ||
|
||
IMAGE_BUILD_TIMEOUT = settings.IMAGE_BUILD_TIMEOUT | ||
IMAGE_BUILD_CHECK_DELAY = settings.IMAGE_BUILD_CHECK_DELAY | ||
REGISTRY = settings.REGISTRY | ||
SUBTUPLE_TMP_DIR = settings.SUBTUPLE_TMP_DIR | ||
|
||
|
||
def wait_for_image_built(function: orchestrator.Function) -> None: | ||
def wait_for_image_built(function: orchestrator.Function, channel: str) -> None: | ||
container_image_tag = utils.container_image_tag_from_function(function) | ||
attempt = 0 | ||
# with 60 attempts we wait max 2 min with a pending pod | ||
max_attempts = IMAGE_BUILD_TIMEOUT / IMAGE_BUILD_CHECK_DELAY | ||
while attempt < max_attempts: | ||
# Consider relying on celery task success so we can move `container_image_exists` in builder | ||
if container_image_exists(container_image_tag): | ||
logger.info("Found existing image", image=container_image_tag) | ||
return | ||
|
||
attempt += 1 | ||
time.sleep(IMAGE_BUILD_CHECK_DELAY) | ||
|
||
raise exceptions.PodTimeoutError( | ||
f"Build for function {function.key} didn't complete after {IMAGE_BUILD_TIMEOUT} seconds" | ||
) | ||
if function.owner == get_owner(): | ||
attempt = 0 | ||
# with 60 attempts we wait max 2 min with a pending pod | ||
max_attempts = IMAGE_BUILD_TIMEOUT / IMAGE_BUILD_CHECK_DELAY | ||
while attempt < max_attempts: | ||
# Consider relying on celery task success so we can move `container_image_exists` in builder | ||
if container_image_exists(container_image_tag): | ||
logger.info("Found existing image", image=container_image_tag) | ||
return | ||
|
||
attempt += 1 | ||
time.sleep(IMAGE_BUILD_CHECK_DELAY) | ||
|
||
raise exceptions.PodTimeoutError( | ||
f"Build for function {function.key} didn't complete after {IMAGE_BUILD_TIMEOUT} seconds" | ||
) | ||
else: | ||
# Ask the backend owner of the function if it's available | ||
logger.info( | ||
f"Initial function URI {function.function_address.uri}; " | ||
f"modified URI{function.function_address.uri.replace('file', 'image')}" | ||
) | ||
attempt = 0 | ||
max_attempts = 10 | ||
while attempt < max_attempts: | ||
try: | ||
function_image_content = organization_client.get( | ||
channel=channel, | ||
organization_id=function.owner, | ||
# TODO create a clean Address for function image | ||
url=function.function_address.uri.replace("file", "image"), | ||
checksum=None, | ||
) | ||
except OrganizationHttpError: | ||
attempt += 1 | ||
time.sleep(5) | ||
|
||
os.makedirs(SUBTUPLE_TMP_DIR, exist_ok=True) | ||
with TemporaryDirectory(dir=SUBTUPLE_TMP_DIR) as tmp_dir: | ||
storage_path = pathlib.Path(tmp_dir) / f"{container_image_tag}.zip" | ||
storage_path.write_bytes(function_image_content) | ||
push_payload(storage_path, registry=REGISTRY, secure=False) | ||
|
||
# | ||
# if exc.status_code == 404: | ||
# raise exceptions.CeleryRetryError(f"Function {function.key} was not found | ||
# on backend {function.owner}") | ||
# else: | ||
# raise exceptions.CeleryNoRetryError("I've got a bad feeling about this.") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
import os | ||
import pathlib | ||
from tempfile import TemporaryDirectory | ||
|
||
import structlog | ||
from django.conf import settings | ||
from django.core.files import File | ||
|
||
import orchestrator | ||
from backend.celery import app | ||
from image_transfer import make_payload | ||
from substrapp.compute_tasks import utils | ||
from substrapp.docker_registry import USER_IMAGE_REPOSITORY | ||
from substrapp.models import FunctionImage | ||
from substrapp.tasks.tasks_compute_task import ComputeTask | ||
|
||
REGISTRY = settings.REGISTRY | ||
REGISTRY_SCHEME = settings.REGISTRY_SCHEME | ||
SUBTUPLE_TMP_DIR = settings.SUBTUPLE_TMP_DIR | ||
|
||
logger = structlog.get_logger("worker") | ||
|
||
|
||
@app.task( | ||
bind=True, | ||
acks_late=True, | ||
reject_on_worker_lost=True, | ||
ignore_result=False, | ||
base=ComputeTask, | ||
) | ||
# Ack late and reject on worker lost allows use to | ||
# see http://docs.celeryproject.org/en/latest/userguide/configuration.html#task-reject-on-worker-lost | ||
# and https://github.com/celery/celery/issues/5106 | ||
def save_image_task(self: ComputeTask, function_serialized: str, channel_name: str, function_key: str) -> None: | ||
logger.info(f"Starting save_image_task") | ||
logger.info( | ||
f"Parameters: function_serialized {function_serialized}, channel_name {channel_name}, function_key {function_key}" | ||
) | ||
# create serialized image | ||
function = orchestrator.Function.parse_raw(function_serialized) | ||
container_image_tag = utils.container_image_tag_from_function(function) | ||
|
||
os.makedirs(SUBTUPLE_TMP_DIR, exist_ok=True) | ||
|
||
logger.info("Serialising the image from the registry") | ||
|
||
with TemporaryDirectory(dir=SUBTUPLE_TMP_DIR) as tmp_dir: | ||
storage_path = pathlib.Path(tmp_dir) / f"{container_image_tag}.zip" | ||
make_payload( | ||
zip_file=storage_path, | ||
docker_images_to_transfer=[f"{USER_IMAGE_REPOSITORY}:{container_image_tag}"], | ||
registry=REGISTRY, | ||
secure=False, | ||
) | ||
|
||
logger.info("Start saving the serialized image") | ||
# save it | ||
FunctionImage.objects.create( | ||
function_id=function.key, file=File(file=storage_path.open(mode="rb"), name=f"{container_image_tag}.zip") | ||
) | ||
logger.info("Serialized image saved") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters