Completed
Push — master ( 1806d1...053f07 )
by Nicolas
01:42
created

Config.__init__()   A

Complexity

Conditions 1

Size

Total Lines 7

Duplication

Lines 0
Ratio 0 %
Metric Value
cc 1
dl 0
loc 7
rs 9.4285
1
# -*- coding: utf-8 -*-
2
#
3
# This file is part of Glances.
4
#
5
# Copyright (C) 2015 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
"""Manage the configuration file."""
21
22
import os
23
import sys
24
from io import open
25
26
from glances import __appname__
27
from glances.compat import ConfigParser, NoOptionError
28
from glances.globals import BSD, LINUX, OSX, WINDOWS, sys_prefix
29
from glances.logger import logger
30
31
32
class Config(object):
33
34
    """This class is used to access/read config file, if it exists.
35
36
    :param config_dir: the path to search for config file
37
    :type config_dir: str or None
38
    """
39
40
    def __init__(self, config_dir=None):
41
        self.config_dir = config_dir
42
        self.config_filename = 'glances.conf'
43
        self._loaded_config_file = None
44
45
        self.parser = ConfigParser()
46
        self.read()
47
48
    def config_file_paths(self):
49
        r"""Get a list of config file paths.
50
51
        The list is built taking into account of the OS, priority and location.
52
53
        * custom path: /path/to/glances
54
        * Linux: ~/.config/glances, /etc/glances
55
        * BSD: ~/.config/glances, /usr/local/etc/glances
56
        * OS X: ~/Library/Application Support/glances, /usr/local/etc/glances
57
        * Windows: %APPDATA%\glances
58
59
        The config file will be searched in the following order of priority:
60
            * /path/to/file (via -C flag)
61
            * user's home directory (per-user settings)
62
            * system-wide directory (system-wide settings)
63
        """
64
        paths = []
65
66
        if self.config_dir:
67
            paths.append(self.config_dir)
68
69
        if LINUX or BSD:
70
            paths.append(
71
                os.path.join(os.environ.get('XDG_CONFIG_HOME') or
72
                             os.path.expanduser('~/.config'),
73
                             __appname__, self.config_filename))
74
            if BSD:
75
                paths.append(
76
                    os.path.join(sys.prefix, 'etc', __appname__, self.config_filename))
77
            else:
78
                paths.append(
79
                    os.path.join('/etc', __appname__, self.config_filename))
80
        elif OSX:
81
            paths.append(
82
                os.path.join(os.path.expanduser('~/Library/Application Support/'),
83
                             __appname__, self.config_filename))
84
            paths.append(
85
                os.path.join(sys_prefix, 'etc', __appname__, self.config_filename))
86
        elif WINDOWS:
87
            paths.append(
88
                os.path.join(os.environ.get('APPDATA'), __appname__, self.config_filename))
89
90
        return paths
91
92
    def read(self):
93
        """Read the config file, if it exists. Using defaults otherwise."""
94
        for config_file in self.config_file_paths():
95
            if os.path.exists(config_file):
96
                try:
97
                    with open(config_file, encoding='utf-8') as f:
98
                        self.parser.read_file(f)
99
                        self.parser.read(f)
100
                    logger.info("Read configuration file '{0}'".format(config_file))
101
                except UnicodeDecodeError as err:
102
                    logger.error("Cannot decode configuration file '{0}': {1}".format(config_file, err))
103
                    sys.exit(1)
104
                # Save the loaded configuration file path (issue #374)
105
                self._loaded_config_file = config_file
106
                break
107
108
        # Quicklook
109
        if not self.parser.has_section('quicklook'):
110
            self.parser.add_section('quicklook')
111
            self.parser.set('quicklook', 'cpu_careful', '50')
112
            self.parser.set('quicklook', 'cpu_warning', '70')
113
            self.parser.set('quicklook', 'cpu_critical', '90')
114
            self.parser.set('quicklook', 'mem_careful', '50')
115
            self.parser.set('quicklook', 'mem_warning', '70')
116
            self.parser.set('quicklook', 'mem_critical', '90')
117
            self.parser.set('quicklook', 'swap_careful', '50')
118
            self.parser.set('quicklook', 'swap_warning', '70')
119
            self.parser.set('quicklook', 'swap_critical', '90')
120
121
        # CPU
122
        if not self.parser.has_section('cpu'):
123
            self.parser.add_section('cpu')
124
            self.parser.set('cpu', 'user_careful', '50')
125
            self.parser.set('cpu', 'user_warning', '70')
126
            self.parser.set('cpu', 'user_critical', '90')
