Test Failed
Push — develop ( abf64f...1d1151 )
by Nicolas
02:59
created

glances/main.py (3 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
"""Glances main class."""
21
22
import argparse
23
import sys
24
import tempfile
25
26
from glances import __version__, psutil_version
27
from glances.compat import input
0 ignored issues
show
Bug Best Practice introduced by
This seems to re-define the built-in input.

It is generally discouraged to redefine built-ins as this makes code very hard to read.

Loading history...
28
from glances.config import Config
29
from glances.globals import WINDOWS
30
from glances.logger import logger
31
32
33
def disable(class_name, var):
34
    """Set disable_<var> to True in the class class_name."""
35
    setattr(class_name, 'disable_' + var, True)
36
37
38
def enable(class_name, var):
39
    """Set disable_<var> to False in the class class_name."""
40
    setattr(class_name, 'disable_' + var, False)
41
42
43
class GlancesMain(object):
44
    """Main class to manage Glances instance."""
45
46
    # Default stats' refresh time is 3 seconds
47
    refresh_time = 3
48
    # Set the default cache lifetime to 1 second (only for server)
49
    cached_time = 1
50
    # By default, Glances is ran in standalone mode (no client/server)
51
    client_tag = False
52
    # Server TCP port number (default is 61209)
53
    server_port = 61209
54
    # Web Server TCP port number (default is 61208)
55
    web_server_port = 61208
56
    # Default username/password for client/server mode
57
    username = "glances"
58
    password = ""
59
60
    # Examples of use
61
    example_of_use = """
62
Examples of use:
63
  Monitor local machine (standalone mode):
64
    $ glances
65
66
  Display all Glances modules (plugins and exporters) and exit:
67
    $ glances --module-list
68
69
  Monitor local machine with the Web interface and start RESTful server:
70
    $ glances -w
71
    Glances web server started on http://0.0.0.0:61208/
72
73
  Only start RESTful API (without the WebUI):
74
    $ glances -w --disable-webui
75
    Glances API available on http://0.0.0.0:61208/api/
76
77
  Monitor local machine and export stats to a CSV file (standalone mode):
78
    $ glances --export csv --export-csv-file /tmp/glances.csv
79
80
  Monitor local machine and export stats to a InfluxDB server with 5s refresh time (standalone mode):
81
    $ glances -t 5 --export influxdb
82
83
  Start a Glances XML/RCP server (server mode):
84
    $ glances -s
85
86
  Connect Glances to a Glances XML/RCP server (client mode):
87
    $ glances -c <ip_server>
88
89
  Connect Glances to a Glances server and export stats to a StatsD server (client mode):
90
    $ glances -c <ip_server> --export statsd
91
92
  Start the client browser (browser mode):
93
    $ glances --browser
94
95
  Display stats to stdout (one stat per line):
96
    $ glances --stdout now,cpu.user,mem.used,load
97
98
  Display CSV stats to stdout (all stats in one line):
99
    $ glances --stdout-csv now,cpu.user,mem.used,load
100
101
  Disable some plugins (comma separated list):
102
    $ glances --disable-plugin network,ports
103
104
  Enable some plugins (comma separated list):
105
    $ glances --enable-plugin sensors
106
"""
107
108
    def __init__(self):
109
        """Manage the command line arguments."""
110
        # Read the command line arguments
111
        self.args = self.parse_args()
112
113
    def init_args(self):
114
        """Init all the command line arguments."""
115
        version = "Glances v" + __version__ + " with psutil v" + psutil_version
116
        parser = argparse.ArgumentParser(
117
            prog='glances',
118
            conflict_handler='resolve',
119
            formatter_class=argparse.RawDescriptionHelpFormatter,
120
            epilog=self.example_of_use)
121
        parser.add_argument(
122
            '-V', '--version', action='version', version=version)
123
        parser.add_argument('-d', '--debug', action='store_true', default=False,
124
                            dest='debug', help='enable debug mode')
125
        parser.add_argument('-C', '--config', dest='conf_file',
126
                            help='path to the configuration file')
127
        # Disable plugin
128
        parser.add_argument('--modules-list', '--module-list',
129
                            action='store_true', default=False,
130
                            dest='modules_list',
131
                            help='display modules (plugins & exports) list and exit')
132
        parser.add_argument('--disable-plugin', '--disable-plugins', dest='disable_plugin',
133
                            help='disable plugin (comma separed list)')
134
        parser.add_argument('--enable-plugin', '--enable-plugins', dest='enable_plugin',
135
                            help='enable plugin (comma separed list)')
136
        parser.add_argument('--disable-process', action='store_true', default=False,
137
                            dest='disable_process', help='disable process module')
138
        # Enable or disable option
139
        parser.add_argument('--disable-webui', action='store_true', default=False,
140
                            dest='disable_webui', help='disable the Web Interface')
141
        parser.add_argument('--light', '--enable-light', action='store_true',
142
                            default=False, dest='enable_light',
143
                            help='light mode for Curses UI (disable all but top menu)')
144
        parser.add_argument('-0', '--disable-irix', action='store_true', default=False,
145
                            dest='disable_irix', help='task\'s cpu usage will be divided by the total number of CPUs')
146
        parser.add_argument('-1', '--percpu', action='store_true', default=False,
147
                            dest='percpu', help='start Glances in per CPU mode')
148
        parser.add_argument('-2', '--disable-left-sidebar', action='store_true',
149
                            default=False, dest='disable_left_sidebar',
150
                            help='disable network, disk I/O, FS and sensors modules')
151
        parser.add_argument('-3', '--disable-quicklook', action='store_true', default=False,
152
                            dest='disable_quicklook', help='disable quick look module')
153
        parser.add_argument('-4', '--full-quicklook', action='store_true', default=False,
154
                            dest='full_quicklook', help='disable all but quick look and load')
155
        parser.add_argument('-5', '--disable-top', action='store_true',
156
                            default=False, dest='disable_top',
157
                            help='disable top menu (QL, CPU, MEM, SWAP and LOAD)')
158
        parser.add_argument('-6', '--meangpu', action='store_true', default=False,
159
                            dest='meangpu', help='start Glances in mean GPU mode')
160
        parser.add_argument('--disable-history', action='store_true', default=False,
161
                            dest='disable_history', help='disable stats history')
162
        parser.add_argument('--disable-bold', action='store_true', default=False,
163
                            dest='disable_bold', help='disable bold mode in the terminal')
164
        parser.add_argument('--disable-bg', action='store_true', default=False,
165
                            dest='disable_bg', help='disable background colors in the terminal')
166
        parser.add_argument('--enable-irq', action='store_true', default=False,
0 ignored issues
show
Unused Code Bug introduced by
The expression (parser.add_argument('--...'enable IRQ module'), ) does not seem to have sideeffects and its result is not used.

If a expression has no sideeffects (any lasting effect after it has been called) and its return value is not used, this usually means that this code can be removed or that an assignment is missing.

Loading history...
167
                            dest='enable_irq', help='enable IRQ module'),
168
        parser.add_argument('--enable-process-extended', action='store_true', default=False,
169
                            dest='enable_process_extended', help='enable extended stats on top process')
170
        # Export modules feature
171
        parser.add_argument('--export', dest='export',
172
                            help='enable export module (comma separed list)')
173
        parser.add_argument('--export-csv-file',
174
                            default='./glances.csv',
175
                            dest='export_csv_file',
176
                            help='file path for CSV exporter')
177
        parser.add_argument('--export-csv-overwrite', action='store_true', default=False,
178
                            dest='export_csv_overwrite', help='overwrite existing CSV file')
179
        parser.add_argument('--export-json-file',
180
                            default='./glances.json',
181
                            dest='export_json_file',
182
                            help='file path for JSON exporter')
183
        parser.add_argument('--export-graph-path',
184
                            default=tempfile.gettempdir(),
185
                            dest='export_graph_path',
186
                            help='Folder for Graph exporter')
187
        # Client/Server option
188
        parser.add_argument('-c', '--client', dest='client',
189
                            help='connect to a Glances server by IPv4/IPv6 address or hostname')
190
        parser.add_argument('-s', '--server', action='store_true', default=False,
191
                            dest='server', help='run Glances in server mode')
192
        parser.add_argument('--browser', action='store_true', default=False,
193
                            dest='browser', help='start the client browser (list of servers)')
194
        parser.add_argument('--disable-autodiscover', action='store_true', default=False,
195
                            dest='disable_autodiscover', help='disable autodiscover feature')
196
        parser.add_argument('-p', '--port', default=None, type=int, dest='port',
197
                            help='define the client/server TCP port [default: {}]'.format(self.server_port))
198
        parser.add_argument('-B', '--bind', default='0.0.0.0', dest='bind_address',
199
                            help='bind server to the given IPv4/IPv6 address or hostname')
200
        parser.add_argument('--username', action='store_true', default=False, dest='username_prompt',
201
                            help='define a client/server username')
202
        parser.add_argument('--password', action='store_true', default=False, dest='password_prompt',
203
                            help='define a client/server password')
204
        parser.add_argument('-u', dest='username_used',
205
                            help='use the given client/server username')
206
        parser.add_argument('--snmp-community', default='public', dest='snmp_community',
207
                            help='SNMP community')
208
        parser.add_argument('--snmp-port', default=161, type=int,
209
                            dest='snmp_port', help='SNMP port')
210
        parser.add_argument('--snmp-version', default='2c', dest='snmp_version',
211
                            help='SNMP version (1, 2c or 3)')
212
        parser.add_argument('--snmp-user', default='private', dest='snmp_user',
213
                            help='SNMP username (only for SNMPv3)')
214
        parser.add_argument('--snmp-auth', default='password', dest='snmp_auth',
215
                            help='SNMP authentication key (only for SNMPv3)')
216
        parser.add_argument('--snmp-force', action='store_true', default=False,
217
                            dest='snmp_force', help='force SNMP mode')
218
        parser.add_argument('-t', '--time', default=self.refresh_time, type=float,
219
                            dest='time', help='set refresh time in seconds [default: {} sec]'.format(self.refresh_time))
220
        parser.add_argument('-w', '--webserver', action='store_true', default=False,
221
                            dest='webserver', help='run Glances in web server mode (bottle needed)')
222
        parser.add_argument('--cached-time', default=self.cached_time, type=int,
223
                            dest='cached_time', help='set the server cache time [default: {} sec]'.format(self.cached_time))
224
        parser.add_argument('--open-web-browser', action='store_true', default=False,
225
                            dest='open_web_browser', help='try to open the Web UI in the default Web browser')
226
        # Display options
227
        parser.add_argument('-q', '--quiet', default=False, action='store_true',
228
                            dest='quiet', help='do not display the curses interface')
229
        parser.add_argument('-f', '--process-filter', default=None, type=str,
230
                            dest='process_filter', help='set the process filter pattern (regular expression)')
231
        parser.add_argument('--process-short-name', action='store_true', default=False,
232
                            dest='process_short_name', help='force short name for processes name')
233
        parser.add_argument('--stdout', default=None,
234
                            dest='stdout', help='display stats to stdout, one stat per line (comma separated list of plugins/plugins.attribute)')
235
        parser.add_argument('--stdout-csv', default=None,
236
                            dest='stdout_csv', help='display stats to stdout, csv format (comma separated list of plugins/plugins.attribute)')
237
        if not WINDOWS:
238
            parser.add_argument('--hide-kernel-threads', action='store_true', default=False,
239
                                dest='no_kernel_threads', help='hide kernel threads in process list (not available on Windows)')
240
        parser.add_argument('-b', '--byte', action='store_true', default=False,
241
                            dest='byte', help='display network rate in byte per second')
242
        parser.add_argument('--diskio-show-ramfs', action='store_true', default=False,
243
                            dest='diskio_show_ramfs', help='show RAM Fs in the DiskIO plugin')
244
        parser.add_argument('--diskio-iops', action='store_true', default=False,
245
                            dest='diskio_iops', help='show IO per second in the DiskIO plugin')
246
        parser.add_argument('--fahrenheit', action='store_true', default=False,
247
                            dest='fahrenheit', help='display temperature in Fahrenheit (default is Celsius)')
248
        parser.add_argument('--fs-free-space', action='store_true', default=False,
249
                            dest='fs_free_space', help='display FS free space instead of used')
250
        parser.add_argument('--sparkline', action='store_true', default=False,
251
                            dest='sparkline', help='display sparklines instead of bar in the curses interface')
252
        parser.add_argument('--theme-white', action='store_true', default=False,
253
                            dest='theme_white', help='optimize display colors for white background')
254
        # Globals options
255
        parser.add_argument('--disable-check-update', action='store_true', default=False,
256
                            dest='disable_check_update', help='disable online Glances version ckeck')
257
        return parser
258
259
    def parse_args(self):
260
        """Parse command line arguments."""
261
        args = self.init_args().parse_args()
262
263
        # Load the configuration file, if it exists
264
        self.config = Config(args.conf_file)
265
266
        # Debug mode
267
        if args.debug:
268
            from logging import DEBUG
269
            logger.setLevel(DEBUG)
270
        else:
271
            from warnings import simplefilter
272
            simplefilter("ignore")
273
274
        # Plugins disable/enable
275
        # Allow users to disable plugins from the glances.conf (issue #1378)
276
        for s in self.config.sections():
277
            if self.config.has_section(s) \
278
               and (self.config.get_bool_value(s, 'disable', False)):
279
                disable(args, s)
280
                logger.debug('{} disabled by the configuration file'.format(s))
281
        # The configuration key can be overwrite from the command line
282
        if args.disable_plugin is not None:
283
            for p in args.disable_plugin.split(','):
284
                disable(args, p)
285
        if args.enable_plugin is not None:
286
            for p in args.enable_plugin.split(','):
287
                enable(args, p)
288
289
        # Exporters activation
290
        if args.export is not None:
291
            for p in args.export.split(','):
292
                setattr(args, 'export_' + p, True)
293
294
        # Client/server Port
295
        if args.port is None:
296
            if args.webserver:
297
                args.port = self.web_server_port
298
            else:
299
                args.port = self.server_port
300
        # Port in the -c URI #996
301
        if args.client is not None:
302
            args.client, args.port = (x if x else y for (x, y) in zip(args.client.partition(':')[::2], (args.client, args.port)))
303
304
        # Autodiscover
305
        if args.disable_autodiscover:
306
            logger.info("Auto discover mode is disabled")
307
308
        # By default Windows is started in Web mode
309
        if WINDOWS:
310
            args.webserver = True
311
312
        # In web server mode
313
        if args.webserver:
314
            args.process_short_name = True
315
316
        # Server or client login/password
317
        if args.username_prompt:
318
            # Every username needs a password
319
            args.password_prompt = True
320
            # Prompt username
321
            if args.server:
322
                args.username = self.__get_username(
323
                    description='Define the Glances server username: ')
324
            elif args.webserver:
325
                args.username = self.__get_username(
326
                    description='Define the Glances webserver username: ')
327
            elif args.client:
328
                args.username = self.__get_username(
329
                    description='Enter the Glances server username: ')
330
        else:
331
            if args.username_used:
332
                # A username has been set using the -u option ?
333
                args.username = args.username_used
334
            else:
335
                # Default user name is 'glances'
336
                args.username = self.username
337
338
        if args.password_prompt or args.username_used:
339
            # Interactive or file password
340
            if args.server:
341
                args.password = self.__get_password(
342
                    description='Define the Glances server password ({} username): '.format(
343
                        args.username),
344
                    confirm=True,
345
                    username=args.username)
346
            elif args.webserver:
347
                args.password = self.__get_password(
348
                    description='Define the Glances webserver password ({} username): '.format(
349
                        args.username),
350
                    confirm=True,
351
                    username=args.username)
352
            elif args.client:
353
                args.password = self.__get_password(
354
                    description='Enter the Glances server password ({} username): '.format(
355
                        args.username),
356
                    clear=True,
357
                    username=args.username)
358
        else:
359
            # Default is no password
360
            args.password = self.password
361
362
        # By default help is hidden
363
        args.help_tag = False
364
365
        # Display Rx and Tx, not the sum for the network
366
        args.network_sum = False
367
        args.network_cumul = False
368
369
        # Manage light mode
370
        if args.enable_light:
371
            logger.info("Light mode is on")
372
            args.disable_left_sidebar = True
373
            disable(args, 'process')
374
            disable(args, 'alert')
375
            disable(args, 'amps')
376
            disable(args, 'docker')
377
378
        # Manage full quicklook option
379
        if args.full_quicklook:
380
            logger.info("Full quicklook mode")
381
            enable(args, 'quicklook')
382
            disable(args, 'cpu')
383
            disable(args, 'mem')
384
            disable(args, 'memswap')
385
            enable(args, 'load')
386
387
        # Manage disable_top option
388
        if args.disable_top:
389
            logger.info("Disable top menu")
390
            disable(args, 'quicklook')
391
            disable(args, 'cpu')
392
            disable(args, 'mem')
393
            disable(args, 'memswap')
394
            disable(args, 'load')
395
396
        # Init the generate_graph tag
397
        # Should be set to True to generate graphs
398
        args.generate_graph = False
399
400
        # Control parameter and exit if it is not OK
401
        self.args = args
402
403
        # Export is only available in standalone or client mode (issue #614)
404
        export_tag = self.args.export is not None and any(self.args.export)
405
        if WINDOWS and export_tag:
406
            # On Windows, export is possible but only in quiet mode
407
            # See issue #1038
408
            logger.info("On Windows OS, export disable the Web interface")
409
            self.args.quiet = True
410
            self.args.webserver = False
411
        elif not (self.is_standalone() or self.is_client()) and export_tag:
412
            logger.critical("Export is only available in standalone or client mode")
413
            sys.exit(2)
414
415
        # Filter is only available in standalone mode
416
        if args.process_filter is not None and not self.is_standalone():
417
            logger.critical(
418
                "Process filter is only available in standalone mode")
419
            sys.exit(2)
420
421
        # Disable HDDTemp if sensors are disabled
422
        if getattr(args, 'disable_sensors', False):
423
            disable(args, 'hddtemp')
424
            logger.debug("Sensors and HDDTemp are disabled")
425
426
        return args
427
428
    def is_standalone(self):
429
        """Return True if Glances is running in standalone mode."""
430
        return (not self.args.client and
431
                not self.args.browser and
432
                not self.args.server and
433
                not self.args.webserver)
434
435
    def is_client(self):
436
        """Return True if Glances is running in client mode."""
437
        return (self.args.client or self.args.browser) and not self.args.server
438
439
    def is_client_browser(self):
440
        """Return True if Glances is running in client browser mode."""
441
        return self.args.browser and not self.args.server
442
443
    def is_server(self):
444
        """Return True if Glances is running in server mode."""
445
        return not self.args.client and self.args.server
446
447
    def is_webserver(self):
448
        """Return True if Glances is running in Web server mode."""
449
        return not self.args.client and self.args.webserver
450
451
    def get_config(self):
452
        """Return configuration file object."""
453
        return self.config
454
455
    def get_args(self):
456
        """Return the arguments."""
457
        return self.args
458
459
    def get_mode(self):
460
        """Return the mode."""
461
        return self.mode
0 ignored issues
show
The Instance of GlancesMain does not seem to have a member named mode.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
462
463
    def __get_username(self, description=''):
464
        """Read an username from the command line."""
465
        return input(description)
466
467
    def __get_password(self, description='',
468
                       confirm=False, clear=False, username='glances'):
469
        """Read a password from the command line.
470
471
        - if confirm = True, with confirmation
472
        - if clear = True, plain (clear password)
473
        """
474
        from glances.password import GlancesPassword
475
        password = GlancesPassword(username=username)
476
        return password.get_password(description, confirm, clear)
477