glances.main   F
last analyzed

Complexity

Total Complexity 75

Size/Duplication

Total Lines 850
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 569
dl 0
loc 850
rs 2.4
c 0
b 0
f 0
wmc 75

20 Methods

Rating   Name   Duplication   Size   Complexity  
A GlancesMain.__init__() 0 4 1
A GlancesMain.version_msg() 0 7 1
A GlancesMain.is_standalone() 0 3 1
A GlancesMain.get_config() 0 3 1
B GlancesMain.init_args() 0 451 2
A GlancesMain.is_client_browser() 0 3 1
B GlancesMain.check_mode_compatibility() 0 16 7
C GlancesMain.parse_args() 0 62 10
A GlancesMain.is_webserver() 0 3 1
B GlancesMain.init_ui_mode() 0 36 6
A GlancesMain.is_server() 0 3 1
A GlancesMain.init_refresh_rate() 0 12 3
A GlancesMain.get_mode() 0 3 1
F GlancesMain.init_plugins() 0 42 17
A GlancesMain.__get_username() 0 3 1
A GlancesMain.is_client() 0 3 1
A GlancesMain.get_args() 0 3 1
A GlancesMain.__get_password() 0 10 1
A GlancesMain.init_debug() 0 6 2
F GlancesMain.init_client_server() 0 61 16

How to fix   Complexity   

Complexity

Complex classes like glances.main often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
# -*- coding: utf-8 -*-
2
#
3
# This file is part of Glances.
4
#
5
# SPDX-FileCopyrightText: 2024 Nicolas Hennion <[email protected]>
6
#
7
# SPDX-License-Identifier: LGPL-3.0-only
8
#
9
10
"""Glances main class."""
11
12
import argparse
13
import sys
14
import tempfile
15
from logging import DEBUG
16
from warnings import simplefilter
17
18
from glances import __version__, psutil_version, __apiversion__
19
from glances.globals import WINDOWS, disable, enable
20
from glances.config import Config
21
from glances.processes import sort_processes_key_list
22
from glances.logger import logger, LOG_FILENAME
23
24
25
class GlancesMain(object):
26
    """Main class to manage Glances instance."""
27
28
    # Default stats' minimum refresh time is 2 seconds
29
    DEFAULT_REFRESH_TIME = 2
30
    # Set the default cache lifetime to 1 second (only for server)
31
    cached_time = 1
32
    # By default, Glances is ran in standalone mode (no client/server)
33
    client_tag = False
34
    # Server TCP port number (default is 61209)
35
    server_port = 61209
36
    # Web Server TCP port number (default is 61208)
37
    web_server_port = 61208
38
    # Default username/password for client/server mode
39
    username = "glances"
40
    password = ""
41
42
    # Examples of use
43
    example_of_use = """
44
Examples of use:
45
  Monitor local machine (standalone mode):
46
    $ glances
47
48
  Display all Glances modules (plugins and exporters) and exit:
49
    $ glances --module-list
50
51
  Monitor local machine with the Web interface and start RESTful server:
52
    $ glances -w
53
    Glances web server started on http://0.0.0.0:61208/
54
55
  Only start RESTful API (without the WebUI):
56
    $ glances -w --disable-webui
57
    Glances API available on http://0.0.0.0:61208/api/
58
59
  Monitor local machine and export stats to a CSV file (standalone mode):
60
    $ glances --export csv --export-csv-file /tmp/glances.csv
61
62
  Monitor local machine and export stats to a InfluxDB server with 5s refresh rate (standalone mode):
63
    $ glances -t 5 --export influxdb
64
65
  Start a Glances XML-RPC server (server mode):
66
    $ glances -s
67
68
  Connect Glances to a Glances XML-RPC server (client mode):
69
    $ glances -c <ip_server>
70
71
  Connect Glances to a Glances server and export stats to a StatsD server (client mode):
72
    $ glances -c <ip_server> --export statsd
73
74
  Start the client browser (browser mode):
75
    $ glances --browser
76
77
  Display stats to stdout (one stat per line, possible to go inside stats using plugin.attribute):
78
    $ glances --stdout now,cpu.user,mem.used,load
79
80
  Display JSON stats to stdout (one stats per line):
81
    $ glances --stdout-json now,cpu,mem,load
82
83
  Display CSV stats to stdout (all stats in one line):
84
    $ glances --stdout-csv now,cpu.user,mem.used,load
85
86
  Enable some plugins disabled by default (comma-separated list):
87
    $ glances --enable-plugin sensors
88
89
  Disable some plugins (comma-separated list):
90
    $ glances --disable-plugin network,ports
91
92
  Disable all plugins except some (comma-separated list):
93
    $ glances --disable-plugin all --enable-plugin cpu,mem,load
94
95
"""
96
97
    def __init__(self):
