Completed
Push — develop ( 0f22ba...c7bcf2 )
by Nicolas
86:05 queued 83:02
created

Plugin.msg_curse()   A

Complexity

Conditions 4

Size

Total Lines 34
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 24
nop 3
dl 0
loc 34
rs 9.304
c 0
b 0
f 0
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
0 ignored issues
show
introduced by
import missing from __future__ import absolute_import
Loading history...
24
from glances.timer import getTimeSinceLastUpdate
0 ignored issues
show
introduced by
import missing from __future__ import absolute_import
Loading history...
Unused Code introduced by
Unused getTimeSinceLastUpdate imported from glances.timer
Loading history...
25
from glances.plugins.glances_plugin import GlancesPlugin
0 ignored issues
show
introduced by
import missing from __future__ import absolute_import
Loading history...
26
from glances.compat import n, u, b, nativestr
0 ignored issues
show
introduced by
import missing from __future__ import absolute_import
Loading history...
Unused Code introduced by
Unused b imported from glances.compat
Loading history...
Unused Code introduced by
Unused u imported from glances.compat
Loading history...
Unused Code introduced by
Unused n imported from glances.compat
Loading history...
27
28
import psutil
0 ignored issues
show
introduced by
import missing from __future__ import absolute_import
Loading history...
introduced by
Unable to import 'psutil'
Loading history...
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',
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (84/80).

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

Loading history...
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
        # @TODO the plugin should be enable only for Linux OS
69
70
    @GlancesPlugin._check_decorator
71
    @GlancesPlugin._log_result_decorator
72
    def update(self):
73
        """Update connections stats using the input method.
74
75
        Stats is a dict
76
        """
77
        # Init new stats
78
        stats = self.get_init_value()
79
80
        if self.input_method == 'local':
81
            # Update stats using the PSUtils lib
82
83
            # Grab network interface stat using the psutil net_connections method
0 ignored issues
show
Coding Style introduced by
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...
84
            try:
85
                net_connections = psutil.net_connections(kind="tcp")
86
            except Exception as e:
0 ignored issues
show
Best Practice introduced by
Catching very general exceptions such as Exception is usually not recommended.

Generally, you would want to handle very specific errors in the exception handler. This ensure that you do not hide other types of errors which should be fixed.

So, unless you specifically plan to handle any error, consider adding a more specific exception.

Loading history...
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...
87
                logger.debug('Can not get network connections stats ({})'.format(e))
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (84/80).

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

Loading history...
introduced by
Use formatting in logging functions and pass the parameters as arguments
Loading history...
88
                return self.stats
89
90
            for s in self.status_list:
0 ignored issues
show
Coding Style Naming introduced by
The name s 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...
91
                stats[s] = len([c for c in net_connections if c.status == s])
92
            initiated = 0
93
            for s in self.initiated_states:
0 ignored issues
show
Coding Style Naming introduced by
The name s 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...
94
                stats[s] = len([c for c in net_connections if c.status == s])
95
                initiated += stats[s]
96
            stats['initiated'] = initiated
97
            terminated = 0
98
            for s in self.initiated_states:
0 ignored issues
show
Coding Style Naming introduced by
The name s 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...
99
                stats[s] = len([c for c in net_connections if c.status == s])
100
                terminated += stats[s]
101
            stats['terminated'] = terminated
102
103
            # Grab connections track directly from the /proc file
104
            for i in self.conntrack:
105
                with open(self.conntrack[i], 'r') as f:
0 ignored issues
show
Coding Style Naming introduced by
The name f 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...
106
                    stats[i] = float(f.readline().rstrip("\n"))
107
            stats['nf_conntrack_percent'] = stats['nf_conntrack_count'] * 100 / stats['nf_conntrack_max']
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (105/80).

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

Loading history...
introduced by
division w/o __future__ statement
Loading history...
108
109
        elif self.input_method == 'snmp':
110
            # Update stats using SNMP
111
            pass
112
113
        # Update the stats
114
        self.stats = stats
115
116
        return self.stats
117
118
    def update_views(self):
119
        """Update stats views."""
120
        # Call the father's method
121
        super(Plugin, self).update_views()
122
123
        # Add specifics informations
124
        try:
125
            # Alert and log
126
            self.views['nf_conntrack_percent']['decoration'] = self.get_alert(header='nf_conntrack_percent')
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (108/80).

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

Loading history...
127
        except KeyError:
128
            # try/except mandatory for Windows compatibility (no conntrack stats)
0 ignored issues
show
Coding Style introduced by
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...
129
            pass
130
131
    def msg_curse(self, args=None, max_width=None):
132
        """Return the dict to display in the curse interface."""
133
        # Init the return message
134
        ret = []
135
136
        logger.info(self.is_disable())
137
138
        # Only process if stats exist and display plugin enable...
139
        if not self.stats or self.is_disable():
140
            return ret
141
142
        # Header
143
        msg = '{}'.format('TCP CONNECTIONS')
144
        ret.append(self.curse_add_line(msg, "TITLE"))
145
        # Connections status
146
        for s in [psutil.CONN_LISTEN, 'initiated', psutil.CONN_ESTABLISHED, 'terminated']:
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (90/80).

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

Loading history...
Coding Style Naming introduced by
The name s 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...
147
            ret.append(self.curse_new_line())
148
            msg = '{:{width}}'.format(nativestr(s).capitalize(), width=len(s))
149
            ret.append(self.curse_add_line(msg))
150
            msg = '{:>{width}}'.format(self.stats[s], width=max_width - len(s) + 2)
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (83/80).

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

Loading history...
151
            ret.append(self.curse_add_line(msg))
152
        # Connections track
153
        s = 'Tracked'
0 ignored issues
show
Coding Style Naming introduced by
The name s 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...
154
        ret.append(self.curse_new_line())
155
        msg = '{:{width}}'.format(nativestr(s).capitalize(), width=len(s))
156
        ret.append(self.curse_add_line(msg))
157
        msg = '{:>{width}}'.format('{:0.0f}/{:0.0f}'.format(self.stats['nf_conntrack_count'],
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (93/80).

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

Loading history...
158
                                                            self.stats['nf_conntrack_max']),
0 ignored issues
show
Coding Style introduced by
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...
159
                                   width=max_width - len(s) + 2)
160
        ret.append(self.curse_add_line(msg,
161
                                       self.get_views(key='nf_conntrack_percent',
0 ignored issues
show
Coding Style introduced by
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...
162
                                                      option='decoration')))
163
164
        return ret
165