Test Failed
Push — develop ( 3e7080...29e3c5 )
by Nicolas
03:08
created

glances/plugins/glances_connections.py (7 issues)

1
# -*- coding: utf-8 -*-
2
#
3
# This file is part of Glances.
4
#
5
# Copyright (C) 2019 Nicolargo <[email protected]>
6
#
7
# Glances is free software; you can redistribute it and/or modify
8
# it under the terms of the GNU Lesser General Public License as published by
9
# the Free Software Foundation, either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Glances is distributed in the hope that it will be useful,
13
# but WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU Lesser General Public License for more details.
16
#
17
# You should have received a copy of the GNU Lesser General Public License
18
# along with this program. If not, see <http://www.gnu.org/licenses/>.
19
20
"""Connections plugin."""
21
from __future__ import unicode_literals
22
23
from glances.logger import logger
24
from glances.timer import getTimeSinceLastUpdate
25
from glances.plugins.glances_plugin import GlancesPlugin
26
from glances.compat import n, u, b, nativestr
27
28
import psutil
29
30
# Define the history items list
31
# items_history_list = [{'name': 'rx',
32
#                        'description': 'Download rate per second',
33
#                        'y_unit': 'bit/s'},
34
#                       {'name': 'tx',
35
#                        'description': 'Upload rate per second',
36
#                        'y_unit': 'bit/s'}]
37
38
39
class Plugin(GlancesPlugin):
40
    """Glances connections plugin.
41
42
    stats is a dict
43
    """
44
45
    status_list = [psutil.CONN_LISTEN,
46
                   psutil.CONN_ESTABLISHED]
47
    initiated_states = [psutil.CONN_SYN_SENT,
48
                        psutil.CONN_SYN_RECV]
49
    terminated_states = [psutil.CONN_FIN_WAIT1,
50
                         psutil.CONN_FIN_WAIT2,
51
                         psutil.CONN_TIME_WAIT,
52
                         psutil.CONN_CLOSE,
53
                         psutil.CONN_CLOSE_WAIT,
54
                         psutil.CONN_LAST_ACK]
55
    conntrack = {'nf_conntrack_count': '/proc/sys/net/netfilter/nf_conntrack_count',
56
                 'nf_conntrack_max': '/proc/sys/net/netfilter/nf_conntrack_max'}
57
58
    def __init__(self, args=None, config=None):
59
        """Init the plugin."""
60
        super(Plugin, self).__init__(args=args,
61
                                     config=config,
62
                                     # items_history_list=items_history_list,
63
                                     stats_init_value={})
64
65
        # We want to display the stat in the curse interface
66
        self.display_curse = True
67
68
        # This plugin is composed if net_connections and nf_conntrack
69
        # Enabled by default
70
        self.net_connections_enabled = True
71
        self.nf_conntrack_enabled = True
72
73
    @GlancesPlugin._check_decorator
74
    @GlancesPlugin._log_result_decorator
75
    def update(self):
76
        """Update connections stats using the input method.
77
78
        Stats is a dict
79
        """
80
        # Init new stats
81
        stats = self.get_init_value()
82
83
        if self.input_method == 'local':
84
            # Update stats using the PSUtils lib
85
86
            # Grab network interface stat using the psutil net_connections method
87
            if self.net_connections_enabled:
88
                try:
89
                    net_connections = psutil.net_connections(kind="tcp")
90
                except Exception as e:
91
                    logger.debug('Can not get network connections stats ({})'.format(e))
92
                    self.net_connections_enabled = False
93
                    self.stats = stats
94
                    return self.stats
95
96
                for s in self.status_list:
97
                    stats[s] = len([c for c in net_connections if c.status == s])
0 ignored issues
show
This line is too long as per the coding-style (81/80).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
98
                initiated = 0
99
                for s in self.initiated_states:
100
                    stats[s] = len([c for c in net_connections if c.status == s])
0 ignored issues
show
This line is too long as per the coding-style (81/80).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
101
                    initiated += stats[s]
102
                stats['initiated'] = initiated
103
                terminated = 0
104
                for s in self.initiated_states:
105
                    stats[s] = len([c for c in net_connections if c.status == s])
0 ignored issues
show
This line is too long as per the coding-style (81/80).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
106
                    terminated += stats[s]
107
                stats['terminated'] = terminated
108
109
            if self.nf_conntrack_enabled:
110
                # Grab connections track directly from the /proc file
111
                for i in self.conntrack:
112
                    try:
113
                        with open(self.conntrack[i], 'r') as f:
114
                            stats[i] = float(f.readline().rstrip("\n"))
115
                    except IOError as e:
0 ignored issues
show
Coding Style Naming introduced by
The name e does not conform to the variable naming conventions ((([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
116
                        logger.debug('Can not get network connections track ({})'.format(e))
0 ignored issues
show
This line is too long as per the coding-style (92/80).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
Use formatting in logging functions and pass the parameters as arguments
Loading history...
117
                        self.nf_conntrack_enabled = False
118
                        self.stats = stats
119
                        return self.stats
120
                stats['nf_conntrack_percent'] = stats['nf_conntrack_count'] * 100 / stats['nf_conntrack_max']
121
122
        elif self.input_method == 'snmp':
123
            # Update stats using SNMP
124
            pass
125
126
        # Update the stats
127
        self.stats = stats
128
        return self.stats
129
130
    def update_views(self):
131
        """Update stats views."""
132
        # Call the father's method
133
        super(Plugin, self).update_views()
134
135
        # Add specifics informations
136
        try:
137
            # Alert and log
138
            if self.nf_conntrack_enabled:
139
                self.views['nf_conntrack_percent']['decoration'] = self.get_alert(header='nf_conntrack_percent')
140
        except KeyError:
141
            # try/except mandatory for Windows compatibility (no conntrack stats)
142
            pass
143
144
    def msg_curse(self, args=None, max_width=None):
145
        """Return the dict to display in the curse interface."""
146
        # Init the return message
147
        ret = []
148
149
        logger.info(self.is_disable())
150
151
        # Only process if stats exist and display plugin enable...
152
        if not self.stats or self.is_disable():
153
            return ret
154
155
        # Header
156
        if self.net_connections_enabled or self.nf_conntrack_enabled:
157
            msg = '{}'.format('TCP CONNECTIONS')
158
            ret.append(self.curse_add_line(msg, "TITLE"))
159
        # Connections status
160
        if self.net_connections_enabled:
161
            for s in [psutil.CONN_LISTEN, 'initiated', psutil.CONN_ESTABLISHED, 'terminated']:
162
                ret.append(self.curse_new_line())
163
                msg = '{:{width}}'.format(nativestr(s).capitalize(), width=len(s))
0 ignored issues
show
This line is too long as per the coding-style (82/80).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
164
                ret.append(self.curse_add_line(msg))
165
                msg = '{:>{width}}'.format(self.stats[s], width=max_width - len(s) + 2)
166
                ret.append(self.curse_add_line(msg))
167
        # Connections track
168
        if self.nf_conntrack_enabled:
169
            s = 'Tracked'
170
            ret.append(self.curse_new_line())
171
            msg = '{:{width}}'.format(nativestr(s).capitalize(), width=len(s))
172
            ret.append(self.curse_add_line(msg))
173
            msg = '{:>{width}}'.format('{:0.0f}/{:0.0f}'.format(self.stats['nf_conntrack_count'],
174
                                                                self.stats['nf_conntrack_max']),
175
                                       width=max_width - len(s) + 2)
176
            ret.append(self.curse_add_line(msg,
177
                                           self.get_views(key='nf_conntrack_percent',
178
                                                          option='decoration')))
179
180
        return ret
181