Completed
Push — master ( bcff18...adb900 )
by Nicolas
01:15
created

glances.GlancesMain.__init__()   A

Complexity

Conditions 1

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %
Metric Value
cc 1
dl 0
loc 3
rs 10
1
# -*- coding: utf-8 -*-
2
#
3
# This file is part of Glances.
4
#
5
# Copyright (C) 2015 Nicolargo <[email protected]>
6
#
7
# Glances is free software; you can redistribute it and/or modify
8
# it under the terms of the GNU Lesser General Public License as published by
9
# the Free Software Foundation, either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Glances is distributed in the hope that it will be useful,
13
# but WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU Lesser General Public License for more details.
16
#
17
# You should have received a copy of the GNU Lesser General Public License
18
# along with this program. If not, see <http://www.gnu.org/licenses/>.
19
20
"""Glances main class."""
21
22
import argparse
23
import os
24
import sys
25
import tempfile
26
27
from glances.compat import input
28
from glances.config import Config
29
from glances.globals import appname, LINUX, WINDOWS, psutil_version, version
30
from glances.logger import logger
31
32
33
class GlancesMain(object):
34
35
    """Main class to manage Glances instance."""
36
37
    # Default stats' refresh time is 3 seconds
38
    refresh_time = 3
39
40
    # Set the default cache lifetime to 1 second (only for server)
41
    # !!! Todo: configuration from the command line
42
    cached_time = 1
43
    # By default, Glances is ran in standalone mode (no client/server)
44
    client_tag = False
45
    # Server TCP port number (default is 61209)
46
    server_port = 61209
47
    # Web Server TCP port number (default is 61208)
48
    web_server_port = 61208
49
    # Default username/password for client/server mode
50
    username = "glances"
51
    password = ""
52
53
    # Exemple of use
54
    example_of_use = "\
55
Examples of use:\n\
56
\n\
57
Monitor local machine (standalone mode):\n\
58
  $ glances\n\
59
\n\
60
Monitor local machine with the Web interface (Web UI):\n\
61
  $ glances -w\n\
62
  Glances web server started on http://0.0.0.0:61208/\n\
63
\n\
64
Monitor local machine and export stats to a CSV file (standalone mode):\n\
65
  $ glances --export-csv\n\
66
\n\
67
Monitor local machine and export stats to a InfluxDB server with 5s refresh time (standalone mode):\n\
68
  $ glances -t 5 --export-influxdb\n\
69
\n\
70
Start a Glances server (server mode):\n\
71
  $ glances -s\n\
72
\n\
73
Connect Glances to a Glances server (client mode):\n\
74
  $ glances -c <ip_server>\n\
75
\n\
76
Connect Glances to a Glances server and export stats to a StatsD server (client mode):\n\
77
  $ glances -c <ip_server> --export-statsd\n\
78
\n\
79
Start the client browser (browser mode):\n\
80
  $ glances --browser\n\
81
    "
82
83
    def __init__(self):
84
        """Manage the command line arguments."""
85
        self.args = self.parse_args()
86
87
    def init_args(self):
88
        """Init all the command line arguments."""
89
        _version = "Glances v" + version + " with psutil v" + psutil_version
90
        parser = argparse.ArgumentParser(
91
            prog=appname,
92
            conflict_handler='resolve',
93
            formatter_class=argparse.RawDescriptionHelpFormatter,
94
            epilog=self.example_of_use)
95
        parser.add_argument(
96
            '-V', '--version', action='version', version=_version)
97
        parser.add_argument('-d', '--debug', action='store_true', default=False,
98
                            dest='debug', help='enable debug mode')
99
        parser.add_argument('-C', '--config', dest='conf_file',
100
                            help='path to the configuration file')
101
        # Enable or disable option on startup
102
        parser.add_argument('-3', '--disable-quicklook', action='store_true', default=False,
103
                            dest='disable_quicklook', help='disable quick look module')
104
        parser.add_argument('-4', '--full-quicklook', action='store_true', default=False,
105
                            dest='full_quicklook', help='disable all but quick look and load')
106
        parser.add_argument('--disable-cpu', action='store_true', default=False,
107
                            dest='disable_cpu', help='disable CPU module')
108
        parser.add_argument('--disable-mem', action='store_true', default=False,
109
                            dest='disable_mem', help='disable memory module')
110
        parser.add_argument('--disable-swap', action='store_true', default=False,
111
                            dest='disable_swap', help='disable swap module')
