Completed
Push — master ( 3dcd25...20576f )
by Nicolas
01:26
created

GlancesAmp.load_config()   F

Complexity

Conditions 9

Size

Total Lines 47

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 9
c 2
b 0
f 0
dl 0
loc 47
rs 3.3333
1
# -*- coding: utf-8 -*-
2
#
3
# This file is part of Glances.
4
#
5
# Copyright (C) 2016 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
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("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("{}: 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("{}: Load parameter: {} = {}".format(self.NAME, param, self.configs[param]))
98
        else:
99
            logger.debug("{}: Can not find section {} in the configuration file".format(self.NAME, self.amp_name))
100
            return False
101
102
        # enable, regex and refresh are mandatories
103
        # if not configured then AMP is disabled
104
        if self.enable():
105
            for k in ['regex', 'refresh']:
106
                if k not in self.configs:
107
                    logger.warning("{}: Can not find configuration key {} in section {}".format(self.NAME, k, self.amp_name))
108
                    self.configs['enable'] = 'false'
109
        else:
110
            logger.debug("{} is disabled".format(self.NAME))
111
112
        # Init the count to 0
113
        self.configs['count'] = 0
114
115
        return self.enable()
116
117
    def get(self, key):
118
        """Generic method to get the item in the AMP configuration"""
119
        if key in self.configs:
120
            return self.configs[key]
121
        else:
122
            return None
123
124
    def enable(self):
125
        """Return True|False if the AMP is enabled in the configuration file (enable=true|false)."""
126
        ret = self.get('enable')
127
        if ret is None:
128
            return False
129
        else:
130
            return ret.lower().startswith('true')
131
132
    def regex(self):
133
        """Return regular expression used to identified the current application."""
134
        return self.get('regex')
135
136
    def refresh(self):
137
        """Return refresh time in seconds for the current application monitoring process."""
138
        return self.get('refresh')
139
140
    def one_line(self):
141
        """Return True|False if the AMP shoukd be displayed in oneline (one_lineline=true|false)."""
142
        ret = self.get('one_line')
143
        if ret is None:
144
            return False
145
        else:
146
            return ret.lower().startswith('true')
147
148
    def time_until_refresh(self):
149
        """Return time in seconds until refresh."""
150
        return self.timer.get()
151
152
    def should_update(self):
153
        """Return True is the AMP should be updated:
154
        - AMP is enable
155
        - only update every 'refresh' seconds
156
        """
157
        if self.timer.finished():
158
            self.timer.set(self.refresh())
159
            self.timer.reset()
160
            return self.enable()
161
        return False
162
163
    def set_count(self, count):
164
        """Set the number of processes matching the regex"""
165
        self.configs['count'] = count
166
167
    def count(self):
168
        """Get the number of processes matching the regex"""
169
        return self.get('count')
170
171
    def count_min(self):
172
        """Get the minimum number of processes"""
173
        return self.get('countmin')
174
175
    def count_max(self):
176
        """Get the maximum number of processes"""
177
        return self.get('countmax')
178
179
    def set_result(self, result, separator=''):
180
        """Store the result (string) into the result key of the AMP
181
        if one_line is true then replace \n by separator
182
        """
183
        if self.one_line():
184
            self.configs['result'] = str(result).replace('\n', separator)
185
        else:
186
            self.configs['result'] = str(result)
187
188
    def result(self):
189
        """ Return the result of the AMP (as a string)"""
190
        ret = self.get('result')
191
        if ret is not None:
192
            ret = u(ret)
193
        return ret
194
195
    def update_wrapper(self, process_list):
196
        """Wrapper for the children update"""
197
        # Set the number of running process
198
        self.set_count(len(process_list))
199
        # Call the children update method
200
        if self.should_update():
201
            return self.update(process_list)
202
        else:
203
            return self.result()
204