Projet

Général

Profil

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

root / plugins / puppet / puppetdb @ a7139bca

Historique | Voir | Annoter | Télécharger (6,12 ko)

1
#!/usr/bin/env python3
2
"""
3
=head1 NAME
4

    
5
puppetdb - Create a graph out of PuppetDB's JVM memory usage.
6

    
7
=head1 CONFIGURATION
8

    
9
This plugin does not need to run with a privileged user.
10

    
11
By default, the plugin will send requests to a PuppetDB instance on localhost.
12

    
13
Plugin configuration parameters:
14

    
15
  * pdburl:
16
    Set the URL to your PuppetDB instance. This url should point to the mbeans
17
    endpoint. By default this has a value of
18
    http://localhost:8080/metrics/v1/mbeans
19

    
20
  * timeout:
21
    Time in seconds (int) to wait for a result when querying the REST API. By
22
    default, wait for 2 seconds
23

    
24
  * ca:
25
    Path to the Certificate Authority used for verifying a cert received from
26
    the PuppetDB server during an https connection. This can be useful if the
27
    cert used by PuppetDB was signed by the puppetmaster's CA. This option is
28
    not necessary if a plaintext connection is used (e.g. if pdburl starts
29
    with 'http://').
30

    
31
  * cert:
32
    Path to the TLS certificate file used for establishing client
33
    communication for an https connection. This option should be paired with
34
    the `key` option. This option is not necessary if a plaintext connection
35
    is used (e.g. if pdburl starts with 'http://').
36

    
37
  * key:
38
    Path to the TLS private key used for establishing client communication for
39
    an https connection. This option should be paired with the `cert` option.
40
    This option is not necessary if a plaintext connection is used (e.g. if
41
    pdburl starts with 'http://').
42

    
43
Example:
44

    
45
  [puppetdb]
46
    env.pdburl https://puppetdb.example.com:8080/metrics/v1/mbeans
47
    env.timeout 5
48
    env.ca /etc/puppetboard/ca.pem
49
    env.cert /etc/puppetboard/client_cert.pem
50
    env.key /etc/puppetboard/client_key.pem
51

    
52
=head1 DEPENDENCIES
53

    
54
python3-requests
55

    
56
=head1 COMPATIBILITY
57

    
58
  * PuppetDB 6.x: https://puppet.com/docs/puppetdb/6.0/api/metrics/v1/mbeans.html#jvm-metrics
59

    
60
=head1 AUTHOR
61

    
62
Copyright (c) 2020, Gabriel Filion, gabster@lelutin.ca
63

    
64
=head1 LICENSE
65

    
66
This code is licensed under GPLv3+
67

    
68
=cut
69
"""
70

    
71
import os
72
import sys
73
import requests
74

    
75

    
76
class WrongStatusCode(Exception):
77
    pass
78

    
79

    
80
def rest_request(url, timeout, ca, key_pair):
81
    """Make a GET request to URL. We expect a 200 response.
82
    This function will let exceptions from requests raise through to indicate
83
    request failure.
84
    If response code is not 200, it will raise a WrongStatusCode exception.
85
    """
86
    headers = {'content-type': 'application/json', 'Accept-Charset': 'UTF-8'}
87

    
88
    ssl_options = {}
89
    if ca:
90
        ssl_options['verify'] = ca
91
    if key_pair:
92
        ssl_options['cert'] = key_pair
93

    
94
    resp = requests.get(url, headers=headers, timeout=timeout, **ssl_options)
95
    if resp.status_code != 200:
96
        err = f"GET Request to '{url}' returned code {resp.status_code}; expected 200."  # noqa: E501
97
        raise WrongStatusCode(err)
98
    return resp
99

    
100

    
101
def config():
102
    """Print all graph configuration for munin."""
103
    print("graph_title PuppetDB JVM Memory usage")
104
    print("graph_args --base 1024")
105
    print("graph_vlabel Bytes")
