mirror of
https://github.com/All-Hands-AI/OpenHands.git
synced 2026-01-08 22:38:05 -05:00
(enh) docker pull (if not found locally) with progress info (#3682)
This commit is contained in:
@@ -71,7 +71,7 @@ def create_runtime(
|
||||
|
||||
# runtime and tools
|
||||
runtime_cls = get_runtime_cls(config.runtime)
|
||||
logger.info(f'Initializing runtime: {runtime_cls}')
|
||||
logger.info(f'Initializing runtime: {runtime_cls.__name__}')
|
||||
runtime: Runtime = runtime_cls(
|
||||
config=config,
|
||||
event_stream=event_stream,
|
||||
|
||||
@@ -69,21 +69,56 @@ class DockerRuntimeBuilder(RuntimeBuilder):
|
||||
bool: Whether the Docker image exists in the registry or in the local store
|
||||
"""
|
||||
try:
|
||||
logger.info(f'Checking, if image {image_name} exists locally.')
|
||||
logger.info(f'Checking, if image exists locally:\n{image_name}')
|
||||
self.docker_client.images.get(image_name)
|
||||
logger.info(f'Image {image_name} found locally.')
|
||||
logger.info('Image found locally.')
|
||||
return True
|
||||
except docker.errors.ImageNotFound:
|
||||
try:
|
||||
logger.info(
|
||||
'Image not found locally. Trying to pull it, please wait...'
|
||||
)
|
||||
self.docker_client.images.pull(image_name)
|
||||
logger.info(f'Image {image_name} pulled successfully.')
|
||||
|
||||
layers = {}
|
||||
for line in self.docker_client.api.pull(
|
||||
image_name, stream=True, decode=True
|
||||
):
|
||||
if 'id' in line and 'progressDetail' in line:
|
||||
layer_id = line['id']
|
||||
if layer_id not in layers:
|
||||
layers[layer_id] = {
|
||||
'last_logged': -10
|
||||
} # Initialize last logged at -10%
|
||||
|
||||
if (
|
||||
'total' in line['progressDetail']
|
||||
and 'current' in line['progressDetail']
|
||||
):
|
||||
total = line['progressDetail']['total']
|
||||
current = line['progressDetail']['current']
|
||||
percentage = (current / total) * 100
|
||||
|
||||
# Log if percentage is at least 10% higher than last logged
|
||||
if percentage - layers[layer_id]['last_logged'] >= 10:
|
||||
logger.info(
|
||||
f'Layer {layer_id}: {percentage:.0f}% downloaded'
|
||||
)
|
||||
layers[layer_id]['last_logged'] = percentage
|
||||
|
||||
elif 'status' in line:
|
||||
logger.info(line['status'])
|
||||
|
||||
logger.info('Image pulled')
|
||||
return True
|
||||
except docker.errors.ImageNotFound:
|
||||
logger.info('Could not find image locally or in registry.')
|
||||
return False
|
||||
except Exception:
|
||||
logger.info('Could not pull image directly.')
|
||||
except Exception as e:
|
||||
msg = 'Image could not be pulled: '
|
||||
ex_msg = str(e)
|
||||
if 'Not Found' in ex_msg:
|
||||
msg += 'image not found in registry.'
|
||||
else:
|
||||
msg += f'{ex_msg}'
|
||||
logger.warning(msg)
|
||||
return False
|
||||
|
||||
@@ -39,8 +39,11 @@ def _put_source_code_to_dir(temp_dir: str):
|
||||
Parameters:
|
||||
- temp_dir (str): The directory to put the source code in
|
||||
"""
|
||||
if not os.path.isdir(temp_dir):
|
||||
raise RuntimeError(f'Temp directory {temp_dir} does not exist')
|
||||
|
||||
project_root = os.path.dirname(os.path.dirname(os.path.abspath(openhands.__file__)))
|
||||
logger.info(f'Using project root: {project_root}')
|
||||
logger.info(f'Building source distribution using project root: {project_root}')
|
||||
|
||||
# Fetch the correct version from pyproject.toml
|
||||
package_version = _get_package_version()
|
||||
@@ -63,12 +66,12 @@ def _put_source_code_to_dir(temp_dir: str):
|
||||
logger.error(err_logs)
|
||||
|
||||
if result.returncode != 0:
|
||||
logger.error(f'Build failed: {result}')
|
||||
raise Exception(f'Build failed: {result}')
|
||||
logger.error(f'Image build failed:\n{result}')
|
||||
raise RuntimeError(f'Image build failed:\n{result}')
|
||||
|
||||
if not os.path.exists(tarball_path):
|
||||
logger.error(f'Source distribution not found at {tarball_path}')
|
||||
raise Exception(f'Source distribution not found at {tarball_path}')
|
||||
raise RuntimeError(f'Source distribution not found at {tarball_path}')
|
||||
logger.info(f'Source distribution created at {tarball_path}')
|
||||
|
||||
# Unzip the tarball
|
||||
@@ -150,14 +153,14 @@ def prep_docker_build_folder(
|
||||
file.write(dockerfile_content)
|
||||
|
||||
# Get the MD5 hash of the dir_path directory
|
||||
hash = dirhash(dir_path, 'md5')
|
||||
dist_hash = dirhash(dir_path, 'md5')
|
||||
logger.info(
|
||||
f'Input base image: {base_image}\n'
|
||||
f'Skip init: {skip_init}\n'
|
||||
f'Extra deps: {extra_deps}\n'
|
||||
f'Hash for docker build directory [{dir_path}] (contents: {os.listdir(dir_path)}): {hash}\n'
|
||||
f'Hash for docker build directory [{dir_path}] (contents: {os.listdir(dir_path)}): {dist_hash}\n'
|
||||
)
|
||||
return hash
|
||||
return dist_hash
|
||||
|
||||
|
||||
def get_runtime_image_repo_and_tag(base_image: str) -> tuple[str, str]:
|
||||
|
||||
Reference in New Issue
Block a user