glances.main.GlancesMain.init_plugins()   F
last analyzed

Complexity

Conditions 18

Size

Total Lines 42
Code Lines 27

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 18
eloc 27
nop 2
dl 0
loc 42
rs 1.2
c 0
b 0
f 0

How to fix   Complexity   

Complexity

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