import os import docker import json DOCKER_BASE_URL = os.environ.get('DOCKER_BASE_URL') or "unix://tmp/docker.sock" VOLUME_TYPE_BIND = "bind" VOLUME_TYPE_VOLUME = "volume" class Container: def __init__(self, data): self.id = data.get('Id') self.names = data.get('Names') self.mounts = [Mount(mnt, container=self) for mnt in data.get('Mounts')] def to_dict(self): return { "Id": self.id, "Mounts": [mnt.data for mnt in self.mounts] } class Mount: """Mount wrapper""" def __init__(self, data, container=None): self.data = data self._container = container @property def container(self): return self._container @property def type(self): return self.data.get('Type') @property def name(self): return self.data.get('Name') @property def source(self): return self.data.get('Source') @property def destination(self): return self.data.get('Destination') @property def driver(self): return self.data.get('Driver') @property def mode(self): return self.data.get('Mode') @property def rw(self): return self.data.get('RW') def mount_string(self): if self.type == VOLUME_TYPE_VOLUME: return "- {}:{}:ro".format(self.name.split('_')[-1], self.destination) elif self.type == VOLUME_TYPE_BIND: return "- {}:{}:ro".format(self.source, self.destination) else: raise ValueError("Uknown volume type: {}".format(self.type)) def __repr__(self): return str(self) def __str__(self): return str(self.data) def __hash__(self): """Uniquness for a volume""" if self.type == VOLUME_TYPE_VOLUME: return hash(self.name) elif self.type == VOLUME_TYPE_BIND: return hash(self.source) else: raise ValueError("Uknown volume type: {}".format(self.type)) class RunningContainers: def __init__(self): client = docker.Client(base_url=DOCKER_BASE_URL) all_containers = client.containers() client.close() self.containers = [] self.backup_container = None for entry in all_containers: if entry['Id'].startswith(os.environ['HOSTNAME']): self.backup_container = Container(entry) else: if entry['State'] == "running": self.containers.append(Container(entry)) if not self.backup_container: raise ValueError("Cannot find metadata for backup container") def backup_volumes(self): return self.backup_container.mounts def gen_volumes(self, volume_type): """Generator yielding volumes of a specific type""" for cont in self.containers: for mnt in cont.mounts: if mnt.type == volume_type: yield mnt def volume_mounts(self): """Docker volumes""" return set(mnt for mnt in self.gen_volumes(VOLUME_TYPE_VOLUME)) def bind_mounts(self): """Host mapped volumes""" return set(mnt for mnt in self.gen_volumes(VOLUME_TYPE_BIND)) def print_all(self): print("Backup container:") print(json.dumps(self.backup_container.to_dict(), indent=2)) print("All containers:") print(json.dumps([cnt.to_dict() for cnt in self.containers], indent=2))