1
0
mirror of https://github.com/projectatomic/atomic.git synced 2026-02-07 06:44:52 +01:00
Files
atomic/Atomic/backendutils.py
Brent Baude 8028c33e00 Introduction of ContainersStorage backend
A new backend is being added to the Atomic CLI called "Containers Storage".  This commit
covers the addition of the backend itself.  The backend is only made available in the
atomic CLI if an export variable called 'DEV' is found.  For example:

sudo DEV=true atomic images list -a

Each method in the backend (with the exceptionof def available) raises an
UnderDevelopment Exception.  As the methods are developed, the exceptions will be removed.

Closes: #1038
Approved by: rhatdan
2017-06-28 15:34:36 +00:00

168 lines
7.1 KiB
Python

from Atomic.backends._docker import DockerBackend
from Atomic.backends._docker_errors import NoDockerDaemon
from Atomic.backends._ostree import OSTreeBackend
from Atomic.backends._containers_storage import ContainersStorageBackend
from Atomic.util import write_out, get_atomic_config
ATOMIC_CONFIG = get_atomic_config()
default_storage = ATOMIC_CONFIG.get('default_storage', "docker")
class BackendUtils(object):
"""
Given an image, returns the back end that owns that image
"""
BACKENDS = [DockerBackend, OSTreeBackend, ContainersStorageBackend]
@property
def available_backends(self):
return self._set_available_backends()
def _set_available_backends(self):
bes = []
for x in self.BACKENDS:
try:
be = x()
if be.available:
bes.append(x)
except NoDockerDaemon:
pass
if len(bes) < 1:
raise ValueError("No backends are enabled for Atomic.")
return bes
def dump_backends(self):
backends = ''
for i in self.available_backends:
be = i()
backends += "{}: Active, ".format(be.backend)
write_out("Backends({})\n".format(backends))
def get_backend_from_string(self, str_backend, init=True):
for _backend in self.BACKENDS:
backend = _backend
backend_obj = _backend()
if backend_obj.backend == str_backend:
if init:
return backend_obj
return backend
raise ValueError("Unable to associate string '{}' with backend".format(str_backend))
def _get_backend(self, backend):
return self.get_backend_from_string(backend, init=False)
def _get_backend_index_from_string(self, str_backend):
return [x().backend for x in self.BACKENDS].index(str_backend)
@staticmethod
def backend_has_image(backend, img):
return True if backend.has_image(img) else False
@staticmethod
def backend_has_container(backend, container):
return True if backend.has_container(container) else False
def get_backend_and_image_obj(self, img, str_preferred_backend=None, required=False):
"""
Given an image name (str) and optionally a str reference to a backend,
this method looks for the image firstly on the preferred backend and
then on the alternate backends. It returns a backend object and an
image object.
:param img: name of image to look for
:param str_preferred_backend: i.e. 'docker'
:return: backend object and image object
"""
backends = list(self.available_backends)
if str_preferred_backend and self._get_backend(str_preferred_backend) not in self.available_backends and required:
raise ValueError("The '{}' backend appears unavailable/inactive".format(str_preferred_backend))
# Check preferred backend first
if str_preferred_backend and self._get_backend(str_preferred_backend) in self.available_backends:
be = self.get_backend_from_string(str_preferred_backend)
img_obj = be.has_image(img)
if img_obj:
return be, img_obj
if required:
raise ValueError("Unable to find {} in the {} backend".format(img, str_preferred_backend))
# Didnt find in preferred, need to remove it from the list now
del backends[self._get_backend_index_from_string(str_preferred_backend)]
# Did not find it in the preferred backend, keep looking
img_in_backends = []
for backend in backends:
be = backend()
img_obj = be.has_image(img)
if img_obj:
img_in_backends.append((be, img_obj))
if len(img_in_backends) == 1:
return img_in_backends[0]
if len(img_in_backends) == 0:
raise ValueError("Unable to find '{}' in the following backends: {}".format(img, ", ".join([x().backend for x in self.available_backends])))
raise ValueError("Found {} in multiple storage backends: {}".
format(img, ', '.join([x.backend for x, _ in img_in_backends])))
def get_backend_and_container_obj(self, container_name, str_preferred_backend=None, required=False):
"""
Given a container name (str) and optionally a str reference to a backend,
this method looks for the container firstly on the preferred backend and
then on the alternate backends. It returns a backend object and a container
object.
:param container_name: name of image to look for
:param str_preferred_backend: i.e. 'docker'
:return: backend object and container object
"""
if str_preferred_backend and self._get_backend(str_preferred_backend) not in self.available_backends and required:
raise ValueError("The '{}' backend appears unavailable/inactive".format(str_preferred_backend))
backends = list(self.available_backends)
# Check preferred backend first
if str_preferred_backend and self._get_backend(str_preferred_backend) in self.available_backends:
be = self.get_backend_from_string(str_preferred_backend)
con_obj = be.has_container(container_name)
if con_obj:
return be, con_obj
if required:
raise ValueError("Unable to find {} in the {} backend".format(container_name, str_preferred_backend))
# Didnt find in preferred, need to remove it from the list now
del backends[self._get_backend_index_from_string(str_preferred_backend)]
container_in_backends = []
for backend in backends:
be = backend()
con_obj = be.has_container(container_name)
if con_obj:
container_in_backends.append((be, con_obj))
if len(container_in_backends) == 1:
return container_in_backends[0]
if len(container_in_backends) == 0:
raise ValueError("Unable to find backend associated with container '{}'".format(container_name))
raise ValueError("Found {} in multiple storage backends: {}".
format(container_name, ', '.join([x.backend for x in container_in_backends])))
def get_images(self, get_all=False):
backends = self.available_backends
img_objs = []
for backend in backends:
be = backend()
img_objs += be.get_images(get_all=get_all)
return img_objs
def get_containers(self):
backends = self.available_backends
con_objs = []
for backend in backends:
be = backend()
con_objs += be.get_containers()
return con_objs
def get_container_obj_by_image_name(self, image_name, str_preferred_backend):
pass
@staticmethod
def message_backend_change(previous, new):
write_out("\nNote: Switching from the '{}' backend to the '{}' backend based on the 'atomic.type' label in the "
"image. You can use --storage to override this behaviour.\n".format(previous, new))