Test Failed
Push — develop ( df4b31...c89eff )
by Nicolas
03:00
created

glances.main   F

Complexity

Total Complexity 86

Size/Duplication

Total Lines 928
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 628
dl 0
loc 928
rs 1.972
c 0
b 0
f 0
wmc 86

21 Methods

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