Attach to a container's log_stream before they're started

So we're not displaying output of all previous logs for a container, we attach,
if possible, to a container before the container is started.

LogPrinter checks if a container has a log_stream already attached and
print from that rather than always attempting to attach one itself.

Signed-off-by: Mazz Mosley <mazz@houseofmnowster.com>
This commit is contained in:
Mazz Mosley 2015-10-21 17:28:16 +01:00 committed by Daniel Nephin
commit d6fa8596d2
6 changed files with 67 additions and 30 deletions

View file

@ -399,13 +399,17 @@ class Service(object):
def execute_convergence_plan(self,
plan,
do_build=True,
timeout=DEFAULT_TIMEOUT):
timeout=DEFAULT_TIMEOUT,
detached=False):
(action, containers) = plan
should_attach_logs = not detached
if action == 'create':
container = self.create_container(
do_build=do_build,
)
container = self.create_container(do_build=do_build)
if should_attach_logs:
container.attach_log_stream()
self.start_container(container)
return [container]
@ -413,15 +417,16 @@ class Service(object):
elif action == 'recreate':
return [
self.recreate_container(
c,
timeout=timeout
container,
timeout=timeout,
attach_logs=should_attach_logs
)
for c in containers
for container in containers
]
elif action == 'start':
for c in containers:
self.start_container_if_stopped(c)
for container in containers:
self.start_container_if_stopped(container, attach_logs=should_attach_logs)
return containers
@ -434,16 +439,7 @@ class Service(object):
else:
raise Exception("Invalid action: {}".format(action))
def recreate_container(self,
container,
timeout=DEFAULT_TIMEOUT):
"""Recreate a container.
The original container is renamed to a temporary name so that data
volumes can be copied to the new container, before the original
container is removed.
"""
log.info("Recreating %s" % container.name)
def _recreate_stop_container(self, container, timeout):
try:
container.stop(timeout=timeout)
except APIError as e:
@ -454,26 +450,46 @@ class Service(object):
else:
raise
def _recreate_rename_container(self, container):
# Use a hopefully unique container name by prepending the short id
self.client.rename(
container.id,
'%s_%s' % (container.short_id, container.name))
'%s_%s' % (container.short_id, container.name)
)
def recreate_container(self,
container,
timeout=DEFAULT_TIMEOUT,
attach_logs=False):
"""Recreate a container.
The original container is renamed to a temporary name so that data
volumes can be copied to the new container, before the original
container is removed.
"""
log.info("Recreating %s" % container.name)
self._recreate_stop_container(container, timeout)
self._recreate_rename_container(container)
new_container = self.create_container(
do_build=False,
previous_container=container,
number=container.labels.get(LABEL_CONTAINER_NUMBER),
quiet=True,
)
if attach_logs:
new_container.attach_log_stream()
self.start_container(new_container)
container.remove()
return new_container
def start_container_if_stopped(self, container):
def start_container_if_stopped(self, container, attach_logs=False):
if container.is_running:
return container
else:
log.info("Starting %s" % container.name)
if attach_logs:
container.attach_log_stream()
return self.start_container(container)
def start_container(self, container):