boinc.chart.py 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. # -*- coding: utf-8 -*-
  2. # Description: BOINC netdata python.d module
  3. # Author: Austin S. Hemmelgarn (Ferroin)
  4. # SPDX-License-Identifier: GPL-3.0-or-later
  5. import socket
  6. from bases.FrameworkServices.SimpleService import SimpleService
  7. from third_party import boinc_client
  8. ORDER = [
  9. 'tasks',
  10. 'states',
  11. 'sched_states',
  12. 'process_states',
  13. ]
  14. CHARTS = {
  15. 'tasks': {
  16. 'options': [None, 'Overall Tasks', 'tasks', 'boinc', 'boinc.tasks', 'line'],
  17. 'lines': [
  18. ['total', 'Total', 'absolute', 1, 1],
  19. ['active', 'Active', 'absolute', 1, 1]
  20. ]
  21. },
  22. 'states': {
  23. 'options': [None, 'Tasks per State', 'tasks', 'boinc', 'boinc.states', 'line'],
  24. 'lines': [
  25. ['new', 'New', 'absolute', 1, 1],
  26. ['downloading', 'Downloading', 'absolute', 1, 1],
  27. ['downloaded', 'Ready to Run', 'absolute', 1, 1],
  28. ['comperror', 'Compute Errors', 'absolute', 1, 1],
  29. ['uploading', 'Uploading', 'absolute', 1, 1],
  30. ['uploaded', 'Uploaded', 'absolute', 1, 1],
  31. ['aborted', 'Aborted', 'absolute', 1, 1],
  32. ['upload_failed', 'Failed Uploads', 'absolute', 1, 1]
  33. ]
  34. },
  35. 'sched_states': {
  36. 'options': [None, 'Tasks per Scheduler State', 'tasks', 'boinc', 'boinc.sched', 'line'],
  37. 'lines': [
  38. ['uninit_sched', 'Uninitialized', 'absolute', 1, 1],
  39. ['preempted', 'Preempted', 'absolute', 1, 1],
  40. ['scheduled', 'Scheduled', 'absolute', 1, 1]
  41. ]
  42. },
  43. 'process_states': {
  44. 'options': [None, 'Tasks per Process State', 'tasks', 'boinc', 'boinc.process', 'line'],
  45. 'lines': [
  46. ['uninit_proc', 'Uninitialized', 'absolute', 1, 1],
  47. ['executing', 'Executing', 'absolute', 1, 1],
  48. ['suspended', 'Suspended', 'absolute', 1, 1],
  49. ['aborting', 'Aborted', 'absolute', 1, 1],
  50. ['quit', 'Quit', 'absolute', 1, 1],
  51. ['copy_pending', 'Copy Pending', 'absolute', 1, 1]
  52. ]
  53. }
  54. }
  55. # A simple template used for pre-loading the return dictionary to make
  56. # the _get_data() method simpler.
  57. _DATA_TEMPLATE = {
  58. 'total': 0,
  59. 'active': 0,
  60. 'new': 0,
  61. 'downloading': 0,
  62. 'downloaded': 0,
  63. 'comperror': 0,
  64. 'uploading': 0,
  65. 'uploaded': 0,
  66. 'aborted': 0,
  67. 'upload_failed': 0,
  68. 'uninit_sched': 0,
  69. 'preempted': 0,
  70. 'scheduled': 0,
  71. 'uninit_proc': 0,
  72. 'executing': 0,
  73. 'suspended': 0,
  74. 'aborting': 0,
  75. 'quit': 0,
  76. 'copy_pending': 0
  77. }
  78. # Map task states to dimensions
  79. _TASK_MAP = {
  80. boinc_client.ResultState.NEW: 'new',
  81. boinc_client.ResultState.FILES_DOWNLOADING: 'downloading',
  82. boinc_client.ResultState.FILES_DOWNLOADED: 'downloaded',
  83. boinc_client.ResultState.COMPUTE_ERROR: 'comperror',
  84. boinc_client.ResultState.FILES_UPLOADING: 'uploading',
  85. boinc_client.ResultState.FILES_UPLOADED: 'uploaded',
  86. boinc_client.ResultState.ABORTED: 'aborted',
  87. boinc_client.ResultState.UPLOAD_FAILED: 'upload_failed'
  88. }
  89. # Map scheduler states to dimensions
  90. _SCHED_MAP = {
  91. boinc_client.CpuSched.UNINITIALIZED: 'uninit_sched',
  92. boinc_client.CpuSched.PREEMPTED: 'preempted',
  93. boinc_client.CpuSched.SCHEDULED: 'scheduled',
  94. }
  95. # Maps process states to dimensions
  96. _PROC_MAP = {
  97. boinc_client.Process.UNINITIALIZED: 'uninit_proc',
  98. boinc_client.Process.EXECUTING: 'executing',
  99. boinc_client.Process.SUSPENDED: 'suspended',
  100. boinc_client.Process.ABORT_PENDING: 'aborted',
  101. boinc_client.Process.QUIT_PENDING: 'quit',
  102. boinc_client.Process.COPY_PENDING: 'copy_pending'
  103. }
  104. class Service(SimpleService):
  105. def __init__(self, configuration=None, name=None):
  106. SimpleService.__init__(self, configuration=configuration, name=name)
  107. self.order = ORDER
  108. self.definitions = CHARTS
  109. self.host = self.configuration.get('host', 'localhost')
  110. self.port = self.configuration.get('port', 0)
  111. self.password = self.configuration.get('password', '')
  112. self.client = boinc_client.BoincClient(host=self.host, port=self.port, passwd=self.password)
  113. self.alive = False
  114. def check(self):
  115. return self.connect()
  116. def connect(self):
  117. self.client.connect()
  118. self.alive = self.client.connected and self.client.authorized
  119. return self.alive
  120. def reconnect(self):
  121. # The client class itself actually disconnects existing
  122. # connections when it is told to connect, so we don't need to
  123. # explicitly disconnect when we're just trying to reconnect.
  124. return self.connect()
  125. def is_alive(self):
  126. if not self.alive:
  127. return self.reconnect()
  128. return True
  129. def _get_data(self):
  130. if not self.is_alive():
  131. return None
  132. data = dict(_DATA_TEMPLATE)
  133. try:
  134. results = self.client.get_tasks()
  135. except socket.error:
  136. self.error('Connection is dead')
  137. self.alive = False
  138. return None
  139. for task in results:
  140. data['total'] += 1
  141. data[_TASK_MAP[task.state]] += 1
  142. try:
  143. if task.active_task:
  144. data['active'] += 1
  145. data[_SCHED_MAP[task.scheduler_state]] += 1
  146. data[_PROC_MAP[task.active_task_state]] += 1
  147. except AttributeError:
  148. pass
  149. return data or None