Skip to content

Commit 750973c

Browse files
committed
refactor: enhance docker images pull
Signed-off-by: thxCode <thxcode0824@gmail.com>
1 parent 488aa04 commit 750973c

File tree

2 files changed

+46
-8
lines changed

2 files changed

+46
-8
lines changed

gpustack_runtime/deployer/__init__.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ def create_workload(workload: WorkloadPlan):
7979
dep.create(workload=workload)
8080
return
8181

82-
msg = "No deployer supports"
82+
msg = "No deployer supports, please provide container runtime"
8383
raise UnsupportedError(msg)
8484

8585

@@ -112,7 +112,7 @@ def get_workload(
112112

113113
return dep.get(name=name, namespace=namespace)
114114

115-
msg = "No deployer supports"
115+
msg = "No deployer supports, please provide container runtime"
116116
raise UnsupportedError(msg)
117117

118118

@@ -145,7 +145,7 @@ def delete_workload(
145145

146146
return dep.delete(name=name, namespace=namespace)
147147

148-
msg = "No deployer supports"
148+
msg = "No deployer supports, please provide container runtime"
149149
raise UnsupportedError(msg)
150150

151151

@@ -178,7 +178,7 @@ def list_workloads(
178178

179179
return dep.list(namespace=namespace, labels=labels)
180180

181-
msg = "No deployer supports"
181+
msg = "No deployer supports, please provide container runtime"
182182
raise UnsupportedError(msg)
183183

184184

@@ -234,7 +234,7 @@ def logs_workload(
234234
follow=follow,
235235
)
236236

237-
msg = "No deployer supports"
237+
msg = "No deployer supports, please provide container runtime"
238238
raise UnsupportedError(msg)
239239

240240

@@ -287,7 +287,7 @@ def exec_workload(
287287
args=args,
288288
)
289289

290-
msg = "No deployer supports"
290+
msg = "No deployer supports, please provide container runtime"
291291
raise UnsupportedError(msg)
292292

293293

gpustack_runtime/deployer/docker.py

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
from __future__ import annotations
22

3+
import json
34
import logging
45
import socket
6+
import sys
57
from dataclasses import dataclass, field
68
from functools import lru_cache
79
from math import ceil
@@ -15,6 +17,7 @@
1517
import docker.models.volumes
1618
import docker.types
1719
from dataclasses_json import dataclass_json
20+
from docker.utils import parse_repository_tag
1821

1922
from .. import envs
2023
from .__types__ import (
@@ -397,8 +400,43 @@ def _pull_image(self, image: str) -> docker.models.images.Image:
397400
except docker.errors.ImageNotFound:
398401
logger.info(f"Pulling image {image}")
399402
try:
400-
# TODO(thxCode): display pull progress
401-
return self._client.images.pull(image)
403+
repo, tag = parse_repository_tag(image)
404+
tag = tag or "latest"
405+
pull_log = self._client.api.pull(
406+
repo,
407+
tag=tag,
408+
stream=True,
409+
)
410+
411+
layers: dict[str, int] = {}
412+
is_tty = sys.stdout.isatty()
413+
for line in pull_log:
414+
line_str = (
415+
line.decode("utf-8", errors="replace")
416+
if isinstance(line, bytes)
417+
else line
418+
)
419+
for log_str in line_str.splitlines():
420+
log = json.loads(log_str)
421+
if "id" not in log:
422+
print(log["status"])
423+
continue
424+
log_id = log["id"]
425+
if log_id not in layers:
426+
layers[log_id] = len(layers)
427+
if is_tty:
428+
print(f"\033[{layers[log_id] + 1};0H", end="")
429+
print("\033[K", end="")
430+
if "progress" in log:
431+
print(f"{log_id}: {log['progress']}", flush=True)
432+
else:
433+
print(f"{log_id}: {log['status']}", flush=True)
434+
435+
sep = "@" if tag.startswith("sha256:") else ":"
436+
return self._client.images.get(f"{repo}{sep}{tag}")
437+
except json.decoder.JSONDecodeError as e:
438+
msg = f"Failed to pull image {image}, invalid response"
439+
raise OperationError(msg) from e
402440
except docker.errors.APIError as e:
403441
msg = f"Failed to pull image {image}"
404442
raise OperationError(msg) from e

0 commit comments

Comments
 (0)