mirror of https://github.com/nicolargo/glances.git
First step done - Rest server are managed in the current TUI client browser
This commit is contained in:
parent
f12de6619b
commit
d538b2dd13
|
|
@ -542,14 +542,23 @@ disable=False
|
|||
# You can also add stats with key, like sensors:value:Ambient (key is case sensitive)
|
||||
#columns=system:hr_name,load:min5,cpu:total,mem:percent,memswap:percent,sensors:value:Ambient,sensors:value:Composite
|
||||
# Define the static servers list
|
||||
# _protocol can be: rpc (default if not defined) or rest
|
||||
# List is limited to 256 servers max (1 to 256)
|
||||
server_1_name=localhost
|
||||
server_1_alias=Local WebUI
|
||||
server_1_port=61208
|
||||
server_1_protocol=rest
|
||||
#server_1_name=localhost
|
||||
#server_1_alias=My local PC
|
||||
#server_1_port=61209
|
||||
#server_1_protocol=rpc
|
||||
#server_2_name=localhost
|
||||
#server_2_port=61235
|
||||
#server_2_protocol=rpc
|
||||
#server_3_name=192.168.0.17
|
||||
#server_3_alias=Another PC on my network
|
||||
#server_3_port=61209
|
||||
#server_1_protocol=rpc
|
||||
#server_4_name=pasbon
|
||||
#server_4_port=61237
|
||||
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ class AutoDiscovered:
|
|||
|
||||
def __init__(self):
|
||||
# server_dict is a list of dict (JSON compliant)
|
||||
# [ {'key': 'zeroconf name', ip': '172.1.2.3', 'port': 61209, 'cpu': 3, 'mem': 34 ...} ... ]
|
||||
# [ {'key': 'zeroconf name', ip': '172.1.2.3', 'port': 61209, 'protocol': 'rpc', 'cpu': 3, 'mem': 34 ...} ... ]
|
||||
self._server_list = []
|
||||
|
||||
def get_servers_list(self):
|
||||
|
|
@ -60,6 +60,7 @@ class AutoDiscovered:
|
|||
'name': name.split(':')[0], # Short name
|
||||
'ip': ip, # IP address seen by the client
|
||||
'port': port, # TCP port
|
||||
'protocol': 'rpc', # RPC protocol
|
||||
'username': 'glances', # Default username
|
||||
'password': '', # Default password
|
||||
'status': 'UNKNOWN', # Server status: 'UNKNOWN', 'OFFLINE', 'ONLINE', 'PROTECTED'
|
||||
|
|
|
|||
|
|
@ -9,9 +9,11 @@
|
|||
"""Manage the Glances client browser (list of Glances server)."""
|
||||
|
||||
import threading
|
||||
import webbrowser
|
||||
|
||||
from defusedxml import xmlrpc
|
||||
|
||||
from glances import __apiversion__
|
||||
from glances.autodiscover import GlancesAutoDiscoverServer
|
||||
from glances.client import GlancesClient, GlancesClientTransport
|
||||
from glances.globals import json_loads
|
||||
|
|
@ -20,6 +22,15 @@ from glances.outputs.glances_curses_browser import GlancesCursesBrowser
|
|||
from glances.password_list import GlancesPasswordList as GlancesPassword
|
||||
from glances.static_list import GlancesStaticServer
|
||||
|
||||
try:
|
||||
import requests
|
||||
except ImportError as e:
|
||||
import_requests_error_tag = True
|
||||
# Display debug message if import error
|
||||
logger.warning(f"Missing Python Lib ({e}), Client browser will not grab stats from Glances REST server")
|
||||
else:
|
||||
import_requests_error_tag = False
|
||||
|
||||
# Correct issue #1025 by monkey path the xmlrpc lib
|
||||
xmlrpc.monkey_patch()
|
||||
|
||||
|
|
@ -77,14 +88,18 @@ class GlancesClientBrowser:
|
|||
clear_password = self.password.get_password(server['name'])
|
||||
if clear_password is not None:
|
||||
server['password'] = self.password.get_hash(clear_password)
|
||||
return 'http://{}:{}@{}:{}'.format(server['username'], server['password'], server['ip'], server['port'])
|
||||
return 'http://{}:{}'.format(server['ip'], server['port'])
|
||||
uri = 'http://{}:{}@{}:{}'.format(server['username'], server['password'], server['ip'], server['port'])
|
||||
else:
|
||||
uri = 'http://{}:{}'.format(server['ip'], server['port'])
|
||||
return uri
|
||||
|
||||
def __update_stats(self, server):
|
||||
"""Update stats for the given server (picked from the server list)"""
|
||||
# Get the server URI
|
||||
uri = self.__get_uri(server)
|
||||
def __get_key(self, column):
|
||||
server_key = column.get('plugin') + '_' + column.get('field')
|
||||
if 'key' in column:
|
||||
server_key += '_' + column.get('key')
|
||||
return server_key
|
||||
|
||||
def __update_stats_rpc(self, uri, server):
|
||||
# Try to connect to the server
|
||||
t = GlancesClientTransport()
|
||||
t.set_timeout(3)
|
||||
|
|
@ -98,9 +113,7 @@ class GlancesClientBrowser:
|
|||
|
||||
# Get the stats
|
||||
for column in self.static_server.get_columns():
|
||||
server_key = column.get('plugin') + '_' + column.get('field')
|
||||
if 'key' in column:
|
||||
server_key += '_' + column.get('key')
|
||||
server_key = self.__get_key(column)
|
||||
try:
|
||||
# Value
|
||||
v_json = json_loads(s.getPlugin(column['plugin']))
|
||||
|
|
@ -132,11 +145,55 @@ class GlancesClientBrowser:
|
|||
|
||||
return server
|
||||
|
||||
def __update_stats_rest(self, uri, server):
|
||||
try:
|
||||
requests.get(f'{uri}/status', timeout=3)
|
||||
except requests.exceptions.RequestException as e:
|
||||
logger.debug(f"Error while grabbing stats form server ({e})")
|
||||
server['status'] = 'OFFLINE'
|
||||
return server
|
||||
else:
|
||||
server['status'] = 'ONLINE'
|
||||
|
||||
for column in self.static_server.get_columns():
|
||||
server_key = self.__get_key(column)
|
||||
try:
|
||||
r = requests.get(f'{uri}/{column['plugin']}/{column['field']}', timeout=3)
|
||||
except requests.exceptions.RequestException as e:
|
||||
logger.debug(f"Error while grabbing stats form server ({e})")
|
||||
return server
|
||||
else:
|
||||
server[server_key] = r.json()[column['field']]
|
||||
|
||||
return server
|
||||
|
||||
def __update_stats(self, server):
|
||||
"""Update stats for the given server (picked from the server list)"""
|
||||
# Get the server URI
|
||||
uri = self.__get_uri(server)
|
||||
|
||||
if server['protocol'].lower() == 'rpc':
|
||||
self.__update_stats_rpc(uri, server)
|
||||
elif server['protocol'].lower() == 'rest' and not import_requests_error_tag:
|
||||
self.__update_stats_rest(f'{uri}/api/{__apiversion__}', server)
|
||||
|
||||
return server
|
||||
|
||||
def __display_server(self, server):
|
||||
"""Connect and display the given server"""
|
||||
# Display the Glances client for the selected server
|
||||
logger.debug(f"Selected server {server}")
|
||||
|
||||
if server['protocol'].lower() == 'rest':
|
||||
# Display a popup
|
||||
self.screen.display_popup(
|
||||
'Open the WebUI {}:{} in a Web Browser'.format(server['name'], server['port']), duration=1
|
||||
)
|
||||
# Try to open a Webbrowser
|
||||
webbrowser.open(self.__get_uri(server), new=2, autoraise=1)
|
||||
self.screen.active_server = None
|
||||
return
|
||||
|
||||
# Connection can take time
|
||||
# Display a popup
|
||||
self.screen.display_popup('Connect to {}:{}'.format(server['name'], server['port']), duration=1)
|
||||
|
|
|
|||
|
|
@ -290,7 +290,7 @@ class GlancesCursesBrowser(_GlancesCurses):
|
|||
|
||||
def __build_column_def(self, current_page):
|
||||
"""Define the column and it size to display in the browser"""
|
||||
column_def = {'name': 16, 'ip': 15, 'status': 9}
|
||||
column_def = {'name': 16, 'ip': 15, 'status': 9, 'protocol': 8}
|
||||
|
||||
# Add dynamic columns
|
||||
for server_stat in current_page:
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ class GlancesStaticServer:
|
|||
|
||||
def __init__(self, config=None, args=None):
|
||||
# server_list is a list of dict (JSON compliant)
|
||||
# [ {'key': 'zeroconf name', ip': '172.1.2.3', 'port': 61209, 'cpu': 3, 'mem': 34 ...} ... ]
|
||||
# [ {'key': 'zeroconf name', ip': '172.1.2.3', 'port': 61209, 'protocol': 'rpc', 'cpu': 3, 'mem': 34 ...} ... ]
|
||||
# Load server list from the Glances configuration file
|
||||
self._server_list = self.load_server_list(config)
|
||||
# Load columns to grab/display in the browser mode
|
||||
|
|
@ -39,34 +39,48 @@ class GlancesStaticServer:
|
|||
else:
|
||||
logger.info(f"Start reading the [{self._section}] section in the configuration file")
|
||||
for i in range(1, 256):
|
||||
# Read the configuration
|
||||
new_server = {}
|
||||
postfix = f'server_{str(i)}_'
|
||||
# Read the server name (mandatory)
|
||||
for s in ['name', 'port', 'alias']:
|
||||
for s in ['name', 'port', 'alias', 'protocol']:
|
||||
new_server[s] = config.get_value(self._section, f'{postfix}{s}')
|
||||
if new_server['name'] is not None:
|
||||
# Manage optional information
|
||||
if new_server['port'] is None:
|
||||
new_server['port'] = '61209'
|
||||
new_server['username'] = 'glances'
|
||||
# By default, try empty (aka no) password
|
||||
new_server['password'] = ''
|
||||
try:
|
||||
new_server['ip'] = gethostbyname(new_server['name'])
|
||||
except gaierror as e:
|
||||
logger.error("Cannot get IP address for server {} ({})".format(new_server['name'], e))
|
||||
continue
|
||||
new_server['key'] = new_server['name'] + ':' + new_server['port']
|
||||
|
||||
# Default status is 'UNKNOWN'
|
||||
new_server['status'] = 'UNKNOWN'
|
||||
if new_server['name'] is None:
|
||||
logger.error(f'Name not define for {postfix}, skip it.')
|
||||
continue
|
||||
|
||||
# Server type is 'STATIC'
|
||||
new_server['type'] = 'STATIC'
|
||||
# Type in order to support both RPC and REST servers (see #1121)
|
||||
if new_server['protocol'] is None:
|
||||
new_server['protocol'] = 'rpc'
|
||||
new_server['protocol'] = new_server['protocol'].lower()
|
||||
if new_server['protocol'] not in ('rpc', 'rest'):
|
||||
logger.error(f'Unknow protocol for {postfix}, skip it.')
|
||||
continue
|
||||
|
||||
# Add the server to the list
|
||||
logger.debug("Add server {} to the static list".format(new_server['name']))
|
||||
server_list.append(new_server)
|
||||
# Default port
|
||||
if new_server['port'] is None:
|
||||
new_server['port'] = '61209' if new_server['type'] == 'rpc' else '61208'
|
||||
|
||||
# By default, try empty (aka no) password
|
||||
new_server['username'] = 'glances'
|
||||
new_server['password'] = ''
|
||||
|
||||
try:
|
||||
new_server['ip'] = gethostbyname(new_server['name'])
|
||||
except gaierror as e:
|
||||
logger.error("Cannot get IP address for server {} ({})".format(new_server['name'], e))
|
||||
continue
|
||||
new_server['key'] = new_server['name'] + ':' + new_server['port']
|
||||
|
||||
# Default status is 'UNKNOWN'
|
||||
new_server['status'] = 'UNKNOWN'
|
||||
|
||||
# Server type is 'STATIC'
|
||||
new_server['type'] = 'STATIC'
|
||||
|
||||
# Add the server to the list
|
||||
logger.debug("Add server {} to the static list".format(new_server['name']))
|
||||
server_list.append(new_server)
|
||||
|
||||
# Server list loaded
|
||||
logger.info(f"{len(server_list)} server(s) loaded from the configuration file")
|
||||
|
|
|
|||
Loading…
Reference in New Issue