106
    print("graph_info This graph shows how much memory from the JVM "
107
          + "Heapspace is being used by PuppetDB")
108
    print("graph_category other")
109
    print("graph_order jvm_mem_max jvm_mem_committed jvm_mem_used")
110

    
111
    # Fields
112
    print("jvm_mem_max.min 0")
113
    print("jvm_mem_max.label JVM Max mem")
114
    print("jvm_mem_max.info Maximum memory allocated to the JVM")
115

    
116
    print("jvm_mem_committed.label JVM Committed mem")
117
    print("jvm_mem_committed.min 0")
118
    print("jvm_mem_committed.info Memory currently committed by the JVM")
119

    
120
    print("jvm_mem_used.label JVM Used mem")
121
    print("jvm_mem_used.min 0")
122
    print("jvm_mem_used.info Memory currently used by objects in the JVM")
123
    print("jvm_mem_used.draw AREA")
124

    
125

    
126
def fetch_field_values(mbeans_url, timeout, ca, key_pair):
127
    """Get values from PuppetDB and print them out."""
128
    memory_url = f"{mbeans_url}/java.lang:type=Memory"
129

    
130
    try:
131
        mem_req = rest_request(memory_url, timeout, ca, key_pair)
132
    except Exception as e:
133
        print(f"HTTP Request did not complete successfully: {e}",
134
              file=sys.stderr)
135
        exit(1)
136

    
137
    try:
138
        memory = mem_req.json()
139
    except Exception as e:
140
        print(f"Could not parse JSON, can't find the info we need: {e}",
141
              file=sys.stderr)
142
        exit(1)
143

    
144
    try:
145
        heap = memory['HeapMemoryUsage']
146
        mem_max = heap['max']
147
        mem_committed = heap['committed']
148
        mem_used = heap['used']
149
    except Exception as e:
150
        print(f"Memory values were not found in the reply JSON: {e}",
151
              file=sys.stderr)
152
        exit(1)
153

    
154
    print(f"jvm_mem_max.value {mem_max}")
155
    print(f"jvm_mem_committed.value {mem_committed}")
156
    print(f"jvm_mem_used.value {mem_used}")
157

    
158

    
159
if __name__ == '__main__':
160
    mbeans_url = os.environ.get('pdburl', 'http://localhost:8080/metrics/v1/mbeans')
161
    try:
162
        timeout = int(os.environ.get('timeout', '2'))
163
    except ValueError as e:
164
        print(f"Invalid value for timeout: {e}", file=sys.stderr)
165
        exit(1)
166

    
167
    ca = os.environ.get('ca', None)
168
    if ca:
169
        if not os.path.exists(ca):
170
            print(f"CA file '{ca}' not found.", file=sys.stderr)
171
            exit(1)
172

    
173
    cert = os.environ.get('cert', None)
174
    key = os.environ.get('key', None)
175
    if cert or key:
176
        if cert and key:
177
            if not os.path.exists(cert):
178
                print(f"Certificate file '{cert}' not found.", file=sys.stderr)
179
                exit(1)
180
            if not os.path.exists(key):
181
                print(f"Key file '{key}' not found.", file=sys.stderr)
182
                exit(1)
183
        else:
184
            print("Only one of 'cert' and 'key' supplied. "
185
                  "Both are needed for client authentication.",
186
                  file=sys.stderr)
187
            exit(1)
188

    
189
    if len(sys.argv) > 1 and sys.argv[1] == 'autoconf':
190
        try:
191
            dummy = rest_request(mbeans_url, timeout, ca, (cert, key))
192
        except Exception as e:
193
            print(f"no ({e})")
194
            exit(0)
195

    
196
        print("yes")
197
        exit(0)
198

    
199
    if len(sys.argv) > 1 and sys.argv[1] == 'config':
200
        config()
201
        exit(0)
202

    
203
    fetch_field_values(mbeans_url, timeout, ca, (cert, key))