mirror of
https://github.com/ZettaIO/restic-compose-backup.git
synced 2025-09-28 14:45:23 +00:00
Initial
This commit is contained in:
128
restic-backup/containers.py
Normal file
128
restic-backup/containers.py
Normal file
@@ -0,0 +1,128 @@
|
||||
import os
|
||||
import docker
|
||||
import json
|
||||
|
||||
DOCKER_BASE_URL = os.environ.get('DOCKER_BASE_URL') or "unix://var/run/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))
|
Reference in New Issue
Block a user