2019-11-15 16:47:40 +01:00
|
|
|
import logging
|
2019-04-17 03:28:07 +02:00
|
|
|
import os
|
|
|
|
import docker
|
|
|
|
|
2019-12-03 09:40:02 +01:00
|
|
|
from restic_compose_backup.config import Config
|
2019-04-17 03:28:07 +02:00
|
|
|
|
2019-11-15 16:47:40 +01:00
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
2019-04-17 04:38:15 +02:00
|
|
|
|
2019-04-18 03:52:28 +02:00
|
|
|
def run(image: str = None, command: str = None, volumes: dict = None,
|
2019-12-03 04:21:27 +01:00
|
|
|
environment: dict = None, labels: dict = None, source_container_id: str = None):
|
2019-11-15 16:47:40 +01:00
|
|
|
logger.info("Starting backup container")
|
2019-04-17 03:45:51 +02:00
|
|
|
config = Config()
|
|
|
|
client = docker.DockerClient(base_url=config.docker_base_url)
|
2019-04-17 03:28:07 +02:00
|
|
|
|
|
|
|
container = client.containers.run(
|
2019-04-17 04:38:15 +02:00
|
|
|
image,
|
|
|
|
command,
|
2019-04-18 03:52:28 +02:00
|
|
|
labels=labels,
|
2019-12-03 04:21:27 +01:00
|
|
|
# auto_remove=True, # We remove the container further down
|
2019-04-17 03:28:07 +02:00
|
|
|
detach=True,
|
2019-11-12 12:39:49 +01:00
|
|
|
environment=environment,
|
2019-04-17 20:20:52 +02:00
|
|
|
volumes=volumes,
|
2019-12-03 04:21:27 +01:00
|
|
|
network_mode=f'container:{source_container_id}', # Reuse original container's network stack.
|
2019-04-17 03:28:07 +02:00
|
|
|
working_dir=os.getcwd(),
|
2019-04-18 07:22:59 +02:00
|
|
|
tty=True,
|
2019-04-17 03:28:07 +02:00
|
|
|
)
|
|
|
|
|
2019-11-15 16:47:40 +01:00
|
|
|
logger.info("Backup process container: %s", container.name)
|
2019-04-18 07:22:59 +02:00
|
|
|
log_generator = container.logs(stdout=True, stderr=True, stream=True, follow=True)
|
2019-11-15 16:47:40 +01:00
|
|
|
|
|
|
|
def readlines(stream):
|
|
|
|
"""Read stream line by line"""
|
|
|
|
while True:
|
|
|
|
line = ""
|
|
|
|
while True:
|
|
|
|
try:
|
2019-12-08 00:08:41 +01:00
|
|
|
# Make log streaming work for docker ce 17 and 18.
|
|
|
|
# For some reason strings are returned instead if bytes.
|
2019-12-06 07:30:39 +01:00
|
|
|
data = next(stream)
|
|
|
|
if isinstance(data, bytes):
|
|
|
|
line += data.decode()
|
|
|
|
elif isinstance(data, str):
|
|
|
|
line += data
|
2019-11-15 16:47:40 +01:00
|
|
|
if line.endswith('\n'):
|
|
|
|
break
|
|
|
|
except StopIteration:
|
|
|
|
break
|
|
|
|
if line:
|
2019-11-26 13:04:30 +01:00
|
|
|
yield line.rstrip()
|
2019-11-15 16:47:40 +01:00
|
|
|
else:
|
|
|
|
break
|
|
|
|
|
2019-04-18 07:22:59 +02:00
|
|
|
with open('backup.log', 'w') as fd:
|
2019-11-15 16:47:40 +01:00
|
|
|
for line in readlines(log_generator):
|
2019-04-18 07:22:59 +02:00
|
|
|
fd.write(line)
|
2019-11-26 19:46:59 +01:00
|
|
|
fd.write('\n')
|
2019-11-15 16:47:40 +01:00
|
|
|
logger.info(line)
|
|
|
|
|
2019-12-06 08:21:21 +01:00
|
|
|
container.wait()
|
2019-04-18 07:22:59 +02:00
|
|
|
container.reload()
|
2019-12-03 07:36:48 +01:00
|
|
|
logger.debug("Container ExitCode %s", container.attrs['State']['ExitCode'])
|
2019-04-18 07:22:59 +02:00
|
|
|
container.remove()
|
2019-12-03 07:36:48 +01:00
|
|
|
|
|
|
|
return container.attrs['State']['ExitCode']
|