Test Failed
Push — master ( ce0fc3...e09530 )
by Nicolas
03:36
created

GlancesClientBrowser.__serve_forever()   A

Complexity

Conditions 3

Size

Total Lines 13
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 6
nop 1
dl 0
loc 13
rs 10
c 0
b 0
f 0
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
"""Manage the Glances client browser (list of Glances server)."""
10
11
import webbrowser
12
13
from glances.client import GlancesClient
14
from glances.logger import LOG_FILENAME, logger
15
from glances.outputs.glances_curses_browser import GlancesCursesBrowser
16
from glances.servers_list import GlancesServersList
17
18
19
class GlancesClientBrowser:
20
    """This class creates and manages the TCP client browser (servers list)."""
21
22
    def __init__(self, config=None, args=None):
23
        # Store the arg/config
24
        self.args = args
25
        self.config = config
26
27
        # Init the server list
28
        self.servers_list = GlancesServersList(config=config, args=args)
29
30
        # Init screen
31
        self.screen = GlancesCursesBrowser(args=self.args)
32
33
    def __display_server(self, server):
34
        """Connect and display the given server"""
35
        # Display the Glances client for the selected server
36
        logger.debug(f"Selected server {server}")
37
38
        if server['protocol'].lower() == 'rest':
39
            # Display a popup
40
            self.screen.display_popup(
41
                'Open the WebUI {}:{} in a Web Browser'.format(server['name'], server['port']), duration=1
42
            )
43
            # Try to open a Webbrowser
44
            webbrowser.open(self.servers_list.get_uri(server), new=2, autoraise=1)
45
            self.screen.active_server = None
46
            return
47
48
        # Connection can take time
49
        # Display a popup
50
        self.screen.display_popup('Connect to {}:{}'.format(server['name'], server['port']), duration=1)
51
52
        # A password is needed to access to the server's stats
53
        if server['password'] is None:
54
            # First of all, check if a password is available in the [passwords] section
55
            clear_password = self.servers_list.password.get_password(server['name'])
56
            if (
57
                clear_password is None
58
                or self.servers_list.get_servers_list()[self.screen.active_server]['status'] == 'PROTECTED'
59
            ):
60
                # Else, the password should be enter by the user
61
                # Display a popup to enter password
62
                clear_password = self.screen.display_popup(
63
                    'Password needed for {}: '.format(server['name']), popup_type='input', is_password=True
64
                )
65
            # Store the password for the selected server
66
            if clear_password is not None:
67
                self.set_in_selected('password', self.servers_list.password.get_hash(clear_password))
68
69
        # Display the Glance client on the selected server
70
        logger.info("Connect Glances client to the {} server".format(server['key']))
71
72
        # Init the client
73
        args_server = self.args
74
75
        # Overwrite connection setting
76
        args_server.client = server['ip']
77
        args_server.port = server['port']
78
        args_server.username = server['username']
79
        args_server.password = server['password']
80
        client = GlancesClient(config=self.config, args=args_server, return_to_browser=True)
81
82
        # Test if client and server are in the same major version
83
        if not client.login():
84
            self.screen.display_popup(
85
                "Sorry, cannot connect to '{}'\n" "See '{}' for more details".format(server['name'], LOG_FILENAME)
86
            )
87
88
            # Set the ONLINE status for the selected server
89
            self.set_in_selected('status', 'OFFLINE')
90
        else:
91
            # Start the client loop
92
            # Return connection type: 'glances' or 'snmp'
93
            connection_type = client.serve_forever()
94
95
            try:
96
                logger.debug("Disconnect Glances client from the {} server".format(server['key']))
97
            except IndexError:
98
                # Server did not exist anymore
99
                pass
100
            else:
101
                # Set the ONLINE status for the selected server
102
                if connection_type == 'snmp':
103
                    self.set_in_selected('status', 'SNMP')
104
                else:
105
                    self.set_in_selected('status', 'ONLINE')
106
107
        # Return to the browser (no server selected)
108
        self.screen.active_server = None
109
110
    def __serve_forever(self):
111
        """Main client loop."""
112
        # No need to update the server list
113
        while not self.screen.is_end:
114
            # Update the stats in the servers list
115
            self.servers_list.update_servers_stats()
116
117
            if self.screen.active_server is None:
118
                # Display Glances browser (servers list)
119
                self.screen.update(self.servers_list.get_servers_list())
120
            else:
121
                # Display selected Glances server
122
                self.__display_server(self.servers_list.get_servers_list()[self.screen.active_server])
123
124
    def serve_forever(self):
125
        """Wrapper to the serve_forever function.
126
127
        This function will restore the terminal to a sane state
128
        before re-raising the exception and generating a traceback.
129
        """
130
        try:
131
            return self.__serve_forever()
132
        finally:
133
            self.end()
134
135
    def set_in_selected(self, key, value):
136
        """Set the (key, value) for the selected server in the list."""
137
        self.servers_list.set_in_selected(self.screen.active_server, key, value)
138
139
    def end(self):
140
        """End of the client browser session."""
141
        self.screen.end()
142