Skip to content

Commit c828e73

Browse files
authored
Merge pull request #239 from girder/log-pull
Log pull status
2 parents c3fad69 + 63f4e77 commit c828e73

File tree

1 file changed

+44
-5
lines changed

1 file changed

+44
-5
lines changed

slicer_cli_web/image_job.py

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
###############################################################################
1818

1919
import json
20+
import time
2021

2122
import docker
2223
from girder import logger
@@ -159,7 +160,7 @@ def jobPullAndLoad(job):
159160

160161
try:
161162
stage = 'pulling'
162-
pullDockerImage(docker_client, pullList)
163+
pullDockerImage(docker_client, pullList, job)
163164
except DockerImageNotFoundError as err:
164165
errorState = True
165166
notExistSet = set(err.imageName)
@@ -325,19 +326,57 @@ def getCliData(name, client, job):
325326
raise DockerImageError('Error getting %s cli data from image ' % (name) + str(err))
326327

327328

328-
def pullDockerImage(client, names):
329+
def pullDockerImage(client, names, job=None):
329330
"""
330331
Attempt to pull the docker images listed in names. Failure results in a
331332
DockerImageNotFoundError being raised
332333
333-
:params client: The docker python client
334-
:params names: A list of docker images to be pulled from the Dockerhub
334+
:param client: The docker python client
335+
:param names: A list of docker images to be pulled from the Dockerhub
336+
:param job: A job to update with status.
335337
"""
336338
imgNotExistList = []
337339
for name in names:
338340
try:
339341
logger.info('Pulling %s image', name)
340-
client.images.pull(name)
342+
lastlog = time.time()
343+
stats = {}
344+
for line in client.api.pull(name, stream=True, decode=True):
345+
try:
346+
line.update(line.get('progressDetail', {}))
347+
if 'id' not in line or ('total' not in line and line['id'] not in stats):
348+
continue
349+
stats.setdefault(line['id'], line).update(line)
350+
if time.time() - lastlog >= 10:
351+
total = sum(record['total'] for record in stats.values())
352+
downloaded = sum(
353+
record['total'] for record in stats.values()
354+
if record['status'] != 'Downloading')
355+
downloaded += sum(
356+
record['current'] for record in stats.values()
357+
if record['status'] == 'Downloading')
358+
extracted = sum(
359+
record['total'] for record in stats.values()
360+
if record['status'] == 'Pull complete')
361+
extracted += sum(
362+
record['current'] for record in stats.values()
363+
if record['status'] == 'Extracting')
364+
if total:
365+
msg = f'Pulling {name} image: '
366+
if downloaded < total:
367+
val = downloaded
368+
msg += 'downloaded '
369+
else:
370+
val = extracted
371+
msg += 'extracted '
372+
msg += f'{val}/{total} ({val * 100 / total:4.2f}%)'
373+
logger.info(msg)
374+
if job:
375+
job = Job().updateJob(job, log=msg + '\n')
376+
lastlog = time.time()
377+
except Exception:
378+
# Don't fail if the log code has an issue
379+
pass
341380
# some invalid image names will not be pulled but the pull method
342381
# will not throw an exception so the only way to confirm if a pull
343382
# succeeded is to attempt a docker inspect on the image

0 commit comments

Comments
 (0)