|
@@ -1,6 +1,6 @@
|
|
|
"""Check that required Docker images are available."""
|
|
|
|
|
|
-from openshift_checks import OpenShiftCheck, get_var
|
|
|
+from openshift_checks import OpenShiftCheck
|
|
|
from openshift_checks.mixins import DockerHostMixin
|
|
|
|
|
|
|
|
@@ -22,25 +22,26 @@ DEPLOYMENT_IMAGE_INFO = {
|
|
|
class DockerImageAvailability(DockerHostMixin, OpenShiftCheck):
|
|
|
"""Check that required Docker images are available.
|
|
|
|
|
|
- This check attempts to ensure that required docker images are
|
|
|
- either present locally, or able to be pulled down from available
|
|
|
- registries defined in a host machine.
|
|
|
+ Determine docker images that an install would require and check that they
|
|
|
+ are either present in the host's docker index, or available for the host to pull
|
|
|
+ with known registries as defined in our inventory file (or defaults).
|
|
|
"""
|
|
|
|
|
|
name = "docker_image_availability"
|
|
|
tags = ["preflight"]
|
|
|
- dependencies = ["skopeo", "python-docker-py"]
|
|
|
+ # we use python-docker-py to check local docker for images, and skopeo
|
|
|
+ # to look for images available remotely without waiting to pull them.
|
|
|
+ dependencies = ["python-docker-py", "skopeo"]
|
|
|
|
|
|
- @classmethod
|
|
|
- def is_active(cls, task_vars):
|
|
|
+ def is_active(self):
|
|
|
"""Skip hosts with unsupported deployment types."""
|
|
|
- deployment_type = get_var(task_vars, "openshift_deployment_type")
|
|
|
+ deployment_type = self.get_var("openshift_deployment_type")
|
|
|
has_valid_deployment_type = deployment_type in DEPLOYMENT_IMAGE_INFO
|
|
|
|
|
|
- return super(DockerImageAvailability, cls).is_active(task_vars) and has_valid_deployment_type
|
|
|
+ return super(DockerImageAvailability, self).is_active() and has_valid_deployment_type
|
|
|
|
|
|
- def run(self, tmp, task_vars):
|
|
|
- msg, failed, changed = self.ensure_dependencies(task_vars)
|
|
|
+ def run(self):
|
|
|
+ msg, failed, changed = self.ensure_dependencies()
|
|
|
if failed:
|
|
|
return {
|
|
|
"failed": True,
|
|
@@ -48,18 +49,18 @@ class DockerImageAvailability(DockerHostMixin, OpenShiftCheck):
|
|
|
"msg": "Some dependencies are required in order to check Docker image availability.\n" + msg
|
|
|
}
|
|
|
|
|
|
- required_images = self.required_images(task_vars)
|
|
|
- missing_images = set(required_images) - set(self.local_images(required_images, task_vars))
|
|
|
+ required_images = self.required_images()
|
|
|
+ missing_images = set(required_images) - set(self.local_images(required_images))
|
|
|
|
|
|
# exit early if all images were found locally
|
|
|
if not missing_images:
|
|
|
return {"changed": changed}
|
|
|
|
|
|
- registries = self.known_docker_registries(task_vars)
|
|
|
+ registries = self.known_docker_registries()
|
|
|
if not registries:
|
|
|
return {"failed": True, "msg": "Unable to retrieve any docker registries.", "changed": changed}
|
|
|
|
|
|
- available_images = self.available_images(missing_images, registries, task_vars)
|
|
|
+ available_images = self.available_images(missing_images, registries)
|
|
|
unavailable_images = set(missing_images) - set(available_images)
|
|
|
|
|
|
if unavailable_images:
|
|
@@ -74,8 +75,7 @@ class DockerImageAvailability(DockerHostMixin, OpenShiftCheck):
|
|
|
|
|
|
return {"changed": changed}
|
|
|
|
|
|
- @staticmethod
|
|
|
- def required_images(task_vars):
|
|
|
+ def required_images(self):
|
|
|
"""
|
|
|
Determine which images we expect to need for this host.
|
|
|
Returns: a set of required images like 'openshift/origin:v3.6'
|
|
@@ -92,17 +92,17 @@ class DockerImageAvailability(DockerHostMixin, OpenShiftCheck):
|
|
|
Registry is not included in constructed images. It may be in oreg_url or etcd image.
|
|
|
"""
|
|
|
required = set()
|
|
|
- deployment_type = get_var(task_vars, "openshift_deployment_type")
|
|
|
- host_groups = get_var(task_vars, "group_names")
|
|
|
+ deployment_type = self.get_var("openshift_deployment_type")
|
|
|
+ host_groups = self.get_var("group_names")
|
|
|
# containerized etcd may not have openshift_image_tag, see bz 1466622
|
|
|
- image_tag = get_var(task_vars, "openshift_image_tag", default="latest")
|
|
|
+ image_tag = self.get_var("openshift_image_tag", default="latest")
|
|
|
image_info = DEPLOYMENT_IMAGE_INFO[deployment_type]
|
|
|
if not image_info:
|
|
|
return required
|
|
|
|
|
|
# template for images that run on top of OpenShift
|
|
|
image_url = "{}/{}-{}:{}".format(image_info["namespace"], image_info["name"], "${component}", "${version}")
|
|
|
- image_url = get_var(task_vars, "oreg_url", default="") or image_url
|
|
|
+ image_url = self.get_var("oreg_url", default="") or image_url
|
|
|
if 'nodes' in host_groups:
|
|
|
for suffix in NODE_IMAGE_SUFFIXES:
|
|
|
required.add(image_url.replace("${component}", suffix).replace("${version}", image_tag))
|
|
@@ -112,7 +112,7 @@ class DockerImageAvailability(DockerHostMixin, OpenShiftCheck):
|
|
|
required.add(image_info["registry_console_image"])
|
|
|
|
|
|
# images for containerized components
|
|
|
- if get_var(task_vars, "openshift", "common", "is_containerized"):
|
|
|
+ if self.get_var("openshift", "common", "is_containerized"):
|
|
|
components = set()
|
|
|
if 'nodes' in host_groups:
|
|
|
components.update(["node", "openvswitch"])
|
|
@@ -125,28 +125,27 @@ class DockerImageAvailability(DockerHostMixin, OpenShiftCheck):
|
|
|
|
|
|
return required
|
|
|
|
|
|
- def local_images(self, images, task_vars):
|
|
|
+ def local_images(self, images):
|
|
|
"""Filter a list of images and return those available locally."""
|
|
|
return [
|
|
|
image for image in images
|
|
|
- if self.is_image_local(image, task_vars)
|
|
|
+ if self.is_image_local(image)
|
|
|
]
|
|
|
|
|
|
- def is_image_local(self, image, task_vars):
|
|
|
+ def is_image_local(self, image):
|
|
|
"""Check if image is already in local docker index."""
|
|
|
- result = self.execute_module("docker_image_facts", {"name": image}, task_vars=task_vars)
|
|
|
+ result = self.execute_module("docker_image_facts", {"name": image})
|
|
|
if result.get("failed", False):
|
|
|
return False
|
|
|
|
|
|
return bool(result.get("images", []))
|
|
|
|
|
|
- @staticmethod
|
|
|
- def known_docker_registries(task_vars):
|
|
|
+ def known_docker_registries(self):
|
|
|
"""Build a list of docker registries available according to inventory vars."""
|
|
|
- docker_facts = get_var(task_vars, "openshift", "docker")
|
|
|
+ docker_facts = self.get_var("openshift", "docker")
|
|
|
regs = set(docker_facts["additional_registries"])
|
|
|
|
|
|
- deployment_type = get_var(task_vars, "openshift_deployment_type")
|
|
|
+ deployment_type = self.get_var("openshift_deployment_type")
|
|
|
if deployment_type == "origin":
|
|
|
regs.update(["docker.io"])
|
|
|
elif "enterprise" in deployment_type:
|
|
@@ -154,24 +153,25 @@ class DockerImageAvailability(DockerHostMixin, OpenShiftCheck):
|
|
|
|
|
|
return list(regs)
|
|
|
|
|
|
- def available_images(self, images, registries, task_vars):
|
|
|
- """Inspect existing images using Skopeo and return all images successfully inspected."""
|
|
|
+ def available_images(self, images, default_registries):
|
|
|
+ """Search remotely for images. Returns: list of images found."""
|
|
|
return [
|
|
|
image for image in images
|
|
|
- if self.is_available_skopeo_image(image, registries, task_vars)
|
|
|
+ if self.is_available_skopeo_image(image, default_registries)
|
|
|
]
|
|
|
|
|
|
- def is_available_skopeo_image(self, image, registries, task_vars):
|
|
|
+ def is_available_skopeo_image(self, image, default_registries):
|
|
|
"""Use Skopeo to determine if required image exists in known registry(s)."""
|
|
|
+ registries = default_registries
|
|
|
|
|
|
- # if image does already includes a registry, just use that
|
|
|
+ # if image already includes a registry, only use that
|
|
|
if image.count("/") > 1:
|
|
|
registry, image = image.split("/", 1)
|
|
|
registries = [registry]
|
|
|
|
|
|
for registry in registries:
|
|
|
args = {"_raw_params": "skopeo inspect --tls-verify=false docker://{}/{}".format(registry, image)}
|
|
|
- result = self.execute_module("command", args, task_vars=task_vars)
|
|
|
+ result = self.execute_module("command", args)
|
|
|
if result.get("rc", 0) == 0 and not result.get("failed"):
|
|
|
return True
|
|
|
|