summaryrefslogtreecommitdiffstats
path: root/src/collectors/python.d.plugin/samba/samba.chart.py
blob: 8eebcd60caf87d7247db475631c4d2b2e94eec78 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
# -*- coding: utf-8 -*-
# Description:  samba netdata python.d module
# Author: Christopher Cox <chris_cox@endlessnow.com>
# SPDX-License-Identifier: GPL-3.0-or-later
#
# The netdata user needs to be able to be able to sudo the smbstatus program
# without password:
# netdata ALL=(ALL)       NOPASSWD: /usr/bin/smbstatus -P
#
# This makes calls to smbstatus -P
#
# This just looks at a couple of values out of syscall, and some from smb2.
#
# The Lesser Ops chart is merely a display of current counter values.  They
# didn't seem to change much to me.  However, if you notice something changing
# a lot there, bring one or more out into its own chart and make it incremental
# (like find and notify... good examples).

import re
import os

from bases.FrameworkServices.ExecutableService import ExecutableService
from bases.collection import find_binary

disabled_by_default = True

update_every = 5

ORDER = [
    'syscall_rw',
    'smb2_rw',
    'smb2_create_close',
    'smb2_info',
    'smb2_find',
    'smb2_notify',
    'smb2_sm_count'
]

CHARTS = {
    'syscall_rw': {
        'options': [None, 'R/Ws', 'KiB/s', 'syscall', 'syscall.rw', 'area'],
        'lines': [
            ['syscall_sendfile_bytes', 'sendfile', 'incremental', 1, 1024],
            ['syscall_recvfile_bytes', 'recvfile', 'incremental', -1, 1024]
        ]
    },
    'smb2_rw': {
        'options': [None, 'R/Ws', 'KiB/s', 'smb2', 'smb2.rw', 'area'],
        'lines': [
            ['smb2_read_outbytes', 'readout', 'incremental', 1, 1024],
            ['smb2_write_inbytes', 'writein', 'incremental', -1, 1024],
            ['smb2_read_inbytes', 'readin', 'incremental', 1, 1024],
            ['smb2_write_outbytes', 'writeout', 'incremental', -1, 1024]
        ]
    },
    'smb2_create_close': {
        'options': [None, 'Create/Close', 'operations/s', 'smb2', 'smb2.create_close', 'line'],
        'lines': [
            ['smb2_create_count', 'create', 'incremental', 1, 1],
            ['smb2_close_count', 'close', 'incremental', -1, 1]
        ]
    },
    'smb2_info': {
        'options': [None, 'Info', 'operations/s', 'smb2', 'smb2.get_set_info', 'line'],
        'lines': [
            ['smb2_getinfo_count', 'getinfo', 'incremental', 1, 1],
            ['smb2_setinfo_count', 'setinfo', 'incremental', -1, 1]
        ]
    },
    'smb2_find': {
        'options': [None, 'Find', 'operations/s', 'smb2', 'smb2.find', 'line'],
        'lines': [
            ['smb2_find_count', 'find', 'incremental', 1, 1]
        ]
    },
    'smb2_notify': {
        'options': [None, 'Notify', 'operations/s', 'smb2', 'smb2.notify', 'line'],
        'lines': [
            ['smb2_notify_count', 'notify', 'incremental', 1, 1]
        ]
    },
    'smb2_sm_count': {
        'options': [None, 'Lesser Ops', 'count', 'smb2', 'smb2.sm_counters', 'stacked'],
        'lines': [
            ['smb2_tcon_count', 'tcon', 'absolute', 1, 1],
            ['smb2_negprot_count', 'negprot', 'absolute', 1, 1],
            ['smb2_tdis_count', 'tdis', 'absolute', 1, 1],
            ['smb2_cancel_count', 'cancel', 'absolute', 1, 1],
            ['smb2_logoff_count', 'logoff', 'absolute', 1, 1],
            ['smb2_flush_count', 'flush', 'absolute', 1, 1],
            ['smb2_lock_count', 'lock', 'absolute', 1, 1],
            ['smb2_keepalive_count', 'keepalive', 'absolute', 1, 1],
            ['smb2_break_count', 'break', 'absolute', 1, 1],
            ['smb2_sessetup_count', 'sessetup', 'absolute', 1, 1]
        ]
    }
}

SUDO = 'sudo'
SMBSTATUS = 'smbstatus'


class Service(ExecutableService):
    def __init__(self, configuration=None, name=None):
        ExecutableService.__init__(self, configuration=configuration, name=name)
        self.order = ORDER
        self.definitions = CHARTS
        self.rgx_smb2 = re.compile(r'(smb2_[^:]+|syscall_.*file_bytes):\s+(\d+)')

    def check(self):
        smbstatus_binary = find_binary(SMBSTATUS)
        if not smbstatus_binary:
            self.error("can't locate '{0}' binary".format(SMBSTATUS))
            return False

        if os.getuid() == 0:
            self.command = ' '.join([smbstatus_binary, '-P'])
            return ExecutableService.check(self)
        
        sudo_binary = find_binary(SUDO)
        if not sudo_binary:
            self.error("can't locate '{0}' binary".format(SUDO))
            return False
        command = [sudo_binary, '-n', '-l', smbstatus_binary, '-P']
        smbstatus = '{0} -P'.format(smbstatus_binary)
        allowed = self._get_raw_data(command=command)
        if not (allowed and allowed[0].strip() == smbstatus):
            self.error("not allowed to run sudo for command '{0}'".format(smbstatus))
            return False
        self.command = ' '.join([sudo_binary, '-n', smbstatus_binary, '-P'])
        return ExecutableService.check(self)

    def _get_data(self):
        """
        Format data received from shell command
        :return: dict
        """
        raw_data = self._get_raw_data()
        if not raw_data:
            return None

        parsed = self.rgx_smb2.findall(' '.join(raw_data))

        return dict(parsed) or None