112
        parser.add_argument('--disable-load', action='store_true', default=False,
113
                            dest='disable_load', help='disable load module')
114
        parser.add_argument('--disable-network', action='store_true', default=False,
115
                            dest='disable_network', help='disable network module')
116
        parser.add_argument('--disable-ip', action='store_true', default=False,
117
                            dest='disable_ip', help='disable IP module')
118
        parser.add_argument('--disable-diskio', action='store_true', default=False,
119
                            dest='disable_diskio', help='disable disk I/O module')
120
        parser.add_argument('--disable-fs', action='store_true', default=False,
121
                            dest='disable_fs', help='disable filesystem module')
122
        parser.add_argument('--disable-folder', action='store_true', default=False,
123
                            dest='disable_folder', help='disable folder module')
124
        parser.add_argument('--disable-sensors', action='store_true', default=False,
125
                            dest='disable_sensors', help='disable sensors module')
126
        parser.add_argument('--disable-hddtemp', action='store_true', default=False,
127
                            dest='disable_hddtemp', help='disable HD temperature module')
128
        parser.add_argument('--disable-raid', action='store_true', default=False,
129
                            dest='disable_raid', help='disable RAID module')
130
        parser.add_argument('--disable-docker', action='store_true', default=False,
131
                            dest='disable_docker', help='disable Docker module')
132
        parser.add_argument('-5', '--disable-top', action='store_true',
133
                            default=False, dest='disable_top',
134
                            help='disable top menu (QL, CPU, MEM, SWAP and LOAD)')
135
        parser.add_argument('-2', '--disable-left-sidebar', action='store_true',
136
                            default=False, dest='disable_left_sidebar',
137
                            help='disable network, disk I/O, FS and sensors modules')
138
        parser.add_argument('--disable-process', action='store_true', default=False,
139
                            dest='disable_process', help='disable process module')
140
        parser.add_argument('--disable-log', action='store_true', default=False,
141
                            dest='disable_log', help='disable log module')
142
        parser.add_argument('--disable-bold', action='store_true', default=False,
143
                            dest='disable_bold', help='disable bold mode in the terminal')
144
        parser.add_argument('--disable-bg', action='store_true', default=False,
145
                            dest='disable_bg', help='disable background colors in the terminal')
146
        parser.add_argument('--enable-process-extended', action='store_true', default=False,
147
                            dest='enable_process_extended', help='enable extended stats on top process')
148
        parser.add_argument('--enable-history', action='store_true', default=False,
149
                            dest='enable_history', help='enable the history mode (matplotlib needed)')
150
        parser.add_argument('--path-history', default=tempfile.gettempdir(),
151
                            dest='path_history', help='set the export path for graph history')
152
        # Export modules feature
153
        parser.add_argument('--export-csv', default=None,
154
                            dest='export_csv', help='export stats to a CSV file')
155
        parser.add_argument('--export-influxdb', action='store_true', default=False,
156
                            dest='export_influxdb', help='export stats to an InfluxDB server (influxdb lib needed)')
157
        parser.add_argument('--export-opentsdb', action='store_true', default=False,
158
                            dest='export_opentsdb', help='export stats to an OpenTSDB server (potsdb lib needed)')
159
        parser.add_argument('--export-statsd', action='store_true', default=False,
160
                            dest='export_statsd', help='export stats to a StatsD server (statsd lib needed)')
161
        parser.add_argument('--export-elasticsearch', action='store_true', default=False,
162
                            dest='export_elasticsearch', help='export stats to an ElasticSearch server (elasticsearch lib needed)')
163
        parser.add_argument('--export-rabbitmq', action='store_true', default=False,
164
                            dest='export_rabbitmq', help='export stats to rabbitmq broker (pika lib needed)')
165
        # Client/Server option
166
        parser.add_argument('-c', '--client', dest='client',
167
                            help='connect to a Glances server by IPv4/IPv6 address or hostname')
168
        parser.add_argument('-s', '--server', action='store_true', default=False,
169
                            dest='server', help='run Glances in server mode')
170
        parser.add_argument('--browser', action='store_true', default=False,
171
                            dest='browser', help='start the client browser (list of servers)')
172
        parser.add_argument('--disable-autodiscover', action='store_true', default=False,
173
                            dest='disable_autodiscover', help='disable autodiscover feature')
174
        parser.add_argument('-p', '--port', default=None, type=int, dest='port',
175
                            help='define the client/server TCP port [default: {0}]'.format(self.server_port))
