~aisrael/charms/precise/mysql/fix-charm-lint

« back to all changes in this revision

Viewing changes to hooks/charmhelpers/contrib/charmsupport/nrpe.py

  • Committer: Charles Butler
  • Date: 2014-08-04 20:06:59 UTC
  • mfrom: (122.1.3 mysql)
  • Revision ID: chuck@dasroot.net-20140804200659-49nc02ddc1g012im
  Jacek Nykis 2014-05-09 Added check_mysql nagios check to nrpe-external-master relation
  Jacek Nykis 2014-05-08 Added support for nrpe-external-master relation. Added simple check_pro...
  Jacek Nykis 2014-05-08 Imported charmhelpers.contrib for NRPE class. Updated charmhelpers to l...

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
"""Compatibility with the nrpe-external-master charm"""
 
2
# Copyright 2012 Canonical Ltd.
 
3
#
 
4
# Authors:
 
5
#  Matthew Wedgwood <matthew.wedgwood@canonical.com>
 
6
 
 
7
import subprocess
 
8
import pwd
 
9
import grp
 
10
import os
 
11
import re
 
12
import shlex
 
13
import yaml
 
14
 
 
15
from charmhelpers.core.hookenv import (
 
16
    config,
 
17
    local_unit,
 
18
    log,
 
19
    relation_ids,
 
20
    relation_set,
 
21
)
 
22
 
 
23
from charmhelpers.core.host import service
 
24
 
 
25
# This module adds compatibility with the nrpe-external-master and plain nrpe
 
26
# subordinate charms. To use it in your charm:
 
27
#
 
28
# 1. Update metadata.yaml
 
29
#
 
30
#   provides:
 
31
#     (...)
 
32
#     nrpe-external-master:
 
33
#       interface: nrpe-external-master
 
34
#       scope: container
 
35
#
 
36
#   and/or
 
37
#
 
38
#   provides:
 
39
#     (...)
 
40
#     local-monitors:
 
41
#       interface: local-monitors
 
42
#       scope: container
 
43
 
 
44
#
 
45
# 2. Add the following to config.yaml
 
46
#
 
47
#    nagios_context:
 
48
#      default: "juju"
 
49
#      type: string
 
50
#      description: |
 
51
#        Used by the nrpe subordinate charms.
 
52
#        A string that will be prepended to instance name to set the host name
 
53
#        in nagios. So for instance the hostname would be something like:
 
54
#            juju-myservice-0
 
55
#        If you're running multiple environments with the same services in them
 
56
#        this allows you to differentiate between them.
 
57
#
 
58
# 3. Add custom checks (Nagios plugins) to files/nrpe-external-master
 
59
#
 
60
# 4. Update your hooks.py with something like this:
 
61
#
 
62
#    from charmsupport.nrpe import NRPE
 
63
#    (...)
 
64
#    def update_nrpe_config():
 
65
#        nrpe_compat = NRPE()
 
66
#        nrpe_compat.add_check(
 
67
#            shortname = "myservice",
 
68
#            description = "Check MyService",
 
69
#            check_cmd = "check_http -w 2 -c 10 http://localhost"
 
70
#            )
 
71
#        nrpe_compat.add_check(
 
72
#            "myservice_other",
 
73
#            "Check for widget failures",
 
74
#            check_cmd = "/srv/myapp/scripts/widget_check"
 
75
#            )
 
76
#        nrpe_compat.write()
 
77
#
 
78
#    def config_changed():
 
79
#        (...)
 
80
#        update_nrpe_config()
 
81
#
 
82
#    def nrpe_external_master_relation_changed():
 
83
#        update_nrpe_config()
 
84
#
 
85
#    def local_monitors_relation_changed():
 
86
#        update_nrpe_config()
 
87
#
 
88
# 5. ln -s hooks.py nrpe-external-master-relation-changed
 
89
#    ln -s hooks.py local-monitors-relation-changed
 
90
 
 
91
 
 
92
class CheckException(Exception):
 
93
    pass
 
94
 
 
95
 
 
96
class Check(object):
 
97
    shortname_re = '[A-Za-z0-9-_]+$'
 
98
    service_template = ("""
 
99
#---------------------------------------------------
 
100
# This file is Juju managed
 
101
#---------------------------------------------------
 
102
define service {{
 
103
    use                             active-service
 
104
    host_name                       {nagios_hostname}
 
105
    service_description             {nagios_hostname}[{shortname}] """
 
106
                        """{description}
 
107
    check_command                   check_nrpe!{command}
 
108
    servicegroups                   {nagios_servicegroup}
 
109
}}
 
110
""")
 
111
 
 
112
    def __init__(self, shortname, description, check_cmd):
 
113
        super(Check, self).__init__()
 
114
        # XXX: could be better to calculate this from the service name
 
115
        if not re.match(self.shortname_re, shortname):
 
116
            raise CheckException("shortname must match {}".format(
 
117
                Check.shortname_re))
 
