| Conditions | 23 |
| Total Lines | 138 |
| Lines | 0 |
| Ratio | 0 % |
Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.
For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.
Commonly applied refactorings include:
If many parameters/temporary variables are present:
Complex classes like glances.GlancesClientBrowser.__serve_forever() often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
| 1 | # -*- coding: utf-8 -*- |
||
| 93 | def __serve_forever(self): |
||
| 94 | """Main client loop.""" |
||
| 95 | while True: |
||
| 96 | # No need to update the server list |
||
| 97 | # It's done by the GlancesAutoDiscoverListener class (autodiscover.py) |
||
| 98 | # Or define staticaly in the configuration file (module static_list.py) |
||
| 99 | # For each server in the list, grab elementary stats (CPU, LOAD, MEM, OS...) |
||
| 100 | # logger.debug(self.get_servers_list()) |
||
| 101 | try: |
||
| 102 | for v in self.get_servers_list(): |
||
| 103 | # Do not retreive stats for statics server |
||
| 104 | # Why ? Because for each offline servers, the timeout will be reached |
||
| 105 | # So ? The curse interface freezes |
||
| 106 | if v['type'] == 'STATIC' and v['status'] in ['UNKNOWN', 'SNMP', 'OFFLINE']: |
||
| 107 | continue |
||
| 108 | |||
| 109 | # Get the server URI |
||
| 110 | uri = self.__get_uri(v) |
||
| 111 | |||
| 112 | # Try to connect to the server |
||
| 113 | t = GlancesClientTransport() |
||
| 114 | t.set_timeout(3) |
||
| 115 | |||
| 116 | # Get common stats |
||
| 117 | try: |
||
| 118 | s = ServerProxy(uri, transport=t) |
||
| 119 | except Exception as e: |
||
| 120 | logger.warning( |
||
| 121 | "Client browser couldn't create socket {0}: {1}".format(uri, e)) |
||
| 122 | else: |
||
| 123 | # Mandatory stats |
||
| 124 | try: |
||
| 125 | # CPU% |
||
| 126 | cpu_percent = 100 - json.loads(s.getCpu())['idle'] |
||
| 127 | v['cpu_percent'] = '{0:.1f}'.format(cpu_percent) |
||
| 128 | # MEM% |
||
| 129 | v['mem_percent'] = json.loads(s.getMem())['percent'] |
||
| 130 | # OS (Human Readable name) |
||
| 131 | v['hr_name'] = json.loads(s.getSystem())['hr_name'] |
||
| 132 | except (socket.error, Fault, KeyError) as e: |
||
| 133 | logger.debug( |
||
| 134 | "Error while grabbing stats form {0}: {1}".format(uri, e)) |
||
| 135 | v['status'] = 'OFFLINE' |
||
| 136 | except ProtocolError as e: |
||
| 137 | if e.errcode == 401: |
||
| 138 | # Error 401 (Authentication failed) |
||
| 139 | # Password is not the good one... |
||
| 140 | v['password'] = None |
||
| 141 | v['status'] = 'PROTECTED' |
||
| 142 | else: |
||
| 143 | v['status'] = 'OFFLINE' |
||
| 144 | logger.debug("Cannot grab stats from {0} ({1} {2})".format(uri, e.errcode, e.errmsg)) |
||
| 145 | else: |
||
| 146 | # Status |
||
| 147 | v['status'] = 'ONLINE' |
||
| 148 | |||
| 149 | # Optional stats (load is not available on Windows OS) |
||
| 150 | try: |
||
| 151 | # LOAD |
||
| 152 | load_min5 = json.loads(s.getLoad())['min5'] |
||
| 153 | v['load_min5'] = '{0:.2f}'.format(load_min5) |
||
| 154 | except Exception as e: |
||
| 155 | logger.warning( |
||
| 156 | "Error while grabbing stats form {0}: {1}".format(uri, e)) |
||
| 157 | # List can change size during iteration... |
||
| 158 | except RuntimeError: |
||
| 159 | logger.debug( |
||
| 160 | "Server list dictionnary change inside the loop (wait next update)") |
||
| 161 | |||
| 162 | # Update the screen (list or Glances client) |
||
| 163 | if not self.screen.active_server: |
||
| 164 | # Display the Glances browser |
||
| 165 | self.screen.update(self.get_servers_list()) |
||
| 166 | else: |
||
| 167 | # Display the Glances client for the selected server |
||
| 168 | logger.debug("Selected server: {0}".format(self.get_servers_list()[self.screen.active_server])) |
||
| 169 | |||
| 170 | # Connection can take time |
||
| 171 | # Display a popup |
||
| 172 | self.screen.display_popup( |
||
| 173 | 'Connect to {0}:{1}'.format(v['name'], v['port']), duration=1) |
||
| 174 | |||
| 175 | # A password is needed to access to the server's stats |
||
| 176 | if self.get_servers_list()[self.screen.active_server]['password'] is None: |
||
| 177 | # First of all, check if a password is available in the [passwords] section |
||
| 178 | clear_password = self.password.get_password(v['name']) |
||
| 179 | if (clear_password is None or self.get_servers_list() |
||
| 180 | [self.screen.active_server]['status'] == 'PROTECTED'): |
||
| 181 | # Else, the password should be enter by the user |
||
| 182 | # Display a popup to enter password |
||
| 183 | clear_password = self.screen.display_popup( |
||
| 184 | 'Password needed for {0}: '.format(v['name']), is_input=True) |
||
| 185 | # Store the password for the selected server |
||
| 186 | if clear_password is not None: |
||
| 187 | self.set_in_selected('password', self.password.sha256_hash(clear_password)) |
||
| 188 | |||
| 189 | # Display the Glance client on the selected server |
||
| 190 | logger.info("Connect Glances client to the {0} server".format( |
||
| 191 | self.get_servers_list()[self.screen.active_server]['key'])) |
||
| 192 | |||
| 193 | # Init the client |
||
| 194 | args_server = self.args |
||
| 195 | |||
| 196 | # Overwrite connection setting |
||
| 197 | args_server.client = self.get_servers_list()[self.screen.active_server]['ip'] |
||
| 198 | args_server.port = self.get_servers_list()[self.screen.active_server]['port'] |
||
| 199 | args_server.username = self.get_servers_list()[self.screen.active_server]['username'] |
||
| 200 | args_server.password = self.get_servers_list()[self.screen.active_server]['password'] |
||
| 201 | client = GlancesClient(config=self.config, args=args_server, return_to_browser=True) |
||
| 202 | |||
| 203 | # Test if client and server are in the same major version |
||
| 204 | if not client.login(): |
||
| 205 | self.screen.display_popup( |
||
| 206 | "Sorry, cannot connect to '{0}'\n" |
||
| 207 | "See 'glances.log' for more details".format(v['name'])) |
||
| 208 | |||
| 209 | # Set the ONLINE status for the selected server |
||
| 210 | self.set_in_selected('status', 'OFFLINE') |
||
| 211 | else: |
||
| 212 | # Start the client loop |
||
| 213 | # Return connection type: 'glances' or 'snmp' |
||
| 214 | connection_type = client.serve_forever() |
||
| 215 | |||
| 216 | try: |
||
| 217 | logger.debug("Disconnect Glances client from the {0} server".format( |
||
| 218 | self.get_servers_list()[self.screen.active_server]['key'])) |
||
| 219 | except IndexError: |
||
| 220 | # Server did not exist anymore |
||
| 221 | pass |
||
| 222 | else: |
||
| 223 | # Set the ONLINE status for the selected server |
||
| 224 | if connection_type == 'snmp': |
||
| 225 | self.set_in_selected('status', 'SNMP') |
||
| 226 | else: |
||
| 227 | self.set_in_selected('status', 'ONLINE') |
||
| 228 | |||
| 229 | # Return to the browser (no server selected) |
||
| 230 | self.screen.active_server = None |
||
| 231 | |||
| 256 |