176
        parser.add_argument('-B', '--bind', default='0.0.0.0', dest='bind_address',
177
                            help='bind server to the given IPv4/IPv6 address or hostname')
178
        parser.add_argument('--username', action='store_true', default=False, dest='username_prompt',
179
                            help='define a client/server username')
180
        parser.add_argument('--password', action='store_true', default=False, dest='password_prompt',
181
                            help='define a client/server password')
182
        parser.add_argument('--snmp-community', default='public', dest='snmp_community',
183
                            help='SNMP community')
184
        parser.add_argument('--snmp-port', default=161, type=int,
185
                            dest='snmp_port', help='SNMP port')
186
        parser.add_argument('--snmp-version', default='2c', dest='snmp_version',
187
                            help='SNMP version (1, 2c or 3)')
188
        parser.add_argument('--snmp-user', default='private', dest='snmp_user',
189
                            help='SNMP username (only for SNMPv3)')
190
        parser.add_argument('--snmp-auth', default='password', dest='snmp_auth',
191
                            help='SNMP authentication key (only for SNMPv3)')
192
        parser.add_argument('--snmp-force', action='store_true', default=False,
193
                            dest='snmp_force', help='force SNMP mode')
194
        parser.add_argument('-t', '--time', default=self.refresh_time, type=float,
195
                            dest='time', help='set refresh time in seconds [default: {0} sec]'.format(self.refresh_time))
196
        parser.add_argument('-w', '--webserver', action='store_true', default=False,
197
                            dest='webserver', help='run Glances in web server mode (bottle needed)')
198
        # Display options
199
        parser.add_argument('-q', '--quiet', default=False, action='store_true',
200
                            dest='quiet', help='do not display the curses interface')
201
        parser.add_argument('-f', '--process-filter', default=None, type=str,
202
                            dest='process_filter', help='set the process filter pattern (regular expression)')
203
        parser.add_argument('--process-short-name', action='store_true', default=False,
204
                            dest='process_short_name', help='force short name for processes name')
205
        parser.add_argument('-0', '--disable-irix', action='store_true', default=False,
206
                            dest='disable_irix', help='Task\'s cpu usage will be divided by the total number of CPUs')
207
        if not WINDOWS:
208
            parser.add_argument('--hide-kernel-threads', action='store_true', default=False,
209
                                dest='no_kernel_threads', help='hide kernel threads in process list')
210
        if LINUX:
211
            parser.add_argument('--tree', action='store_true', default=False,
212
                                dest='process_tree', help='display processes as a tree')
213
        parser.add_argument('-b', '--byte', action='store_true', default=False,
214
                            dest='byte', help='display network rate in byte per second')
215
        parser.add_argument('--diskio-show-ramfs', action='store_true', default=False,
216
                            dest='diskio_show_ramfs', help='show RAM Fs in the DiskIO plugin')
217
        parser.add_argument('--diskio-iops', action='store_true', default=False,
218
                            dest='diskio_iops', help='show IO per second in the DiskIO plugin')
219
        parser.add_argument('--fahrenheit', action='store_true', default=False,
220
                            dest='fahrenheit', help='display temperature in Fahrenheit (default is Celsius)')
221
        parser.add_argument('-1', '--percpu', action='store_true', default=False,
222
                            dest='percpu', help='start Glances in per CPU mode')
223
        parser.add_argument('--fs-free-space', action='store_true', default=False,
224
                            dest='fs_free_space', help='display FS free space instead of used')
225
        parser.add_argument('--theme-white', action='store_true', default=False,
226
                            dest='theme_white', help='optimize display colors for white background')
227
228
        return parser
229
230
    def parse_args(self):
231
        """Parse command line arguments."""
232
        args = self.init_args().parse_args()
233
234
        # Load the configuration file, if it exists
235
        self.config = Config(args.conf_file)
236
237
        # Debug mode
238
        if args.debug:
239
            from logging import DEBUG
240
            logger.setLevel(DEBUG)
241
242
        # Client/server Port
243
        if args.port is None:
244
            if args.webserver:
245
                args.port = self.web_server_port
246
            else:
247
                args.port = self.server_port
248
249
        # Autodiscover
250
        if args.disable_autodiscover:
251
            logger.info("Auto discover mode is disabled")
252
253
        # In web server mode
254
        if args.webserver:
255
            args.process_short_name = True
256
257
        # Server or client login/password
258
        if args.username_prompt:
259
            # Every username needs a password
260
            args.password_prompt = True
261
            # Prompt username
