Projet

Général

Profil

Paste
Télécharger au format
Statistiques
| Branche: | Révision:

root / plugins / monit / monit_parser @ a7139bca

Historique | Voir | Annoter | Télécharger (3,52 ko)

1
#!/usr/bin/env python3
2

    
3
"""
4
=head1 NAME
5

    
6
monit_parser -  Monit status parser plugin for munin.
7

    
8

    
9
=head1 APPLICABLE SYSTEMS
10

    
11
Any system being able to query monit servers via http.
12

    
13
Monit needs to be configured with the httpd port enabled, e.g.:
14

    
15
    set httpd port 2812
16

    
17
Optionally monit authentication can be configured, e.g.:
18

    
19
    set httpd port 2812
20
      allow munin:s3cr3t read-only
21

    
22

    
23
=head1 CONFIGURATION
24

    
25
By default the monit instance at localhost is queried:
26

    
27
  [monit_parser]
28
  env.port 2812
29
  env.host localhost
30

    
31
Optionally monit authentication can be configured, e.g.:
32

    
33
  [monit_parser]
34
  env.username munin
35
  env.password s3cr3t
36

    
37

    
38
=head1 AUTHOR
39

    
40
  Todd Troxell <ttroxell@debian.org>
41
  Lars Kruse <devel@sumpfralle.de>
42

    
43

    
44
=head1 MAGIC MARKERS
45

    
46
  family=auto
47
  capabilities=autoconf
48

    
49
=cut
50
"""
51

    
52
import xml.dom.minidom
53
import os
54
import sys
55
import urllib.request
56
import base64
57

    
58
MONIT_XML_URL = ("http://{host}:{port}/_status?format=xml"
59
                 .format(host=os.getenv("host", "localhost"),
60
                         port=os.getenv("port", "2812")))
61

    
62

    
63
def sanitize(s):
64
    ok_chars = "abcdefghijklmnopqrstuvwxyz0123456789"
65
    return "".join([char for char in s if char in ok_chars])
66

    
67

    
68
def get_monit_status_xml():
69
    try:
70
        req = urllib.request.Request(url=MONIT_XML_URL)
71
        if os.getenv("password"):
72
            auth_str = "%s:%s" % (os.getenv("username"), os.getenv("password"))
73
            auth_bytes = bytes(auth_str, "utf-8")
74
            auth_base64_bytes = base64.b64encode(auth_bytes)
75
            auth_base64_str = str(auth_base64_bytes, "ascii")
76
            auth_value = "Basic %s" % auth_base64_str
77
            req.add_header("Authorization", auth_value)
78
        conn = urllib.request.urlopen(req)
79
    except urllib.error.URLError:
80
        conn = None
81
    if conn is None:
82
        raise RuntimeError("Failed to open monit status URL: {}".format(MONIT_XML_URL))
83
    else:
84
        return xml.dom.minidom.parse(conn)
85

    
86

    
87
def parse_processes():
88
    dom = get_monit_status_xml()
89
    procs = {}
90
    for item in dom.getElementsByTagName("service"):
91
        if item.getAttribute("type") == "3":
92
            # daemon with memory usage and CPU
93
            name = item.getElementsByTagName("name")[0].childNodes[0].data
94
            memory_usage = item.getElementsByTagName("memory")[0].getElementsByTagName(
95
                "kilobytetotal")[0].childNodes[0].data
96
            cpu_usage = item.getElementsByTagName("cpu")[0].getElementsByTagName(
97
                "percenttotal")[0].childNodes[0].data
98
            procs[name] = {}
99
            procs[name]["total_memory"] = memory_usage
100
            procs[name]["total_cpu"] = cpu_usage
101
    return procs
102

    
103

    
104
action = sys.argv[1] if (len(sys.argv) > 1) else None
105

    
106
if action == 'autoconf':
107
    try:
108
        get_monit_status_xml()
109
        print("yes")
110
    except RuntimeError:
111
        print("no (failed to request monit status)")
112
elif action == 'config':
113
    procs = parse_processes()
114
    print('graph_title Per process stats from Monit')
115
    print('graph_vlabel usage of memory [kB] or cpu [%]')
116
    print('graph_category munin')
117
    for process in procs:
118
        for stat in procs[process]:
119
            print("monit_%s_%s.label %s.%s" % (sanitize(process), stat, process, stat))
120
            if stat == 'total_memory':
121
                # the allocated memory may never be zero
122
                print("monit_%s_%s.warning 1:" % (sanitize(process), stat))
123
else:
124
    for process, stats in parse_processes().items():
125
        for stat_key, stat_value in stats.items():
126
            print("monit_%s_%s.value %s" % (sanitize(process), stat_key, stat_value))