summaryrefslogtreecommitdiffstats
path: root/roles/openshift_health_checker/openshift_checks/logging/logging.py
blob: 05b4d300c673991481e3d5f8ffc5c56d64632693 (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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
"""
Util functions for performing checks on an Elasticsearch, Fluentd, and Kibana stack
"""

import json
import os

from openshift_checks import OpenShiftCheck, OpenShiftCheckException, get_var


class LoggingCheck(OpenShiftCheck):
    """Base class for logging component checks"""

    name = "logging"

    @classmethod
    def is_active(cls, task_vars):
        return super(LoggingCheck, cls).is_active(task_vars) and cls.is_first_master(task_vars)

    @staticmethod
    def is_first_master(task_vars):
        """Run only on first master and only when logging is configured. Returns: bool"""
        logging_deployed = get_var(task_vars, "openshift_hosted_logging_deploy", default=True)
        # Note: It would be nice to use membership in oo_first_master group, however for now it
        # seems best to avoid requiring that setup and just check this is the first master.
        hostname = get_var(task_vars, "ansible_ssh_host") or [None]
        masters = get_var(task_vars, "groups", "masters", default=None) or [None]
        return logging_deployed and masters[0] == hostname

    def run(self, tmp, task_vars):
        pass

    def get_pods_for_component(self, execute_module, namespace, logging_component, task_vars):
        """Get all pods for a given component. Returns: list of pods for component, error string"""
        pod_output = self.exec_oc(
            execute_module,
            namespace,
            "get pods -l component={} -o json".format(logging_component),
            [],
            task_vars
        )
        try:
            pods = json.loads(pod_output)
            if not pods or not pods.get('items'):
                raise ValueError()
        except ValueError:
            # successful run but non-parsing data generally means there were no pods in the namespace
            return None, 'There are no pods in the {} namespace. Is logging deployed?'.format(namespace)

        return pods['items'], None

    @staticmethod
    def not_running_pods(pods):
        """Returns: list of pods not in a ready and running state"""
        return [
            pod for pod in pods
            if any(
                container['ready'] is False
                for container in pod['status']['containerStatuses']
            ) or not any(
                condition['type'] == 'Ready' and condition['status'] == 'True'
                for condition in pod['status']['conditions']
            )
        ]

    @staticmethod
    def exec_oc(execute_module=None, namespace="logging", cmd_str="", extra_args=None, task_vars=None):
        """
        Execute an 'oc' command in the remote host.
        Returns: output of command and namespace,
        or raises OpenShiftCheckException on error
        """
        config_base = get_var(task_vars, "openshift", "common", "config_base")
        args = {
            "namespace": namespace,
            "config_file": os.path.join(config_base, "master", "admin.kubeconfig"),
            "cmd": cmd_str,
            "extra_args": list(extra_args) if extra_args else [],
        }

        result = execute_module("ocutil", args, task_vars)
        if result.get("failed"):
            msg = (
                'Unexpected error using `oc` to validate the logging stack components.\n'
                'Error executing `oc {cmd}`:\n'
                '{error}'
            ).format(cmd=args['cmd'], error=result['result'])

            if result['result'] == '[Errno 2] No such file or directory':
                msg = (
                    "This host is supposed to be a master but does not have the `oc` command where expected.\n"
                    "Has an installation been run on this host yet?"
                )
            raise OpenShiftCheckException(msg)

        return result.get("result", "")