mirror of https://github.com/nicolargo/glances.git
Correct an issue on the Webbrowser, the column list is now shared between static and dynamic Glances servers list
This commit is contained in:
parent
a9e3820947
commit
efd79b0bd8
|
|
@ -540,7 +540,7 @@ disable=False
|
|||
# Define columns (comma separated list of <plugin>:<field>:(<key>)) to grab/display
|
||||
# Default is: system:hr_name,load:min5,cpu:total,mem:percent
|
||||
# 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
|
||||
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)
|
||||
|
|
|
|||
|
|
@ -195,7 +195,7 @@ class GlancesRestfulApi:
|
|||
|
||||
def __update_servers_list(self):
|
||||
# Never update more than 1 time per cached_time
|
||||
if self.timer.finished():
|
||||
if self.timer.finished() and self.servers_list is not None:
|
||||
self.servers_list.update_servers_stats()
|
||||
self.timer = Timer(self.args.cached_time)
|
||||
|
||||
|
|
@ -246,6 +246,8 @@ class GlancesRestfulApi:
|
|||
f'{plugin_path}/{{item}}/history/{{nb}}': self._api_item_history,
|
||||
f'{plugin_path}/{{item}}/description': self._api_item_description,
|
||||
f'{plugin_path}/{{item}}/unit': self._api_item_unit,
|
||||
f'{plugin_path}/{{item}}/{{key}}': self._api_key,
|
||||
f'{plugin_path}/{{item}}/{{key}}/views': self._api_key_views,
|
||||
f'{plugin_path}/{{item}}/{{value:path}}': self._api_value,
|
||||
}
|
||||
|
||||
|
|
@ -420,7 +422,7 @@ class GlancesRestfulApi:
|
|||
# Update the servers list (and the stats for all the servers)
|
||||
self.__update_servers_list()
|
||||
|
||||
return GlancesJSONResponse(self.servers_list.get_servers_list())
|
||||
return GlancesJSONResponse(self.servers_list.get_servers_list() if self.servers_list else [])
|
||||
|
||||
def _api_all(self):
|
||||
"""Glances API RESTful implementation.
|
||||
|
|
@ -623,6 +625,30 @@ class GlancesRestfulApi:
|
|||
|
||||
return GlancesJSONResponse(ret)
|
||||
|
||||
def _api_key(self, plugin: str, item: str, key: str):
|
||||
"""Glances API RESTful implementation.
|
||||
|
||||
Return the JSON representation of plugin/item/key
|
||||
HTTP/200 if OK
|
||||
HTTP/400 if plugin is not found
|
||||
HTTP/404 if others error
|
||||
"""
|
||||
self._check_if_plugin_available(plugin)
|
||||
|
||||
# Update the stat
|
||||
self.__update_stats()
|
||||
|
||||
try:
|
||||
# Get the RAW value of the stat views
|
||||
ret = self.stats.get_plugin(plugin).get_raw_stats_key(item, key)
|
||||
except Exception as e:
|
||||
raise HTTPException(
|
||||
status.HTTP_404_NOT_FOUND,
|
||||
f"Cannot get item {item} in plugin {plugin} ({str(e)})",
|
||||
)
|
||||
|
||||
return GlancesJSONResponse(ret)
|
||||
|
||||
def _api_item_views(self, plugin: str, item: str):
|
||||
"""Glances API RESTful implementation.
|
||||
|
||||
|
|
@ -647,6 +673,30 @@ class GlancesRestfulApi:
|
|||
|
||||
return GlancesJSONResponse(ret)
|
||||
|
||||
def _api_key_views(self, plugin: str, item: str, key: str):
|
||||
"""Glances API RESTful implementation.
|
||||
|
||||
Return the JSON view representation of plugin/item/key
|
||||
HTTP/200 if OK
|
||||
HTTP/400 if plugin is not found
|
||||
HTTP/404 if others error
|
||||
"""
|
||||
self._check_if_plugin_available(plugin)
|
||||
|
||||
# Update the stat
|
||||
self.__update_stats()
|
||||
|
||||
try:
|
||||
# Get the RAW value of the stat views
|
||||
ret = self.stats.get_plugin(plugin).get_views().get(key).get(item)
|
||||
except Exception as e:
|
||||
raise HTTPException(
|
||||
status.HTTP_404_NOT_FOUND,
|
||||
f"Cannot get item {item} in plugin view {plugin} ({str(e)})",
|
||||
)
|
||||
|
||||
return GlancesJSONResponse(ret)
|
||||
|
||||
def _api_item_history(self, plugin: str, item: str, nb: int = 0):
|
||||
"""Glances API RESTful implementation.
|
||||
|
||||
|
|
|
|||
|
|
@ -393,6 +393,17 @@ class GlancesPluginModel:
|
|||
"""
|
||||
return dictlist(self.get_raw(), item)
|
||||
|
||||
def get_raw_stats_key(self, item, key):
|
||||
"""Return the stats object for a specific item in RAW format.
|
||||
|
||||
Stats should be a list of dict (processlist, network...)
|
||||
"""
|
||||
try:
|
||||
return {item: [i for i in self.get_raw() if 'key' in i and i[i['key']] == key][0].get(item)}
|
||||
except (KeyError, ValueError) as e:
|
||||
logger.error(f"Cannot get item ({item}) for key ({key}) ({e})")
|
||||
return None
|
||||
|
||||
def get_stats_item(self, item):
|
||||
"""Return the stats object for a specific item in JSON format.
|
||||
|
||||
|
|
|
|||
|
|
@ -32,8 +32,12 @@ else:
|
|||
# Correct issue #1025 by monkey path the xmlrpc lib
|
||||
xmlrpc.monkey_patch()
|
||||
|
||||
DEFAULT_COLUMNS = "system:hr_name,load:min5,cpu:total,mem:percent"
|
||||
|
||||
|
||||
class GlancesServersList:
|
||||
_section = "serverlist"
|
||||
|
||||
def __init__(self, config=None, args=None):
|
||||
# Store the arg/config
|
||||
self.args = args
|
||||
|
|
@ -59,6 +63,30 @@ class GlancesServersList:
|
|||
self.static_server = GlancesStaticServer(config=self.config)
|
||||
# Init the password list (if defined)
|
||||
self.password = GlancesPassword(config=self.config)
|
||||
# Load columns to grab/display
|
||||
self._columns = self.load_columns()
|
||||
|
||||
def load_columns(self):
|
||||
"""Load columns definition from the configuration file.
|
||||
Read: 'system:hr_name,load:min5,cpu:total,mem:percent,sensors:value:Ambient'
|
||||
Return: [{'plugin': 'system', 'field': 'hr_name'},
|
||||
{'plugin': 'load', 'field': 'min5'},
|
||||
{'plugin': 'cpu', 'field': 'total'},
|
||||
{'plugin': 'mem', 'field': 'percent'},
|
||||
{'plugin': 'sensors', 'field': 'value', 'key': 'Ambient'}]
|
||||
"""
|
||||
if self.config is None:
|
||||
logger.debug("No configuration file available. Cannot load columns definition.")
|
||||
elif not self.config.has_section(self._section):
|
||||
logger.warning(f"No [{self._section}] section in the configuration file. Cannot load columns definition.")
|
||||
|
||||
columns_def = (
|
||||
self.config.get_value(self._section, 'columns')
|
||||
if self.config.get_value(self._section, 'columns')
|
||||
else DEFAULT_COLUMNS
|
||||
)
|
||||
|
||||
return [dict(zip(['plugin', 'field', 'key'], i.split(':'))) for i in columns_def.split(',')]
|
||||
|
||||
def get_servers_list(self):
|
||||
"""Return the current server list (list of dict).
|
||||
|
|
@ -74,6 +102,10 @@ class GlancesServersList:
|
|||
|
||||
return ret
|
||||
|
||||
def get_columns(self):
|
||||
"""Return the columns definitions"""
|
||||
return self._columns
|
||||
|
||||
def update_servers_stats(self):
|
||||
"""For each server in the servers list, update the stats"""
|
||||
for v in self.get_servers_list():
|
||||
|
|
@ -84,9 +116,6 @@ class GlancesServersList:
|
|||
self.threads_list[key] = thread
|
||||
thread.start()
|
||||
|
||||
def get_columns(self):
|
||||
return self.static_server.get_columns()
|
||||
|
||||
def get_uri(self, server):
|
||||
"""Return the URI for the given server dict."""
|
||||
# Select the connection mode (with or without password)
|
||||
|
|
@ -112,7 +141,7 @@ class GlancesServersList:
|
|||
def __update_stats(self, server):
|
||||
"""Update stats for the given server"""
|
||||
server['uri'] = self.get_uri(server)
|
||||
server['columns'] = [self.__get_key(column) for column in self.static_server.get_columns()]
|
||||
server['columns'] = [self.__get_key(column) for column in self.get_columns()]
|
||||
if server['protocol'].lower() == 'rpc':
|
||||
self.__update_stats_rpc(server['uri'], server)
|
||||
elif server['protocol'].lower() == 'rest' and not import_requests_error_tag:
|
||||
|
|
@ -133,7 +162,7 @@ class GlancesServersList:
|
|||
return server
|
||||
|
||||
# Get the stats
|
||||
for column in self.static_server.get_columns():
|
||||
for column in self.get_columns():
|
||||
server_key = self.__get_key(column)
|
||||
try:
|
||||
# Value
|
||||
|
|
@ -176,11 +205,14 @@ class GlancesServersList:
|
|||
else:
|
||||
server['status'] = 'ONLINE'
|
||||
|
||||
for column in self.static_server.get_columns():
|
||||
for column in self.get_columns():
|
||||
server_key = self.__get_key(column)
|
||||
request_uri = f'{uri}/{column['plugin']}/{column['field']}'
|
||||
if 'key' in column:
|
||||
request_uri += f'/{column['key']}'
|
||||
# Value
|
||||
try:
|
||||
r = requests.get(f'{uri}/{column['plugin']}/{column['field']}', timeout=3)
|
||||
r = requests.get(request_uri, timeout=3)
|
||||
except requests.exceptions.RequestException as e:
|
||||
logger.debug(f"Error while grabbing stats form server ({e})")
|
||||
return server
|
||||
|
|
@ -188,7 +220,7 @@ class GlancesServersList:
|
|||
server[server_key] = r.json()[column['field']]
|
||||
# Decoration
|
||||
try:
|
||||
r = requests.get(f'{uri}/{column['plugin']}/{column['field']}/views', timeout=3)
|
||||
r = requests.get(request_uri + '/views', timeout=3)
|
||||
except requests.exceptions.RequestException as e:
|
||||
logger.debug(f"Error while grabbing stats view form server ({e})")
|
||||
return server
|
||||
|
|
|
|||
|
|
@ -12,8 +12,6 @@ from socket import gaierror, gethostbyname
|
|||
|
||||
from glances.logger import logger
|
||||
|
||||
DEFAULT_COLUMNS = "system:hr_name,load:min5,cpu:total,mem:percent"
|
||||
|
||||
|
||||
class GlancesStaticServer:
|
||||
"""Manage the static servers list for the client browser."""
|
||||
|
|
@ -25,8 +23,6 @@ class GlancesStaticServer:
|
|||
# [ {'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
|
||||
self._columns = self.load_columns(config)
|
||||
|
||||
def load_server_list(self, config):
|
||||
"""Load the server list from the configuration file."""
|
||||
|
|
@ -87,28 +83,6 @@ class GlancesStaticServer:
|
|||
|
||||
return server_list
|
||||
|
||||
def load_columns(self, config):
|
||||
"""Load columns definition from the configuration file.
|
||||
Read: 'system:hr_name,load:min5,cpu:total,mem:percent,sensors:value:Ambient'
|
||||
Return: [{'plugin': 'system', 'field': 'hr_name'},
|
||||
{'plugin': 'load', 'field': 'min5'},
|
||||
{'plugin': 'cpu', 'field': 'total'},
|
||||
{'plugin': 'mem', 'field': 'percent'},
|
||||
{'plugin': 'sensors', 'field': 'value', 'key': 'Ambient'}]
|
||||
"""
|
||||
if config is None:
|
||||
logger.debug("No configuration file available. Cannot load columns definition.")
|
||||
elif not config.has_section(self._section):
|
||||
logger.warning(f"No [{self._section}] section in the configuration file. Cannot load columns definition.")
|
||||
|
||||
columns_def = (
|
||||
config.get_value(self._section, 'columns')
|
||||
if config.get_value(self._section, 'columns')
|
||||
else DEFAULT_COLUMNS
|
||||
)
|
||||
|
||||
return [dict(zip(['plugin', 'field', 'key'], i.split(':'))) for i in columns_def.split(',')]
|
||||
|
||||
def get_servers_list(self):
|
||||
"""Return the current server list (list of dict)."""
|
||||
return self._server_list
|
||||
|
|
@ -116,7 +90,3 @@ class GlancesStaticServer:
|
|||
def set_server(self, server_pos, key, value):
|
||||
"""Set the key to the value for the server_pos (position in the list)."""
|
||||
self._server_list[server_pos][key] = value
|
||||
|
||||
def get_columns(self):
|
||||
"""Return the columns definitions"""
|
||||
return self._columns
|
||||
|
|
|
|||
Loading…
Reference in New Issue