Test Failed
Push — master ( 4c6c3d...040528 )
by Nicolas
04:27
created

glances/amps/glances_amp.py (4 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
"""
21
I am your father...
22
23
...for all Glances Application Monitoring Processes (AMP).
24
25
AMP (Application Monitoring Process)
26
A Glances AMP is a Python script called (every *refresh* seconds) if:
27
- the AMP is *enabled* in the Glances configuration file
28
- a process is running (match the *regex* define in the configuration file)
29
The script should define a Amp (GlancesAmp) class with, at least, an update method.
30
The update method should call the set_result method to set the AMP return string.
31
The return string is a string with one or more line (\n between lines).
32
If the *one_line* var is true then the AMP will be displayed in one line.
33
"""
34
35
from glances.compat import u, b, n, nativestr
36
from glances.timer import Timer
37
from glances.logger import logger
38
39
40
class GlancesAmp(object):
41
    """Main class for Glances AMP."""
42
43
    NAME = '?'
44
    VERSION = '?'
45
    DESCRIPTION = '?'
46
    AUTHOR = '?'
47
    EMAIL = '?'
48
49
    def __init__(self, name=None, args=None):
50
        """Init AMP classe."""
51
        logger.debug("AMP - Init {} version {}".format(self.NAME, self.VERSION))
52
53
        # AMP name (= module name without glances_)
54
        if name is None:
55
            self.amp_name = self.__class__.__module__[len('glances_'):]
56
        else:
57
            self.amp_name = name
58
59
        # Init the args
60
        self.args = args
61
62
        # Init the configs
63
        self.configs = {}
64
65
        # A timer is needed to only update every refresh seconds
66
        # Init to 0 in order to update the AMP on startup
67
        self.timer = Timer(0)
68
69
    def load_config(self, config):
70
        """Load AMP parameters from the configuration file."""
71
72
        # Read AMP confifuration.
73
        # For ex, the AMP foo should have the following section:
74
        #
75
        # [foo]
76
        # enable=true
77
        # regex=\/usr\/bin\/nginx
78
        # refresh=60
79
        #
80
        # and optionnaly:
81
        #
82
        # one_line=false
83
        # option1=opt1
84
        # ...
85
        #
86
        amp_section = 'amp_' + self.amp_name
87
        if (hasattr(config, 'has_section') and
88
                config.has_section(amp_section)):
89
            logger.debug("AMP - {}: Load configuration".format(self.NAME))
90
            for param, _ in config.items(amp_section):
91
                try:
92
                    self.configs[param] = config.get_float_value(amp_section, param)
93
                except ValueError:
94
                    self.configs[param] = config.get_value(amp_section, param).split(',')
95
                    if len(self.configs[param]) == 1:
96
                        self.configs[param] = self.configs[param][0]
97
                logger.debug("AMP - {}: Load parameter: {} = {}".format(self.NAME, param, self.configs[param]))
98
        else:
99
            logger.debug("AMP - {}: Can not find section {} in the configuration file".format(self.NAME, self.amp_name))
100
            return False
101
102
        if self.enable():
103
            # Refresh option is mandatory
104
            for k in ['refresh']:
105
                if k not in self.configs:
106
                    logger.warning("AMP - {}: Can not find configuration key {} in section {} (the AMP will be disabled)".format(self.NAME, k, self.amp_name))
107
                    self.configs['enable'] = 'false'
108
        else:
109
            logger.debug("AMP - {} is disabled".format(self.NAME))
110
111
        # Init the count to 0
112
        self.configs['count'] = 0
113
114
        return self.enable()
115
116
    def get(self, key):
117
        """Generic method to get the item in the AMP configuration"""
118
        if key in self.configs:
0 ignored issues
show
Unnecessary "else" after "return"
Loading history...
119
            return self.configs[key]
120
        else:
121
            return None
122
123
    def enable(self):
124
        """Return True|False if the AMP is enabled in the configuration file (enable=true|false)."""
125
        ret = self.get('enable')
126
        if ret is None:
0 ignored issues
show
Unnecessary "else" after "return"
Loading history...
127
            return False
128
        else:
129
            return ret.lower().startswith('true')
130
131
    def regex(self):
132
        """Return regular expression used to identified the current application."""
133
        return self.get('regex')
134
135
    def refresh(self):
136
        """Return refresh time in seconds for the current application monitoring process."""
137
        return self.get('refresh')
138
139
    def one_line(self):
140
        """Return True|False if the AMP shoukd be displayed in oneline (one_lineline=true|false)."""
141
        ret = self.get('one_line')
142
        if ret is None:
0 ignored issues
show
Unnecessary "else" after "return"
Loading history...
143
            return False
144
        else:
145
            return ret.lower().startswith('true')
146
147
    def time_until_refresh(self):
148
        """Return time in seconds until refresh."""
149
        return self.timer.get()
150
151
    def should_update(self):
152
        """Return True is the AMP should be updated:
153
        - AMP is enable
154
        - only update every 'refresh' seconds
155
        """
156
        if self.timer.finished():
157
            self.timer.set(self.refresh())
158
            self.timer.reset()
159
            return self.enable()
160
        return False
161
162
    def set_count(self, count):
163
        """Set the number of processes matching the regex"""
164
        self.configs['count'] = count
165
166
    def count(self):
167
        """Get the number of processes matching the regex"""
168
        return self.get('count')
169
170
    def count_min(self):
171
        """Get the minimum number of processes"""
172
        return self.get('countmin')
173
174
    def count_max(self):
175
        """Get the maximum number of processes"""
176
        return self.get('countmax')
177
178
    def set_result(self, result, separator=''):
179
        """Store the result (string) into the result key of the AMP
180
        if one_line is true then replace \n by separator
181
        """
182
        if self.one_line():
183
            self.configs['result'] = u(result).replace('\n', separator)
184
        else:
185
            self.configs['result'] = u(result)
186
187
    def result(self):
188
        """ Return the result of the AMP (as a string)"""
189
        ret = self.get('result')
190
        if ret is not None:
191
            ret = u(ret)
192
        return ret
193
194
    def update_wrapper(self, process_list):
195
        """Wrapper for the children update"""
196
        # Set the number of running process
197
        self.set_count(len(process_list))
198
        # Call the children update method
199
        if self.should_update():
0 ignored issues
show
Unnecessary "else" after "return"
Loading history...
200
            return self.update(process_list)
201
        else:
202
            return self.result()
203