openldap.chart.py 7.0 KB

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