123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168 |
- # -*- coding: utf-8 -*-
- # Description: BOINC netdata python.d module
- # Author: Austin S. Hemmelgarn (Ferroin)
- # SPDX-License-Identifier: GPL-3.0-or-later
- import socket
- from bases.FrameworkServices.SimpleService import SimpleService
- from third_party import boinc_client
- ORDER = [
- 'tasks',
- 'states',
- 'sched_states',
- 'process_states',
- ]
- CHARTS = {
- 'tasks': {
- 'options': [None, 'Overall Tasks', 'tasks', 'boinc', 'boinc.tasks', 'line'],
- 'lines': [
- ['total', 'Total', 'absolute', 1, 1],
- ['active', 'Active', 'absolute', 1, 1]
- ]
- },
- 'states': {
- 'options': [None, 'Tasks per State', 'tasks', 'boinc', 'boinc.states', 'line'],
- 'lines': [
- ['new', 'New', 'absolute', 1, 1],
- ['downloading', 'Downloading', 'absolute', 1, 1],
- ['downloaded', 'Ready to Run', 'absolute', 1, 1],
- ['comperror', 'Compute Errors', 'absolute', 1, 1],
- ['uploading', 'Uploading', 'absolute', 1, 1],
- ['uploaded', 'Uploaded', 'absolute', 1, 1],
- ['aborted', 'Aborted', 'absolute', 1, 1],
- ['upload_failed', 'Failed Uploads', 'absolute', 1, 1]
- ]
- },
- 'sched_states': {
- 'options': [None, 'Tasks per Scheduler State', 'tasks', 'boinc', 'boinc.sched', 'line'],
- 'lines': [
- ['uninit_sched', 'Uninitialized', 'absolute', 1, 1],
- ['preempted', 'Preempted', 'absolute', 1, 1],
- ['scheduled', 'Scheduled', 'absolute', 1, 1]
- ]
- },
- 'process_states': {
- 'options': [None, 'Tasks per Process State', 'tasks', 'boinc', 'boinc.process', 'line'],
- 'lines': [
- ['uninit_proc', 'Uninitialized', 'absolute', 1, 1],
- ['executing', 'Executing', 'absolute', 1, 1],
- ['suspended', 'Suspended', 'absolute', 1, 1],
- ['aborting', 'Aborted', 'absolute', 1, 1],
- ['quit', 'Quit', 'absolute', 1, 1],
- ['copy_pending', 'Copy Pending', 'absolute', 1, 1]
- ]
- }
- }
- # A simple template used for pre-loading the return dictionary to make
- # the _get_data() method simpler.
- _DATA_TEMPLATE = {
- 'total': 0,
- 'active': 0,
- 'new': 0,
- 'downloading': 0,
- 'downloaded': 0,
- 'comperror': 0,
- 'uploading': 0,
- 'uploaded': 0,
- 'aborted': 0,
- 'upload_failed': 0,
- 'uninit_sched': 0,
- 'preempted': 0,
- 'scheduled': 0,
- 'uninit_proc': 0,
- 'executing': 0,
- 'suspended': 0,
- 'aborting': 0,
- 'quit': 0,
- 'copy_pending': 0
- }
- # Map task states to dimensions
- _TASK_MAP = {
- boinc_client.ResultState.NEW: 'new',
- boinc_client.ResultState.FILES_DOWNLOADING: 'downloading',
- boinc_client.ResultState.FILES_DOWNLOADED: 'downloaded',
- boinc_client.ResultState.COMPUTE_ERROR: 'comperror',
- boinc_client.ResultState.FILES_UPLOADING: 'uploading',
- boinc_client.ResultState.FILES_UPLOADED: 'uploaded',
- boinc_client.ResultState.ABORTED: 'aborted',
- boinc_client.ResultState.UPLOAD_FAILED: 'upload_failed'
- }
- # Map scheduler states to dimensions
- _SCHED_MAP = {
- boinc_client.CpuSched.UNINITIALIZED: 'uninit_sched',
- boinc_client.CpuSched.PREEMPTED: 'preempted',
- boinc_client.CpuSched.SCHEDULED: 'scheduled',
- }
- # Maps process states to dimensions
- _PROC_MAP = {
- boinc_client.Process.UNINITIALIZED: 'uninit_proc',
- boinc_client.Process.EXECUTING: 'executing',
- boinc_client.Process.SUSPENDED: 'suspended',
- boinc_client.Process.ABORT_PENDING: 'aborted',
- boinc_client.Process.QUIT_PENDING: 'quit',
- boinc_client.Process.COPY_PENDING: 'copy_pending'
- }
- class Service(SimpleService):
- def __init__(self, configuration=None, name=None):
- SimpleService.__init__(self, configuration=configuration, name=name)
- self.order = ORDER
- self.definitions = CHARTS
- self.host = self.configuration.get('host', 'localhost')
- self.port = self.configuration.get('port', 0)
- self.password = self.configuration.get('password', '')
- self.client = boinc_client.BoincClient(host=self.host, port=self.port, passwd=self.password)
- self.alive = False
- def check(self):
- return self.connect()
- def connect(self):
- self.client.connect()
- self.alive = self.client.connected and self.client.authorized
- return self.alive
- def reconnect(self):
- # The client class itself actually disconnects existing
- # connections when it is told to connect, so we don't need to
- # explicitly disconnect when we're just trying to reconnect.
- return self.connect()
- def is_alive(self):
- if not self.alive:
- return self.reconnect()
- return True
- def _get_data(self):
- if not self.is_alive():
- return None
- data = dict(_DATA_TEMPLATE)
- try:
- results = self.client.get_tasks()
- except socket.error:
- self.error('Connection is dead')
- self.alive = False
- return None
- for task in results:
- data['total'] += 1
- data[_TASK_MAP[task.state]] += 1
- try:
- if task.active_task:
- data['active'] += 1
- data[_SCHED_MAP[task.scheduler_state]] += 1
- data[_PROC_MAP[task.active_task_state]] += 1
- except AttributeError:
- pass
- return data or None
|