98
        """Manage the command line arguments."""
99
        # Read the command line arguments
100
        self.args = self.parse_args()
101
102
    def version_msg(self):
103
        """Return the version message."""
104
        version = 'Glances version:\t{}\n'.format(__version__)
105
        version += 'Glances API version:\t{}\n'.format(__apiversion__)
106
        version += 'PsUtil version:\t\t{}\n'.format(psutil_version)
107
        version += 'Log file:\t\t{}\n'.format(LOG_FILENAME)
108
        return version
109
110
    def init_args(self):
111
        """Init all the command line arguments."""
112
        parser = argparse.ArgumentParser(
113
            prog='glances',
114
            conflict_handler='resolve',
115
            formatter_class=argparse.RawDescriptionHelpFormatter,
116
            epilog=self.example_of_use,
117
        )
118
        parser.add_argument('-V', '--version', action='version', version=self.version_msg())
119
        parser.add_argument('-d', '--debug', action='store_true', default=False, dest='debug', help='enable debug mode')
120
        parser.add_argument('-C', '--config', dest='conf_file', help='path to the configuration file')
121
        parser.add_argument('-P', '--plugins', dest='plugin_dir', help='path to additional plugin directory')
122
        # Disable plugin
123
        parser.add_argument(
124
            '--modules-list',
125
            '--module-list',
126
            action='store_true',
127
            default=False,
128
            dest='modules_list',
129
            help='display modules (plugins & exports) list and exit',
130
        )
131
        parser.add_argument(
132
            '--disable-plugin',
133
            '--disable-plugins',
134
            '--disable',
135
            dest='disable_plugin',
136
            help='disable plugin (comma-separated list or all). If all is used, \
137
                then you need to configure --enable-plugin.',
138
        )
139
        parser.add_argument(
140
            '--enable-plugin',
141
            '--enable-plugins',
142
            '--enable',
143
            dest='enable_plugin',
144
            help='enable plugin (comma-separated list)',
145
        )
146
        parser.add_argument(
147
            '--disable-process',
148
            action='store_true',
149
            default=False,
150
            dest='disable_process',
151
            help='disable process module',
152
        )
153
        # Enable or disable option
154
        parser.add_argument(
155
            '--disable-webui',
156
            action='store_true',
157
            default=False,
158
            dest='disable_webui',
159
            help='disable the Web Interface',
160
        )
161
        parser.add_argument(
162
            '--light',
163
            '--enable-light',
164
            action='store_true',
165
            default=False,
166
            dest='enable_light',
167
            help='light mode for Curses UI (disable all but the top menu)',
168
        )
169
        parser.add_argument(
170
            '-0',
171
            '--disable-irix',
172
            action='store_true',
173
            default=False,
174
            dest='disable_irix',
175
            help='task\'s cpu usage will be divided by the total number of CPUs',
176
        )
177
        parser.add_argument(
178
            '-1',
179
            '--percpu',
180
            '--per-cpu',
181
            action='store_true',
182
            default=False,
183
            dest='percpu',
184
            help='start Glances in per CPU mode',
185
        )
186
        parser.add_argument(
187
            '-2',
188
            '--disable-left-sidebar',
189
            action='store_true',
190
            default=False,
191
            dest='disable_left_sidebar',
192
            help='disable network, disk I/O, FS and sensors modules',
193
        )
194
        parser.add_argument(
195
            '-3',
196
            '--disable-quicklook',
197
            action='store_true',
198
            default=False,
199
            dest='disable_quicklook',
200
            help='disable quick look module',
201
        )
202
        parser.add_argument(
203
            '-4',
204
            '--full-quicklook',
205
            action='store_true',
206
            default=False,
207
            dest='full_quicklook',
208
            help='disable all but quick look and load',
209
        )
210
        parser.add_argument(
211
            '-5',
212
            '--disable-top',
213
            action='store_true',
214
            default=False,
215
            dest='disable_top',
216
            help='disable top menu (QL, CPU, MEM, SWAP and LOAD)',
217
        )
