1
+# -*- coding: utf-8 -*-
2
+# Description: openldap netdata python.d module
3
+# Author: Manolis Kartsonakis (ekartsonakis)
4
+# SPDX-License-Identifier: GPL-3.0+
5
+
6
+try:
7
+ import ldap
8
+ HAS_LDAP = True
9
+except ImportError:
10
+ HAS_LDAP = False
11
+
12
+from bases.FrameworkServices.SimpleService import SimpleService
13
+
14
+# default module values (can be overridden per job in `config`)
15
+priority = 60000
16
+
17
+DEFAULT_SERVER = 'localhost'
18
+DEFAULT_PORT = '389'
19
+DEFAULT_TIMEOUT = 1
20
+
21
+ORDER = [
22
+ 'total_connections',
23
+ 'bytes_sent',
24
+ 'operations',
25
+ 'referrals_sent',
26
+ 'entries_sent',
27
+ 'ldap_operations',
28
+ 'waiters'
29
+]
30
+
31
+CHARTS = {
32
+ 'total_connections': {
33
+ 'options': [None, 'Total Connections', 'connections/s', 'ldap', 'openldap.total_connections', 'line'],
34
+ 'lines': [
35
+ ['total_connections', 'connections', 'incremental']
36
+ ]
37
+ },
38
+ 'bytes_sent': {
39
+ 'options': [None, 'Traffic', 'KB/s', 'ldap', 'openldap.traffic_stats', 'line'],
40
+ 'lines': [
41
+ ['bytes_sent', 'sent', 'incremental', 1, 1024]
42
+ ]
43
+ },
44
+ 'operations': {
45
+ 'options': [None, 'Operations Status', 'ops/s', 'ldap', 'openldap.operations_status', 'line'],
46
+ 'lines': [
47
+ ['completed_operations', 'completed', 'incremental'],
48
+ ['initiated_operations', 'initiated', 'incremental']
49
+ ]
50
+ },
51
+ 'referrals_sent': {
52
+ 'options': [None, 'Referrals', 'referals/s', 'ldap', 'openldap.referrals', 'line'],
53
+ 'lines': [
54
+ ['referrals_sent', 'sent', 'incremental']
55
+ ]
56
+ },
57
+ 'entries_sent': {
58
+ 'options': [None, 'Entries', 'entries/s', 'ldap', 'openldap.entries', 'line'],
59
+ 'lines': [
60
+ ['entries_sent', 'sent', 'incremental']
61
+ ]
62
+ },
63
+ 'ldap_operations': {
64
+ 'options': [None, 'Operations', 'ops/s', 'ldap', 'openldap.ldap_operations', 'line'],
65
+ 'lines': [
66
+ ['bind_operations', 'bind', 'incremental'],
67
+ ['search_operations', 'search', 'incremental'],
68
+ ['unbind_operations', 'unbind', 'incremental'],
69
+ ['add_operations', 'add', 'incremental'],
70
+ ['delete_operations', 'delete', 'incremental'],
71
+ ['modify_operations', 'modify', 'incremental'],
72
+ ['compare_operations', 'compare', 'incremental']
73
+ ]
74
+ },
75
+ 'waiters': {
76
+ 'options': [None, 'Waiters', 'waiters/s', 'ldap', 'openldap.waiters', 'line'],
77
+ 'lines': [
78
+ ['write_waiters', 'write', 'incremental'],
79
+ ['read_waiters', 'read', 'incremental']
80
+ ]
81
+ },
82
+}
83
+
84
+# Stuff to gather - make tuples of DN dn and attrib to get
85
+SEARCH_LIST = {
86
+ 'total_connections': (
87
+ 'cn=Total,cn=Connections,cn=Monitor', 'monitorCounter',
88
+ ),
89
+ 'bytes_sent': (
90
+ 'cn=Bytes,cn=Statistics,cn=Monitor', 'monitorCounter',
91
+ ),
92
+ 'completed_operations': (
93
+ 'cn=Operations,cn=Monitor', 'monitorOpCompleted',
94
+ ),
95
+ 'initiated_operations': (
96
+ 'cn=Operations,cn=Monitor', 'monitorOpInitiated',
97
+ ),
98
+ 'referrals_sent': (
99
+ 'cn=Referrals,cn=Statistics,cn=Monitor', 'monitorCounter',
100
+ ),
101
+ 'entries_sent': (
102
+ 'cn=Entries,cn=Statistics,cn=Monitor', 'monitorCounter',
103
+ ),
104
+ 'bind_operations': (
105
+ 'cn=Bind,cn=Operations,cn=Monitor', 'monitorOpCompleted',
106
+ ),
107
+ 'unbind_operations': (
108
+ 'cn=Unbind,cn=Operations,cn=Monitor', 'monitorOpCompleted',
109
+ ),
110
+ 'add_operations': (
111
+ 'cn=Add,cn=Operations,cn=Monitor', 'monitorOpInitiated',
112
+ ),
113
+ 'delete_operations': (
114
+ 'cn=Delete,cn=Operations,cn=Monitor', 'monitorOpCompleted',
115
+ ),
116
+ 'modify_operations': (
117
+ 'cn=Modify,cn=Operations,cn=Monitor', 'monitorOpCompleted',
118
+ ),
119
+ 'compare_operations': (
120
+ 'cn=Compare,cn=Operations,cn=Monitor', 'monitorOpCompleted',
121
+ ),
122
+ 'search_operations': (
123
+ 'cn=Search,cn=Operations,cn=Monitor', 'monitorOpCompleted',
124
+ ),
125
+ 'write_waiters': (
126
+ 'cn=Write,cn=Waiters,cn=Monitor', 'monitorCounter',
127
+ ),
128
+ 'read_waiters': (
129
+ 'cn=Read,cn=Waiters,cn=Monitor', 'monitorCounter',
130
+ ),
131
+}
132
+
133
+
134
+class Service(SimpleService):
135
+ def __init__(self, configuration=None, name=None):
136
+ SimpleService.__init__(self, configuration=configuration, name=name)
137
+ self.order = ORDER
138
+ self.definitions = CHARTS
139
+
140
+ self.server = configuration.get('server', DEFAULT_SERVER)
141
+ self.port = configuration.get('port', DEFAULT_PORT)
142
+ self.username = configuration.get('username')
143
+ self.password = configuration.get('password')
144
+ self.timeout = configuration.get('timeout', DEFAULT_TIMEOUT)
145
+
146
+ self.alive = False
147
+ self.conn = None
148
+
149
+ def disconnect(self):
150
+ if self.conn:
151
+ self.conn.unbind()
152
+ self.conn = None
153
+ self.alive = False
154
+
155
+ def connect(self):
156
+ try:
157
+ self.conn = ldap.initialize('ldap://%s:%s' % (self.server, self.port))
158
+ self.conn.set_option(ldap.OPT_NETWORK_TIMEOUT, self.timeout)
159
+ if self.username and self.password:
160
+ self.conn.simple_bind(self.username, self.password)
161
+ except ldap.LDAPError as error:
162
+ self.error(error)
163
+ return False
164
+
165
+ self.alive = True
166
+ return True
167
+
168
+ def reconnect(self):
169
+ self.disconnect()
170
+ return self.connect()
171
+
172
+ def check(self):
173
+ if not HAS_LDAP:
174
+ self.error("'python-ldap' package is needed")
175
+ return None
176
+
177
+ return self.connect() and self.get_data()
178
+
179
+ def get_data(self):
180
+ if not self.alive and not self.reconnect():
181
+ return None
182
+
183
+ data = dict()
184
+ for key in SEARCH_LIST:
185
+ dn = SEARCH_LIST[key][0]
186
+ attr = SEARCH_LIST[key][1]
187
+ try:
188
+ num = self.conn.search(dn, ldap.SCOPE_BASE, 'objectClass=*', [attr, ])
189
+ result_type, result_data = self.conn.result(num, 1)
190
+ except ldap.LDAPError as error:
191
+ self.error("Empty result. Check bind username/password. Message: ",error)
192
+ self.alive = False
193
+ return None
194
+
195
+ try:
196
+ if result_type == 101:
197
+ val = int(result_data[0][1].values()[0][0])
198
+ except (ValueError, IndexError) as error:
199
+ self.debug(error)
200
+ continue
201
+
202
+ data[key] = val
203
+
204
+ return data