summaryrefslogtreecommitdiffstats
path: root/roles/openshift_health_checker/openshift_checks/disk_availability.py
diff options
context:
space:
mode:
Diffstat (limited to 'roles/openshift_health_checker/openshift_checks/disk_availability.py')
-rw-r--r--roles/openshift_health_checker/openshift_checks/disk_availability.py96
1 files changed, 59 insertions, 37 deletions
diff --git a/roles/openshift_health_checker/openshift_checks/disk_availability.py b/roles/openshift_health_checker/openshift_checks/disk_availability.py
index e93e81efa..cdf56e959 100644
--- a/roles/openshift_health_checker/openshift_checks/disk_availability.py
+++ b/roles/openshift_health_checker/openshift_checks/disk_availability.py
@@ -1,9 +1,8 @@
"""Check that there is enough disk space in predefined paths."""
-import os.path
import tempfile
-from openshift_checks import OpenShiftCheck, OpenShiftCheckException, get_var
+from openshift_checks import OpenShiftCheck, OpenShiftCheckException
class DiskAvailability(OpenShiftCheck):
@@ -35,22 +34,27 @@ class DiskAvailability(OpenShiftCheck):
},
}
- @classmethod
- def is_active(cls, task_vars):
+ # recommended disk space for each location under an upgrade context
+ recommended_disk_upgrade_bytes = {
+ '/var': {
+ 'masters': 10 * 10**9,
+ 'nodes': 5 * 10 ** 9,
+ 'etcd': 5 * 10 ** 9,
+ },
+ }
+
+ def is_active(self):
"""Skip hosts that do not have recommended disk space requirements."""
- group_names = get_var(task_vars, "group_names", default=[])
+ group_names = self.get_var("group_names", default=[])
active_groups = set()
- for recommendation in cls.recommended_disk_space_bytes.values():
+ for recommendation in self.recommended_disk_space_bytes.values():
active_groups.update(recommendation.keys())
has_disk_space_recommendation = bool(active_groups.intersection(group_names))
- 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")
- ansible_mounts = {mount['mount']: mount for mount in ansible_mounts}
+ return super(DiskAvailability, self).is_active() and has_disk_space_recommendation
- user_config = get_var(task_vars, "openshift_check_min_host_disk_gb", default={})
+ def run(self):
+ group_names = self.get_var("group_names")
+ user_config = self.get_var("openshift_check_min_host_disk_gb", default={})
try:
# For backwards-compatibility, if openshift_check_min_host_disk_gb
# is a number, then it overrides the required config for '/var'.
@@ -66,13 +70,17 @@ class DiskAvailability(OpenShiftCheck):
# If it is not a number, then it should be a nested dict.
pass
+ self.register_log("recommended thresholds", self.recommended_disk_space_bytes)
+ if user_config:
+ self.register_log("user-configured thresholds", user_config)
+
# TODO: as suggested in
# https://github.com/openshift/openshift-ansible/pull/4436#discussion_r122180021,
# maybe we could support checking disk availability in paths that are
# not part of the official recommendation but present in the user
# configuration.
for path, recommendation in self.recommended_disk_space_bytes.items():
- free_bytes = self.free_bytes(path, ansible_mounts)
+ free_bytes = self.free_bytes(path)
recommended_bytes = max(recommendation.get(name, 0) for name in group_names)
config = user_config.get(path, {})
@@ -81,35 +89,49 @@ class DiskAvailability(OpenShiftCheck):
config_bytes = max(config.get(name, 0) for name in group_names) * 10**9
recommended_bytes = config_bytes or recommended_bytes
+ # if an "upgrade" context is set, update the minimum disk requirement
+ # as this signifies an in-place upgrade - the node might have the
+ # required total disk space, but some of that space may already be
+ # in use by the existing OpenShift deployment.
+ context = self.get_var("r_openshift_health_checker_playbook_context", default="")
+ if context == "upgrade":
+ recommended_upgrade_paths = self.recommended_disk_upgrade_bytes.get(path, {})
+ if recommended_upgrade_paths:
+ recommended_bytes = config_bytes or max(recommended_upgrade_paths.get(name, 0)
+ for name in group_names)
+
if free_bytes < recommended_bytes:
free_gb = float(free_bytes) / 10**9
recommended_gb = float(recommended_bytes) / 10**9
- return {
- 'failed': True,
- 'msg': (
- 'Available disk space in "{}" ({:.1f} GB) '
- 'is below minimum recommended ({:.1f} GB)'
- ).format(path, free_gb, recommended_gb)
- }
+ msg = (
+ 'Available disk space in "{}" ({:.1f} GB) '
+ 'is below minimum recommended ({:.1f} GB)'
+ ).format(path, free_gb, recommended_gb)
+
+ # warn if check failed under an "upgrade" context
+ # due to limits imposed by the user config
+ if config_bytes and context == "upgrade":
+ msg += ('\n\nMake sure to account for decreased disk space during an upgrade\n'
+ 'due to an existing OpenShift deployment. Please check the value of\n'
+ ' openshift_check_min_host_disk_gb={}\n'
+ 'in your Ansible inventory, and lower the recommended disk space availability\n'
+ 'if necessary for this upgrade.').format(config_bytes)
+
+ self.register_failure(msg)
return {}
- @staticmethod
- def free_bytes(path, ansible_mounts):
+ def free_bytes(self, path):
"""Return the size available in path based on ansible_mounts."""
- mount_point = path
- # arbitry value to prevent an infinite loop, in the unlike case that '/'
- # is not in ansible_mounts.
- max_depth = 32
- while mount_point not in ansible_mounts and max_depth > 0:
- mount_point = os.path.dirname(mount_point)
- max_depth -= 1
-
+ mount = self.find_ansible_mount(path)
try:
- free_bytes = ansible_mounts[mount_point]['size_available']
+ return mount['size_available']
except KeyError:
- known_mounts = ', '.join('"{}"'.format(mount) for mount in sorted(ansible_mounts)) or 'none'
- msg = 'Unable to determine disk availability for "{}". Known mount points: {}.'
- raise OpenShiftCheckException(msg.format(path, known_mounts))
-
- return free_bytes
+ raise OpenShiftCheckException(
+ 'Unable to retrieve disk availability for "{path}".\n'
+ 'Ansible facts included a matching mount point for this path:\n'
+ ' {mount}\n'
+ 'however it is missing the size_available field.\n'
+ 'To investigate, you can inspect the output of `ansible -m setup <host>`'
+ ''.format(path=path, mount=mount)
+ )