218
        parser.add_argument(
219
            '-6', '--meangpu', action='store_true', default=False, dest='meangpu', help='start Glances in mean GPU mode'
220
        )
221
        parser.add_argument(
222
            '--disable-history',
223
            action='store_true',
224
            default=False,
225
            dest='disable_history',
226
            help='disable stats history',
227
        )
228
        parser.add_argument(
229
            '--disable-bold',
230
            action='store_true',
231
            default=False,
232
            dest='disable_bold',
233
            help='disable bold mode in the terminal',
234
        )
235
        parser.add_argument(
236
            '--disable-bg',
237
            action='store_true',
238
            default=False,
239
            dest='disable_bg',
240
            help='disable background colors in the terminal',
241
        )
242
        parser.add_argument(
243
            '--enable-irq', action='store_true', default=False, dest='enable_irq', help='enable IRQ module'
244
        ),
245
        parser.add_argument(
246
            '--enable-process-extended',
247
            action='store_true',
248
            default=False,
249
            dest='enable_process_extended',
250
            help='enable extended stats on top process',
251
        )
252
        parser.add_argument(
253
            '--disable-separator',
254
            action='store_false',
255
            default=True,
256
            dest='enable_separator',
257
            help='disable separator in the UI (between top and others modules)',
258
        ),
259
        parser.add_argument(
260
            '--disable-cursor',
261
            action='store_true',
262
            default=False,
263
            dest='disable_cursor',
264
            help='disable cursor (process selection) in the UI',
265
        ),
266
        # Sort processes list
267
        parser.add_argument(
268
            '--sort-processes',
269
            dest='sort_processes_key',
270
            choices=sort_processes_key_list,
271
            help='Sort processes by: {}'.format(', '.join(sort_processes_key_list)),
272
        )
273
        # Display processes list by program name and not by thread
274
        parser.add_argument(
275
            '--programs',
276
            '--program',
277
            action='store_true',
278
            default=False,
279
            dest='programs',
280
            help='Accumulate processes by program',
281
        )
282
        # Export modules feature
283
        parser.add_argument('--export', dest='export', help='enable export module (comma-separated list)')
284
        parser.add_argument(
285
            '--export-csv-file', default='./glances.csv', dest='export_csv_file', help='file path for CSV exporter'
286
        )
287
        parser.add_argument(
288
            '--export-csv-overwrite',
289
            action='store_true',
290
            default=False,
291
            dest='export_csv_overwrite',
292
            help='overwrite existing CSV file',
293
        )
294
        parser.add_argument(
295
            '--export-json-file', default='./glances.json', dest='export_json_file', help='file path for JSON exporter'
296
        )
297
        parser.add_argument(
298
            '--export-graph-path',
299
            default=tempfile.gettempdir(),
300
            dest='export_graph_path',
301
            help='Folder for Graph exporter',
302
        )
303
        parser.add_argument(
304
            '--export-process-filter',
305
            default=None,
306
            type=str,
307
            dest='export_process_filter',
308
            help='set the export process filter (comman separated list of regular expression)',
309
        )
310
        # Client/Server option
311
        parser.add_argument(
312
            '-c', '--client', dest='client', help='connect to a Glances server by IPv4/IPv6 address or hostname'
313
        )
314
        parser.add_argument(
315
            '-s', '--server', action='store_true', default=False, dest='server', help='run Glances in server mode'
316
        )
317
        parser.add_argument(
318
            '--browser',
319
            action='store_true',
320
            default=False,
321
            dest='browser',
322
            help='start the client browser (list of servers)',
323
        )
324
        parser.add_argument(
325
            '--disable-autodiscover',
326
            action='store_true',
327
            default=False,
328
            dest='disable_autodiscover',
329
            help='disable autodiscover feature',
330
        )
331
        parser.add_argument(
332
            '-p',
333
            '--port',
334
            default=None,
335
            type=int,
336
            dest='port',
337
            help='define the client/server TCP port [default: {}]'.format(self.server_port),
338
        )
339
        parser.add_argument(
340
            '-B',
341
            '--bind',
342
            default='0.0.0.0',
343
            dest='bind_address',
344
            help='bind server to the given IPv4/IPv6 address or hostname',
345
        )
