summaryrefslogtreecommitdiffstats
path: root/roles/openshift_health_checker/openshift_checks/disk_availability.py
blob: c2792a0fe23b4fd1d436f83ee05bfbc499b67b25 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# pylint: disable=missing-docstring
from openshift_checks import OpenShiftCheck, OpenShiftCheckException, get_var
from openshift_checks.mixins import NotContainerizedMixin


class DiskAvailability(NotContainerizedMixin, OpenShiftCheck):
    """Check that recommended disk space is available before a first-time install."""

    name = "disk_availability"
    tags = ["preflight"]

    # Values taken from the official installation documentation:
    # https://docs.openshift.org/latest/install_config/install/prerequisites.html#system-requirements
    recommended_disk_space_bytes = {
        "masters": 40 * 10**9,
        "nodes": 15 * 10**9,
        "etcd": 20 * 10**9,
    }

    @classmethod
    def is_active(cls, task_vars):
        """Skip hosts that do not have recommended disk space requirements."""
        group_names = get_var(task_vars, "group_names", default=[])
        has_disk_space_recommendation = bool(set(group_names).intersection(cls.recommended_disk_space_bytes))
        return super(DiskAvailability, cls).is_active(task_vars) and has_disk_space_recommendation

    def run(self, tmp, task_vars):
        group_names = get_var(task_vars, "group_names")
        ansible_mounts = get_var(task_vars, "ansible_mounts")

        min_free_bytes = max(self.recommended_disk_space_bytes.get(name, 0) for name in group_names)
        free_bytes = self.openshift_available_disk(ansible_mounts)

        if free_bytes < min_free_bytes:
            return {
                'failed': True,
                'msg': (
                    'Available disk space ({:.1f} GB) for the volume containing '
                    '"/var" is below minimum recommended space ({:.1f} GB)'
                ).format(float(free_bytes) / 10**9, float(min_free_bytes) / 10**9)
            }

        return {}

    @staticmethod
    def openshift_available_disk(ansible_mounts):
        """Determine the available disk space for an OpenShift installation.

        ansible_mounts should be a list of dicts like the 'setup' Ansible module
        returns.
        """
        # priority list in descending order
        supported_mnt_paths = ["/var", "/"]
        available_mnts = {mnt.get("mount"): mnt for mnt in ansible_mounts}

        try:
            for path in supported_mnt_paths:
                if path in available_mnts:
                    return available_mnts[path]["size_available"]
        except KeyError:
            pass

        paths = ''.join(sorted(available_mnts)) or 'none'
        msg = "Unable to determine available disk space. Paths mounted: {}.".format(paths)
        raise OpenShiftCheckException(msg)