262
            if args.server:
263
                args.username = self.__get_username(description='Define the Glances server username: ')
264
            elif args.webserver:
265
                args.username = self.__get_username(description='Define the Glances webserver username: ')
266
            elif args.client:
267
                args.username = self.__get_username(description='Enter the Glances server username: ')
268
        else:
269
            # Default user name is 'glances'
270
            args.username = self.username
271
272
        if args.password_prompt:
273
            # Interactive or file password
274
            if args.server:
275
                args.password = self.__get_password(
276
                    description='Define the Glances server password ({0} username): '.format(args.username),
277
                    confirm=True,
278
                    username=args.username)
279
            elif args.webserver:
280
                args.password = self.__get_password(
281
                    description='Define the Glances webserver password ({0} username): '.format(args.username),
282
                    confirm=True,
283
                    username=args.username)
284
            elif args.client:
285
                args.password = self.__get_password(
286
                    description='Enter the Glances server password ({0} username): '.format(args.username),
287
                    clear=True,
288
                    username=args.username)
289
        else:
290
            # Default is no password
291
            args.password = self.password
292
293
        # By default help is hidden
294
        args.help_tag = False
295
296
        # Display Rx and Tx, not the sum for the network
297
        args.network_sum = False
298
        args.network_cumul = False
299
300
        # Manage full quicklook option
301
        if args.full_quicklook:
302
            logger.info("Disable QuickLook menu")
303
            args.disable_quicklook = False
304
            args.disable_cpu = True
305
            args.disable_mem = True
306
            args.disable_swap = True
307
            args.disable_load = False
308
309
        # Manage disable_top option
310
        if args.disable_top:
311
            logger.info("Disable top menu")
312
            args.disable_quicklook = True
313
            args.disable_cpu = True
314
            args.disable_mem = True
315
            args.disable_swap = True
316
            args.disable_load = True
317
318
        # Control parameter and exit if it is not OK
319
        self.args = args
320
321
        # Export is only available in standalone or client mode (issue #614)
322
        export_tag = args.export_csv or args.export_elasticsearch or args.export_statsd or args.export_influxdb or args.export_opentsdb or args.export_rabbitmq
323
        if not (self.is_standalone() or self.is_client()) and export_tag:
324
            logger.critical("Export is only available in standalone or client mode")
325
            sys.exit(2)
326
327
        # Filter is only available in standalone mode
328
        if args.process_filter is not None and not self.is_standalone():
329
            logger.critical("Process filter is only available in standalone mode")
330
            sys.exit(2)
331
332
        # Check graph output path
333
        if args.enable_history and args.path_history is not None:
334
            if not os.access(args.path_history, os.W_OK):
335
                logger.critical("History output path {0} do not exist or is not writable".format(args.path_history))
336
                sys.exit(2)
337
            logger.debug("History output path is set to {0}".format(args.path_history))
338
339
        # Disable HDDTemp if sensors are disabled
340
        if args.disable_sensors:
341
            args.disable_hddtemp = True
342
            logger.debug("Sensors and HDDTemp are disabled")
343
344
        return args
345
346
    def __get_username(self, description=''):
347
        """Read a username from the command line.
348
        """
349
        return input(description)
350
351
    def __get_password(self, description='', confirm=False, clear=False, username='glances'):
352
        """Read a password from the command line.
353
354
        - if confirm = True, with confirmation
355
        - if clear = True, plain (clear password)
356
        """
357
        from glances.password import GlancesPassword
358
        password = GlancesPassword(username=username)
359
        return password.get_password(description, confirm, clear)
360
361
    def is_standalone(self):
362
        """Return True if Glances is running in standalone mode."""
363
        return not self.args.client and not self.args.browser and not self.args.server and not self.args.webserver
364
365
    def is_client(self):
366
        """Return True if Glances is running in client mode."""
367
        return (self.args.client or self.args.browser) and not self.args.server
368
369
    def is_client_browser(self):
370
        """Return True if Glances is running in client browser mode."""
371
        return self.args.browser and not self.args.server
372
373
    def is_server(self):
374
        """Return True if Glances is running in server mode."""
375
        return not self.args.client and self.args.server
376
377
    def is_webserver(self):
378
        """Return True if Glances is running in Web server mode."""
379
        return not self.args.client and self.args.webserver
380
381
    def get_config(self):
382
        """Return configuration file object."""
383
        return self.config
384
385
    def get_args(self):
386
        """Return the arguments."""
387
        return self.args
388