346
        parser.add_argument(
347
            '--username',
348
            action='store_true',
349
            default=False,
350
            dest='username_prompt',
351
            help='define a client/server username',
352
        )
353
        parser.add_argument(
354
            '--password',
355
            action='store_true',
356
            default=False,
357
            dest='password_prompt',
358
            help='define a client/server password',
359
        )
360
        parser.add_argument('-u', dest='username_used', help='use the given client/server username')
361
        parser.add_argument('--snmp-community', default='public', dest='snmp_community', help='SNMP community')
362
        parser.add_argument('--snmp-port', default=161, type=int, dest='snmp_port', help='SNMP port')
363
        parser.add_argument('--snmp-version', default='2c', dest='snmp_version', help='SNMP version (1, 2c or 3)')
364
        parser.add_argument('--snmp-user', default='private', dest='snmp_user', help='SNMP username (only for SNMPv3)')
365
        parser.add_argument(
366
            '--snmp-auth', default='password', dest='snmp_auth', help='SNMP authentication key (only for SNMPv3)'
367
        )
368
        parser.add_argument(
369
            '--snmp-force', action='store_true', default=False, dest='snmp_force', help='force SNMP mode'
370
        )
371
        parser.add_argument(
372
            '-t',
373
            '--time',
374
            default=self.DEFAULT_REFRESH_TIME,
375
            type=float,
376
            dest='time',
377
            help='set minimum refresh rate in seconds [default: {} sec]'.format(self.DEFAULT_REFRESH_TIME),
378
        )
379
        parser.add_argument(
380
            '-w',
381
            '--webserver',
382
            action='store_true',
383
            default=False,
384
            dest='webserver',
385
            help='run Glances in web server mode (FastAPI, Uvicorn, Jinja2 and OrJsonLib needed)',
386
        )
387
        parser.add_argument(
388
            '--cached-time',
389
            default=self.cached_time,
390
            type=int,
391
            dest='cached_time',
392
            help='set the server cache time [default: {} sec]'.format(self.cached_time),
393
        )
394
        parser.add_argument(
395
            '--stop-after',
396
            default=None,
397
            type=int,
398
            dest='stop_after',
399
            help='stop Glances after n refresh',
400
        )
401
        parser.add_argument(
402
            '--open-web-browser',
403
            action='store_true',
404
            default=False,
405
            dest='open_web_browser',
406
            help='try to open the Web UI in the default Web browser',
407
        )
408
        # Display options
409
        parser.add_argument(
410
            '-q',
411
            '--quiet',
412
            default=False,
413
            action='store_true',
414
            dest='quiet',
415
            help='do not display the curses interface',
416
        )
417
        parser.add_argument(
418
            '-f',
419
            '--process-filter',
420
            default=None,
421
            type=str,
422
            dest='process_filter',
423
            help='set the process filter pattern (regular expression)',
424
        )
425
        parser.add_argument(
426
            '--process-short-name',
427
            action='store_true',
428
            default=True,
429
            dest='process_short_name',
430
            help='force short name for processes name',
431
        )
432
        parser.add_argument(
433
            '--process-long-name',
434
            action='store_false',
435
            default=False,
436
            dest='process_short_name',
437
            help='force long name for processes name',
438
        )
439
        parser.add_argument(
440
            '--stdout',
441
            default=None,
442
            dest='stdout',
443
            help='display stats to stdout, one stat per line (comma-separated list of plugins/plugins.attribute)',
444
        )
445
        parser.add_argument(
446
            '--stdout-json',
447
            default=None,
448
            dest='stdout_json',
449
            help='display stats to stdout, JSON format (comma-separated list of plugins/plugins.attribute)',
450
        )
451
        parser.add_argument(
452
            '--stdout-csv',
453
            default=None,
454
            dest='stdout_csv',
455
            help='display stats to stdout, CSV format (comma-separated list of plugins/plugins.attribute)',
456
        )
457
        parser.add_argument(
458
            '--issue',
459
            default=None,
460
            action='store_true',
461
            dest='stdout_issue',
462
            help='test all plugins and exit (please copy/paste the output if you open an issue)',
463
        )
464
        parser.add_argument(
465
            '--trace-malloc',
466
            default=False,
467
            action='store_true',
468
            dest='trace_malloc',
469
            help='trace memory allocation and display it at the end of the process (python 3.4 or higher needed)',
470
        )