118
        self.shortname = shortname
 
119
        self.command = "check_{}".format(shortname)
 
120
        # Note: a set of invalid characters is defined by the
 
121
        # Nagios server config
 
122
        # The default is: illegal_object_name_chars=`~!$%^&*"|'<>?,()=
 
123
        self.description = description
 
124
        self.check_cmd = self._locate_cmd(check_cmd)
 
125
 
 
126
    def _locate_cmd(self, check_cmd):
 
127
        search_path = (
 
128
            '/usr/lib/nagios/plugins',
 
129
            '/usr/local/lib/nagios/plugins',
 
130
        )
 
131
        parts = shlex.split(check_cmd)
 
132
        for path in search_path:
 
133
            if os.path.exists(os.path.join(path, parts[0])):
 
134
                command = os.path.join(path, parts[0])
 
135
                if len(parts) > 1:
 
136
                    command += " " + " ".join(parts[1:])
 
137
                return command
 
138
        log('Check command not found: {}'.format(parts[0]))
 
139
        return ''
 
140
 
 
141
    def write(self, nagios_context, hostname):
 
142
        nrpe_check_file = '/etc/nagios/nrpe.d/{}.cfg'.format(
 
143
            self.command)
 
144
        with open(nrpe_check_file, 'w') as nrpe_check_config:
 
145
            nrpe_check_config.write("# check {}\n".format(self.shortname))
 
146
            nrpe_check_config.write("command[{}]={}\n".format(
 
147
                self.command, self.check_cmd))
 
148
 
 
149
        if not os.path.exists(NRPE.nagios_exportdir):
 
150
            log('Not writing service config as {} is not accessible'.format(
 
151
                NRPE.nagios_exportdir))
 
152
        else:
 
153
            self.write_service_config(nagios_context, hostname)
 
154
 
 
155
    def write_service_config(self, nagios_context, hostname):
 
156
        for f in os.listdir(NRPE.nagios_exportdir):
 
157
            if re.search('.*{}.cfg'.format(self.command), f):
 
158
                os.remove(os.path.join(NRPE.nagios_exportdir, f))
 
159
 
 
160
        templ_vars = {
 
161
            'nagios_hostname': hostname,
 
162
            'nagios_servicegroup': nagios_context,
 
163
            'description': self.description,
 
164
            'shortname': self.shortname,
 
165
            'command': self.command,
 
166
        }
 
167
        nrpe_service_text = Check.service_template.format(**templ_vars)
 
168
        nrpe_service_file = '{}/service__{}_{}.cfg'.format(
 
169
            NRPE.nagios_exportdir, hostname, self.command)
 
170
        with open(nrpe_service_file, 'w') as nrpe_service_config:
 
171
            nrpe_service_config.write(str(nrpe_service_text))
 
172
 
 
173
    def run(self):
 
174
        subprocess.call(self.check_cmd)
 
175
 
 
176
 
 
177
class NRPE(object):
 
178
    nagios_logdir = '/var/log/nagios'
 
179
    nagios_exportdir = '/var/lib/nagios/export'
 
180
    nrpe_confdir = '/etc/nagios/nrpe.d'
 
181
 
 
182
    def __init__(self, hostname=None):
 
183
        super(NRPE, self).__init__()
 
184
        self.config = config()
 
185
        self.nagios_context = self.config['nagios_context']
 
186
        self.unit_name = local_unit().replace('/', '-')
 
187
        if hostname:
 
188
            self.hostname = hostname
 
189
        else:
 
190
            self.hostname = "{}-{}".format(self.nagios_context, self.unit_name)
 
191
        self.checks = []
 
192
 
 
193
    def add_check(self, *args, **kwargs):
 
194
        self.checks.append(Check(*args, **kwargs))
 
195
 
 
196
    def write(self):
 
197
        try:
 
198
            nagios_uid = pwd.getpwnam('nagios').pw_uid
 
199
            nagios_gid = grp.getgrnam('nagios').gr_gid
 
200
        except:
 
201
            log("Nagios user not set up, nrpe checks not updated")
 
202
            return
 
203
 
 
204
        if not os.path.exists(NRPE.nagios_logdir):
 
205
            os.mkdir(NRPE.nagios_logdir)
 
206
            os.chown(NRPE.nagios_logdir, nagios_uid, nagios_gid)
 
207
 
 
208
        nrpe_monitors = {}
 
209
        monitors = {"monitors": {"remote": {"nrpe": nrpe_monitors}}}
 
210
        for nrpecheck in self.checks:
 
211
            nrpecheck.write(self.nagios_context, self.hostname)
 
212
            nrpe_monitors[nrpecheck.shortname] = {
 
213
                "command": nrpecheck.command,
 
214
            }
 
215
 
 
216
        service('restart', 'nagios-nrpe-server')
 
217
 
 
218
        for rid in relation_ids("local-monitors"):
 
219
            relation_set(relation_id=rid, monitors=yaml.dump(monitors))