127
            self.parser.set('cpu', 'iowait_careful', '50')
128
            self.parser.set('cpu', 'iowait_warning', '70')
129
            self.parser.set('cpu', 'iowait_critical', '90')
130
            self.parser.set('cpu', 'system_careful', '50')
131
            self.parser.set('cpu', 'system_warning', '70')
132
            self.parser.set('cpu', 'system_critical', '90')
133
            self.parser.set('cpu', 'steal_careful', '50')
134
            self.parser.set('cpu', 'steal_warning', '70')
135
            self.parser.set('cpu', 'steal_critical', '90')
136
137
        # Per-CPU
138
        if not self.parser.has_section('percpu'):
139
            self.parser.add_section('percpu')
140
            self.parser.set('percpu', 'user_careful', '50')
141
            self.parser.set('percpu', 'user_warning', '70')
142
            self.parser.set('percpu', 'user_critical', '90')
143
            self.parser.set('percpu', 'iowait_careful', '50')
144
            self.parser.set('percpu', 'iowait_warning', '70')
145
            self.parser.set('percpu', 'iowait_critical', '90')
146
            self.parser.set('percpu', 'system_careful', '50')
147
            self.parser.set('percpu', 'system_warning', '70')
148
            self.parser.set('percpu', 'system_critical', '90')
149
150
        # Load
151
        if not self.parser.has_section('load'):
152
            self.parser.add_section('load')
153
            self.parser.set('load', 'careful', '0.7')
154
            self.parser.set('load', 'warning', '1.0')
155
            self.parser.set('load', 'critical', '5.0')
156
157
        # Mem
158
        if not self.parser.has_section('mem'):
159
            self.parser.add_section('mem')
160
            self.parser.set('mem', 'careful', '50')
161
            self.parser.set('mem', 'warning', '70')
162
            self.parser.set('mem', 'critical', '90')
163
164
        # Swap
165
        if not self.parser.has_section('memswap'):
166
            self.parser.add_section('memswap')
167
            self.parser.set('memswap', 'careful', '50')
168
            self.parser.set('memswap', 'warning', '70')
169
            self.parser.set('memswap', 'critical', '90')
170
171
        # FS
172
        if not self.parser.has_section('fs'):
173
            self.parser.add_section('fs')
174
            self.parser.set('fs', 'careful', '50')
175
            self.parser.set('fs', 'warning', '70')
176
            self.parser.set('fs', 'critical', '90')
177
178
        # Sensors
179
        if not self.parser.has_section('sensors'):
180
            self.parser.add_section('sensors')
181
            self.parser.set('sensors', 'temperature_core_careful', '60')
182
            self.parser.set('sensors', 'temperature_core_warning', '70')
183
            self.parser.set('sensors', 'temperature_core_critical', '80')
184
            self.parser.set('sensors', 'temperature_hdd_careful', '45')
185
            self.parser.set('sensors', 'temperature_hdd_warning', '52')
186
            self.parser.set('sensors', 'temperature_hdd_critical', '60')
187
            self.parser.set('sensors', 'battery_careful', '80')
188
            self.parser.set('sensors', 'battery_warning', '90')
189
            self.parser.set('sensors', 'battery_critical', '95')
190
191
        # Process list
192
        if not self.parser.has_section('processlist'):
193
            self.parser.add_section('processlist')
194
            self.parser.set('processlist', 'cpu_careful', '50')
195
            self.parser.set('processlist', 'cpu_warning', '70')
196
            self.parser.set('processlist', 'cpu_critical', '90')
197
            self.parser.set('processlist', 'mem_careful', '50')
198
            self.parser.set('processlist', 'mem_warning', '70')
199
            self.parser.set('processlist', 'mem_critical', '90')
200
201
    @property
202
    def loaded_config_file(self):
203
        """Return the loaded configuration file."""
204
        return self._loaded_config_file
205
206
    def items(self, section):
207
        """Return the items list of a section."""
208
        return self.parser.items(section)
209
210
    def has_section(self, section):
211
        """Return info about the existence of a section."""
212
        return self.parser.has_section(section)
213
214
    def get_value(self, section, option, default=None):
215
        """Get the value of an option, if it exists."""
216
        try:
217
            return self.parser.get(section, option)
218
        except NoOptionError:
219
            return default
220
221
    def get_float_value(self, section, option, default=0.0):
222
        """Get the float value of an option, if it exists."""
223
        try:
224
            return self.parser.getfloat(section, option)
225
        except NoOptionError:
226
            return float(default)
227