471
        parser.add_argument(
472
            '--memory-leak',
473
            default=False,
474
            action='store_true',
475
            dest='memory_leak',
476
            help='test memory leak (python 3.4 or higher needed)',
477
        )
478
        parser.add_argument(
479
            '--api-doc', default=None, action='store_true', dest='stdout_apidoc', help='display fields descriptions'
480
        )
481
        if not WINDOWS:
482
            parser.add_argument(
483
                '--hide-kernel-threads',
484
                action='store_true',
485
                default=False,
486
                dest='no_kernel_threads',
487
                help='hide kernel threads in the process list (not available on Windows)',
488
            )
489
        parser.add_argument(
490
            '-b',
491
            '--byte',
492
            action='store_true',
493
            default=False,
494
            dest='byte',
495
            help='display network rate in bytes per second',
496
        )
497
        parser.add_argument(
498
            '--diskio-show-ramfs',
499
            action='store_true',
500
            default=False,
501
            dest='diskio_show_ramfs',
502
            help='show RAM Fs in the DiskIO plugin',
503
        )
504
        parser.add_argument(
505
            '--diskio-iops',
506
            action='store_true',
507
            default=False,
508
            dest='diskio_iops',
509
            help='show IO per second in the DiskIO plugin',
510
        )
511
        parser.add_argument(
512
            '--fahrenheit',
513
            action='store_true',
514
            default=False,
515
            dest='fahrenheit',
516
            help='display temperature in Fahrenheit (default is Celsius)',
517
        )
518
        parser.add_argument(
519
            '--fs-free-space',
520
            action='store_true',
521
            default=False,
522
            dest='fs_free_space',
523
            help='display FS free space instead of used',
524
        )
525
        parser.add_argument(
526
            '--sparkline',
527
            action='store_true',
528
            default=False,
529
            dest='sparkline',
530
            help='display sparklines instead of bar in the curses interface',
531
        )
532
        parser.add_argument(
533
            '--disable-unicode',
534
            action='store_true',
535
            default=False,
536
            dest='disable_unicode',
537
            help='disable unicode characters in the curses interface',
538
        )
539
        parser.add_argument(
540
            '--hide-public-info',
541
            action='store_true',
542
            default=False,
543
            help='hide public information (like public IP)',
544
        )
545
        # Globals options
546
        parser.add_argument(
547
            '--disable-check-update',
548
            action='store_true',
549
            default=False,
550
            dest='disable_check_update',
551
            help='disable online Glances version ckeck',
552
        )
553
        parser.add_argument(
554
            '--strftime',
555
            dest='strftime_format',
556
            default='',
557
            help='strftime format string for displaying current date in standalone mode',
558
        )
559
560
        return parser
561
562
    def init_debug(self, args):
563
        """Init Glances debug mode."""
564
        if args.debug:
565
            logger.setLevel(DEBUG)
566
        else:
567
            simplefilter("ignore")
568
569
    def init_refresh_rate(self, args):
570
        """Init Glances refresh rate"""
571
        if self.config.has_section('global'):
572
            global_refresh = self.config.get_float_value('global', 'refresh', default=self.DEFAULT_REFRESH_TIME)
573
        else:
574
            global_refresh = self.DEFAULT_REFRESH_TIME
575
576
        # The configuration key can be overwrite from the command line (-t <time>)
577
        if args.time == self.DEFAULT_REFRESH_TIME:
578
            args.time = global_refresh
579
580
        logger.debug('Global refresh rate is set to {} seconds'.format(args.time))
581
582
    def init_plugins(self, args):
583
        """Init Glances plugins"""
584
        # Allow users to disable plugins from the glances.conf (issue #1378)
585
        for s in self.config.sections():
586
            if self.config.has_section(s) and (self.config.get_bool_value(s, 'disable', False)):
587
                disable(args, s)
588
                logger.debug('{} disabled by the configuration file'.format(s))
589
        # The configuration key can be overwrite from the command line
590
        if args and args.disable_plugin and 'all' in args.disable_plugin.split(','):
591
            if not args.enable_plugin:
592
                logger.critical("'all' key in --disable-plugin needs to be used with --enable-plugin")
593
                sys.exit(2)
594
            else:
595
                logger.info(
596
                    "'all' key in --disable-plugin, only plugins defined with --enable-plugin will be available"
597
                )
598
        if args.disable_plugin is not None:
599
            for p in args.disable_plugin.split(','):
600
                disable(args, p)
601
        if args.enable_plugin is not None:
602
            for p in args.enable_plugin.split(','):
603
                enable(args, p)
604
605
        # Exporters activation
606
        if args.export is not None:
607
            for p in args.export.split(','):
608
                setattr(args, 'export_' + p, True)
609
610
        # By default help is hidden
611
        args.help_tag = False
612
613
        # Display Rx and Tx, not the sum for the network
614
        args.network_sum = False
615
        args.network_cumul = False
616
617
        # Processlist id updated in processcount
618
        if getattr(args, 'enable_processlist', False):
619
            enable(args, 'processcount')
620
621
        # Set a default export_process_filter (with all process) when using the stdout mode
622
        if getattr(args, 'stdout', True) and args.process_filter is None:
623
            setattr(args, 'export_process_filter', '.*')
624
625
    def init_client_server(self, args):
626
        """Init Glances client/server mode."""
627
628
        # Client/server Port
629
        if args.port is None:
630
            if args.webserver:
631
                args.port = self.web_server_port
632
            else:
633
                args.port = self.server_port
634
        # Port in the -c URI #996
635
        if args.client is not None:
636
            args.client, args.port = (
637
                x if x else y for (x, y) in zip(args.client.partition(':')[::2], (args.client, args.port))
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable x does not seem to be defined.
Loading history...
Comprehensibility Best Practice introduced by
The variable y does not seem to be defined.
Loading history...
638
            )
639
640
        # Client autodiscover mode
641
        if args.disable_autodiscover:
642
            logger.info("Auto discover mode is disabled")
643
644
        # Server or client login/password
645
        if args.username_prompt:
646
            # Every username needs a password
647
            args.password_prompt = True
648
            # Prompt username
649
            if args.server:
650
                args.username = self.__get_username(description='Define the Glances server username: ')
651
            elif args.webserver:
652
                args.username = self.__get_username(description='Define the Glances webserver username: ')
653
            elif args.client:
654
                args.username = self.__get_username(description='Enter the Glances server username: ')
655
        else:
656
            if args.username_used:
657
                # A username has been set using the -u option ?
658
                args.username = args.username_used
659
            else:
660
                # Default user name is 'glances'
661
                args.username = self.username
662
663
        if args.password_prompt or args.username_used:
664
            # Interactive or file password
665
            if args.server:
666
                args.password = self.__get_password(
667
                    description='Define the Glances server password ({} username): '.format(args.username),
668
                    confirm=True,
669
                    username=args.username,
670
                )
671
            elif args.webserver:
672
                args.password = self.__get_password(
673
                    description='Define the Glances webserver password ({} username): '.format(args.username),
674
                    confirm=True,
675
                    username=args.username,
676
                )
677
            elif args.client:
678
                args.password = self.__get_password(
679
                    description='Enter the Glances server password ({} username): '.format(args.username),
680
                    clear=True,
681
                    username=args.username,
682
                )
683
        else:
684
            # Default is no password
685
            args.password = self.password
686
687
    def init_ui_mode(self, args):
688
        # Manage light mode
689
        if getattr(args, 'enable_light', False):
690
            logger.info("Light mode is on")
691
            args.disable_left_sidebar = True
692
            disable(args, 'process')
693
            disable(args, 'alert')
694
            disable(args, 'amps')
695
            disable(args, 'containers')
696
697
        # Manage full quicklook option
698
        if getattr(args, 'full_quicklook', False):
699
            logger.info("Full quicklook mode")
700
            enable(args, 'quicklook')
701
            disable(args, 'cpu')
702
            disable(args, 'mem')
703
            disable(args, 'memswap')
704
            enable(args, 'load')
705
706
        # Manage disable_top option
707
        if getattr(args, 'disable_top', False):
708
            logger.info("Disable top menu")
709
            disable(args, 'quicklook')
710
            disable(args, 'cpu')
711
            disable(args, 'mem')
712
            disable(args, 'memswap')
713
            disable(args, 'load')
714
715
        # Memory leak
716
        if getattr(args, 'memory_leak', False):
717
            logger.info('Memory leak detection enabled')
718
            args.quiet = True
719
            if not args.stop_after:
720
                args.stop_after = 60
721
            args.time = 1
722
            args.disable_history = True
723
724
    def parse_args(self):
725
        """Parse command line arguments."""
726
        args = self.init_args().parse_args()
727
728
        # Load the configuration file, if it exists
729
        # This function should be called after the parse_args
730
        # because the configuration file path can be defined
731
        self.config = Config(args.conf_file)
732
733
        # Init Glances debug mode
734
        self.init_debug(args)
735
736
        # Plugins Glances refresh rate
737
        self.init_refresh_rate(args)
738
739
        # Manage Plugins disable/enable option
740
        self.init_plugins(args)
741
742
        # Init Glances client/server mode
743
        self.init_client_server(args)
744
745
        # Init UI mode
746
        self.init_ui_mode(args)
747
748
        # Init the generate_graph tag
749
        # Should be set to True to generate graphs
750
        args.generate_graph = False
751
752
        # Control parameter and exit if it is not OK
753
        self.args = args
754
755
        # Export is only available in standalone or client mode (issue #614)
756
        export_tag = self.args.export is not None and any(self.args.export)
757
        if WINDOWS and export_tag:
758
            # On Windows, export is possible but only in quiet mode
759
            # See issue #1038
760
            logger.info("On Windows OS, export disable the Web interface")
761
            self.args.quiet = True
762
            self.args.webserver = False
763
        elif not (self.is_standalone() or self.is_client()) and export_tag:
764
            logger.critical("Export is only available in standalone or client mode")
765
            sys.exit(2)
766
767
        # Filter is only available in standalone mode
768
        if not args.process_filter and not self.is_standalone():
769
            logger.debug("Process filter is only available in standalone mode")
770
771
        # Cursor option is only available in standalone mode
772
        if not args.disable_cursor and not self.is_standalone():
773
            logger.debug("Cursor is only available in standalone mode")
774
775
        # Let the plugins known the Glances mode
776
        self.args.is_standalone = self.is_standalone()
777
        self.args.is_client = self.is_client()
778
        self.args.is_client_browser = self.is_client_browser()
779
        self.args.is_server = self.is_server()
780
        self.args.is_webserver = self.is_webserver()
781
782
        # Check mode compatibility
783
        self.check_mode_compatibility()
784
785
        return args
786
787
    def check_mode_compatibility(self):
788
        """Check mode compatibility"""
789
        # Server and Web server are not compatible
790
        if self.args.is_server and self.args.is_webserver:
791
            logger.critical("Server and Web server modes should not be used together")
792
            sys.exit(2)
793
794
        # Trace malloc option
795
        if getattr(self.args, 'trace_malloc', True) and not self.is_standalone():
796
            logger.critical("Option --trace-malloc is only available in the terminal mode")
797
            sys.exit(2)
798
799
        # Memory leak option
800
        if getattr(self.args, 'memory_leak', True) and not self.is_standalone():
801
            logger.critical("Option --memory-leak is only available in the terminal mode")
802
            sys.exit(2)
803
804
    def is_standalone(self):
805
        """Return True if Glances is running in standalone mode."""
806
        return not self.args.client and not self.args.browser and not self.args.server and not self.args.webserver
807
808
    def is_client(self):
809
        """Return True if Glances is running in client mode."""
810
        return (self.args.client or self.args.browser) and not self.args.server
811
812
    def is_client_browser(self):
813
        """Return True if Glances is running in client browser mode."""
814
        return self.args.browser and not self.args.server
815
816
    def is_server(self):
817
        """Return True if Glances is running in server mode."""
818
        return not self.args.client and self.args.server
819
820
    def is_webserver(self):
821
        """Return True if Glances is running in Web server mode."""
822
        return not self.args.client and self.args.webserver
823
824
    def get_config(self):
825
        """Return configuration file object."""
826
        return self.config
827
828
    def get_args(self):
829
        """Return the arguments."""
830
        return self.args
831
832
    def get_mode(self):
833
        """Return the mode."""
834
        return self.mode
835
836
    def __get_username(self, description=''):
837
        """Read an username from the command line."""
838
        return input(description)
839
840
    def __get_password(self, description='', confirm=False, clear=False, username='glances'):
841
        """Read a password from the command line.
842
843
        - if confirm = True, with confirmation
844
        - if clear = True, plain (clear password)
845
        """
846
        from glances.password import GlancesPassword
847
848
        password = GlancesPassword(username=username, config=self.get_config())
849
        return password.get_password(description, confirm, clear)
850