mirror of
https://github.com/nicolargo/glances.git
synced 2024-11-23 11:35:19 +03:00
chg: ruff - pyupgrade
This commit is contained in:
parent
f9a06a31f0
commit
108ffcdfb6
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Glances documentation build configuration file, created by
|
||||
# sphinx-quickstart on Tue Mar 1 10:53:59 2016.
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -44,11 +43,6 @@ try:
|
||||
except locale.Error:
|
||||
print("Warning: Unable to set locale. Expect encoding problems.")
|
||||
|
||||
# Check Python version
|
||||
if sys.version_info < (3, 4):
|
||||
print('Glances requires at least Python 3.4 to run.')
|
||||
sys.exit(1)
|
||||
|
||||
# Check psutil version
|
||||
psutil_min_version = (5, 3, 0)
|
||||
psutil_version_info = tuple([int(num) for num in psutil_version.split('.')])
|
||||
@ -56,11 +50,12 @@ if psutil_version_info < psutil_min_version:
|
||||
print('psutil 5.3.0 or higher is needed. Glances cannot start.')
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
# Trac malloc is only available on Python 3.4 or higher
|
||||
|
||||
|
||||
def __signal_handler(signal, frame):
|
||||
logger.debug("Signal {} catched".format(signal))
|
||||
logger.debug(f"Signal {signal} catched")
|
||||
end()
|
||||
|
||||
|
||||
@ -103,20 +98,16 @@ def start(config, args):
|
||||
from glances.webserver import GlancesWebServer as GlancesMode
|
||||
|
||||
# Init the mode
|
||||
logger.info("Start {} mode".format(GlancesMode.__name__))
|
||||
logger.info(f"Start {GlancesMode.__name__} mode")
|
||||
mode = GlancesMode(config=config, args=args)
|
||||
|
||||
# Start the main loop
|
||||
logger.debug("Glances started in {} seconds".format(start_duration.get()))
|
||||
logger.debug(f"Glances started in {start_duration.get()} seconds")
|
||||
if args.stop_after:
|
||||
logger.info('Glances will be stopped in ~{} seconds'.format(args.stop_after * args.time))
|
||||
logger.info(f'Glances will be stopped in ~{args.stop_after * args.time} seconds')
|
||||
|
||||
if args.memory_leak:
|
||||
print(
|
||||
'Memory leak detection, please wait ~{} seconds...'.format(
|
||||
args.stop_after * args.time * args.memory_leak * 2
|
||||
)
|
||||
)
|
||||
print(f'Memory leak detection, please wait ~{args.stop_after * args.time * args.memory_leak * 2} seconds...')
|
||||
# First run without dump to fill the memory
|
||||
mode.serve_n(args.stop_after)
|
||||
# Then start the memory-leak loop
|
||||
@ -133,7 +124,7 @@ def start(config, args):
|
||||
snapshot_end = tracemalloc.take_snapshot()
|
||||
snapshot_diff = snapshot_end.compare_to(snapshot_begin, 'filename')
|
||||
memory_leak = sum([s.size_diff for s in snapshot_diff])
|
||||
print("Memory consumption: {0:.1f}KB (see log for details)".format(memory_leak / 1000))
|
||||
print(f"Memory consumption: {memory_leak / 1000:.1f}KB (see log for details)")
|
||||
logger.info("Memory consumption (top 5):")
|
||||
for stat in snapshot_diff[:5]:
|
||||
logger.info(stat)
|
||||
@ -165,12 +156,10 @@ def main():
|
||||
signal.signal(sig, __signal_handler)
|
||||
|
||||
# Log Glances and psutil version
|
||||
logger.info('Start Glances {}'.format(__version__))
|
||||
logger.info(
|
||||
'{} {} ({}) and psutil {} detected'.format(
|
||||
platform.python_implementation(), platform.python_version(), sys.executable, psutil_version
|
||||
)
|
||||
)
|
||||
logger.info(f'Start Glances {__version__}')
|
||||
python_impl = platform.python_implementation()
|
||||
python_ver = platform.python_version()
|
||||
logger.info(f'{python_impl} {python_ver} ({sys.executable}) and psutil {psutil_version} detected')
|
||||
|
||||
# Share global var
|
||||
global core
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Glances - An eye on your system
|
||||
#
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -22,7 +21,7 @@ else:
|
||||
chevron_tag = True
|
||||
|
||||
|
||||
class GlancesActions(object):
|
||||
class GlancesActions:
|
||||
"""This class manage action if an alert is reached."""
|
||||
|
||||
def __init__(self, args=None):
|
||||
@ -80,13 +79,13 @@ class GlancesActions(object):
|
||||
else:
|
||||
cmd_full = cmd
|
||||
# Execute the action
|
||||
logger.info("Action triggered for {} ({}): {}".format(stat_name, criticality, cmd_full))
|
||||
logger.info(f"Action triggered for {stat_name} ({criticality}): {cmd_full}")
|
||||
try:
|
||||
ret = secure_popen(cmd_full)
|
||||
except OSError as e:
|
||||
logger.error("Action error for {} ({}): {}".format(stat_name, criticality, e))
|
||||
logger.error(f"Action error for {stat_name} ({criticality}): {e}")
|
||||
else:
|
||||
logger.debug("Action result for {} ({}): {}".format(stat_name, criticality, ret))
|
||||
logger.debug(f"Action result for {stat_name} ({criticality}): {ret}")
|
||||
|
||||
self.set(stat_name, criticality)
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -27,7 +26,7 @@ from glances.logger import logger
|
||||
from glances.timer import Timer
|
||||
|
||||
|
||||
class GlancesAmp(object):
|
||||
class GlancesAmp:
|
||||
"""Main class for Glances AMP."""
|
||||
|
||||
NAME = '?'
|
||||
@ -38,7 +37,7 @@ class GlancesAmp(object):
|
||||
|
||||
def __init__(self, name=None, args=None):
|
||||
"""Init AMP class."""
|
||||
logger.debug("AMP - Init {} version {}".format(self.NAME, self.VERSION))
|
||||
logger.debug(f"AMP - Init {self.NAME} version {self.VERSION}")
|
||||
|
||||
# AMP name (= module name without glances_)
|
||||
if name is None:
|
||||
@ -74,7 +73,7 @@ class GlancesAmp(object):
|
||||
|
||||
amp_section = 'amp_' + self.amp_name
|
||||
if hasattr(config, 'has_section') and config.has_section(amp_section):
|
||||
logger.debug("AMP - {}: Load configuration".format(self.NAME))
|
||||
logger.debug(f"AMP - {self.NAME}: Load configuration")
|
||||
for param, _ in config.items(amp_section):
|
||||
try:
|
||||
self.configs[param] = config.get_float_value(amp_section, param)
|
||||
@ -82,9 +81,9 @@ class GlancesAmp(object):
|
||||
self.configs[param] = config.get_value(amp_section, param).split(',')
|
||||
if len(self.configs[param]) == 1:
|
||||
self.configs[param] = self.configs[param][0]
|
||||
logger.debug("AMP - {}: Load parameter: {} = {}".format(self.NAME, param, self.configs[param]))
|
||||
logger.debug(f"AMP - {self.NAME}: Load parameter: {param} = {self.configs[param]}")
|
||||
else:
|
||||
logger.debug("AMP - {}: Can not find section {} in the configuration file".format(self.NAME, self.amp_name))
|
||||
logger.debug(f"AMP - {self.NAME}: Can not find section {self.amp_name} in the configuration file")
|
||||
return False
|
||||
|
||||
if self.enable():
|
||||
@ -92,13 +91,12 @@ class GlancesAmp(object):
|
||||
for k in ['refresh']:
|
||||
if k not in self.configs:
|
||||
logger.warning(
|
||||
"AMP - {}: Can not find configuration key {} in section {} (the AMP will be disabled)".format(
|
||||
self.NAME, k, self.amp_name
|
||||
)
|
||||
f"AMP - {self.NAME}: Can not find configuration key {k} in section {self.amp_name} "
|
||||
f"(the AMP will be disabled)"
|
||||
)
|
||||
self.configs['enable'] = 'false'
|
||||
else:
|
||||
logger.debug("AMP - {} is disabled".format(self.NAME))
|
||||
logger.debug(f"AMP - {self.NAME} is disabled")
|
||||
|
||||
# Init the count to 0
|
||||
self.configs['count'] = 0
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -44,7 +43,7 @@ class Amp(GlancesAmp):
|
||||
def __init__(self, name=None, args=None):
|
||||
"""Init the AMP."""
|
||||
self.NAME = name.capitalize()
|
||||
super(Amp, self).__init__(name=name, args=args)
|
||||
super().__init__(name=name, args=args)
|
||||
|
||||
def update(self, process_list):
|
||||
"""Update the AMP"""
|
||||
@ -54,7 +53,7 @@ class Amp(GlancesAmp):
|
||||
try:
|
||||
res = self.get('command')
|
||||
except OSError as e:
|
||||
logger.debug('{}: Error while executing command ({})'.format(self.NAME, e))
|
||||
logger.debug(f'{self.NAME}: Error while executing command ({e})')
|
||||
return self.result()
|
||||
# No command found, use default message
|
||||
if res is None:
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -62,7 +61,7 @@ class Amp(GlancesAmp):
|
||||
try:
|
||||
res = check_output(self.get('systemctl_cmd').split())
|
||||
except (OSError, CalledProcessError) as e:
|
||||
logger.debug('{}: Error while executing systemctl ({})'.format(self.NAME, e))
|
||||
logger.debug(f'{self.NAME}: Error while executing systemctl ({e})')
|
||||
else:
|
||||
status = {}
|
||||
# For each line
|
||||
@ -79,7 +78,7 @@ class Amp(GlancesAmp):
|
||||
# Build the output (string) message
|
||||
output = 'Services\n'
|
||||
for k, v in iteritems(status):
|
||||
output += '{}: {}\n'.format(k, v)
|
||||
output += f'{k}: {v}\n'
|
||||
self.set_result(output, separator=' ')
|
||||
|
||||
return self.result()
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -61,7 +60,7 @@ class Amp(GlancesAmp):
|
||||
try:
|
||||
res = check_output(self.get('service_cmd').split(), stderr=STDOUT).decode('utf-8')
|
||||
except OSError as e:
|
||||
logger.debug('{}: Error while executing service ({})'.format(self.NAME, e))
|
||||
logger.debug(f'{self.NAME}: Error while executing service ({e})')
|
||||
else:
|
||||
status = {'running': 0, 'stopped': 0, 'upstart': 0}
|
||||
# For each line
|
||||
@ -79,7 +78,7 @@ class Amp(GlancesAmp):
|
||||
# Build the output (string) message
|
||||
output = 'Services\n'
|
||||
for k, v in iteritems(status):
|
||||
output += '{}: {}\n'.format(k, v)
|
||||
output += f'{k}: {v}\n'
|
||||
self.set_result(output, separator=' ')
|
||||
|
||||
return self.result()
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -18,7 +17,7 @@ from glances.logger import logger
|
||||
from glances.processes import glances_processes
|
||||
|
||||
|
||||
class AmpsList(object):
|
||||
class AmpsList:
|
||||
"""This class describes the optional application monitoring process list.
|
||||
|
||||
The AMP list is a list of processes with a specific monitoring action.
|
||||
@ -57,9 +56,9 @@ class AmpsList(object):
|
||||
try:
|
||||
amp = __import__(os.path.basename(amp_module))
|
||||
except ImportError as e:
|
||||
logger.warning("Missing Python Lib ({}), cannot load AMP {}".format(e, amp_name))
|
||||
logger.warning(f"Missing Python Lib ({e}), cannot load AMP {amp_name}")
|
||||
except Exception as e:
|
||||
logger.warning("Cannot load AMP {} ({})".format(amp_name, e))
|
||||
logger.warning(f"Cannot load AMP {amp_name} ({e})")
|
||||
else:
|
||||
# Add the AMP to the dictionary
|
||||
# The key is the AMP name
|
||||
@ -69,7 +68,7 @@ class AmpsList(object):
|
||||
# Load the AMP configuration
|
||||
self.__amps_dict[amp_name].load_config(self.config)
|
||||
# Log AMPs list
|
||||
logger.debug("AMPs list: {}".format(self.getList()))
|
||||
logger.debug(f"AMPs list: {self.getList()}")
|
||||
|
||||
return True
|
||||
|
||||
@ -108,7 +107,7 @@ class AmpsList(object):
|
||||
|
||||
if len(amps_list) > 0:
|
||||
# At least one process is matching the regex
|
||||
logger.debug("AMPS: {} processes {} detected ({})".format(len(amps_list), k, amps_list))
|
||||
logger.debug(f"AMPS: {len(amps_list)} processes {k} detected ({amps_list})")
|
||||
# Call the AMP update method
|
||||
thread = threading.Thread(target=v.update_wrapper, args=[amps_list])
|
||||
thread.start()
|
||||
@ -140,7 +139,7 @@ class AmpsList(object):
|
||||
)
|
||||
|
||||
except (TypeError, KeyError) as e:
|
||||
logger.debug("Can not build AMPS list ({})".format(e))
|
||||
logger.debug(f"Can not build AMPS list ({e})")
|
||||
|
||||
return ret
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -12,7 +11,7 @@
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
class GlancesAttribute(object):
|
||||
class GlancesAttribute:
|
||||
def __init__(self, name, description='', history_max_size=None):
|
||||
"""Init the attribute
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -27,7 +26,7 @@ except ImportError:
|
||||
if zeroconf_tag:
|
||||
zeroconf_min_version = (0, 17, 0)
|
||||
zeroconf_version = tuple([int(num) for num in __zeroconf_version.split('.')])
|
||||
logger.debug("Zeroconf version {} detected.".format(__zeroconf_version))
|
||||
logger.debug(f"Zeroconf version {__zeroconf_version} detected.")
|
||||
if zeroconf_version < zeroconf_min_version:
|
||||
logger.critical("Please install zeroconf 0.17 or higher.")
|
||||
sys.exit(1)
|
||||
@ -35,10 +34,10 @@ if zeroconf_tag:
|
||||
# Global var
|
||||
# Recent versions of the zeroconf python package doesn't like a zeroconf type that ends with '._tcp.'.
|
||||
# Correct issue: zeroconf problem with zeroconf_type = "_%s._tcp." % 'glances' #888
|
||||
zeroconf_type = "_%s._tcp.local." % 'glances'
|
||||
zeroconf_type = "_{}._tcp.local.".format('glances')
|
||||
|
||||
|
||||
class AutoDiscovered(object):
|
||||
class AutoDiscovered:
|
||||
"""Class to manage the auto discovered servers dict."""
|
||||
|
||||
def __init__(self):
|
||||
@ -67,7 +66,7 @@ class AutoDiscovered(object):
|
||||
'type': 'DYNAMIC',
|
||||
} # Server type: 'STATIC' or 'DYNAMIC'
|
||||
self._server_list.append(new_server)
|
||||
logger.debug("Updated servers list (%s servers): %s" % (len(self._server_list), self._server_list))
|
||||
logger.debug(f"Updated servers list ({len(self._server_list)} servers): {self._server_list}")
|
||||
|
||||
def remove_server(self, name):
|
||||
"""Remove a server from the dict."""
|
||||
@ -75,13 +74,13 @@ class AutoDiscovered(object):
|
||||
if i['key'] == name:
|
||||
try:
|
||||
self._server_list.remove(i)
|
||||
logger.debug("Remove server %s from the list" % name)
|
||||
logger.debug("Updated servers list (%s servers): %s" % (len(self._server_list), self._server_list))
|
||||
logger.debug(f"Remove server {name} from the list")
|
||||
logger.debug(f"Updated servers list ({len(self._server_list)} servers): {self._server_list}")
|
||||
except ValueError:
|
||||
logger.error("Cannot remove server %s from the list" % name)
|
||||
logger.error(f"Cannot remove server {name} from the list")
|
||||
|
||||
|
||||
class GlancesAutoDiscoverListener(object):
|
||||
class GlancesAutoDiscoverListener:
|
||||
"""Zeroconf listener for Glances server."""
|
||||
|
||||
def __init__(self):
|
||||
@ -105,7 +104,7 @@ class GlancesAutoDiscoverListener(object):
|
||||
"""
|
||||
if srv_type != zeroconf_type:
|
||||
return False
|
||||
logger.debug("Check new Zeroconf server: %s / %s" % (srv_type, srv_name))
|
||||
logger.debug(f"Check new Zeroconf server: {srv_type} / {srv_name}")
|
||||
info = zeroconf.get_service_info(srv_type, srv_name)
|
||||
if info and (info.addresses or info.parsed_addresses):
|
||||
address = info.addresses[0] if info.addresses else info.parsed_addresses[0]
|
||||
@ -114,7 +113,7 @@ class GlancesAutoDiscoverListener(object):
|
||||
|
||||
# Add server to the global dict
|
||||
self.servers.add_server(srv_name, new_server_ip, new_server_port)
|
||||
logger.info("New Glances server detected (%s from %s:%s)" % (srv_name, new_server_ip, new_server_port))
|
||||
logger.info(f"New Glances server detected ({srv_name} from {new_server_ip}:{new_server_port})")
|
||||
else:
|
||||
logger.warning("New Glances server detected, but failed to be get Zeroconf ServiceInfo ")
|
||||
return True
|
||||
@ -122,10 +121,10 @@ class GlancesAutoDiscoverListener(object):
|
||||
def remove_service(self, zeroconf, srv_type, srv_name):
|
||||
"""Remove the server from the list."""
|
||||
self.servers.remove_server(srv_name)
|
||||
logger.info("Glances server %s removed from the autodetect list" % srv_name)
|
||||
logger.info(f"Glances server {srv_name} removed from the autodetect list")
|
||||
|
||||
|
||||
class GlancesAutoDiscoverServer(object):
|
||||
class GlancesAutoDiscoverServer:
|
||||
"""Implementation of the Zeroconf protocol (server side for the Glances client)."""
|
||||
|
||||
def __init__(self, args=None):
|
||||
@ -133,8 +132,8 @@ class GlancesAutoDiscoverServer(object):
|
||||
logger.info("Init autodiscover mode (Zeroconf protocol)")
|
||||
try:
|
||||
self.zeroconf = Zeroconf()
|
||||
except socket.error as e:
|
||||
logger.error("Cannot start Zeroconf (%s)" % e)
|
||||
except OSError as e:
|
||||
logger.error(f"Cannot start Zeroconf ({e})")
|
||||
self.zeroconf_enable_tag = False
|
||||
else:
|
||||
self.listener = GlancesAutoDiscoverListener()
|
||||
@ -160,7 +159,7 @@ class GlancesAutoDiscoverServer(object):
|
||||
self.zeroconf.close()
|
||||
|
||||
|
||||
class GlancesAutoDiscoverClient(object):
|
||||
class GlancesAutoDiscoverClient:
|
||||
"""Implementation of the zeroconf protocol (client side for the Glances server)."""
|
||||
|
||||
def __init__(self, hostname, args=None):
|
||||
@ -168,8 +167,8 @@ class GlancesAutoDiscoverClient(object):
|
||||
zeroconf_bind_address = args.bind_address
|
||||
try:
|
||||
self.zeroconf = Zeroconf()
|
||||
except socket.error as e:
|
||||
logger.error("Cannot start zeroconf: {}".format(e))
|
||||
except OSError as e:
|
||||
logger.error(f"Cannot start zeroconf: {e}")
|
||||
|
||||
# XXX *BSDs: Segmentation fault (core dumped)
|
||||
# -- https://bitbucket.org/al45tair/netifaces/issues/15
|
||||
@ -192,7 +191,7 @@ class GlancesAutoDiscoverClient(object):
|
||||
try:
|
||||
self.info = ServiceInfo(
|
||||
zeroconf_type,
|
||||
'{}:{}.{}'.format(hostname, args.port, zeroconf_type),
|
||||
f'{hostname}:{args.port}.{zeroconf_type}',
|
||||
address=socket.inet_pton(address_family, zeroconf_bind_address),
|
||||
port=args.port,
|
||||
weight=0,
|
||||
@ -205,7 +204,7 @@ class GlancesAutoDiscoverClient(object):
|
||||
# address (only one address) is replaced by addresses (list of addresses)
|
||||
self.info = ServiceInfo(
|
||||
zeroconf_type,
|
||||
name='{}:{}.{}'.format(hostname, args.port, zeroconf_type),
|
||||
name=f'{hostname}:{args.port}.{zeroconf_type}',
|
||||
addresses=[socket.inet_pton(address_family, zeroconf_bind_address)],
|
||||
port=args.port,
|
||||
weight=0,
|
||||
@ -216,9 +215,9 @@ class GlancesAutoDiscoverClient(object):
|
||||
try:
|
||||
self.zeroconf.register_service(self.info)
|
||||
except Exception as e:
|
||||
logger.error("Error while announcing Glances server: {}".format(e))
|
||||
logger.error(f"Error while announcing Glances server: {e}")
|
||||
else:
|
||||
print("Announce the Glances server on the LAN (using {} IP address)".format(zeroconf_bind_address))
|
||||
print(f"Announce the Glances server on the LAN (using {zeroconf_bind_address} IP address)")
|
||||
else:
|
||||
logger.error("Cannot announce Glances server on the network: zeroconf library not found.")
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -9,7 +8,6 @@
|
||||
|
||||
"""Manage the Glances client."""
|
||||
|
||||
import socket
|
||||
import sys
|
||||
import time
|
||||
|
||||
@ -30,7 +28,7 @@ class GlancesClientTransport(Transport):
|
||||
self.timeout = timeout
|
||||
|
||||
|
||||
class GlancesClient(object):
|
||||
class GlancesClient:
|
||||
"""This class creates and manages the TCP client."""
|
||||
|
||||
def __init__(self, config=None, args=None, timeout=7, return_to_browser=False):
|
||||
@ -49,10 +47,10 @@ class GlancesClient(object):
|
||||
|
||||
# Build the URI
|
||||
if args.password != "":
|
||||
self.uri = 'http://{}:{}@{}:{}'.format(args.username, args.password, args.client, args.port)
|
||||
self.uri = f'http://{args.username}:{args.password}@{args.client}:{args.port}'
|
||||
else:
|
||||
self.uri = 'http://{}:{}'.format(args.client, args.port)
|
||||
logger.debug("Try to connect to {}".format(self.uri))
|
||||
self.uri = f'http://{args.client}:{args.port}'
|
||||
logger.debug(f"Try to connect to {self.uri}")
|
||||
|
||||
# Try to connect to the URI
|
||||
transport = GlancesClientTransport()
|
||||
@ -61,7 +59,7 @@ class GlancesClient(object):
|
||||
try:
|
||||
self.client = ServerProxy(self.uri, transport=transport)
|
||||
except Exception as e:
|
||||
self.log_and_exit("Client couldn't create socket {}: {}".format(self.uri, e))
|
||||
self.log_and_exit(f"Client couldn't create socket {self.uri}: {e}")
|
||||
|
||||
@property
|
||||
def quiet(self):
|
||||
@ -94,10 +92,10 @@ class GlancesClient(object):
|
||||
client_version = None
|
||||
try:
|
||||
client_version = self.client.init()
|
||||
except socket.error as err:
|
||||
except OSError as err:
|
||||
# Fallback to SNMP
|
||||
self.client_mode = 'snmp'
|
||||
logger.error("Connection to Glances server failed ({} {})".format(err.errno, err.strerror))
|
||||
logger.error(f"Connection to Glances server failed ({err.errno} {err.strerror})")
|
||||
fall_back_msg = 'No Glances server found. Trying fallback to SNMP...'
|
||||
if not self.return_to_browser:
|
||||
print(fall_back_msg)
|
||||
@ -105,11 +103,11 @@ class GlancesClient(object):
|
||||
logger.info(fall_back_msg)
|
||||
except ProtocolError as err:
|
||||
# Other errors
|
||||
msg = "Connection to server {} failed".format(self.uri)
|
||||
msg = f"Connection to server {self.uri} failed"
|
||||
if err.errcode == 401:
|
||||
msg += " (Bad username/password)"
|
||||
else:
|
||||
msg += " ({} {})".format(err.errcode, err.errmsg)
|
||||
msg += f" ({err.errcode} {err.errmsg})"
|
||||
self.log_and_exit(msg)
|
||||
return False
|
||||
|
||||
@ -119,14 +117,11 @@ class GlancesClient(object):
|
||||
# Init stats
|
||||
self.stats = GlancesStatsClient(config=self.config, args=self.args)
|
||||
self.stats.set_plugins(ujson.loads(self.client.getAllPlugins()))
|
||||
logger.debug("Client version: {} / Server version: {}".format(__version__, client_version))
|
||||
logger.debug(f"Client version: {__version__} / Server version: {client_version}")
|
||||
else:
|
||||
self.log_and_exit(
|
||||
(
|
||||
'Client and server not compatible: ' 'Client version: {} / Server version: {}'.format(
|
||||
__version__, client_version
|
||||
)
|
||||
)
|
||||
'Client and server not compatible: '
|
||||
f'Client version: {__version__} / Server version: {client_version}'
|
||||
)
|
||||
return False
|
||||
|
||||
@ -186,7 +181,7 @@ class GlancesClient(object):
|
||||
return self.update_snmp()
|
||||
|
||||
self.end()
|
||||
logger.critical("Unknown server mode: {}".format(self.client_mode))
|
||||
logger.critical(f"Unknown server mode: {self.client_mode}")
|
||||
sys.exit(2)
|
||||
|
||||
def update_glances(self):
|
||||
@ -199,7 +194,7 @@ class GlancesClient(object):
|
||||
# Update the stats
|
||||
try:
|
||||
server_stats = ujson.loads(self.client.getAll())
|
||||
except socket.error:
|
||||
except OSError:
|
||||
# Client cannot get server stats
|
||||
return "Disconnected"
|
||||
except Fault:
|
||||
@ -242,12 +237,12 @@ class GlancesClient(object):
|
||||
# Update the stats
|
||||
counter = Counter()
|
||||
cs_status = self.update()
|
||||
logger.debug('Stats updated duration: {} seconds'.format(counter.get()))
|
||||
logger.debug(f'Stats updated duration: {counter.get()} seconds')
|
||||
|
||||
# Export stats using export modules
|
||||
counter_export = Counter()
|
||||
self.stats.export(self.stats)
|
||||
logger.debug('Stats exported duration: {} seconds'.format(counter_export.get()))
|
||||
logger.debug(f'Stats exported duration: {counter_export.get()} seconds')
|
||||
|
||||
# Patch for issue1326 to avoid < 0 refresh
|
||||
adapted_refresh = self.refresh_time - counter.get()
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -9,7 +8,6 @@
|
||||
|
||||
"""Manage the Glances client browser (list of Glances server)."""
|
||||
|
||||
import socket
|
||||
import threading
|
||||
|
||||
import ujson
|
||||
@ -23,7 +21,7 @@ from glances.password_list import GlancesPasswordList as GlancesPassword
|
||||
from glances.static_list import GlancesStaticServer
|
||||
|
||||
|
||||
class GlancesClientBrowser(object):
|
||||
class GlancesClientBrowser:
|
||||
"""This class creates and manages the TCP client browser (servers list)."""
|
||||
|
||||
def __init__(self, config=None, args=None):
|
||||
@ -92,19 +90,19 @@ class GlancesClientBrowser(object):
|
||||
try:
|
||||
s = ServerProxy(uri, transport=t)
|
||||
except Exception as e:
|
||||
logger.warning("Client browser couldn't create socket ({})".format(e))
|
||||
logger.warning(f"Client browser couldn't create socket ({e})")
|
||||
else:
|
||||
# Mandatory stats
|
||||
try:
|
||||
# CPU%
|
||||
cpu_percent = 100 - ujson.loads(s.getCpu())['idle']
|
||||
server['cpu_percent'] = '{:.1f}'.format(cpu_percent)
|
||||
server['cpu_percent'] = f'{cpu_percent:.1f}'
|
||||
# MEM%
|
||||
server['mem_percent'] = ujson.loads(s.getMem())['percent']
|
||||
# OS (Human Readable name)
|
||||
server['hr_name'] = ujson.loads(s.getSystem())['hr_name']
|
||||
except (socket.error, Fault, KeyError) as e:
|
||||
logger.debug("Error while grabbing stats form server ({})".format(e))
|
||||
except (OSError, Fault, KeyError) as e:
|
||||
logger.debug(f"Error while grabbing stats form server ({e})")
|
||||
server['status'] = 'OFFLINE'
|
||||
except ProtocolError as e:
|
||||
if e.errcode == 401:
|
||||
@ -114,7 +112,7 @@ class GlancesClientBrowser(object):
|
||||
server['status'] = 'PROTECTED'
|
||||
else:
|
||||
server['status'] = 'OFFLINE'
|
||||
logger.debug("Cannot grab stats from server ({} {})".format(e.errcode, e.errmsg))
|
||||
logger.debug(f"Cannot grab stats from server ({e.errcode} {e.errmsg})")
|
||||
else:
|
||||
# Status
|
||||
server['status'] = 'ONLINE'
|
||||
@ -123,16 +121,16 @@ class GlancesClientBrowser(object):
|
||||
try:
|
||||
# LOAD
|
||||
load_min5 = ujson.loads(s.getLoad())['min5']
|
||||
server['load_min5'] = '{:.2f}'.format(load_min5)
|
||||
server['load_min5'] = f'{load_min5:.2f}'
|
||||
except Exception as e:
|
||||
logger.warning("Error while grabbing stats form server ({})".format(e))
|
||||
logger.warning(f"Error while grabbing stats form server ({e})")
|
||||
|
||||
return server
|
||||
|
||||
def __display_server(self, server):
|
||||
"""Connect and display the given server"""
|
||||
# Display the Glances client for the selected server
|
||||
logger.debug("Selected server {}".format(server))
|
||||
logger.debug(f"Selected server {server}")
|
||||
|
||||
# Connection can take time
|
||||
# Display a popup
|
||||
@ -201,7 +199,7 @@ class GlancesClientBrowser(object):
|
||||
# For each server in the list, grab elementary stats (CPU, LOAD, MEM, OS...)
|
||||
thread_list = {}
|
||||
while not self.screen.is_end:
|
||||
logger.debug("Iter through the following server list: {}".format(self.get_servers_list()))
|
||||
logger.debug(f"Iter through the following server list: {self.get_servers_list()}")
|
||||
for v in self.get_servers_list():
|
||||
key = v["key"]
|
||||
thread = thread_list.get(key, None)
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -9,11 +8,11 @@
|
||||
|
||||
"""Manage the configuration file."""
|
||||
|
||||
import builtins
|
||||
import multiprocessing
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
from io import open
|
||||
|
||||
from glances.globals import BSD, LINUX, MACOS, SUNOS, WINDOWS, ConfigParser, NoOptionError, NoSectionError, system_exec
|
||||
from glances.logger import logger
|
||||
@ -94,7 +93,7 @@ def default_config_dir():
|
||||
return [path]
|
||||
|
||||
|
||||
class Config(object):
|
||||
class Config:
|
||||
"""This class is used to access/read config file, if it exists.
|
||||
|
||||
:param config_dir: the path to search for config file
|
||||
@ -153,15 +152,15 @@ class Config(object):
|
||||
def read(self):
|
||||
"""Read the config file, if it exists. Using defaults otherwise."""
|
||||
for config_file in self.config_file_paths():
|
||||
logger.debug('Search glances.conf file in {}'.format(config_file))
|
||||
logger.debug(f'Search glances.conf file in {config_file}')
|
||||
if os.path.exists(config_file):
|
||||
try:
|
||||
with open(config_file, encoding='utf-8') as f:
|
||||
with builtins.open(config_file, encoding='utf-8') as f:
|
||||
self.parser.read_file(f)
|
||||
self.parser.read(f)
|
||||
logger.info("Read configuration file '{}'".format(config_file))
|
||||
logger.info(f"Read configuration file '{config_file}'")
|
||||
except UnicodeDecodeError as err:
|
||||
logger.error("Can not read configuration file '{}': {}".format(config_file, err))
|
||||
logger.error(f"Can not read configuration file '{config_file}': {err}")
|
||||
sys.exit(1)
|
||||
# Save the loaded configuration file path (issue #374)
|
||||
self._loaded_config_file = config_file
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -15,7 +14,7 @@ from glances.logger import logger
|
||||
from glances.timer import Timer
|
||||
|
||||
|
||||
class CpuPercent(object):
|
||||
class CpuPercent:
|
||||
"""Get and store the CPU percent."""
|
||||
|
||||
def __init__(self, cached_timer_cpu=3):
|
||||
@ -56,7 +55,7 @@ class CpuPercent(object):
|
||||
try:
|
||||
cpu_freq = psutil.cpu_freq()
|
||||
except Exception as e:
|
||||
logger.debug('Can not grab CPU information ({})'.format(e))
|
||||
logger.debug(f'Can not grab CPU information ({e})')
|
||||
else:
|
||||
if hasattr(cpu_freq, 'current'):
|
||||
self.cpu_info['cpu_hz_current'] = cpu_freq.current
|
||||
@ -74,7 +73,7 @@ class CpuPercent(object):
|
||||
# Get the CPU name once from the /proc/cpuinfo file
|
||||
# TODO: Multisystem...
|
||||
try:
|
||||
self.cpu_info['cpu_name'] = open('/proc/cpuinfo', 'r').readlines()[4].split(':')[1].strip()
|
||||
self.cpu_info['cpu_name'] = open('/proc/cpuinfo').readlines()[4].split(':')[1].strip()
|
||||
except (FileNotFoundError, PermissionError, IndexError, KeyError, AttributeError):
|
||||
self.cpu_info['cpu_name'] = 'CPU'
|
||||
return self.cpu_info['cpu_name']
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -161,7 +160,7 @@ def build_global_message():
|
||||
return tree[0]['msg']
|
||||
|
||||
|
||||
class GlancesEventsList(object):
|
||||
class GlancesEventsList:
|
||||
"""This class manages events inside the Glances software.
|
||||
GlancesEventsList is a list of GlancesEvent.
|
||||
GlancesEvent is defined in the event.py file
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -18,7 +17,7 @@ from glances.logger import logger
|
||||
from glances.timer import Counter
|
||||
|
||||
|
||||
class GlancesExport(object):
|
||||
class GlancesExport:
|
||||
"""Main class for Glances export IF."""
|
||||
|
||||
# List of non exportable plugins
|
||||
@ -39,7 +38,7 @@ class GlancesExport(object):
|
||||
"""Init the export class."""
|
||||
# Export name
|
||||
self.export_name = self.__class__.__module__
|
||||
logger.debug("Init export module %s" % self.export_name)
|
||||
logger.debug(f"Init export module {self.export_name}")
|
||||
|
||||
# Init the config & args
|
||||
self.config = config
|
||||
@ -63,18 +62,16 @@ class GlancesExport(object):
|
||||
counter = Counter()
|
||||
ret = fct(*args, **kw)
|
||||
duration = counter.get()
|
||||
logger.debug(
|
||||
"{} {} {} return {} in {} seconds".format(
|
||||
args[0].__class__.__name__, args[0].__class__.__module__, fct.__name__, ret, duration
|
||||
)
|
||||
)
|
||||
class_name = args[0].__class__.__name__
|
||||
class_module = args[0].__class__.__module__
|
||||
logger.debug(f"{class_name} {class_module} {fct.__name__} return {ret} in {duration} seconds")
|
||||
return ret
|
||||
|
||||
return wrapper
|
||||
|
||||
def exit(self):
|
||||
"""Close the export module."""
|
||||
logger.debug("Finalise export interface %s" % self.export_name)
|
||||
logger.debug(f"Finalise export interface {self.export_name}")
|
||||
|
||||
def load_conf(self, section, mandatories=['host', 'port'], options=None):
|
||||
"""Load the export <section> configuration in the Glances configuration file.
|
||||
@ -95,10 +92,10 @@ class GlancesExport(object):
|
||||
for opt in mandatories:
|
||||
setattr(self, opt, self.config.get_value(section, opt))
|
||||
except NoSectionError:
|
||||
logger.error("No {} configuration found".format(section))
|
||||
logger.error(f"No {section} configuration found")
|
||||
return False
|
||||
except NoOptionError as e:
|
||||
logger.error("Error in the {} configuration ({})".format(section, e))
|
||||
logger.error(f"Error in the {section} configuration ({e})")
|
||||
return False
|
||||
|
||||
# Load options
|
||||
@ -108,8 +105,8 @@ class GlancesExport(object):
|
||||
except NoOptionError:
|
||||
pass
|
||||
|
||||
logger.debug("Load {} from the Glances configuration file".format(section))
|
||||
logger.debug("{} parameters: {}".format(section, {opt: getattr(self, opt) for opt in mandatories + options}))
|
||||
logger.debug(f"Load {section} from the Glances configuration file")
|
||||
logger.debug(f"{section} parameters: {({opt: getattr(self, opt) for opt in mandatories + options})}")
|
||||
|
||||
return True
|
||||
|
||||
@ -119,7 +116,7 @@ class GlancesExport(object):
|
||||
try:
|
||||
ret = item[item['key']]
|
||||
except KeyError:
|
||||
logger.error("No 'key' available in {}".format(item))
|
||||
logger.error(f"No 'key' available in {item}")
|
||||
if isinstance(ret, list):
|
||||
return ret[0]
|
||||
return ret
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -27,7 +26,7 @@ class Export(GlancesExport):
|
||||
|
||||
def __init__(self, config=None, args=None):
|
||||
"""Init the Cassandra export IF."""
|
||||
super(Export, self).__init__(config=config, args=args)
|
||||
super().__init__(config=config, args=args)
|
||||
|
||||
# Mandatory configuration keys (additional to host and port)
|
||||
self.keyspace = None
|
||||
@ -69,53 +68,52 @@ class Export(GlancesExport):
|
||||
)
|
||||
session = cluster.connect()
|
||||
except Exception as e:
|
||||
logger.critical("Cannot connect to Cassandra cluster '%s:%s' (%s)" % (self.host, self.port, e))
|
||||
logger.critical(f"Cannot connect to Cassandra cluster '{self.host}:{self.port}' ({e})")
|
||||
sys.exit(2)
|
||||
|
||||
# Keyspace
|
||||
try:
|
||||
session.set_keyspace(self.keyspace)
|
||||
except InvalidRequest:
|
||||
logger.info("Create keyspace {} on the Cassandra cluster".format(self.keyspace))
|
||||
c = "CREATE KEYSPACE %s WITH replication = { 'class': 'SimpleStrategy', 'replication_factor': '%s' }" % (
|
||||
self.keyspace,
|
||||
self.replication_factor,
|
||||
logger.info(f"Create keyspace {self.keyspace} on the Cassandra cluster")
|
||||
c = (
|
||||
f"CREATE KEYSPACE {self.keyspace} WITH "
|
||||
f"replication = {{ 'class': 'SimpleStrategy', 'replication_factor': '{self.replication_factor}' }}"
|
||||
)
|
||||
session.execute(c)
|
||||
session.set_keyspace(self.keyspace)
|
||||
|
||||
logger.info(
|
||||
"Stats will be exported to Cassandra cluster {} ({}) in keyspace {}".format(
|
||||
cluster.metadata.cluster_name, cluster.metadata.all_hosts(), self.keyspace
|
||||
)
|
||||
f"Stats will be exported to Cassandra cluster {cluster.metadata.cluster_name} "
|
||||
f"({cluster.metadata.all_hosts()}) in keyspace {self.keyspace}"
|
||||
)
|
||||
|
||||
# Table
|
||||
try:
|
||||
session.execute(
|
||||
"CREATE TABLE %s (plugin text, time timeuuid, stat map<text,float>, PRIMARY KEY (plugin, time)) \
|
||||
WITH CLUSTERING ORDER BY (time DESC)"
|
||||
% self.table
|
||||
f"CREATE TABLE {self.table} "
|
||||
f"(plugin text, time timeuuid, stat map<text,float>, PRIMARY KEY (plugin, time)) "
|
||||
f"WITH CLUSTERING ORDER BY (time DESC)"
|
||||
)
|
||||
except Exception:
|
||||
logger.debug("Cassandra table %s already exist" % self.table)
|
||||
logger.debug(f"Cassandra table {self.table} already exist")
|
||||
|
||||
return cluster, session
|
||||
|
||||
def export(self, name, columns, points):
|
||||
"""Write the points to the Cassandra cluster."""
|
||||
logger.debug("Export {} stats to Cassandra".format(name))
|
||||
logger.debug(f"Export {name} stats to Cassandra")
|
||||
|
||||
# Remove non number stats and convert all to float (for Boolean)
|
||||
data = {k: float(v) for (k, v) in dict(zip(columns, points)).iteritems() if isinstance(v, Number)}
|
||||
|
||||
# Write input to the Cassandra table
|
||||
try:
|
||||
stmt = "INSERT INTO {} (plugin, time, stat) VALUES (?, ?, ?)".format(self.table)
|
||||
stmt = f"INSERT INTO {self.table} (plugin, time, stat) VALUES (?, ?, ?)"
|
||||
query = self.session.prepare(stmt)
|
||||
self.session.execute(query, (name, uuid_from_time(datetime.now()), data))
|
||||
except Exception as e:
|
||||
logger.error("Cannot export {} stats to Cassandra ({})".format(name, e))
|
||||
logger.error(f"Cannot export {name} stats to Cassandra ({e})")
|
||||
|
||||
def exit(self):
|
||||
"""Close the Cassandra export module."""
|
||||
@ -123,4 +121,4 @@ class Export(GlancesExport):
|
||||
self.session.shutdown()
|
||||
self.cluster.shutdown()
|
||||
# Call the father method
|
||||
super(Export, self).exit()
|
||||
super().exit()
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -31,7 +30,7 @@ class Export(GlancesExport):
|
||||
|
||||
def __init__(self, config=None, args=None):
|
||||
"""Init the CouchDB export IF."""
|
||||
super(Export, self).__init__(config=config, args=args)
|
||||
super().__init__(config=config, args=args)
|
||||
|
||||
# Load the CouchDB configuration file section
|
||||
# User and Password are mandatory with CouchDB 3.0 and higher
|
||||
@ -48,15 +47,15 @@ class Export(GlancesExport):
|
||||
return None
|
||||
|
||||
# @TODO: https
|
||||
server_uri = 'http://{}:{}@{}:{}/'.format(self.user, self.password, self.host, self.port)
|
||||
server_uri = f'http://{self.user}:{self.password}@{self.host}:{self.port}/'
|
||||
|
||||
try:
|
||||
s = pycouchdb.Server(server_uri)
|
||||
except Exception as e:
|
||||
logger.critical("Cannot connect to CouchDB server (%s)" % e)
|
||||
logger.critical(f"Cannot connect to CouchDB server ({e})")
|
||||
sys.exit(2)
|
||||
else:
|
||||
logger.info("Connected to the CouchDB server version %s" % s.info()['version'])
|
||||
logger.info("Connected to the CouchDB server version {}".format(s.info()['version']))
|
||||
|
||||
try:
|
||||
s.database(self.db)
|
||||
@ -64,15 +63,15 @@ class Export(GlancesExport):
|
||||
# Database did not exist
|
||||
# Create it...
|
||||
s.create(self.db)
|
||||
logger.info("Create CouchDB database %s" % self.db)
|
||||
logger.info(f"Create CouchDB database {self.db}")
|
||||
else:
|
||||
logger.info("CouchDB database %s already exist" % self.db)
|
||||
logger.info(f"CouchDB database {self.db} already exist")
|
||||
|
||||
return s.database(self.db)
|
||||
|
||||
def export(self, name, columns, points):
|
||||
"""Write the points to the CouchDB server."""
|
||||
logger.debug("Export {} stats to CouchDB".format(name))
|
||||
logger.debug(f"Export {name} stats to CouchDB")
|
||||
|
||||
# Create DB input
|
||||
data = dict(zip(columns, points))
|
||||
@ -85,4 +84,4 @@ class Export(GlancesExport):
|
||||
try:
|
||||
self.client.save(data)
|
||||
except Exception as e:
|
||||
logger.error("Cannot export {} stats to CouchDB ({})".format(name, e))
|
||||
logger.error(f"Cannot export {name} stats to CouchDB ({e})")
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -23,7 +22,7 @@ class Export(GlancesExport):
|
||||
|
||||
def __init__(self, config=None, args=None):
|
||||
"""Init the CSV export IF."""
|
||||
super(Export, self).__init__(config=config, args=args)
|
||||
super().__init__(config=config, args=args)
|
||||
|
||||
# CSV file name
|
||||
self.csv_filename = args.export_csv_file
|
||||
@ -42,8 +41,8 @@ class Export(GlancesExport):
|
||||
try:
|
||||
self.csv_file = open_csv_file(self.csv_filename, 'r')
|
||||
reader = csv.reader(self.csv_file)
|
||||
except IOError as e:
|
||||
logger.critical("Cannot open existing CSV file: {}".format(e))
|
||||
except OSError as e:
|
||||
logger.critical(f"Cannot open existing CSV file: {e}")
|
||||
sys.exit(2)
|
||||
self.old_header = next(reader, None)
|
||||
self.csv_file.close()
|
||||
@ -51,11 +50,11 @@ class Export(GlancesExport):
|
||||
try:
|
||||
self.csv_file = open_csv_file(self.csv_filename, file_mode)
|
||||
self.writer = csv.writer(self.csv_file)
|
||||
except IOError as e:
|
||||
logger.critical("Cannot create the CSV file: {}".format(e))
|
||||
except OSError as e:
|
||||
logger.critical(f"Cannot create the CSV file: {e}")
|
||||
sys.exit(2)
|
||||
|
||||
logger.info("Stats exported to CSV file: {}".format(self.csv_filename))
|
||||
logger.info(f"Stats exported to CSV file: {self.csv_filename}")
|
||||
|
||||
self.export_enable = True
|
||||
|
||||
@ -63,7 +62,7 @@ class Export(GlancesExport):
|
||||
|
||||
def exit(self):
|
||||
"""Close the CSV file."""
|
||||
logger.debug("Finalise export interface %s" % self.export_name)
|
||||
logger.debug(f"Finalise export interface {self.export_name}")
|
||||
self.csv_file.close()
|
||||
|
||||
def update(self, stats):
|
||||
@ -95,8 +94,8 @@ class Export(GlancesExport):
|
||||
if self.old_header != csv_header and self.old_header is not None:
|
||||
# Header are different, log an error and do not write data
|
||||
logger.error("Cannot append data to existing CSV file. Headers are different.")
|
||||
logger.debug("Old header: {}".format(self.old_header))
|
||||
logger.debug("New header: {}".format(csv_header))
|
||||
logger.debug(f"Old header: {self.old_header}")
|
||||
logger.debug(f"New header: {csv_header}")
|
||||
else:
|
||||
# Header are equals, ready to write data
|
||||
self.old_header = None
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -23,7 +22,7 @@ class Export(GlancesExport):
|
||||
|
||||
def __init__(self, config=None, args=None):
|
||||
"""Init the ES export IF."""
|
||||
super(Export, self).__init__(config=config, args=args)
|
||||
super().__init__(config=config, args=args)
|
||||
|
||||
# Mandatory configuration keys (additional to host and port)
|
||||
self.index = None
|
||||
@ -44,24 +43,22 @@ class Export(GlancesExport):
|
||||
return None
|
||||
|
||||
try:
|
||||
es = Elasticsearch(hosts=['{}://{}:{}'.format(self.scheme, self.host, self.port)])
|
||||
es = Elasticsearch(hosts=[f'{self.scheme}://{self.host}:{self.port}'])
|
||||
except Exception as e:
|
||||
logger.critical(
|
||||
"Cannot connect to ElasticSearch server %s://%s:%s (%s)" % (self.scheme, self.host, self.port, e)
|
||||
)
|
||||
logger.critical(f"Cannot connect to ElasticSearch server {self.scheme}://{self.host}:{self.port} ({e})")
|
||||
sys.exit(2)
|
||||
|
||||
if not es.ping():
|
||||
logger.critical("Cannot ping the ElasticSearch server %s://%s:%s" % (self.scheme, self.host, self.port))
|
||||
logger.critical(f"Cannot ping the ElasticSearch server {self.scheme}://{self.host}:{self.port}")
|
||||
sys.exit(2)
|
||||
else:
|
||||
logger.info("Connected to the ElasticSearch server %s://%s:%s" % (self.scheme, self.host, self.port))
|
||||
logger.info(f"Connected to the ElasticSearch server {self.scheme}://{self.host}:{self.port}")
|
||||
|
||||
return es
|
||||
|
||||
def export(self, name, columns, points):
|
||||
"""Write the points to the ES server."""
|
||||
logger.debug("Export {} stats to ElasticSearch".format(name))
|
||||
logger.debug(f"Export {name} stats to ElasticSearch")
|
||||
|
||||
# Generate index name with the index field + current day
|
||||
index = '{}-{}'.format(self.index, datetime.utcnow().strftime("%Y.%m.%d"))
|
||||
@ -72,17 +69,17 @@ class Export(GlancesExport):
|
||||
dt_now = datetime.utcnow().isoformat('T')
|
||||
action = {
|
||||
"_index": index,
|
||||
"_id": '{}.{}'.format(name, dt_now),
|
||||
"_type": 'glances-{}'.format(name),
|
||||
"_id": f'{name}.{dt_now}',
|
||||
"_type": f'glances-{name}',
|
||||
"_source": {"plugin": name, "timestamp": dt_now},
|
||||
}
|
||||
action['_source'].update(zip(columns, [str(p) for p in points]))
|
||||
actions.append(action)
|
||||
|
||||
logger.debug("Exporting the following object to elasticsearch: {}".format(action))
|
||||
logger.debug(f"Exporting the following object to elasticsearch: {action}")
|
||||
|
||||
# Write input to the ES index
|
||||
try:
|
||||
helpers.bulk(self.client, actions)
|
||||
except Exception as e:
|
||||
logger.error("Cannot export {} stats to ElasticSearch ({})".format(name, e))
|
||||
logger.error(f"Cannot export {name} stats to ElasticSearch ({e})")
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -28,7 +27,7 @@ class Export(GlancesExport):
|
||||
|
||||
def __init__(self, config=None, args=None):
|
||||
"""Init the export IF."""
|
||||
super(Export, self).__init__(config=config, args=args)
|
||||
super().__init__(config=config, args=args)
|
||||
|
||||
# Load the Graph configuration file section (is exists)
|
||||
self.export_enable = self.load_conf('graph', options=['path', 'generate_every', 'width', 'height', 'style'])
|
||||
@ -45,19 +44,19 @@ class Export(GlancesExport):
|
||||
os.makedirs(self.path)
|
||||
except OSError as e:
|
||||
if e.errno != errno.EEXIST:
|
||||
logger.critical("Cannot create the Graph output folder {} ({})".format(self.path, e))
|
||||
logger.critical(f"Cannot create the Graph output folder {self.path} ({e})")
|
||||
sys.exit(2)
|
||||
|
||||
# Check if output folder is writeable
|
||||
try:
|
||||
tempfile.TemporaryFile(dir=self.path)
|
||||
except OSError:
|
||||
logger.critical("Graph output folder {} is not writeable".format(self.path))
|
||||
logger.critical(f"Graph output folder {self.path} is not writeable")
|
||||
sys.exit(2)
|
||||
|
||||
logger.info("Graphs will be created in the {} folder".format(self.path))
|
||||
logger.info(f"Graphs will be created in the {self.path} folder")
|
||||
if self.generate_every != 0:
|
||||
logger.info("Graphs will be created automatically every {} seconds".format(self.generate_every))
|
||||
logger.info(f"Graphs will be created automatically every {self.generate_every} seconds")
|
||||
logger.info("or when 'g' key is pressed (only through the CLI interface)")
|
||||
# Start the timer
|
||||
self._timer = Timer(self.generate_every)
|
||||
@ -67,7 +66,7 @@ class Export(GlancesExport):
|
||||
|
||||
def exit(self):
|
||||
"""Close the files."""
|
||||
logger.debug("Finalise export interface %s" % self.export_name)
|
||||
logger.debug(f"Finalise export interface {self.export_name}")
|
||||
|
||||
def update(self, stats):
|
||||
"""Generate Graph file in the output folder."""
|
||||
@ -85,7 +84,7 @@ class Export(GlancesExport):
|
||||
if plugin_name in self.plugins_to_export(stats):
|
||||
self.export(plugin_name, plugin.get_export_history())
|
||||
|
||||
logger.info("Graphs created in {}".format(self.path))
|
||||
logger.info(f"Graphs created in {self.path}")
|
||||
self.args.generate_graph = False
|
||||
|
||||
def export(self, title, data):
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -23,7 +22,7 @@ class Export(GlancesExport):
|
||||
|
||||
def __init__(self, config=None, args=None):
|
||||
"""Init the Graphite export IF."""
|
||||
super(Export, self).__init__(config=config, args=args)
|
||||
super().__init__(config=config, args=args)
|
||||
|
||||
# Mandatory configuration keys (additional to host and port)
|
||||
# N/A
|
||||
@ -74,25 +73,25 @@ class Export(GlancesExport):
|
||||
debug=self.debug,
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error("Can not write data to Graphite server: {}:{} ({})".format(self.host, self.port, e))
|
||||
logger.error(f"Can not write data to Graphite server: {self.host}:{self.port} ({e})")
|
||||
client = None
|
||||
else:
|
||||
logger.info("Stats will be exported to Graphite server: {}:{}".format(self.host, self.port))
|
||||
logger.info(f"Stats will be exported to Graphite server: {self.host}:{self.port}")
|
||||
return client
|
||||
|
||||
def export(self, name, columns, points):
|
||||
"""Export the stats to the Graphite server."""
|
||||
if self.client is None:
|
||||
return False
|
||||
before_filtering_dict = dict(zip([normalize('{}.{}'.format(name, i)) for i in columns], points))
|
||||
before_filtering_dict = dict(zip([normalize(f'{name}.{i}') for i in columns], points))
|
||||
after_filtering_dict = dict(filter(lambda i: isinstance(i[1], Number), before_filtering_dict.items()))
|
||||
try:
|
||||
self.client.send_dict(after_filtering_dict)
|
||||
except Exception as e:
|
||||
logger.error("Can not export stats to Graphite (%s)" % e)
|
||||
logger.error(f"Can not export stats to Graphite ({e})")
|
||||
return False
|
||||
else:
|
||||
logger.debug("Export {} stats to Graphite".format(name))
|
||||
logger.debug(f"Export {name} stats to Graphite")
|
||||
return True
|
||||
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -26,7 +25,7 @@ class Export(GlancesExport):
|
||||
|
||||
def __init__(self, config=None, args=None):
|
||||
"""Init the InfluxDB export IF."""
|
||||
super(Export, self).__init__(config=config, args=args)
|
||||
super().__init__(config=config, args=args)
|
||||
|
||||
# Mandatory configuration keys (additional to host and port)
|
||||
self.user = None
|
||||
@ -75,13 +74,13 @@ class Export(GlancesExport):
|
||||
)
|
||||
get_all_db = [i['name'] for i in db.get_list_database()]
|
||||
except InfluxDBClientError as e:
|
||||
logger.critical("Cannot connect to InfluxDB database '%s' (%s)" % (self.db, e))
|
||||
logger.critical(f"Cannot connect to InfluxDB database '{self.db}' ({e})")
|
||||
sys.exit(2)
|
||||
|
||||
if self.db in get_all_db:
|
||||
logger.info("Stats will be exported to InfluxDB server: {}".format(db._baseurl))
|
||||
logger.info(f"Stats will be exported to InfluxDB server: {db._baseurl}")
|
||||
else:
|
||||
logger.critical("InfluxDB database '%s' did not exist. Please create it" % self.db)
|
||||
logger.critical(f"InfluxDB database '{self.db}' did not exist. Please create it")
|
||||
sys.exit(2)
|
||||
|
||||
return db
|
||||
@ -106,9 +105,7 @@ class Export(GlancesExport):
|
||||
# Manage field
|
||||
if measurement is not None:
|
||||
fields = {
|
||||
k.replace('{}.'.format(measurement), ''): data_dict[k]
|
||||
for k in data_dict
|
||||
if k.startswith('{}.'.format(measurement))
|
||||
k.replace(f'{measurement}.', ''): data_dict[k] for k in data_dict if k.startswith(f'{measurement}.')
|
||||
}
|
||||
else:
|
||||
fields = data_dict
|
||||
@ -155,12 +152,12 @@ class Export(GlancesExport):
|
||||
name = self.prefix + '.' + name
|
||||
# Write input to the InfluxDB database
|
||||
if len(points) == 0:
|
||||
logger.debug("Cannot export empty {} stats to InfluxDB".format(name))
|
||||
logger.debug(f"Cannot export empty {name} stats to InfluxDB")
|
||||
else:
|
||||
try:
|
||||
self.client.write_points(self._normalize(name, columns, points), time_precision="s")
|
||||
except Exception as e:
|
||||
# Log level set to debug instead of error (see: issue #1561)
|
||||
logger.debug("Cannot export {} stats to InfluxDB ({})".format(name, e))
|
||||
logger.debug(f"Cannot export {name} stats to InfluxDB ({e})")
|
||||
else:
|
||||
logger.debug("Export {} stats to InfluxDB".format(name))
|
||||
logger.debug(f"Export {name} stats to InfluxDB")
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -25,7 +24,7 @@ class Export(GlancesExport):
|
||||
|
||||
def __init__(self, config=None, args=None):
|
||||
"""Init the InfluxDB export IF."""
|
||||
super(Export, self).__init__(config=config, args=args)
|
||||
super().__init__(config=config, args=args)
|
||||
|
||||
# Mandatory configuration keys (additional to host and port)
|
||||
self.org = None
|
||||
@ -58,7 +57,7 @@ class Export(GlancesExport):
|
||||
self.interval = 0
|
||||
# and should be set to the Glances refresh time if the value is 0
|
||||
self.interval = self.interval if self.interval > 0 else self.args.time
|
||||
logger.debug("InfluxDB export interval is set to {} seconds".format(self.interval))
|
||||
logger.debug(f"InfluxDB export interval is set to {self.interval} seconds")
|
||||
|
||||
# The hostname is always add as a tag
|
||||
self.hostname = node().split('.')[0]
|
||||
@ -71,17 +70,15 @@ class Export(GlancesExport):
|
||||
if not self.export_enable:
|
||||
return None
|
||||
|
||||
url = '{}://{}:{}'.format(self.protocol, self.host, self.port)
|
||||
url = f'{self.protocol}://{self.host}:{self.port}'
|
||||
try:
|
||||
# See docs: https://influxdb-client.readthedocs.io/en/stable/api.html#influxdbclient
|
||||
client = InfluxDBClient(url=url, enable_gzip=False, verify_ssl=False, org=self.org, token=self.token)
|
||||
except Exception as e:
|
||||
logger.critical("Cannot connect to InfluxDB server '%s' (%s)" % (url, e))
|
||||
logger.critical(f"Cannot connect to InfluxDB server '{url}' ({e})")
|
||||
sys.exit(2)
|
||||
else:
|
||||
logger.info(
|
||||
"Connected to InfluxDB server version {} ({})".format(client.health().version, client.health().message)
|
||||
)
|
||||
logger.info(f"Connected to InfluxDB server version {client.health().version} ({client.health().message})")
|
||||
|
||||
# Create the write client
|
||||
return client.write_api(
|
||||
@ -116,9 +113,7 @@ class Export(GlancesExport):
|
||||
# Manage field
|
||||
if measurement is not None:
|
||||
fields = {
|
||||
k.replace('{}.'.format(measurement), ''): data_dict[k]
|
||||
for k in data_dict
|
||||
if k.startswith('{}.'.format(measurement))
|
||||
k.replace(f'{measurement}.', ''): data_dict[k] for k in data_dict if k.startswith(f'{measurement}.')
|
||||
}
|
||||
else:
|
||||
fields = data_dict
|
||||
@ -165,12 +160,12 @@ class Export(GlancesExport):
|
||||
name = self.prefix + '.' + name
|
||||
# Write input to the InfluxDB database
|
||||
if len(points) == 0:
|
||||
logger.debug("Cannot export empty {} stats to InfluxDB".format(name))
|
||||
logger.debug(f"Cannot export empty {name} stats to InfluxDB")
|
||||
else:
|
||||
try:
|
||||
self.client.write(self.bucket, self.org, self._normalize(name, columns, points), time_precision="s")
|
||||
except Exception as e:
|
||||
# Log level set to debug instead of error (see: issue #1561)
|
||||
logger.debug("Cannot export {} stats to InfluxDB ({})".format(name, e))
|
||||
logger.debug(f"Cannot export {name} stats to InfluxDB ({e})")
|
||||
else:
|
||||
logger.debug("Export {} stats to InfluxDB".format(name))
|
||||
logger.debug(f"Export {name} stats to InfluxDB")
|
||||
|
@ -12,7 +12,7 @@ class Export(GlancesExport):
|
||||
|
||||
def __init__(self, config=None, args=None):
|
||||
"""Init the JSON export IF."""
|
||||
super(Export, self).__init__(config=config, args=args)
|
||||
super().__init__(config=config, args=args)
|
||||
|
||||
# JSON file name
|
||||
self.json_filename = args.export_json_file
|
||||
@ -21,11 +21,11 @@ class Export(GlancesExport):
|
||||
try:
|
||||
self.json_file = open(self.json_filename, 'w')
|
||||
self.json_file.close()
|
||||
except IOError as e:
|
||||
logger.critical("Cannot create the JSON file: {}".format(e))
|
||||
except OSError as e:
|
||||
logger.critical(f"Cannot create the JSON file: {e}")
|
||||
sys.exit(2)
|
||||
|
||||
logger.info("Exporting stats to file: {}".format(self.json_filename))
|
||||
logger.info(f"Exporting stats to file: {self.json_filename}")
|
||||
|
||||
self.export_enable = True
|
||||
|
||||
@ -34,7 +34,7 @@ class Export(GlancesExport):
|
||||
|
||||
def exit(self):
|
||||
"""Close the JSON file."""
|
||||
logger.debug("Finalise export interface %s" % self.export_name)
|
||||
logger.debug(f"Finalise export interface {self.export_name}")
|
||||
self.json_file.close()
|
||||
|
||||
def export(self, name, columns, points):
|
||||
@ -44,11 +44,11 @@ class Export(GlancesExport):
|
||||
if name == self.last_exported_list()[0] and self.buffer != {}:
|
||||
# One whole loop has been completed
|
||||
# Flush stats to file
|
||||
logger.debug("Exporting stats ({}) to JSON file ({})".format(listkeys(self.buffer), self.json_filename))
|
||||
logger.debug(f"Exporting stats ({listkeys(self.buffer)}) to JSON file ({self.json_filename})")
|
||||
|
||||
# Export stats to JSON file
|
||||
with open(self.json_filename, "w") as self.json_file:
|
||||
self.json_file.write("{}\n".format(json_dumps(self.buffer)))
|
||||
self.json_file.write(f"{json_dumps(self.buffer)}\n")
|
||||
|
||||
# Reset buffer
|
||||
self.buffer = {}
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -23,7 +22,7 @@ class Export(GlancesExport):
|
||||
|
||||
def __init__(self, config=None, args=None):
|
||||
"""Init the Kafka export IF."""
|
||||
super(Export, self).__init__(config=config, args=args)
|
||||
super().__init__(config=config, args=args)
|
||||
|
||||
# Mandatory configuration keys (additional to host and port)
|
||||
self.topic = None
|
||||
@ -48,7 +47,7 @@ class Export(GlancesExport):
|
||||
return None
|
||||
|
||||
# Build the server URI with host and port
|
||||
server_uri = '{}:{}'.format(self.host, self.port)
|
||||
server_uri = f'{self.host}:{self.port}'
|
||||
|
||||
try:
|
||||
s = KafkaProducer(
|
||||
@ -57,16 +56,16 @@ class Export(GlancesExport):
|
||||
compression_type=self.compression,
|
||||
)
|
||||
except Exception as e:
|
||||
logger.critical("Cannot connect to Kafka server %s (%s)" % (server_uri, e))
|
||||
logger.critical(f"Cannot connect to Kafka server {server_uri} ({e})")
|
||||
sys.exit(2)
|
||||
else:
|
||||
logger.info("Connected to the Kafka server %s" % server_uri)
|
||||
logger.info(f"Connected to the Kafka server {server_uri}")
|
||||
|
||||
return s
|
||||
|
||||
def export(self, name, columns, points):
|
||||
"""Write the points to the kafka server."""
|
||||
logger.debug("Export {} stats to Kafka".format(name))
|
||||
logger.debug(f"Export {name} stats to Kafka")
|
||||
|
||||
# Create DB input
|
||||
data = dict(zip(columns, points))
|
||||
@ -84,7 +83,7 @@ class Export(GlancesExport):
|
||||
value=data,
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error("Cannot export {} stats to Kafka ({})".format(name, e))
|
||||
logger.error(f"Cannot export {name} stats to Kafka ({e})")
|
||||
|
||||
def exit(self):
|
||||
"""Close the Kafka export module."""
|
||||
@ -92,4 +91,4 @@ class Export(GlancesExport):
|
||||
self.client.flush()
|
||||
self.client.close()
|
||||
# Call the father method
|
||||
super(Export, self).exit()
|
||||
super().exit()
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -23,7 +22,7 @@ class Export(GlancesExport):
|
||||
|
||||
def __init__(self, config=None, args=None):
|
||||
"""Init the MongoDB export IF."""
|
||||
super(Export, self).__init__(config=config, args=args)
|
||||
super().__init__(config=config, args=args)
|
||||
|
||||
# Mandatory configuration keys (additional to host and port)
|
||||
self.db = None
|
||||
@ -45,13 +44,13 @@ class Export(GlancesExport):
|
||||
if not self.export_enable:
|
||||
return None
|
||||
|
||||
server_uri = 'mongodb://%s:%s@%s:%s' % (quote_plus(self.user), quote_plus(self.password), self.host, self.port)
|
||||
server_uri = f'mongodb://{quote_plus(self.user)}:{quote_plus(self.password)}@{self.host}:{self.port}'
|
||||
|
||||
try:
|
||||
client = pymongo.MongoClient(server_uri)
|
||||
client.admin.command('ping')
|
||||
except Exception as e:
|
||||
logger.critical("Cannot connect to MongoDB server %s:%s (%s)" % (self.host, self.port, e))
|
||||
logger.critical(f"Cannot connect to MongoDB server {self.host}:{self.port} ({e})")
|
||||
sys.exit(2)
|
||||
else:
|
||||
logger.info("Connected to the MongoDB server")
|
||||
@ -64,7 +63,7 @@ class Export(GlancesExport):
|
||||
|
||||
def export(self, name, columns, points):
|
||||
"""Write the points to the MongoDB server."""
|
||||
logger.debug("Export {} stats to MongoDB".format(name))
|
||||
logger.debug(f"Export {name} stats to MongoDB")
|
||||
|
||||
# Create DB input
|
||||
data = dict(zip(columns, points))
|
||||
@ -73,4 +72,4 @@ class Export(GlancesExport):
|
||||
try:
|
||||
self.database()[name].insert_one(data)
|
||||
except Exception as e:
|
||||
logger.error("Cannot export {} stats to MongoDB ({})".format(name, e))
|
||||
logger.error(f"Cannot export {name} stats to MongoDB ({e})")
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -27,7 +26,7 @@ class Export(GlancesExport):
|
||||
|
||||
def __init__(self, config=None, args=None):
|
||||
"""Init the MQTT export IF."""
|
||||
super(Export, self).__init__(config=config, args=args)
|
||||
super().__init__(config=config, args=args)
|
||||
|
||||
# Mandatory configuration keys (additional to host and port)
|
||||
self.user = None
|
||||
@ -87,7 +86,7 @@ class Export(GlancesExport):
|
||||
client.loop_start()
|
||||
return client
|
||||
except Exception as e:
|
||||
logger.critical("Connection to MQTT server %s:%s failed with error: %s " % (self.host, self.port, e))
|
||||
logger.critical(f"Connection to MQTT server {self.host}:{self.port} failed with error: {e} ")
|
||||
return None
|
||||
|
||||
def export(self, name, columns, points):
|
||||
@ -109,7 +108,7 @@ class Export(GlancesExport):
|
||||
|
||||
self.client.publish(topic, value)
|
||||
except Exception as e:
|
||||
logger.error("Can not export stats to MQTT server (%s)" % e)
|
||||
logger.error(f"Can not export stats to MQTT server ({e})")
|
||||
elif self.topic_structure == 'per-plugin':
|
||||
try:
|
||||
topic = '/'.join([self.topic, self.devicename, name])
|
||||
@ -133,4 +132,4 @@ class Export(GlancesExport):
|
||||
json_value = json_dumps(output_value)
|
||||
self.client.publish(topic, json_value)
|
||||
except Exception as e:
|
||||
logger.error("Can not export stats to MQTT server (%s)" % e)
|
||||
logger.error(f"Can not export stats to MQTT server ({e})")
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -23,7 +22,7 @@ class Export(GlancesExport):
|
||||
|
||||
def __init__(self, config=None, args=None):
|
||||
"""Init the OpenTSDB export IF."""
|
||||
super(Export, self).__init__(config=config, args=args)
|
||||
super().__init__(config=config, args=args)
|
||||
|
||||
# Mandatory configuration keys (additional to host and port)
|
||||
# N/A
|
||||
@ -52,7 +51,7 @@ class Export(GlancesExport):
|
||||
try:
|
||||
db = potsdb.Client(self.host, port=int(self.port), check_host=True)
|
||||
except Exception as e:
|
||||
logger.critical("Cannot connect to OpenTSDB server %s:%s (%s)" % (self.host, self.port, e))
|
||||
logger.critical(f"Cannot connect to OpenTSDB server {self.host}:{self.port} ({e})")
|
||||
sys.exit(2)
|
||||
|
||||
return db
|
||||
@ -62,18 +61,18 @@ class Export(GlancesExport):
|
||||
for i in range(len(columns)):
|
||||
if not isinstance(points[i], Number):
|
||||
continue
|
||||
stat_name = '{}.{}.{}'.format(self.prefix, name, columns[i])
|
||||
stat_name = f'{self.prefix}.{name}.{columns[i]}'
|
||||
stat_value = points[i]
|
||||
tags = self.parse_tags(self.tags)
|
||||
try:
|
||||
self.client.send(stat_name, stat_value, **tags)
|
||||
except Exception as e:
|
||||
logger.error("Can not export stats %s to OpenTSDB (%s)" % (name, e))
|
||||
logger.debug("Export {} stats to OpenTSDB".format(name))
|
||||
logger.error(f"Can not export stats {name} to OpenTSDB ({e})")
|
||||
logger.debug(f"Export {name} stats to OpenTSDB")
|
||||
|
||||
def exit(self):
|
||||
"""Close the OpenTSDB export module."""
|
||||
# Waits for all outstanding metrics to be sent and background thread closes
|
||||
self.client.wait()
|
||||
# Call the father method
|
||||
super(Export, self).exit()
|
||||
super().exit()
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -26,7 +25,7 @@ class Export(GlancesExport):
|
||||
|
||||
def __init__(self, config=None, args=None):
|
||||
"""Init the Prometheus export IF."""
|
||||
super(Export, self).__init__(config=config, args=args)
|
||||
super().__init__(config=config, args=args)
|
||||
|
||||
# Load the Prometheus configuration file section
|
||||
self.export_enable = self.load_conf('prometheus', mandatories=['host', 'port', 'labels'], options=['prefix'])
|
||||
@ -52,14 +51,14 @@ class Export(GlancesExport):
|
||||
try:
|
||||
start_http_server(port=int(self.port), addr=self.host)
|
||||
except Exception as e:
|
||||
logger.critical("Can not start Prometheus exporter on {}:{} ({})".format(self.host, self.port, e))
|
||||
logger.critical(f"Can not start Prometheus exporter on {self.host}:{self.port} ({e})")
|
||||
sys.exit(2)
|
||||
else:
|
||||
logger.info("Start Prometheus exporter on {}:{}".format(self.host, self.port))
|
||||
logger.info(f"Start Prometheus exporter on {self.host}:{self.port}")
|
||||
|
||||
def export(self, name, columns, points):
|
||||
"""Write the points to the Prometheus exporter using Gauge."""
|
||||
logger.debug("Export {} stats to Prometheus exporter".format(name))
|
||||
logger.debug(f"Export {name} stats to Prometheus exporter")
|
||||
|
||||
# Remove non number stats and convert all to float (for Boolean)
|
||||
data = {k: float(v) for (k, v) in iteritems(dict(zip(columns, points))) if isinstance(v, Number)}
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -26,7 +25,7 @@ class Export(GlancesExport):
|
||||
|
||||
def __init__(self, config=None, args=None):
|
||||
"""Init the RabbitMQ export IF."""
|
||||
super(Export, self).__init__(config=config, args=args)
|
||||
super().__init__(config=config, args=args)
|
||||
|
||||
# Mandatory configuration keys (additional to host and port)
|
||||
self.user = None
|
||||
@ -69,7 +68,7 @@ class Export(GlancesExport):
|
||||
connection = pika.BlockingConnection(parameters)
|
||||
return connection.channel()
|
||||
except Exception as e:
|
||||
logger.critical("Connection to rabbitMQ server %s:%s failed. %s" % (self.host, self.port, e))
|
||||
logger.critical(f"Connection to rabbitMQ server {self.host}:{self.port} failed. {e}")
|
||||
sys.exit(2)
|
||||
|
||||
def export(self, name, columns, points):
|
||||
@ -84,4 +83,4 @@ class Export(GlancesExport):
|
||||
try:
|
||||
self.client.basic_publish(exchange='', routing_key=self.queue, body=data)
|
||||
except Exception as e:
|
||||
logger.error("Can not export stats to RabbitMQ (%s)" % e)
|
||||
logger.error(f"Can not export stats to RabbitMQ ({e})")
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -22,7 +21,7 @@ class Export(GlancesExport):
|
||||
|
||||
def __init__(self, config=None, args=None):
|
||||
"""Init the RESTful export IF."""
|
||||
super(Export, self).__init__(config=config, args=args)
|
||||
super().__init__(config=config, args=args)
|
||||
|
||||
# Mandatory configuration keys (additional to host and port)
|
||||
self.protocol = None
|
||||
@ -45,15 +44,15 @@ class Export(GlancesExport):
|
||||
if not self.export_enable:
|
||||
return None
|
||||
# Build the RESTful URL where the stats will be posted
|
||||
url = '{}://{}:{}{}'.format(self.protocol, self.host, self.port, self.path)
|
||||
logger.info("Stats will be exported to the RESTful endpoint {}".format(url))
|
||||
url = f'{self.protocol}://{self.host}:{self.port}{self.path}'
|
||||
logger.info(f"Stats will be exported to the RESTful endpoint {url}")
|
||||
return url
|
||||
|
||||
def export(self, name, columns, points):
|
||||
"""Export the stats to the Statsd server."""
|
||||
if name == self.last_exported_list()[0] and self.buffer != {}:
|
||||
# One complete loop have been done
|
||||
logger.debug("Export stats ({}) to RESTful endpoint ({})".format(listkeys(self.buffer), self.client))
|
||||
logger.debug(f"Export stats ({listkeys(self.buffer)}) to RESTful endpoint ({self.client})")
|
||||
# Export stats
|
||||
post(self.client, json=self.buffer, allow_redirects=True)
|
||||
# Reset buffer
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -24,7 +23,7 @@ class Export(GlancesExport):
|
||||
|
||||
def __init__(self, config=None, args=None):
|
||||
"""Init the Riemann export IF."""
|
||||
super(Export, self).__init__(config=config, args=args)
|
||||
super().__init__(config=config, args=args)
|
||||
|
||||
# Mandatory configuration keys (additional to host and port)
|
||||
# N/A
|
||||
@ -50,7 +49,7 @@ class Export(GlancesExport):
|
||||
try:
|
||||
return bernhard.Client(host=self.host, port=self.port)
|
||||
except Exception as e:
|
||||
logger.critical("Connection to Riemann failed : %s " % e)
|
||||
logger.critical(f"Connection to Riemann failed : {e} ")
|
||||
return None
|
||||
|
||||
def export(self, name, columns, points):
|
||||
@ -64,4 +63,4 @@ class Export(GlancesExport):
|
||||
try:
|
||||
self.client.send(data)
|
||||
except Exception as e:
|
||||
logger.error("Cannot export stats to Riemann (%s)" % e)
|
||||
logger.error(f"Cannot export stats to Riemann ({e})")
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -22,7 +21,7 @@ class Export(GlancesExport):
|
||||
|
||||
def __init__(self, config=None, args=None):
|
||||
"""Init the Statsd export IF."""
|
||||
super(Export, self).__init__(config=config, args=args)
|
||||
super().__init__(config=config, args=args)
|
||||
|
||||
# Mandatory configuration keys (additional to host and port)
|
||||
# N/A
|
||||
@ -46,7 +45,7 @@ class Export(GlancesExport):
|
||||
"""Init the connection to the Statsd server."""
|
||||
if not self.export_enable:
|
||||
return None
|
||||
logger.info("Stats will be exported to StatsD server: {}:{}".format(self.host, self.port))
|
||||
logger.info(f"Stats will be exported to StatsD server: {self.host}:{self.port}")
|
||||
return StatsClient(self.host, int(self.port), prefix=self.prefix)
|
||||
|
||||
def export(self, name, columns, points):
|
||||
@ -54,13 +53,13 @@ class Export(GlancesExport):
|
||||
for i in range(len(columns)):
|
||||
if not isinstance(points[i], Number):
|
||||
continue
|
||||
stat_name = '{}.{}'.format(name, columns[i])
|
||||
stat_name = f'{name}.{columns[i]}'
|
||||
stat_value = points[i]
|
||||
try:
|
||||
self.client.gauge(normalize(stat_name), stat_value)
|
||||
except Exception as e:
|
||||
logger.error("Can not export stats to Statsd (%s)" % e)
|
||||
logger.debug("Export {} stats to Statsd".format(name))
|
||||
logger.error(f"Can not export stats to Statsd ({e})")
|
||||
logger.debug(f"Export {name} stats to Statsd")
|
||||
|
||||
|
||||
def normalize(name):
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -24,7 +23,7 @@ class Export(GlancesExport):
|
||||
|
||||
def __init__(self, config=None, args=None):
|
||||
"""Init the ZeroMQ export IF."""
|
||||
super(Export, self).__init__(config=config, args=args)
|
||||
super().__init__(config=config, args=args)
|
||||
|
||||
# Mandatory configuration keys (additional to host and port)
|
||||
self.prefix = None
|
||||
@ -46,17 +45,17 @@ class Export(GlancesExport):
|
||||
if not self.export_enable:
|
||||
return None
|
||||
|
||||
server_uri = 'tcp://{}:{}'.format(self.host, self.port)
|
||||
server_uri = f'tcp://{self.host}:{self.port}'
|
||||
|
||||
try:
|
||||
self.context = zmq.Context()
|
||||
publisher = self.context.socket(zmq.PUB)
|
||||
publisher.bind(server_uri)
|
||||
except Exception as e:
|
||||
logger.critical("Cannot connect to ZeroMQ server %s (%s)" % (server_uri, e))
|
||||
logger.critical(f"Cannot connect to ZeroMQ server {server_uri} ({e})")
|
||||
sys.exit(2)
|
||||
else:
|
||||
logger.info("Connected to the ZeroMQ server %s" % server_uri)
|
||||
logger.info(f"Connected to the ZeroMQ server {server_uri}")
|
||||
|
||||
return publisher
|
||||
|
||||
@ -69,7 +68,7 @@ class Export(GlancesExport):
|
||||
|
||||
def export(self, name, columns, points):
|
||||
"""Write the points to the ZeroMQ server."""
|
||||
logger.debug("Export {} stats to ZeroMQ".format(name))
|
||||
logger.debug(f"Export {name} stats to ZeroMQ")
|
||||
|
||||
# Create DB input
|
||||
data = dict(zip(columns, points))
|
||||
@ -89,6 +88,6 @@ class Export(GlancesExport):
|
||||
try:
|
||||
self.client.send_multipart(message)
|
||||
except Exception as e:
|
||||
logger.error("Cannot export {} stats to ZeroMQ ({})".format(name, e))
|
||||
logger.error(f"Cannot export {name} stats to ZeroMQ ({e})")
|
||||
|
||||
return True
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -12,7 +11,7 @@ import re
|
||||
from glances.logger import logger
|
||||
|
||||
|
||||
class GlancesFilterList(object):
|
||||
class GlancesFilterList:
|
||||
"""Manage a lis of GlancesFilter objects
|
||||
|
||||
>>> fl = GlancesFilterList()
|
||||
@ -55,7 +54,7 @@ class GlancesFilterList(object):
|
||||
return False
|
||||
|
||||
|
||||
class GlancesFilter(object):
|
||||
class GlancesFilter:
|
||||
"""Allow Glances to filter processes
|
||||
|
||||
>>> f = GlancesFilter()
|
||||
@ -127,9 +126,9 @@ class GlancesFilter(object):
|
||||
# Compute the regular expression
|
||||
try:
|
||||
self._filter_re = re.compile(self.filter)
|
||||
logger.debug("Filter regex compilation OK: {}".format(self.filter))
|
||||
logger.debug(f"Filter regex compilation OK: {self.filter}")
|
||||
except Exception as e:
|
||||
logger.error("Cannot compile filter regex: {} ({})".format(self.filter, e))
|
||||
logger.error(f"Cannot compile filter regex: {self.filter} ({e})")
|
||||
self._filter = None
|
||||
self._filter_re = None
|
||||
self._filter_key = None
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -9,14 +8,12 @@
|
||||
|
||||
"""Manage the folder list."""
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from glances.globals import folder_size, nativestr
|
||||
from glances.logger import logger
|
||||
from glances.timer import Timer
|
||||
|
||||
|
||||
class FolderList(object):
|
||||
class FolderList:
|
||||
"""This class describes the optional monitored folder list.
|
||||
|
||||
The folder list is a list of 'important' folder to monitor.
|
||||
|
@ -1,5 +1,4 @@
|
||||
# ruff: noqa: F401
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -145,7 +144,7 @@ def system_exec(command):
|
||||
try:
|
||||
res = subprocess.run(command.split(' '), stdout=subprocess.PIPE).stdout.decode('utf-8')
|
||||
except Exception as e:
|
||||
res = 'ERROR: {}'.format(e)
|
||||
res = f'ERROR: {e}'
|
||||
return res.rstrip()
|
||||
|
||||
|
||||
@ -202,7 +201,7 @@ def is_admin():
|
||||
try:
|
||||
return ctypes.windll.shell32.IsUserAnAdmin()
|
||||
except Exception as e:
|
||||
print("Admin check failed with error: %s" % e)
|
||||
print(f"Admin check failed with error: {e}")
|
||||
traceback.print_exc()
|
||||
return False
|
||||
else:
|
||||
@ -299,7 +298,7 @@ def urlopen_auth(url, username, password):
|
||||
return urlopen(
|
||||
Request(
|
||||
url,
|
||||
headers={'Authorization': 'Basic ' + base64.b64encode(('%s:%s' % (username, password)).encode()).decode()},
|
||||
headers={'Authorization': 'Basic ' + base64.b64encode((f'{username}:{password}').encode()).decode()},
|
||||
)
|
||||
)
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -12,7 +11,7 @@
|
||||
from glances.attribute import GlancesAttribute
|
||||
|
||||
|
||||
class GlancesHistory(object):
|
||||
class GlancesHistory:
|
||||
"""This class manage a dict of GlancesAttribute
|
||||
- key: stats name
|
||||
- value: GlancesAttribute"""
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -36,7 +35,7 @@ elif os.path.isdir(_XDG_CACHE_HOME) and os.access(_XDG_CACHE_HOME, os.W_OK):
|
||||
safe_makedirs(os.path.join(_XDG_CACHE_HOME, 'glances'))
|
||||
LOG_FILENAME = os.path.join(_XDG_CACHE_HOME, 'glances', 'glances.log')
|
||||
else:
|
||||
LOG_FILENAME = os.path.join(tempfile.gettempdir(), 'glances-{}.log'.format(getpass.getuser()))
|
||||
LOG_FILENAME = os.path.join(tempfile.gettempdir(), f'glances-{getpass.getuser()}.log')
|
||||
|
||||
# Define the logging configuration
|
||||
LOGGING_CFG = {
|
||||
@ -88,7 +87,7 @@ def glances_logger(env_key='LOG_CFG'):
|
||||
user_file = os.getenv(env_key, None)
|
||||
if user_file and os.path.exists(user_file):
|
||||
# A user file as been defined. Use it...
|
||||
with open(user_file, 'rt') as f:
|
||||
with open(user_file) as f:
|
||||
config = json.load(f)
|
||||
|
||||
# Load the configuration
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -22,7 +21,7 @@ from glances.logger import LOG_FILENAME, logger
|
||||
from glances.processes import sort_processes_key_list
|
||||
|
||||
|
||||
class GlancesMain(object):
|
||||
class GlancesMain:
|
||||
"""Main class to manage Glances instance."""
|
||||
|
||||
# Default stats' minimum refresh time is 2 seconds
|
||||
@ -101,10 +100,10 @@ Examples of use:
|
||||
|
||||
def version_msg(self):
|
||||
"""Return the version message."""
|
||||
version = 'Glances version:\t{}\n'.format(__version__)
|
||||
version += 'Glances API version:\t{}\n'.format(__apiversion__)
|
||||
version += 'PsUtil version:\t\t{}\n'.format(psutil_version)
|
||||
version += 'Log file:\t\t{}\n'.format(LOG_FILENAME)
|
||||
version = f'Glances version:\t{__version__}\n'
|
||||
version += f'Glances API version:\t{__apiversion__}\n'
|
||||
version += f'PsUtil version:\t\t{psutil_version}\n'
|
||||
version += f'Log file:\t\t{LOG_FILENAME}\n'
|
||||
return version
|
||||
|
||||
def init_args(self):
|
||||
@ -334,7 +333,7 @@ Examples of use:
|
||||
default=None,
|
||||
type=int,
|
||||
dest='port',
|
||||
help='define the client/server TCP port [default: {}]'.format(self.server_port),
|
||||
help=f'define the client/server TCP port [default: {self.server_port}]',
|
||||
)
|
||||
parser.add_argument(
|
||||
'-B',
|
||||
@ -374,7 +373,7 @@ Examples of use:
|
||||
default=self.DEFAULT_REFRESH_TIME,
|
||||
type=float,
|
||||
dest='time',
|
||||
help='set minimum refresh rate in seconds [default: {} sec]'.format(self.DEFAULT_REFRESH_TIME),
|
||||
help=f'set minimum refresh rate in seconds [default: {self.DEFAULT_REFRESH_TIME} sec]',
|
||||
)
|
||||
parser.add_argument(
|
||||
'-w',
|
||||
@ -389,7 +388,7 @@ Examples of use:
|
||||
default=self.cached_time,
|
||||
type=int,
|
||||
dest='cached_time',
|
||||
help='set the server cache time [default: {} sec]'.format(self.cached_time),
|
||||
help=f'set the server cache time [default: {self.cached_time} sec]',
|
||||
)
|
||||
parser.add_argument(
|
||||
'--stop-after',
|
||||
@ -577,7 +576,7 @@ Examples of use:
|
||||
if args.time == self.DEFAULT_REFRESH_TIME:
|
||||
args.time = global_refresh
|
||||
|
||||
logger.debug('Global refresh rate is set to {} seconds'.format(args.time))
|
||||
logger.debug(f'Global refresh rate is set to {args.time} seconds')
|
||||
|
||||
def init_plugins(self, args):
|
||||
"""Init Glances plugins"""
|
||||
@ -585,7 +584,7 @@ Examples of use:
|
||||
for s in self.config.sections():
|
||||
if self.config.has_section(s) and (self.config.get_bool_value(s, 'disable', False)):
|
||||
disable(args, s)
|
||||
logger.debug('{} disabled by the configuration file'.format(s))
|
||||
logger.debug(f'{s} disabled by the configuration file')
|
||||
# The configuration key can be overwrite from the command line
|
||||
if args and args.disable_plugin and 'all' in args.disable_plugin.split(','):
|
||||
if not args.enable_plugin:
|
||||
@ -664,19 +663,19 @@ Examples of use:
|
||||
# Interactive or file password
|
||||
if args.server:
|
||||
args.password = self.__get_password(
|
||||
description='Define the Glances server password ({} username): '.format(args.username),
|
||||
description=f'Define the Glances server password ({args.username} username): ',
|
||||
confirm=True,
|
||||
username=args.username,
|
||||
)
|
||||
elif args.webserver:
|
||||
args.password = self.__get_password(
|
||||
description='Define the Glances webserver password ({} username): '.format(args.username),
|
||||
description=f'Define the Glances webserver password ({args.username} username): ',
|
||||
confirm=True,
|
||||
username=args.username,
|
||||
)
|
||||
elif args.client:
|
||||
args.password = self.__get_password(
|
||||
description='Enter the Glances server password ({} username): '.format(args.username),
|
||||
description=f'Enter the Glances server password ({args.username} username): ',
|
||||
clear=True,
|
||||
username=args.username,
|
||||
)
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -26,13 +25,13 @@ try:
|
||||
|
||||
PACKAGING_IMPORT = True
|
||||
except Exception as e:
|
||||
logger.warning("Unable to import 'packaging' module ({}). Glances cannot check for updates.".format(e))
|
||||
logger.warning(f"Unable to import 'packaging' module ({e}). Glances cannot check for updates.")
|
||||
PACKAGING_IMPORT = False
|
||||
|
||||
PYPI_API_URL = 'https://pypi.python.org/pypi/Glances/json'
|
||||
|
||||
|
||||
class Outdated(object):
|
||||
class Outdated:
|
||||
"""
|
||||
This class aims at providing methods to warn the user when a new Glances
|
||||
version is available on the PyPI repository (https://pypi.python.org/pypi/Glances/).
|
||||
@ -56,7 +55,7 @@ class Outdated(object):
|
||||
if not self.args.disable_check_update:
|
||||
self.load_config(config)
|
||||
|
||||
logger.debug("Check Glances version up-to-date: {}".format(not self.args.disable_check_update))
|
||||
logger.debug(f"Check Glances version up-to-date: {not self.args.disable_check_update}")
|
||||
|
||||
# And update !
|
||||
self.get_pypi_version()
|
||||
@ -68,7 +67,7 @@ class Outdated(object):
|
||||
if hasattr(config, 'has_section') and config.has_section(global_section):
|
||||
self.args.disable_check_update = config.get_value(global_section, 'check_update').lower() == 'false'
|
||||
else:
|
||||
logger.debug("Cannot find section {} in the configuration file".format(global_section))
|
||||
logger.debug(f"Cannot find section {global_section} in the configuration file")
|
||||
return False
|
||||
|
||||
return True
|
||||
@ -110,9 +109,7 @@ class Outdated(object):
|
||||
# Check is disabled by configuration
|
||||
return False
|
||||
|
||||
logger.debug(
|
||||
"Check Glances version (installed: {} / latest: {})".format(self.installed_version(), self.latest_version())
|
||||
)
|
||||
logger.debug(f"Check Glances version (installed: {self.installed_version()} / latest: {self.latest_version()})")
|
||||
return Version(self.latest_version()) > Version(self.installed_version())
|
||||
|
||||
def _load_cache(self):
|
||||
@ -124,7 +121,7 @@ class Outdated(object):
|
||||
with open(self.cache_file, 'rb') as f:
|
||||
cached_data = pickle.load(f)
|
||||
except Exception as e:
|
||||
logger.debug("Cannot read version from cache file: {} ({})".format(self.cache_file, e))
|
||||
logger.debug(f"Cannot read version from cache file: {self.cache_file} ({e})")
|
||||
else:
|
||||
logger.debug("Read version from cache file")
|
||||
if (
|
||||
@ -147,11 +144,11 @@ class Outdated(object):
|
||||
with open(self.cache_file, 'wb') as f:
|
||||
pickle.dump(self.data, f)
|
||||
except Exception as e:
|
||||
logger.error("Cannot write version to cache file {} ({})".format(self.cache_file, e))
|
||||
logger.error(f"Cannot write version to cache file {self.cache_file} ({e})")
|
||||
|
||||
def _update_pypi_version(self):
|
||||
"""Get the latest PyPI version (as a string) via the RESTful JSON API"""
|
||||
logger.debug("Get latest Glances version from the PyPI RESTful API ({})".format(PYPI_API_URL))
|
||||
logger.debug(f"Get latest Glances version from the PyPI RESTful API ({PYPI_API_URL})")
|
||||
|
||||
# Update the current time
|
||||
self.data['refresh_date'] = datetime.now()
|
||||
@ -159,7 +156,7 @@ class Outdated(object):
|
||||
try:
|
||||
res = urlopen(PYPI_API_URL, timeout=3).read()
|
||||
except (HTTPError, URLError, CertificateError) as e:
|
||||
logger.debug("Cannot get Glances version from the PyPI RESTful API ({})".format(e))
|
||||
logger.debug(f"Cannot get Glances version from the PyPI RESTful API ({e})")
|
||||
else:
|
||||
self.data['latest_version'] = json.loads(nativestr(res))['info']['version']
|
||||
logger.debug("Save Glances version to the cache file")
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -9,12 +8,10 @@
|
||||
|
||||
"""Manage bars for Glances output."""
|
||||
|
||||
from __future__ import division
|
||||
|
||||
from math import modf
|
||||
|
||||
|
||||
class Bar(object):
|
||||
class Bar:
|
||||
"""Manage bar (progression or status).
|
||||
|
||||
import sys
|
||||
@ -115,7 +112,7 @@ class Bar(object):
|
||||
ret, '>' if self.percent > self.max_value else ' ', self.max_value, self.__unit_char
|
||||
)
|
||||
else:
|
||||
ret = '{}{:5.1f}{}'.format(ret, self.percent, self.__unit_char)
|
||||
ret = f'{ret}{self.percent:5.1f}{self.__unit_char}'
|
||||
|
||||
# Add overlay
|
||||
if overlay and len(overlay) < len(ret) - 6:
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -9,8 +8,6 @@
|
||||
|
||||
"""Curses interface class."""
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import getpass
|
||||
import sys
|
||||
|
||||
@ -33,7 +30,7 @@ except ImportError:
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
class _GlancesCurses(object):
|
||||
class _GlancesCurses:
|
||||
"""This class manages the curses display (and key pressed).
|
||||
|
||||
Note: It is a private class, use GlancesCursesClient or GlancesCursesBrowser.
|
||||
@ -148,14 +145,14 @@ class _GlancesCurses(object):
|
||||
logger.critical("Cannot init the curses library.\n")
|
||||
sys.exit(1)
|
||||
else:
|
||||
logger.debug("Curses library initialized with term: {}".format(curses.longname()))
|
||||
logger.debug(f"Curses library initialized with term: {curses.longname()}")
|
||||
except Exception as e:
|
||||
if args.export:
|
||||
logger.info("Cannot init the curses library, quiet mode on and export.")
|
||||
args.quiet = True
|
||||
return
|
||||
|
||||
logger.critical("Cannot init the curses library ({})".format(e))
|
||||
logger.critical(f"Cannot init the curses library ({e})")
|
||||
sys.exit(1)
|
||||
|
||||
# Load configuration file
|
||||
@ -224,11 +221,11 @@ class _GlancesCurses(object):
|
||||
try:
|
||||
if hasattr(curses, 'start_color'):
|
||||
curses.start_color()
|
||||
logger.debug('Curses interface compatible with {} colors'.format(curses.COLORS))
|
||||
logger.debug(f'Curses interface compatible with {curses.COLORS} colors')
|
||||
if hasattr(curses, 'use_default_colors'):
|
||||
curses.use_default_colors()
|
||||
except Exception as e:
|
||||
logger.warning('Error initializing terminal color ({})'.format(e))
|
||||
logger.warning(f'Error initializing terminal color ({e})')
|
||||
|
||||
# Init colors
|
||||
if self.args.disable_bold:
|
||||
@ -368,7 +365,7 @@ class _GlancesCurses(object):
|
||||
return -1
|
||||
|
||||
# Actions (available in the global hotkey dict)...
|
||||
logger.debug("Keypressed (code: {})".format(self.pressedkey))
|
||||
logger.debug(f"Keypressed (code: {self.pressedkey})")
|
||||
for hotkey in self._hotkeys:
|
||||
if self.pressedkey == ord(hotkey) and 'switch' in self._hotkeys[hotkey]:
|
||||
self._handle_switch(hotkey)
|
||||
@ -495,7 +492,7 @@ class _GlancesCurses(object):
|
||||
if return_to_browser:
|
||||
logger.info("Stop Glances client and return to the browser")
|
||||
else:
|
||||
logger.info("Stop Glances (keypressed: {})".format(self.pressedkey))
|
||||
logger.info(f"Stop Glances (keypressed: {self.pressedkey})")
|
||||
|
||||
def _handle_refresh(self):
|
||||
pass
|
||||
@ -716,7 +713,7 @@ class _GlancesCurses(object):
|
||||
# Display graph generation popup
|
||||
if self.args.generate_graph:
|
||||
if 'graph' in stats.getExportsList():
|
||||
self.display_popup('Generate graph in {}'.format(self.args.export_graph_path))
|
||||
self.display_popup(f'Generate graph in {self.args.export_graph_path}')
|
||||
else:
|
||||
logger.warning('Graph export module is disable. Run Glances with --export graph to enable it.')
|
||||
self.args.generate_graph = False
|
||||
@ -735,7 +732,7 @@ class _GlancesCurses(object):
|
||||
:param process
|
||||
:return: None
|
||||
"""
|
||||
logger.debug("Selected process to kill: {}".format(process))
|
||||
logger.debug(f"Selected process to kill: {process}")
|
||||
|
||||
if 'childrens' in process:
|
||||
pid_to_kill = process['childrens']
|
||||
@ -755,9 +752,9 @@ class _GlancesCurses(object):
|
||||
try:
|
||||
ret_kill = glances_processes.kill(pid)
|
||||
except Exception as e:
|
||||
logger.error('Can not kill process {} ({})'.format(pid, e))
|
||||
logger.error(f'Can not kill process {pid} ({e})')
|
||||
else:
|
||||
logger.info('Kill signal has been sent to process {} (return code: {})'.format(pid, ret_kill))
|
||||
logger.info(f'Kill signal has been sent to process {pid} (return code: {ret_kill})')
|
||||
|
||||
def __display_header(self, stat_display):
|
||||
"""Display the firsts lines (header) in the Curses interface.
|
||||
@ -829,7 +826,7 @@ class _GlancesCurses(object):
|
||||
max_width=quicklook_width, args=self.args
|
||||
)
|
||||
except AttributeError as e:
|
||||
logger.debug("Quicklook plugin not available (%s)" % e)
|
||||
logger.debug(f"Quicklook plugin not available ({e})")
|
||||
else:
|
||||
plugin_widths['quicklook'] = self.get_stats_display_width(stat_display["quicklook"])
|
||||
stats_width = sum(itervalues(plugin_widths)) + 1
|
||||
@ -1258,7 +1255,7 @@ class _GlancesCurses(object):
|
||||
)
|
||||
)
|
||||
except Exception as e:
|
||||
logger.debug('ERROR: Can not compute plugin width ({})'.format(e))
|
||||
logger.debug(f'ERROR: Can not compute plugin width ({e})')
|
||||
return 0
|
||||
else:
|
||||
return c
|
||||
@ -1271,7 +1268,7 @@ class _GlancesCurses(object):
|
||||
try:
|
||||
c = [i['msg'] for i in curse_msg['msgdict']].count('\n')
|
||||
except Exception as e:
|
||||
logger.debug('ERROR: Can not compute plugin height ({})'.format(e))
|
||||
logger.debug(f'ERROR: Can not compute plugin height ({e})')
|
||||
return 0
|
||||
else:
|
||||
return c + 1
|
||||
@ -1285,21 +1282,21 @@ class GlancesCursesClient(_GlancesCurses):
|
||||
"""Class for the Glances curse client."""
|
||||
|
||||
|
||||
class GlancesTextbox(Textbox, object):
|
||||
class GlancesTextbox(Textbox):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(GlancesTextbox, self).__init__(*args, **kwargs)
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
def do_command(self, ch):
|
||||
if ch == 10: # Enter
|
||||
return 0
|
||||
if ch == 127: # Back
|
||||
return 8
|
||||
return super(GlancesTextbox, self).do_command(ch)
|
||||
return super().do_command(ch)
|
||||
|
||||
|
||||
class GlancesTextboxYesNo(Textbox, object):
|
||||
class GlancesTextboxYesNo(Textbox):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(GlancesTextboxYesNo, self).__init__(*args, **kwargs)
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
def do_command(self, ch):
|
||||
return super(GlancesTextboxYesNo, self).do_command(ch)
|
||||
return super().do_command(ch)
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -22,7 +21,7 @@ class GlancesCursesBrowser(_GlancesCurses):
|
||||
|
||||
def __init__(self, args=None):
|
||||
"""Init the father class."""
|
||||
super(GlancesCursesBrowser, self).__init__(args=args)
|
||||
super().__init__(args=args)
|
||||
|
||||
_colors_list = {
|
||||
'UNKNOWN': self.no_color,
|
||||
@ -151,7 +150,7 @@ class GlancesCursesBrowser(_GlancesCurses):
|
||||
self.pressedkey = self.get_key(self.term_window)
|
||||
refresh = False
|
||||
if self.pressedkey != -1:
|
||||
logger.debug("Key pressed. Code=%s" % self.pressedkey)
|
||||
logger.debug(f"Key pressed. Code={self.pressedkey}")
|
||||
|
||||
# Actions...
|
||||
if self.pressedkey == ord('\x1b') or self.pressedkey == ord('q'):
|
||||
@ -163,23 +162,23 @@ class GlancesCursesBrowser(_GlancesCurses):
|
||||
elif self.pressedkey == 10:
|
||||
# 'ENTER' > Run Glances on the selected server
|
||||
self.active_server = self._current_page * self._page_max_lines + self.cursor_position
|
||||
logger.debug("Server {}/{} selected".format(self.active_server, len(stats)))
|
||||
logger.debug(f"Server {self.active_server}/{len(stats)} selected")
|
||||
elif self.pressedkey == curses.KEY_UP or self.pressedkey == 65:
|
||||
# 'UP' > Up in the server list
|
||||
self.cursor_up(stats)
|
||||
logger.debug("Server {}/{} selected".format(self.cursor + 1, len(stats)))
|
||||
logger.debug(f"Server {self.cursor + 1}/{len(stats)} selected")
|
||||
elif self.pressedkey == curses.KEY_DOWN or self.pressedkey == 66:
|
||||
# 'DOWN' > Down in the server list
|
||||
self.cursor_down(stats)
|
||||
logger.debug("Server {}/{} selected".format(self.cursor + 1, len(stats)))
|
||||
logger.debug(f"Server {self.cursor + 1}/{len(stats)} selected")
|
||||
elif self.pressedkey == curses.KEY_PPAGE:
|
||||
# 'Page UP' > Prev page in the server list
|
||||
self.cursor_pageup(stats)
|
||||
logger.debug("PageUP: Server ({}/{}) pages.".format(self._current_page + 1, self._page_max))
|
||||
logger.debug(f"PageUP: Server ({self._current_page + 1}/{self._page_max}) pages.")
|
||||
elif self.pressedkey == curses.KEY_NPAGE:
|
||||
# 'Page Down' > Next page in the server list
|
||||
self.cursor_pagedown(stats)
|
||||
logger.debug("PageDown: Server {}/{} pages".format(self._current_page + 1, self._page_max))
|
||||
logger.debug(f"PageDown: Server {self._current_page + 1}/{self._page_max} pages")
|
||||
elif self.pressedkey == ord('1'):
|
||||
self._stats_list = None
|
||||
refresh = True
|
||||
@ -211,7 +210,7 @@ class GlancesCursesBrowser(_GlancesCurses):
|
||||
:param return_to_browser:
|
||||
"""
|
||||
# Flush display
|
||||
logger.debug('Servers list: {}'.format(stats))
|
||||
logger.debug(f'Servers list: {stats}')
|
||||
self.flush(stats)
|
||||
|
||||
# Wait
|
||||
@ -268,19 +267,19 @@ class GlancesCursesBrowser(_GlancesCurses):
|
||||
elif len(stats) == 1:
|
||||
msg = 'One Glances server available'
|
||||
else:
|
||||
msg = '{} Glances servers available'.format(stats_len)
|
||||
msg = f'{stats_len} Glances servers available'
|
||||
if self.args.disable_autodiscover:
|
||||
msg += ' (auto discover is disabled)'
|
||||
if screen_y > 1:
|
||||
self.term_window.addnstr(y, x, msg, screen_x - x, self.colors_list['TITLE'])
|
||||
|
||||
msg = '{}'.format(self._get_status_count(stats))
|
||||
msg = f'{self._get_status_count(stats)}'
|
||||
self.term_window.addnstr(y + 1, x, msg, screen_x - x)
|
||||
|
||||
if stats_len > stats_max and screen_y > 2:
|
||||
msg = '{} servers displayed.({}/{}) {}'.format(
|
||||
self.get_pagelines(stats), self._current_page + 1, self._page_max, self._get_status_count(stats)
|
||||
)
|
||||
page_lines = self.get_pagelines(stats)
|
||||
status_count = self._get_status_count(stats)
|
||||
msg = f'{page_lines} servers displayed.({self._current_page + 1}/{self._page_max}) {status_count}'
|
||||
self.term_window.addnstr(y + 1, x, msg, screen_x - x)
|
||||
|
||||
if stats_len == 0:
|
||||
@ -335,7 +334,7 @@ class GlancesCursesBrowser(_GlancesCurses):
|
||||
try:
|
||||
server_stat[c[0]] = v[c[0]]
|
||||
except KeyError as e:
|
||||
logger.debug("Cannot grab stats {} from server (KeyError: {})".format(c[0], e))
|
||||
logger.debug(f"Cannot grab stats {c[0]} from server (KeyError: {e})")
|
||||
server_stat[c[0]] = '?'
|
||||
# Display alias instead of name
|
||||
try:
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -13,7 +12,6 @@ import os
|
||||
import sys
|
||||
import tempfile
|
||||
import webbrowser
|
||||
from io import open
|
||||
from urllib.parse import urljoin
|
||||
|
||||
try:
|
||||
@ -46,6 +44,7 @@ try:
|
||||
except ImportError:
|
||||
logger.critical('Uvicorn import error. Glances cannot start in web server mode.')
|
||||
sys.exit(2)
|
||||
import builtins
|
||||
import contextlib
|
||||
import threading
|
||||
import time
|
||||
@ -77,7 +76,7 @@ class GlancesUvicornServer(uvicorn.Server):
|
||||
thread.join()
|
||||
|
||||
|
||||
class GlancesRestfulApi(object):
|
||||
class GlancesRestfulApi:
|
||||
"""This class manages the Restful API server."""
|
||||
|
||||
API_VERSION = __apiversion__
|
||||
@ -102,7 +101,7 @@ class GlancesRestfulApi(object):
|
||||
self.load_config(config)
|
||||
|
||||
# Set the bind URL
|
||||
self.bind_url = urljoin('http://{}:{}/'.format(self.args.bind_address, self.args.port), self.url_prefix)
|
||||
self.bind_url = urljoin(f'http://{self.args.bind_address}:{self.args.port}/', self.url_prefix)
|
||||
|
||||
# FastAPI Init
|
||||
if self.args.password:
|
||||
@ -151,9 +150,9 @@ class GlancesRestfulApi(object):
|
||||
self.url_prefix = '/'
|
||||
if config is not None and config.has_section('outputs'):
|
||||
n = config.get_value('outputs', 'max_processes_display', default=None)
|
||||
logger.debug('Number of processes to display in the WebUI: {}'.format(n))
|
||||
logger.debug(f'Number of processes to display in the WebUI: {n}')
|
||||
self.url_prefix = config.get_value('outputs', 'url_prefix', default='/')
|
||||
logger.debug('URL prefix: {}'.format(self.url_prefix))
|
||||
logger.debug(f'URL prefix: {self.url_prefix}')
|
||||
|
||||
def __update__(self):
|
||||
# Never update more than 1 time per cached_time
|
||||
@ -184,92 +183,92 @@ class GlancesRestfulApi(object):
|
||||
|
||||
# REST API
|
||||
router.add_api_route(
|
||||
'/api/%s/status' % self.API_VERSION,
|
||||
f'/api/{self.API_VERSION}/status',
|
||||
status_code=status.HTTP_200_OK,
|
||||
response_class=ORJSONResponse,
|
||||
endpoint=self._api_status,
|
||||
)
|
||||
|
||||
router.add_api_route(
|
||||
'/api/%s/config' % self.API_VERSION, response_class=ORJSONResponse, endpoint=self._api_config
|
||||
f'/api/{self.API_VERSION}/config', response_class=ORJSONResponse, endpoint=self._api_config
|
||||
)
|
||||
router.add_api_route(
|
||||
'/api/%s/config/{section}' % self.API_VERSION,
|
||||
f'/api/{self.API_VERSION}/config/{{section}}',
|
||||
response_class=ORJSONResponse,
|
||||
endpoint=self._api_config_section,
|
||||
)
|
||||
router.add_api_route(
|
||||
'/api/%s/config/{section}/{item}' % self.API_VERSION,
|
||||
f'/api/{self.API_VERSION}/config/{{section}}/{{item}}',
|
||||
response_class=ORJSONResponse,
|
||||
endpoint=self._api_config_section_item,
|
||||
)
|
||||
|
||||
router.add_api_route('/api/%s/args' % self.API_VERSION, response_class=ORJSONResponse, endpoint=self._api_args)
|
||||
router.add_api_route(f'/api/{self.API_VERSION}/args', response_class=ORJSONResponse, endpoint=self._api_args)
|
||||
router.add_api_route(
|
||||
'/api/%s/args/{item}' % self.API_VERSION, response_class=ORJSONResponse, endpoint=self._api_args_item
|
||||
f'/api/{self.API_VERSION}/args/{{item}}', response_class=ORJSONResponse, endpoint=self._api_args_item
|
||||
)
|
||||
|
||||
router.add_api_route(
|
||||
'/api/%s/pluginslist' % self.API_VERSION, response_class=ORJSONResponse, endpoint=self._api_plugins
|
||||
f'/api/{self.API_VERSION}/pluginslist', response_class=ORJSONResponse, endpoint=self._api_plugins
|
||||
)
|
||||
router.add_api_route('/api/%s/all' % self.API_VERSION, response_class=ORJSONResponse, endpoint=self._api_all)
|
||||
router.add_api_route(f'/api/{self.API_VERSION}/all', response_class=ORJSONResponse, endpoint=self._api_all)
|
||||
router.add_api_route(
|
||||
'/api/%s/all/limits' % self.API_VERSION, response_class=ORJSONResponse, endpoint=self._api_all_limits
|
||||
f'/api/{self.API_VERSION}/all/limits', response_class=ORJSONResponse, endpoint=self._api_all_limits
|
||||
)
|
||||
router.add_api_route(
|
||||
'/api/%s/all/views' % self.API_VERSION, response_class=ORJSONResponse, endpoint=self._api_all_views
|
||||
f'/api/{self.API_VERSION}/all/views', response_class=ORJSONResponse, endpoint=self._api_all_views
|
||||
)
|
||||
|
||||
router.add_api_route('/api/%s/help' % self.API_VERSION, response_class=ORJSONResponse, endpoint=self._api_help)
|
||||
router.add_api_route('/api/%s/{plugin}' % self.API_VERSION, response_class=ORJSONResponse, endpoint=self._api)
|
||||
router.add_api_route(f'/api/{self.API_VERSION}/help', response_class=ORJSONResponse, endpoint=self._api_help)
|
||||
router.add_api_route(f'/api/{self.API_VERSION}/{{plugin}}', response_class=ORJSONResponse, endpoint=self._api)
|
||||
router.add_api_route(
|
||||
'/api/%s/{plugin}/history' % self.API_VERSION, response_class=ORJSONResponse, endpoint=self._api_history
|
||||
f'/api/{self.API_VERSION}/{{plugin}}/history', response_class=ORJSONResponse, endpoint=self._api_history
|
||||
)
|
||||
router.add_api_route(
|
||||
'/api/%s/{plugin}/history/{nb}' % self.API_VERSION,
|
||||
f'/api/{self.API_VERSION}/{{plugin}}/history/{{nb}}',
|
||||
response_class=ORJSONResponse,
|
||||
endpoint=self._api_history,
|
||||
)
|
||||
router.add_api_route(
|
||||
'/api/%s/{plugin}/top/{nb}' % self.API_VERSION, response_class=ORJSONResponse, endpoint=self._api_top
|
||||
f'/api/{self.API_VERSION}/{{plugin}}/top/{{nb}}', response_class=ORJSONResponse, endpoint=self._api_top
|
||||
)
|
||||
router.add_api_route(
|
||||
'/api/%s/{plugin}/limits' % self.API_VERSION, response_class=ORJSONResponse, endpoint=self._api_limits
|
||||
f'/api/{self.API_VERSION}/{{plugin}}/limits', response_class=ORJSONResponse, endpoint=self._api_limits
|
||||
)
|
||||
router.add_api_route(
|
||||
'/api/%s/{plugin}/views' % self.API_VERSION, response_class=ORJSONResponse, endpoint=self._api_views
|
||||
f'/api/{self.API_VERSION}/{{plugin}}/views', response_class=ORJSONResponse, endpoint=self._api_views
|
||||
)
|
||||
router.add_api_route(
|
||||
'/api/%s/{plugin}/{item}' % self.API_VERSION, response_class=ORJSONResponse, endpoint=self._api_item
|
||||
f'/api/{self.API_VERSION}/{{plugin}}/{{item}}', response_class=ORJSONResponse, endpoint=self._api_item
|
||||
)
|
||||
router.add_api_route(
|
||||
'/api/%s/{plugin}/{item}/history' % self.API_VERSION,
|
||||
f'/api/{self.API_VERSION}/{{plugin}}/{{item}}/history',
|
||||
response_class=ORJSONResponse,
|
||||
endpoint=self._api_item_history,
|
||||
)
|
||||
router.add_api_route(
|
||||
'/api/%s/{plugin}/{item}/history/{nb}' % self.API_VERSION,
|
||||
f'/api/{self.API_VERSION}/{{plugin}}/{{item}}/history/{{nb}}',
|
||||
response_class=ORJSONResponse,
|
||||
endpoint=self._api_item_history,
|
||||
)
|
||||
router.add_api_route(
|
||||
'/api/%s/{plugin}/{item}/description' % self.API_VERSION,
|
||||
f'/api/{self.API_VERSION}/{{plugin}}/{{item}}/description',
|
||||
response_class=ORJSONResponse,
|
||||
endpoint=self._api_item_description,
|
||||
)
|
||||
router.add_api_route(
|
||||
'/api/%s/{plugin}/{item}/unit' % self.API_VERSION,
|
||||
f'/api/{self.API_VERSION}/{{plugin}}/{{item}}/unit',
|
||||
response_class=ORJSONResponse,
|
||||
endpoint=self._api_item_unit,
|
||||
)
|
||||
router.add_api_route(
|
||||
'/api/%s/{plugin}/{item}/{value}' % self.API_VERSION,
|
||||
f'/api/{self.API_VERSION}/{{plugin}}/{{item}}/{{value}}',
|
||||
response_class=ORJSONResponse,
|
||||
endpoint=self._api_value,
|
||||
)
|
||||
|
||||
# Restful API
|
||||
bindmsg = 'Glances RESTful API Server started on {}api/{}'.format(self.bind_url, self.API_VERSION)
|
||||
bindmsg = f'Glances RESTful API Server started on {self.bind_url}api/{self.API_VERSION}'
|
||||
logger.info(bindmsg)
|
||||
|
||||
# WEB UI
|
||||
@ -280,9 +279,9 @@ class GlancesRestfulApi(object):
|
||||
# Statics files
|
||||
self._app.mount("/static", StaticFiles(directory=self.STATIC_PATH), name="static")
|
||||
|
||||
logger.info("Get WebUI in {}".format(self.STATIC_PATH))
|
||||
logger.info(f"Get WebUI in {self.STATIC_PATH}")
|
||||
|
||||
bindmsg = 'Glances Web User Interface started on {}'.format(self.bind_url)
|
||||
bindmsg = f'Glances Web User Interface started on {self.bind_url}'
|
||||
else:
|
||||
bindmsg = 'The WebUI is disable (--disable-webui)'
|
||||
|
||||
@ -317,7 +316,7 @@ class GlancesRestfulApi(object):
|
||||
try:
|
||||
self.uvicorn_server = GlancesUvicornServer(config=uvicorn_config)
|
||||
except Exception as e:
|
||||
logger.critical('Error: Can not ran Glances Web server ({})'.format(e))
|
||||
logger.critical(f'Error: Can not ran Glances Web server ({e})')
|
||||
self.uvicorn_server = None
|
||||
else:
|
||||
with self.uvicorn_server.run_in_thread():
|
||||
@ -369,7 +368,7 @@ class GlancesRestfulApi(object):
|
||||
try:
|
||||
plist = self.stats.get_plugin("help").get_view_data()
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Cannot get help view data (%s)" % str(e))
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f"Cannot get help view data ({str(e)})")
|
||||
|
||||
return ORJSONResponse(plist)
|
||||
|
||||
@ -405,7 +404,7 @@ class GlancesRestfulApi(object):
|
||||
try:
|
||||
plist = self.plugins_list
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Cannot get plugin list (%s)" % str(e))
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f"Cannot get plugin list ({str(e)})")
|
||||
|
||||
return ORJSONResponse(plist)
|
||||
|
||||
@ -420,10 +419,10 @@ class GlancesRestfulApi(object):
|
||||
if self.args.debug:
|
||||
fname = os.path.join(tempfile.gettempdir(), 'glances-debug.json')
|
||||
try:
|
||||
with open(fname) as f:
|
||||
with builtins.open(fname) as f:
|
||||
return f.read()
|
||||
except IOError:
|
||||
logger.debug("Debug file (%s) not found" % fname)
|
||||
except OSError:
|
||||
logger.debug(f"Debug file ({fname}) not found")
|
||||
|
||||
# Update the stat
|
||||
self.__update__()
|
||||
@ -432,7 +431,7 @@ class GlancesRestfulApi(object):
|
||||
# Get the RAW value of the stat ID
|
||||
statval = self.stats.getAllAsDict()
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Cannot get stats (%s)" % str(e))
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f"Cannot get stats ({str(e)})")
|
||||
|
||||
return ORJSONResponse(statval)
|
||||
|
||||
@ -448,7 +447,7 @@ class GlancesRestfulApi(object):
|
||||
# Get the RAW value of the stat limits
|
||||
limits = self.stats.getAllLimitsAsDict()
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Cannot get limits (%s)" % str(e))
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f"Cannot get limits ({str(e)})")
|
||||
|
||||
return ORJSONResponse(limits)
|
||||
|
||||
@ -464,7 +463,7 @@ class GlancesRestfulApi(object):
|
||||
# Get the RAW value of the stat view
|
||||
limits = self.stats.getAllViewsAsDict()
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Cannot get views (%s)" % str(e))
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f"Cannot get views ({str(e)})")
|
||||
|
||||
return ORJSONResponse(limits)
|
||||
|
||||
@ -479,7 +478,7 @@ class GlancesRestfulApi(object):
|
||||
if plugin not in self.plugins_list:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail="Unknown plugin %s (available plugins: %s)" % (plugin, self.plugins_list),
|
||||
detail=f"Unknown plugin {plugin} (available plugins: {self.plugins_list})",
|
||||
)
|
||||
|
||||
# Update the stat
|
||||
@ -489,9 +488,7 @@ class GlancesRestfulApi(object):
|
||||
# Get the RAW value of the stat ID
|
||||
statval = self.stats.get_plugin(plugin).get_raw()
|
||||
except Exception as e:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND, detail="Cannot get plugin %s (%s)" % (plugin, str(e))
|
||||
)
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f"Cannot get plugin {plugin} ({str(e)})")
|
||||
|
||||
return ORJSONResponse(statval)
|
||||
|
||||
@ -508,7 +505,7 @@ class GlancesRestfulApi(object):
|
||||
if plugin not in self.plugins_list:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail="Unknown plugin %s (available plugins: %s)" % (plugin, self.plugins_list),
|
||||
detail=f"Unknown plugin {plugin} (available plugins: {self.plugins_list})",
|
||||
)
|
||||
|
||||
# Update the stat
|
||||
@ -518,9 +515,7 @@ class GlancesRestfulApi(object):
|
||||
# Get the RAW value of the stat ID
|
||||
statval = self.stats.get_plugin(plugin).get_raw()
|
||||
except Exception as e:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND, detail="Cannot get plugin %s (%s)" % (plugin, str(e))
|
||||
)
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f"Cannot get plugin {plugin} ({str(e)})")
|
||||
|
||||
print(statval)
|
||||
|
||||
@ -541,7 +536,7 @@ class GlancesRestfulApi(object):
|
||||
if plugin not in self.plugins_list:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail="Unknown plugin %s (available plugins: %s)" % (plugin, self.plugins_list),
|
||||
detail=f"Unknown plugin {plugin} (available plugins: {self.plugins_list})",
|
||||
)
|
||||
|
||||
# Update the stat
|
||||
@ -552,7 +547,7 @@ class GlancesRestfulApi(object):
|
||||
statval = self.stats.get_plugin(plugin).get_raw_history(nb=int(nb))
|
||||
except Exception as e:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND, detail="Cannot get plugin history %s (%s)" % (plugin, str(e))
|
||||
status_code=status.HTTP_404_NOT_FOUND, detail=f"Cannot get plugin history {plugin} ({str(e)})"
|
||||
)
|
||||
|
||||
return statval
|
||||
@ -568,7 +563,7 @@ class GlancesRestfulApi(object):
|
||||
if plugin not in self.plugins_list:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail="Unknown plugin %s (available plugins: %s)" % (plugin, self.plugins_list),
|
||||
detail=f"Unknown plugin {plugin} (available plugins: {self.plugins_list})",
|
||||
)
|
||||
|
||||
try:
|
||||
@ -576,7 +571,7 @@ class GlancesRestfulApi(object):
|
||||
ret = self.stats.get_plugin(plugin).limits
|
||||
except Exception as e:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND, detail="Cannot get limits for plugin %s (%s)" % (plugin, str(e))
|
||||
status_code=status.HTTP_404_NOT_FOUND, detail=f"Cannot get limits for plugin {plugin} ({str(e)})"
|
||||
)
|
||||
|
||||
return ORJSONResponse(ret)
|
||||
@ -592,7 +587,7 @@ class GlancesRestfulApi(object):
|
||||
if plugin not in self.plugins_list:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail="Unknown plugin %s (available plugins: %s)" % (plugin, self.plugins_list),
|
||||
detail=f"Unknown plugin {plugin} (available plugins: {self.plugins_list})",
|
||||
)
|
||||
|
||||
try:
|
||||
@ -600,7 +595,7 @@ class GlancesRestfulApi(object):
|
||||
ret = self.stats.get_plugin(plugin).get_views()
|
||||
except Exception as e:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND, detail="Cannot get views for plugin %s (%s)" % (plugin, str(e))
|
||||
status_code=status.HTTP_404_NOT_FOUND, detail=f"Cannot get views for plugin {plugin} ({str(e)})"
|
||||
)
|
||||
|
||||
return ORJSONResponse(ret)
|
||||
@ -616,7 +611,7 @@ class GlancesRestfulApi(object):
|
||||
if plugin not in self.plugins_list:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail="Unknown plugin %s (available plugins: %s)" % (plugin, self.plugins_list),
|
||||
detail=f"Unknown plugin {plugin} (available plugins: {self.plugins_list})",
|
||||
)
|
||||
|
||||
# Update the stat
|
||||
@ -628,7 +623,7 @@ class GlancesRestfulApi(object):
|
||||
except Exception as e:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
detail="Cannot get item %s in plugin %s (%s)" % (item, plugin, str(e)),
|
||||
detail=f"Cannot get item {item} in plugin {plugin} ({str(e)})",
|
||||
)
|
||||
|
||||
return ORJSONResponse(ret)
|
||||
@ -645,7 +640,7 @@ class GlancesRestfulApi(object):
|
||||
if plugin not in self.plugins_list:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail="Unknown plugin %s (available plugins: %s)" % (plugin, self.plugins_list),
|
||||
detail=f"Unknown plugin {plugin} (available plugins: {self.plugins_list})",
|
||||
)
|
||||
|
||||
# Update the stat
|
||||
@ -656,7 +651,7 @@ class GlancesRestfulApi(object):
|
||||
ret = self.stats.get_plugin(plugin).get_raw_history(item, nb=nb)
|
||||
except Exception as e:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND, detail="Cannot get history for plugin %s (%s)" % (plugin, str(e))
|
||||
status_code=status.HTTP_404_NOT_FOUND, detail=f"Cannot get history for plugin {plugin} ({str(e)})"
|
||||
)
|
||||
else:
|
||||
return ORJSONResponse(ret)
|
||||
@ -672,7 +667,7 @@ class GlancesRestfulApi(object):
|
||||
if plugin not in self.plugins_list:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail="Unknown plugin %s (available plugins: %s)" % (plugin, self.plugins_list),
|
||||
detail=f"Unknown plugin {plugin} (available plugins: {self.plugins_list})",
|
||||
)
|
||||
|
||||
try:
|
||||
@ -681,7 +676,7 @@ class GlancesRestfulApi(object):
|
||||
except Exception as e:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
detail="Cannot get %s description for plugin %s (%s)" % (item, plugin, str(e)),
|
||||
detail=f"Cannot get {item} description for plugin {plugin} ({str(e)})",
|
||||
)
|
||||
else:
|
||||
return ORJSONResponse(ret)
|
||||
@ -697,7 +692,7 @@ class GlancesRestfulApi(object):
|
||||
if plugin not in self.plugins_list:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail="Unknown plugin %s (available plugins: %s)" % (plugin, self.plugins_list),
|
||||
detail=f"Unknown plugin {plugin} (available plugins: {self.plugins_list})",
|
||||
)
|
||||
|
||||
try:
|
||||
@ -706,7 +701,7 @@ class GlancesRestfulApi(object):
|
||||
except Exception as e:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
detail="Cannot get %s unit for plugin %s (%s)" % (item, plugin, str(e)),
|
||||
detail=f"Cannot get {item} unit for plugin {plugin} ({str(e)})",
|
||||
)
|
||||
else:
|
||||
return ORJSONResponse(ret)
|
||||
@ -722,7 +717,7 @@ class GlancesRestfulApi(object):
|
||||
if plugin not in self.plugins_list:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail="Unknown plugin %s (available plugins: %s)" % (plugin, self.plugins_list),
|
||||
detail=f"Unknown plugin {plugin} (available plugins: {self.plugins_list})",
|
||||
)
|
||||
|
||||
# Update the stat
|
||||
@ -734,7 +729,7 @@ class GlancesRestfulApi(object):
|
||||
except Exception as e:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
detail="Cannot get %s = %s for plugin %s (%s)" % (item, value, plugin, str(e)),
|
||||
detail=f"Cannot get {item} = {value} for plugin {plugin} ({str(e)})",
|
||||
)
|
||||
else:
|
||||
return ORJSONResponse(ret)
|
||||
@ -750,7 +745,7 @@ class GlancesRestfulApi(object):
|
||||
# Get the RAW value of the config' dict
|
||||
args_json = self.config.as_dict()
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Cannot get config (%s)" % str(e))
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f"Cannot get config ({str(e)})")
|
||||
else:
|
||||
return ORJSONResponse(args_json)
|
||||
|
||||
@ -764,16 +759,14 @@ class GlancesRestfulApi(object):
|
||||
"""
|
||||
config_dict = self.config.as_dict()
|
||||
if section not in config_dict:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST, detail="Unknown configuration item %s" % section
|
||||
)
|
||||
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=f"Unknown configuration item {section}")
|
||||
|
||||
try:
|
||||
# Get the RAW value of the config' dict
|
||||
ret_section = config_dict[section]
|
||||
except Exception as e:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND, detail="Cannot get config section %s (%s)" % (section, str(e))
|
||||
status_code=status.HTTP_404_NOT_FOUND, detail=f"Cannot get config section {section} ({str(e)})"
|
||||
)
|
||||
|
||||
return ORJSONResponse(ret_section)
|
||||
@ -788,16 +781,14 @@ class GlancesRestfulApi(object):
|
||||
"""
|
||||
config_dict = self.config.as_dict()
|
||||
if section not in config_dict:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST, detail="Unknown configuration item %s" % section
|
||||
)
|
||||
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=f"Unknown configuration item {section}")
|
||||
|
||||
try:
|
||||
# Get the RAW value of the config' dict section
|
||||
ret_section = config_dict[section]
|
||||
except Exception as e:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND, detail="Cannot get config section %s (%s)" % (section, str(e))
|
||||
status_code=status.HTTP_404_NOT_FOUND, detail=f"Cannot get config section {section} ({str(e)})"
|
||||
)
|
||||
|
||||
try:
|
||||
@ -806,7 +797,7 @@ class GlancesRestfulApi(object):
|
||||
except Exception as e:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
detail="Cannot get item %s in config section %s (%s)" % (item, section, str(e)),
|
||||
detail=f"Cannot get item {item} in config section {section} ({str(e)})",
|
||||
)
|
||||
|
||||
return ORJSONResponse(ret_item)
|
||||
@ -824,7 +815,7 @@ class GlancesRestfulApi(object):
|
||||
# Source: https://docs.python.org/%s/library/functions.html#vars
|
||||
args_json = vars(self.args)
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Cannot get args (%s)" % str(e))
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f"Cannot get args ({str(e)})")
|
||||
|
||||
return ORJSONResponse(args_json)
|
||||
|
||||
@ -837,7 +828,7 @@ class GlancesRestfulApi(object):
|
||||
HTTP/404 if others error
|
||||
"""
|
||||
if item not in self.args:
|
||||
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="Unknown argument item %s" % item)
|
||||
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=f"Unknown argument item {item}")
|
||||
|
||||
try:
|
||||
# Get the RAW value of the args' dict
|
||||
@ -845,6 +836,6 @@ class GlancesRestfulApi(object):
|
||||
# Source: https://docs.python.org/%s/library/functions.html#vars
|
||||
args_json = vars(self.args)[item]
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Cannot get args item (%s)" % str(e))
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f"Cannot get args item ({str(e)})")
|
||||
|
||||
return ORJSONResponse(args_json)
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -9,8 +8,6 @@
|
||||
|
||||
"""Manage sparklines for Glances output."""
|
||||
|
||||
from __future__ import division, unicode_literals
|
||||
|
||||
import sys
|
||||
|
||||
from glances.globals import nativestr
|
||||
@ -21,17 +18,17 @@ sparklines_module = True
|
||||
try:
|
||||
from sparklines import sparklines
|
||||
except ImportError as e:
|
||||
logger.warning("Sparklines module not found ({})".format(e))
|
||||
logger.warning(f"Sparklines module not found ({e})")
|
||||
sparklines_module = False
|
||||
|
||||
try:
|
||||
'┌┬┐╔╦╗╒╤╕╓╥╖│║─═├┼┤╠╬╣╞╪╡╟╫╢└┴┘╚╩╝╘╧╛╙╨╜'.encode(sys.stdout.encoding)
|
||||
except (UnicodeEncodeError, TypeError) as e:
|
||||
logger.warning("UTF-8 is mandatory for sparklines ({})".format(e))
|
||||
logger.warning(f"UTF-8 is mandatory for sparklines ({e})")
|
||||
sparklines_module = False
|
||||
|
||||
|
||||
class Sparkline(object):
|
||||
class Sparkline:
|
||||
"""Manage sparklines (see https://pypi.org/project/sparklines/)."""
|
||||
|
||||
def __init__(self, size, pre_char='[', post_char=']', unit_char='%', display_value=True):
|
||||
@ -83,7 +80,7 @@ class Sparkline(object):
|
||||
if self.__display_value:
|
||||
percents_without_none = [x for x in self.percents if x is not None]
|
||||
if len(percents_without_none) > 0:
|
||||
ret = '{}{:5.1f}{}'.format(ret, percents_without_none[-1], self.__unit_char)
|
||||
ret = f'{ret}{percents_without_none[-1]:5.1f}{self.__unit_char}'
|
||||
ret = nativestr(ret)
|
||||
if overwrite and len(overwrite) < len(ret) - 6:
|
||||
ret = overwrite + ret[len(overwrite) :]
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -15,7 +14,7 @@ from glances.globals import printandflush
|
||||
from glances.logger import logger
|
||||
|
||||
|
||||
class GlancesStdout(object):
|
||||
class GlancesStdout:
|
||||
"""This class manages the Stdout display."""
|
||||
|
||||
def __init__(self, config=None, args=None):
|
||||
@ -65,9 +64,9 @@ class GlancesStdout(object):
|
||||
# With attribute
|
||||
if isinstance(stat, dict):
|
||||
try:
|
||||
printandflush("{}.{}: {}".format(plugin, attribute, stat[attribute]))
|
||||
printandflush(f"{plugin}.{attribute}: {stat[attribute]}")
|
||||
except KeyError as err:
|
||||
logger.error("Can not display stat {}.{} ({})".format(plugin, attribute, err))
|
||||
logger.error(f"Can not display stat {plugin}.{attribute} ({err})")
|
||||
elif isinstance(stat, list):
|
||||
for i in stat:
|
||||
if key is None:
|
||||
@ -77,12 +76,12 @@ class GlancesStdout(object):
|
||||
else:
|
||||
continue
|
||||
try:
|
||||
printandflush("{}.{}.{}: {}".format(plugin, i_key, attribute, i[attribute]))
|
||||
printandflush(f"{plugin}.{i_key}.{attribute}: {i[attribute]}")
|
||||
except KeyError as err:
|
||||
logger.error("Can not display stat {}.{} ({})".format(plugin, attribute, err))
|
||||
logger.error(f"Can not display stat {plugin}.{attribute} ({err})")
|
||||
else:
|
||||
# Without attribute
|
||||
printandflush("{}: {}".format(plugin, stat))
|
||||
printandflush(f"{plugin}: {stat}")
|
||||
|
||||
# Wait until next refresh
|
||||
if duration > 0:
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -17,15 +16,15 @@ from glances import __apiversion__
|
||||
from glances.globals import iteritems
|
||||
from glances.logger import logger
|
||||
|
||||
API_URL = "http://localhost:61208/api/{api_version}".format(api_version=__apiversion__)
|
||||
API_URL = f"http://localhost:61208/api/{__apiversion__}"
|
||||
|
||||
APIDOC_HEADER = """\
|
||||
APIDOC_HEADER = f"""\
|
||||
.. _api:
|
||||
|
||||
API (Restfull/JSON) documentation
|
||||
=================================
|
||||
|
||||
This documentation describes the Glances API version {api_version} (Restfull/JSON) interface.
|
||||
This documentation describes the Glances API version {__apiversion__} (Restfull/JSON) interface.
|
||||
|
||||
For Glances version 3, please have a look on:
|
||||
``https://github.com/nicolargo/glances/blob/support/glancesv3/docs/api.rst``
|
||||
@ -44,7 +43,7 @@ It is also ran automatically when Glances is started in Web server mode (-w).
|
||||
API URL
|
||||
-------
|
||||
|
||||
The default root API URL is ``http://localhost:61208/api/{api_version}``.
|
||||
The default root API URL is ``http://localhost:61208/api/{__apiversion__}``.
|
||||
|
||||
The bind address and port could be changed using the ``--bind`` and ``--port`` command line options.
|
||||
|
||||
@ -59,7 +58,7 @@ For example:
|
||||
[outputs]
|
||||
url_prefix = /glances/
|
||||
|
||||
will change the root API URL to ``http://localhost:61208/glances/api/{api_version}`` and the Web UI URL to
|
||||
will change the root API URL to ``http://localhost:61208/glances/api/{__apiversion__}`` and the Web UI URL to
|
||||
``http://localhost:61208/glances/``
|
||||
|
||||
API documentation URL
|
||||
@ -74,7 +73,7 @@ WebUI refresh
|
||||
It is possible to change the Web UI refresh rate (default is 2 seconds) using the following option in the URL:
|
||||
``http://localhost:61208/glances/?refresh=5``
|
||||
|
||||
""".format(api_version=__apiversion__)
|
||||
"""
|
||||
|
||||
|
||||
def indent_stat(stat, indent=' '):
|
||||
@ -95,7 +94,7 @@ def print_api_status():
|
||||
print('')
|
||||
print('Get the Rest API status::')
|
||||
print('')
|
||||
print(' # curl -I {}/status'.format(API_URL))
|
||||
print(f' # curl -I {API_URL}/status')
|
||||
print(indent_stat('HTTP/1.0 200 OK'))
|
||||
print('')
|
||||
|
||||
@ -107,20 +106,20 @@ def print_plugins_list(stat):
|
||||
print('')
|
||||
print('Get the plugins list::')
|
||||
print('')
|
||||
print(' # curl {}/pluginslist'.format(API_URL))
|
||||
print(f' # curl {API_URL}/pluginslist')
|
||||
print(indent_stat(stat))
|
||||
print('')
|
||||
|
||||
|
||||
def print_plugin_stats(plugin, stat):
|
||||
sub_title = 'GET {}'.format(plugin)
|
||||
sub_title = f'GET {plugin}'
|
||||
print(sub_title)
|
||||
print('-' * len(sub_title))
|
||||
print('')
|
||||
|
||||
print('Get plugin stats::')
|
||||
print('')
|
||||
print(' # curl {}/{}'.format(API_URL, plugin))
|
||||
print(f' # curl {API_URL}/{plugin}')
|
||||
print(indent_stat(json.loads(stat.get_stats())))
|
||||
print('')
|
||||
|
||||
@ -179,7 +178,7 @@ def print_plugin_description(plugin, stat):
|
||||
|
||||
print('')
|
||||
else:
|
||||
logger.error('No fields_description variable defined for plugin {}'.format(plugin))
|
||||
logger.error(f'No fields_description variable defined for plugin {plugin}')
|
||||
|
||||
|
||||
def print_plugin_item_value(plugin, stat, stat_export):
|
||||
@ -201,13 +200,13 @@ def print_plugin_item_value(plugin, stat, stat_export):
|
||||
value = stat_item[item]
|
||||
print('Get a specific field::')
|
||||
print('')
|
||||
print(' # curl {}/{}/{}'.format(API_URL, plugin, item))
|
||||
print(f' # curl {API_URL}/{plugin}/{item}')
|
||||
print(indent_stat(stat_item))
|
||||
print('')
|
||||
if item and value and stat.get_stats_value(item, value):
|
||||
print('Get a specific item when field matches the given value::')
|
||||
print('')
|
||||
print(' # curl {}/{}/{}/{}'.format(API_URL, plugin, item, value))
|
||||
print(f' # curl {API_URL}/{plugin}/{item}/{value}')
|
||||
print(indent_stat(json.loads(stat.get_stats_value(item, value))))
|
||||
print('')
|
||||
|
||||
@ -219,7 +218,7 @@ def print_all():
|
||||
print('')
|
||||
print('Get all Glances stats::')
|
||||
print('')
|
||||
print(' # curl {}/all'.format(API_URL))
|
||||
print(f' # curl {API_URL}/all')
|
||||
print(' Return a very big dictionary (avoid using this request, performances will be poor)...')
|
||||
print('')
|
||||
|
||||
@ -233,7 +232,7 @@ def print_top(stats):
|
||||
print('')
|
||||
print('Get top 2 processes of the processlist plugin::')
|
||||
print('')
|
||||
print(' # curl {}/processlist/top/2'.format(API_URL))
|
||||
print(f' # curl {API_URL}/processlist/top/2')
|
||||
print(indent_stat(stats.get_plugin('processlist').get_export()[:2]))
|
||||
print('')
|
||||
print('Note: Only work for plugin with a list of items')
|
||||
@ -246,7 +245,7 @@ def print_fields_info(stats):
|
||||
print('-' * len(sub_title))
|
||||
print('Get item description (human readable) for a specific plugin/item::')
|
||||
print('')
|
||||
print(' # curl {}/diskio/read_bytes/description'.format(API_URL))
|
||||
print(f' # curl {API_URL}/diskio/read_bytes/description')
|
||||
print(indent_stat(stats.get_plugin('diskio').get_item_info('read_bytes', 'description')))
|
||||
print('')
|
||||
print('Note: the description is defined in the fields_description variable of the plugin.')
|
||||
@ -256,7 +255,7 @@ def print_fields_info(stats):
|
||||
print('-' * len(sub_title))
|
||||
print('Get item unit for a specific plugin/item::')
|
||||
print('')
|
||||
print(' # curl {}/diskio/read_bytes/unit'.format(API_URL))
|
||||
print(f' # curl {API_URL}/diskio/read_bytes/unit')
|
||||
print(indent_stat(stats.get_plugin('diskio').get_item_info('read_bytes', 'unit')))
|
||||
print('')
|
||||
print('Note: the description is defined in the fields_description variable of the plugin.')
|
||||
@ -274,22 +273,22 @@ def print_history(stats):
|
||||
print('')
|
||||
print('History of a plugin::')
|
||||
print('')
|
||||
print(' # curl {}/cpu/history'.format(API_URL))
|
||||
print(f' # curl {API_URL}/cpu/history')
|
||||
print(indent_stat(json.loads(stats.get_plugin('cpu').get_stats_history(nb=3))))
|
||||
print('')
|
||||
print('Limit history to last 2 values::')
|
||||
print('')
|
||||
print(' # curl {}/cpu/history/2'.format(API_URL))
|
||||
print(f' # curl {API_URL}/cpu/history/2')
|
||||
print(indent_stat(json.loads(stats.get_plugin('cpu').get_stats_history(nb=2))))
|
||||
print('')
|
||||
print('History for a specific field::')
|
||||
print('')
|
||||
print(' # curl {}/cpu/system/history'.format(API_URL))
|
||||
print(f' # curl {API_URL}/cpu/system/history')
|
||||
print(indent_stat(json.loads(stats.get_plugin('cpu').get_stats_history('system'))))
|
||||
print('')
|
||||
print('Limit history for a specific field to last 2 values::')
|
||||
print('')
|
||||
print(' # curl {}/cpu/system/history'.format(API_URL))
|
||||
print(f' # curl {API_URL}/cpu/system/history')
|
||||
print(indent_stat(json.loads(stats.get_plugin('cpu').get_stats_history('system', nb=2))))
|
||||
print('')
|
||||
|
||||
@ -301,17 +300,17 @@ def print_limits(stats):
|
||||
print('')
|
||||
print('All limits/thresholds::')
|
||||
print('')
|
||||
print(' # curl {}/all/limits'.format(API_URL))
|
||||
print(f' # curl {API_URL}/all/limits')
|
||||
print(indent_stat(stats.getAllLimitsAsDict()))
|
||||
print('')
|
||||
print('Limits/thresholds for the cpu plugin::')
|
||||
print('')
|
||||
print(' # curl {}/cpu/limits'.format(API_URL))
|
||||
print(f' # curl {API_URL}/cpu/limits')
|
||||
print(indent_stat(stats.get_plugin('cpu').limits))
|
||||
print('')
|
||||
|
||||
|
||||
class GlancesStdoutApiDoc(object):
|
||||
class GlancesStdoutApiDoc:
|
||||
"""This class manages the fields description display."""
|
||||
|
||||
def __init__(self, config=None, args=None):
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -14,7 +13,7 @@ import time
|
||||
from glances.globals import printandflush
|
||||
|
||||
|
||||
class GlancesStdoutCsv(object):
|
||||
class GlancesStdoutCsv:
|
||||
"""This class manages the StdoutCsv display."""
|
||||
|
||||
separator = ','
|
||||
@ -53,18 +52,18 @@ class GlancesStdoutCsv(object):
|
||||
line = ''
|
||||
|
||||
if attribute is not None:
|
||||
line += '{}.{}{}'.format(plugin, attribute, self.separator)
|
||||
line += f'{plugin}.{attribute}{self.separator}'
|
||||
else:
|
||||
if isinstance(stat, dict):
|
||||
for k in stat.keys():
|
||||
line += '{}.{}{}'.format(plugin, str(k), self.separator)
|
||||
line += f'{plugin}.{str(k)}{self.separator}'
|
||||
elif isinstance(stat, list):
|
||||
for i in stat:
|
||||
if isinstance(i, dict) and 'key' in i:
|
||||
for k in i.keys():
|
||||
line += '{}.{}.{}{}'.format(plugin, str(i[i['key']]), str(k), self.separator)
|
||||
else:
|
||||
line += '{}{}'.format(plugin, self.separator)
|
||||
line += f'{plugin}{self.separator}'
|
||||
|
||||
return line
|
||||
|
||||
@ -73,18 +72,18 @@ class GlancesStdoutCsv(object):
|
||||
line = ''
|
||||
|
||||
if attribute is not None:
|
||||
line += '{}{}'.format(str(stat.get(attribute, self.na)), self.separator)
|
||||
line += f'{str(stat.get(attribute, self.na))}{self.separator}'
|
||||
else:
|
||||
if isinstance(stat, dict):
|
||||
for v in stat.values():
|
||||
line += '{}{}'.format(str(v), self.separator)
|
||||
line += f'{str(v)}{self.separator}'
|
||||
elif isinstance(stat, list):
|
||||
for i in stat:
|
||||
if isinstance(i, dict) and 'key' in i:
|
||||
for v in i.values():
|
||||
line += '{}{}'.format(str(v), self.separator)
|
||||
line += f'{str(v)}{self.separator}'
|
||||
else:
|
||||
line += '{}{}'.format(str(stat), self.separator)
|
||||
line += f'{str(stat)}{self.separator}'
|
||||
|
||||
return line
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -39,7 +38,7 @@ class colors:
|
||||
self.NO = ''
|
||||
|
||||
|
||||
class GlancesStdoutIssue(object):
|
||||
class GlancesStdoutIssue:
|
||||
"""This class manages the Issue display."""
|
||||
|
||||
def __init__(self, config=None, args=None):
|
||||
@ -52,18 +51,14 @@ class GlancesStdoutIssue(object):
|
||||
|
||||
def print_version(self):
|
||||
sys.stdout.write('=' * TERMINAL_WIDTH + '\n')
|
||||
sys.stdout.write(
|
||||
'Glances {} ({})\n'.format(colors.BLUE + __version__ + colors.NO, os.path.realpath(glances.__file__))
|
||||
)
|
||||
sys.stdout.write('Python {} ({})\n'.format(colors.BLUE + platform.python_version() + colors.NO, sys.executable))
|
||||
sys.stdout.write(
|
||||
'PsUtil {} ({})\n'.format(colors.BLUE + psutil_version + colors.NO, os.path.realpath(psutil.__file__))
|
||||
)
|
||||
sys.stdout.write(f'Glances {colors.BLUE + __version__ + colors.NO} ({os.path.realpath(glances.__file__)})\n')
|
||||
sys.stdout.write(f'Python {colors.BLUE + platform.python_version() + colors.NO} ({sys.executable})\n')
|
||||
sys.stdout.write(f'PsUtil {colors.BLUE + psutil_version + colors.NO} ({os.path.realpath(psutil.__file__)})\n')
|
||||
sys.stdout.write('=' * TERMINAL_WIDTH + '\n')
|
||||
sys.stdout.flush()
|
||||
|
||||
def print_issue(self, plugin, result, message):
|
||||
sys.stdout.write('{}{}{}'.format(colors.BLUE + plugin, result, message))
|
||||
sys.stdout.write(f'{colors.BLUE + plugin}{result}{message}')
|
||||
sys.stdout.write(colors.NO + '\n')
|
||||
sys.stdout.flush()
|
||||
|
||||
@ -108,9 +103,7 @@ class GlancesStdoutIssue(object):
|
||||
except Exception as e:
|
||||
stat_error = e
|
||||
if stat_error is None:
|
||||
result = (colors.GREEN + '[OK] ' + colors.BLUE + ' {:.5f}s '.format(counter.get())).rjust(
|
||||
41 - len(plugin)
|
||||
)
|
||||
result = (colors.GREEN + '[OK] ' + colors.BLUE + f' {counter.get():.5f}s ').rjust(41 - len(plugin))
|
||||
if isinstance(stat, list) and len(stat) > 0 and 'key' in stat[0]:
|
||||
key = 'key={} '.format(stat[0]['key'])
|
||||
stat_output = pprint.pformat([stat[0]], compact=True, width=120, depth=3)
|
||||
@ -118,9 +111,7 @@ class GlancesStdoutIssue(object):
|
||||
else:
|
||||
message = '\n' + colors.NO + pprint.pformat(stat, compact=True, width=120, depth=2)
|
||||
else:
|
||||
result = (colors.RED + '[ERROR]' + colors.BLUE + ' {:.5f}s '.format(counter.get())).rjust(
|
||||
41 - len(plugin)
|
||||
)
|
||||
result = (colors.RED + '[ERROR]' + colors.BLUE + f' {counter.get():.5f}s ').rjust(41 - len(plugin))
|
||||
message = colors.NO + str(stat_error)[0 : TERMINAL_WIDTH - 41]
|
||||
|
||||
# Display the result
|
||||
@ -128,7 +119,7 @@ class GlancesStdoutIssue(object):
|
||||
|
||||
# Display total time need to update all plugins
|
||||
sys.stdout.write('=' * TERMINAL_WIDTH + '\n')
|
||||
print("Total time to update all stats: {}{:.5f}s{}".format(colors.BLUE, counter_total.get(), colors.NO))
|
||||
print(f"Total time to update all stats: {colors.BLUE}{counter_total.get():.5f}s{colors.NO}")
|
||||
sys.stdout.write('=' * TERMINAL_WIDTH + '\n')
|
||||
|
||||
# Return True to exit directly (no refresh)
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -14,7 +13,7 @@ import time
|
||||
from glances.globals import printandflush
|
||||
|
||||
|
||||
class GlancesStdoutJson(object):
|
||||
class GlancesStdoutJson:
|
||||
"""This class manages the Stdout JSON display."""
|
||||
|
||||
def __init__(self, config=None, args=None):
|
||||
@ -47,7 +46,7 @@ class GlancesStdoutJson(object):
|
||||
else:
|
||||
continue
|
||||
# Display stats
|
||||
printandflush('{}: {}'.format(plugin, stat))
|
||||
printandflush(f'{plugin}: {stat}')
|
||||
|
||||
# Wait until next refresh
|
||||
if duration > 0:
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -9,19 +8,19 @@
|
||||
|
||||
"""Manage password."""
|
||||
|
||||
import builtins
|
||||
import getpass
|
||||
import hashlib
|
||||
import os
|
||||
import sys
|
||||
import uuid
|
||||
from io import open
|
||||
|
||||
from glances.config import user_config_dir
|
||||
from glances.globals import b, safe_makedirs, weak_lru_cache
|
||||
from glances.logger import logger
|
||||
|
||||
|
||||
class GlancesPassword(object):
|
||||
class GlancesPassword:
|
||||
"""This class contains all the methods relating to password."""
|
||||
|
||||
def __init__(self, username='glances', config=None):
|
||||
@ -77,7 +76,7 @@ class GlancesPassword(object):
|
||||
"""
|
||||
if os.path.exists(self.password_file) and not clear:
|
||||
# If the password file exist then use it
|
||||
logger.info("Read password from file {}".format(self.password_file))
|
||||
logger.info(f"Read password from file {self.password_file}")
|
||||
password = self.load_password()
|
||||
else:
|
||||
# password_hash is the plain SHA-pbkdf2_hmac password
|
||||
@ -112,11 +111,11 @@ class GlancesPassword(object):
|
||||
safe_makedirs(self.password_dir)
|
||||
|
||||
# Create/overwrite the password file
|
||||
with open(self.password_file, 'wb') as file_pwd:
|
||||
with builtins.open(self.password_file, 'wb') as file_pwd:
|
||||
file_pwd.write(b(hashed_password))
|
||||
|
||||
def load_password(self):
|
||||
"""Load the hashed password from the Glances folder."""
|
||||
# Read the password file, if it exists
|
||||
with open(self.password_file, 'r') as file_pwd:
|
||||
with builtins.open(self.password_file) as file_pwd:
|
||||
return file_pwd.read()
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -19,7 +18,7 @@ class GlancesPasswordList(GlancesPassword):
|
||||
_section = "passwords"
|
||||
|
||||
def __init__(self, config=None, args=None):
|
||||
super(GlancesPasswordList, self).__init__()
|
||||
super().__init__()
|
||||
# password_dict is a dict (JSON compliant)
|
||||
# {'host': 'password', ... }
|
||||
# Load the configuration file
|
||||
@ -32,14 +31,14 @@ class GlancesPasswordList(GlancesPassword):
|
||||
if config is None:
|
||||
logger.warning("No configuration file available. Cannot load password list.")
|
||||
elif not config.has_section(self._section):
|
||||
logger.warning("No [%s] section in the configuration file. Cannot load password list." % self._section)
|
||||
logger.warning(f"No [{self._section}] section in the configuration file. Cannot load password list.")
|
||||
else:
|
||||
logger.info("Start reading the [%s] section in the configuration file" % self._section)
|
||||
logger.info(f"Start reading the [{self._section}] section in the configuration file")
|
||||
|
||||
password_dict = dict(config.items(self._section))
|
||||
|
||||
# Password list loaded
|
||||
logger.info("%s password(s) loaded from the configuration file" % len(password_dict))
|
||||
logger.info(f"{len(password_dict)} password(s) loaded from the configuration file")
|
||||
|
||||
return password_dict
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -101,9 +100,7 @@ class PluginModel(GlancesPluginModel):
|
||||
|
||||
def __init__(self, args=None, config=None):
|
||||
"""Init the plugin."""
|
||||
super(PluginModel, self).__init__(
|
||||
args=args, config=config, stats_init_value=[], fields_description=fields_description
|
||||
)
|
||||
super().__init__(args=args, config=config, stats_init_value=[], fields_description=fields_description)
|
||||
|
||||
# We want to display the stat in the curse interface
|
||||
self.display_curse = True
|
||||
@ -174,7 +171,7 @@ class PluginModel(GlancesPluginModel):
|
||||
# Top processes
|
||||
top_process = ', '.join(alert['top'])
|
||||
if top_process != '':
|
||||
msg = ': {}'.format(top_process)
|
||||
msg = f': {top_process}'
|
||||
ret.append(self.curse_add_line(msg))
|
||||
|
||||
return ret
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -35,9 +34,7 @@ class PluginModel(GlancesPluginModel):
|
||||
|
||||
def __init__(self, args=None, config=None):
|
||||
"""Init the plugin."""
|
||||
super(PluginModel, self).__init__(
|
||||
args=args, config=config, stats_init_value=[], fields_description=fields_description
|
||||
)
|
||||
super().__init__(args=args, config=config, stats_init_value=[], fields_description=fields_description)
|
||||
self.args = args
|
||||
self.config = config
|
||||
|
||||
@ -119,10 +116,10 @@ class PluginModel(GlancesPluginModel):
|
||||
second_column = '{}'.format(m['count'] if m['regex'] else '')
|
||||
for line in m['result'].split('\n'):
|
||||
# Display first column with the process name...
|
||||
msg = '{:<16} '.format(first_column)
|
||||
msg = f'{first_column:<16} '
|
||||
ret.append(self.curse_add_line(msg, first_column_style))
|
||||
# ... and second column with the number of matching processes...
|
||||
msg = '{:<4} '.format(second_column)
|
||||
msg = f'{second_column:<4} '
|
||||
ret.append(self.curse_add_line(msg))
|
||||
# ... only on the first line
|
||||
first_column = second_column = ''
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -26,7 +25,7 @@ try:
|
||||
except ImportError as e:
|
||||
import_error_tag = True
|
||||
# Display debug message if import error
|
||||
logger.warning("Missing Python Lib ({}), Cloud plugin is disabled".format(e))
|
||||
logger.warning(f"Missing Python Lib ({e}), Cloud plugin is disabled")
|
||||
else:
|
||||
import_error_tag = False
|
||||
|
||||
@ -44,7 +43,7 @@ class PluginModel(GlancesPluginModel):
|
||||
|
||||
def __init__(self, args=None, config=None):
|
||||
"""Init the plugin."""
|
||||
super(PluginModel, self).__init__(args=args, config=config)
|
||||
super().__init__(args=args, config=config)
|
||||
|
||||
# We want to display the stat in the curse interface
|
||||
self.display_curse = True
|
||||
@ -65,7 +64,7 @@ class PluginModel(GlancesPluginModel):
|
||||
self.OPENSTACK.stop()
|
||||
self.OPENSTACKEC2.stop()
|
||||
# Call the father class
|
||||
super(PluginModel, self).exit()
|
||||
super().exit()
|
||||
|
||||
@GlancesPluginModel._check_decorator
|
||||
@GlancesPluginModel._log_result_decorator
|
||||
@ -145,7 +144,7 @@ class ThreadOpenStack(threading.Thread):
|
||||
def __init__(self):
|
||||
"""Init the class."""
|
||||
logger.debug("cloud plugin - Create thread for OpenStack metadata")
|
||||
super(ThreadOpenStack, self).__init__()
|
||||
super().__init__()
|
||||
# Event needed to stop properly the thread
|
||||
self._stopper = threading.Event()
|
||||
# The class return the stats as a dict
|
||||
@ -161,12 +160,12 @@ class ThreadOpenStack(threading.Thread):
|
||||
return False
|
||||
|
||||
for k, v in iteritems(self.OPENSTACK_API_METADATA):
|
||||
r_url = '{}/{}'.format(self.OPENSTACK_API_URL, v)
|
||||
r_url = f'{self.OPENSTACK_API_URL}/{v}'
|
||||
try:
|
||||
# Local request, a timeout of 3 seconds is OK
|
||||
r = requests.get(r_url, timeout=3)
|
||||
except Exception as e:
|
||||
logger.debug('cloud plugin - Cannot connect to the OpenStack metadata API {}: {}'.format(r_url, e))
|
||||
logger.debug(f'cloud plugin - Cannot connect to the OpenStack metadata API {r_url}: {e}')
|
||||
break
|
||||
else:
|
||||
if r.ok:
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -9,8 +8,6 @@
|
||||
|
||||
"""Connections plugin."""
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import psutil
|
||||
|
||||
from glances.globals import nativestr
|
||||
@ -94,7 +91,7 @@ class PluginModel(GlancesPluginModel):
|
||||
|
||||
def __init__(self, args=None, config=None):
|
||||
"""Init the plugin."""
|
||||
super(PluginModel, self).__init__(
|
||||
super().__init__(
|
||||
args=args,
|
||||
config=config,
|
||||
# items_history_list=items_history_list,
|
||||
@ -123,7 +120,7 @@ class PluginModel(GlancesPluginModel):
|
||||
try:
|
||||
net_connections = psutil.net_connections(kind="tcp")
|
||||
except Exception as e:
|
||||
logger.warning('Can not get network connections stats ({})'.format(e))
|
||||
logger.warning(f'Can not get network connections stats ({e})')
|
||||
logger.info('Disable connections stats')
|
||||
stats['net_connections_enabled'] = False
|
||||
self.stats = stats
|
||||
@ -146,10 +143,10 @@ class PluginModel(GlancesPluginModel):
|
||||
# Grab connections track directly from the /proc file
|
||||
for i in self.conntrack:
|
||||
try:
|
||||
with open(self.conntrack[i], 'r') as f:
|
||||
with open(self.conntrack[i]) as f:
|
||||
stats[i] = float(f.readline().rstrip("\n"))
|
||||
except (IOError, FileNotFoundError) as e:
|
||||
logger.warning('Can not get network connections track ({})'.format(e))
|
||||
except (OSError, FileNotFoundError) as e:
|
||||
logger.warning(f'Can not get network connections track ({e})')
|
||||
logger.info('Disable connections track')
|
||||
stats['nf_conntrack_enabled'] = False
|
||||
self.stats = stats
|
||||
@ -172,7 +169,7 @@ class PluginModel(GlancesPluginModel):
|
||||
def update_views(self):
|
||||
"""Update stats views."""
|
||||
# Call the father's method
|
||||
super(PluginModel, self).update_views()
|
||||
super().update_views()
|
||||
|
||||
# Add specific information
|
||||
try:
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -127,7 +126,7 @@ class PluginModel(GlancesPluginModel):
|
||||
|
||||
def __init__(self, args=None, config=None):
|
||||
"""Init the plugin."""
|
||||
super(PluginModel, self).__init__(
|
||||
super().__init__(
|
||||
args=args, config=config, items_history_list=items_history_list, fields_description=fields_description
|
||||
)
|
||||
|
||||
@ -173,7 +172,7 @@ class PluginModel(GlancesPluginModel):
|
||||
if self.podman_extension:
|
||||
self.podman_extension.stop()
|
||||
# Call the father class
|
||||
super(PluginModel, self).exit()
|
||||
super().exit()
|
||||
|
||||
def get_key(self):
|
||||
"""Return the key of the list."""
|
||||
@ -188,7 +187,7 @@ class PluginModel(GlancesPluginModel):
|
||||
try:
|
||||
ret = deepcopy(self.stats)
|
||||
except KeyError as e:
|
||||
logger.debug("docker plugin - Docker export error {}".format(e))
|
||||
logger.debug(f"docker plugin - Docker export error {e}")
|
||||
ret = []
|
||||
|
||||
# Remove fields uses to compute rate
|
||||
@ -260,7 +259,7 @@ class PluginModel(GlancesPluginModel):
|
||||
def update_views(self):
|
||||
"""Update stats views."""
|
||||
# Call the father's method
|
||||
super(PluginModel, self).update_views()
|
||||
super().update_views()
|
||||
|
||||
if not self.stats:
|
||||
return False
|
||||
@ -319,9 +318,9 @@ class PluginModel(GlancesPluginModel):
|
||||
# Title
|
||||
msg = '{}'.format('CONTAINERS')
|
||||
ret.append(self.curse_add_line(msg, "TITLE"))
|
||||
msg = ' {}'.format(len(self.stats))
|
||||
msg = f' {len(self.stats)}'
|
||||
ret.append(self.curse_add_line(msg))
|
||||
msg = ' sorted by {}'.format(sort_for_human[self.sort_key])
|
||||
msg = f' sorted by {sort_for_human[self.sort_key]}'
|
||||
ret.append(self.curse_add_line(msg))
|
||||
ret.append(self.curse_new_line())
|
||||
# Header
|
||||
@ -402,13 +401,13 @@ class PluginModel(GlancesPluginModel):
|
||||
unit = 'B'
|
||||
try:
|
||||
value = self.auto_unit(int(container['io_rx'])) + unit
|
||||
msg = '{:>7}'.format(value)
|
||||
msg = f'{value:>7}'
|
||||
except (KeyError, TypeError):
|
||||
msg = '{:>7}'.format('_')
|
||||
ret.append(self.curse_add_line(msg))
|
||||
try:
|
||||
value = self.auto_unit(int(container['io_wx'])) + unit
|
||||
msg = ' {:<7}'.format(value)
|
||||
msg = f' {value:<7}'
|
||||
except (KeyError, TypeError):
|
||||
msg = ' {:<7}'.format('_')
|
||||
ret.append(self.curse_add_line(msg))
|
||||
@ -423,13 +422,13 @@ class PluginModel(GlancesPluginModel):
|
||||
unit = 'b'
|
||||
try:
|
||||
value = self.auto_unit(int(container['network_rx'] * to_bit)) + unit
|
||||
msg = '{:>7}'.format(value)
|
||||
msg = f'{value:>7}'
|
||||
except (KeyError, TypeError):
|
||||
msg = '{:>7}'.format('_')
|
||||
ret.append(self.curse_add_line(msg))
|
||||
try:
|
||||
value = self.auto_unit(int(container['network_tx'] * to_bit)) + unit
|
||||
msg = ' {:<7}'.format(value)
|
||||
msg = f' {value:<7}'
|
||||
except (KeyError, TypeError):
|
||||
msg = ' {:<7}'.format('_')
|
||||
ret.append(self.curse_add_line(msg))
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -24,7 +23,7 @@ try:
|
||||
except Exception as e:
|
||||
import_docker_error_tag = True
|
||||
# Display debug message if import KeyError
|
||||
logger.warning("Error loading Docker deps Lib. Docker plugin is disabled ({})".format(e))
|
||||
logger.warning(f"Error loading Docker deps Lib. Docker plugin is disabled ({e})")
|
||||
else:
|
||||
import_docker_error_tag = False
|
||||
|
||||
@ -47,7 +46,7 @@ class DockerStatsFetcher:
|
||||
self._streamer = StatsStreamer(stats_iterable, initial_stream_value={})
|
||||
|
||||
def _log_debug(self, msg, exception=None):
|
||||
logger.debug("containers (Docker) ID: {} - {} ({}) ".format(self._container.id, msg, exception))
|
||||
logger.debug(f"containers (Docker) ID: {self._container.id} - {msg} ({exception}) ")
|
||||
logger.debug(self._streamer.stats)
|
||||
|
||||
def stop(self):
|
||||
@ -229,7 +228,7 @@ class DockerContainersExtension:
|
||||
# Do not use the timeout option (see issue #1878)
|
||||
self.client = docker.from_env()
|
||||
except Exception as e:
|
||||
logger.error("{} plugin - Can't connect to Docker ({})".format(self.ext_name, e))
|
||||
logger.error(f"{self.ext_name} plugin - Can't connect to Docker ({e})")
|
||||
self.client = None
|
||||
|
||||
def update_version(self):
|
||||
@ -256,7 +255,7 @@ class DockerContainersExtension:
|
||||
# The Containers/all key of the configuration file should be set to True
|
||||
containers = self.client.containers.list(all=all_tag)
|
||||
except Exception as e:
|
||||
logger.error("{} plugin - Can't get containers list ({})".format(self.ext_name, e))
|
||||
logger.error(f"{self.ext_name} plugin - Can't get containers list ({e})")
|
||||
return version_stats, []
|
||||
|
||||
# Start new thread for new container
|
||||
@ -264,14 +263,14 @@ class DockerContainersExtension:
|
||||
if container.id not in self.stats_fetchers:
|
||||
# StatsFetcher did not exist in the internal dict
|
||||
# Create it, add it to the internal dict
|
||||
logger.debug("{} plugin - Create thread for container {}".format(self.ext_name, container.id[:12]))
|
||||
logger.debug(f"{self.ext_name} plugin - Create thread for container {container.id[:12]}")
|
||||
self.stats_fetchers[container.id] = DockerStatsFetcher(container)
|
||||
|
||||
# Stop threads for non-existing containers
|
||||
absent_containers = set(iterkeys(self.stats_fetchers)) - set(c.id for c in containers)
|
||||
for container_id in absent_containers:
|
||||
# Stop the StatsFetcher
|
||||
logger.debug("{} plugin - Stop thread for old container {}".format(self.ext_name, container_id[:12]))
|
||||
logger.debug(f"{self.ext_name} plugin - Stop thread for old container {container_id[:12]}")
|
||||
self.stats_fetchers[container_id].stop()
|
||||
# Delete the StatsFetcher from the dict
|
||||
del self.stats_fetchers[container_id]
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -21,7 +20,7 @@ try:
|
||||
except Exception as e:
|
||||
import_podman_error_tag = True
|
||||
# Display debug message if import KeyError
|
||||
logger.warning("Error loading Podman deps Lib. Podman feature in the Containers plugin is disabled ({})".format(e))
|
||||
logger.warning(f"Error loading Podman deps Lib. Podman feature in the Containers plugin is disabled ({e})")
|
||||
else:
|
||||
import_podman_error_tag = False
|
||||
|
||||
@ -37,7 +36,7 @@ class PodmanContainerStatsFetcher:
|
||||
self._streamer = StatsStreamer(stats_iterable, initial_stream_value={})
|
||||
|
||||
def _log_debug(self, msg, exception=None):
|
||||
logger.debug("containers (Podman) ID: {} - {} ({})".format(self._container.id, msg, exception))
|
||||
logger.debug(f"containers (Podman) ID: {self._container.id} - {msg} ({exception})")
|
||||
logger.debug(self._streamer.stats)
|
||||
|
||||
def stop(self):
|
||||
@ -96,7 +95,7 @@ class PodmanPodStatsFetcher:
|
||||
self._streamer = StatsStreamer(stats_iterable, initial_stream_value={}, sleep_duration=2)
|
||||
|
||||
def _log_debug(self, msg, exception=None):
|
||||
logger.debug("containers (Podman): Pod Manager - {} ({})".format(msg, exception))
|
||||
logger.debug(f"containers (Podman): Pod Manager - {msg} ({exception})")
|
||||
logger.debug(self._streamer.stats)
|
||||
|
||||
def stop(self):
|
||||
@ -235,7 +234,7 @@ class PodmanContainersExtension:
|
||||
# PodmanClient works lazily, so make a ping to determine if socket is open
|
||||
self.client.ping()
|
||||
except Exception as e:
|
||||
logger.debug("{} plugin - Can't connect to Podman ({})".format(self.ext_name, e))
|
||||
logger.debug(f"{self.ext_name} plugin - Can't connect to Podman ({e})")
|
||||
self.client = None
|
||||
|
||||
def update_version(self):
|
||||
@ -267,7 +266,7 @@ class PodmanContainersExtension:
|
||||
if not self.pods_stats_fetcher:
|
||||
self.pods_stats_fetcher = PodmanPodStatsFetcher(self.client.pods)
|
||||
except Exception as e:
|
||||
logger.error("{} plugin - Can't get containers list ({})".format(self.ext_name, e))
|
||||
logger.error(f"{self.ext_name} plugin - Can't get containers list ({e})")
|
||||
return version_stats, []
|
||||
|
||||
# Start new thread for new container
|
||||
@ -275,14 +274,14 @@ class PodmanContainersExtension:
|
||||
if container.id not in self.container_stats_fetchers:
|
||||
# StatsFetcher did not exist in the internal dict
|
||||
# Create it, add it to the internal dict
|
||||
logger.debug("{} plugin - Create thread for container {}".format(self.ext_name, container.id[:12]))
|
||||
logger.debug(f"{self.ext_name} plugin - Create thread for container {container.id[:12]}")
|
||||
self.container_stats_fetchers[container.id] = PodmanContainerStatsFetcher(container)
|
||||
|
||||
# Stop threads for non-existing containers
|
||||
absent_containers = set(iterkeys(self.container_stats_fetchers)) - set(c.id for c in containers)
|
||||
for container_id in absent_containers:
|
||||
# Stop the StatsFetcher
|
||||
logger.debug("{} plugin - Stop thread for old container {}".format(self.ext_name, container_id[:12]))
|
||||
logger.debug(f"{self.ext_name} plugin - Stop thread for old container {container_id[:12]}")
|
||||
self.container_stats_fetchers[container_id].stop()
|
||||
# Delete the StatsFetcher from the dict
|
||||
del self.container_stats_fetchers[container_id]
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -63,7 +62,7 @@ class StatsStreamer:
|
||||
break
|
||||
|
||||
except Exception as e:
|
||||
logger.debug("docker plugin - Exception thrown during run ({})".format(e))
|
||||
logger.debug(f"docker plugin - Exception thrown during run ({e})")
|
||||
self.stop()
|
||||
|
||||
def _pre_update_hook(self):
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -34,7 +33,7 @@ class PluginModel(GlancesPluginModel):
|
||||
|
||||
def __init__(self, args=None, config=None):
|
||||
"""Init the plugin."""
|
||||
super(PluginModel, self).__init__(args=args, config=config, fields_description=fields_description)
|
||||
super().__init__(args=args, config=config, fields_description=fields_description)
|
||||
|
||||
# We dot not want to display the stat in the curse interface
|
||||
# The core number is displayed by the load plugin
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -144,7 +143,7 @@ class PluginModel(GlancesPluginModel):
|
||||
|
||||
def __init__(self, args=None, config=None):
|
||||
"""Init the CPU plugin."""
|
||||
super(PluginModel, self).__init__(
|
||||
super().__init__(
|
||||
args=args, config=config, items_history_list=items_history_list, fields_description=fields_description
|
||||
)
|
||||
|
||||
@ -273,7 +272,7 @@ class PluginModel(GlancesPluginModel):
|
||||
def update_views(self):
|
||||
"""Update stats views."""
|
||||
# Call the father's method
|
||||
super(PluginModel, self).update_views()
|
||||
super().update_views()
|
||||
|
||||
# Add specifics information
|
||||
# Alert and log
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -9,8 +8,6 @@
|
||||
|
||||
"""Disk I/O plugin."""
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import psutil
|
||||
|
||||
from glances.globals import nativestr
|
||||
@ -62,7 +59,7 @@ class PluginModel(GlancesPluginModel):
|
||||
|
||||
def __init__(self, args=None, config=None):
|
||||
"""Init the plugin."""
|
||||
super(PluginModel, self).__init__(
|
||||
super().__init__(
|
||||
args=args,
|
||||
config=config,
|
||||
items_history_list=items_history_list,
|
||||
@ -142,7 +139,7 @@ class PluginModel(GlancesPluginModel):
|
||||
def update_views(self):
|
||||
"""Update stats views."""
|
||||
# Call the father's method
|
||||
super(PluginModel, self).update_views()
|
||||
super().update_views()
|
||||
|
||||
# Check if the stats should be hidden
|
||||
self.update_views_hidden()
|
||||
@ -172,7 +169,7 @@ class PluginModel(GlancesPluginModel):
|
||||
name_max_width = max_width - 13
|
||||
else:
|
||||
# No max_width defined, return an emptu curse message
|
||||
logger.debug("No max_width defined for the {} plugin, it will not be displayed.".format(self.plugin_name))
|
||||
logger.debug(f"No max_width defined for the {self.plugin_name} plugin, it will not be displayed.")
|
||||
return ret
|
||||
|
||||
# Header
|
||||
@ -206,13 +203,13 @@ class PluginModel(GlancesPluginModel):
|
||||
# count
|
||||
txps = self.auto_unit(i.get('read_count_rate_per_sec', None))
|
||||
rxps = self.auto_unit(i.get('write_count_rate_per_sec', None))
|
||||
msg = '{:>7}'.format(txps)
|
||||
msg = f'{txps:>7}'
|
||||
ret.append(
|
||||
self.curse_add_line(
|
||||
msg, self.get_views(item=i[self.get_key()], key='read_count', option='decoration')
|
||||
)
|
||||
)
|
||||
msg = '{:>7}'.format(rxps)
|
||||
msg = f'{rxps:>7}'
|
||||
ret.append(
|
||||
self.curse_add_line(
|
||||
msg, self.get_views(item=i[self.get_key()], key='write_count', option='decoration')
|
||||
@ -222,13 +219,13 @@ class PluginModel(GlancesPluginModel):
|
||||
# Bitrate
|
||||
txps = self.auto_unit(i.get('read_bytes_rate_per_sec', None))
|
||||
rxps = self.auto_unit(i.get('write_bytes_rate_per_sec', None))
|
||||
msg = '{:>7}'.format(txps)
|
||||
msg = f'{txps:>7}'
|
||||
ret.append(
|
||||
self.curse_add_line(
|
||||
msg, self.get_views(item=i[self.get_key()], key='read_bytes', option='decoration')
|
||||
)
|
||||
)
|
||||
msg = '{:>7}'.format(rxps)
|
||||
msg = f'{rxps:>7}'
|
||||
ret.append(
|
||||
self.curse_add_line(
|
||||
msg, self.get_views(item=i[self.get_key()], key='write_bytes', option='decoration')
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -9,8 +8,6 @@
|
||||
|
||||
"""Folder plugin."""
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from glances.folder_list import FolderList as glancesFolderList
|
||||
from glances.globals import nativestr
|
||||
from glances.logger import logger
|
||||
@ -56,9 +53,7 @@ class PluginModel(GlancesPluginModel):
|
||||
|
||||
def __init__(self, args=None, config=None):
|
||||
"""Init the plugin."""
|
||||
super(PluginModel, self).__init__(
|
||||
args=args, config=config, stats_init_value=[], fields_description=fields_description
|
||||
)
|
||||
super().__init__(args=args, config=config, stats_init_value=[], fields_description=fields_description)
|
||||
|
||||
self.args = args
|
||||
self.config = config
|
||||
@ -138,7 +133,7 @@ class PluginModel(GlancesPluginModel):
|
||||
name_max_width = max_width - 7
|
||||
else:
|
||||
# No max_width defined, return an emptu curse message
|
||||
logger.debug("No max_width defined for the {} plugin, it will not be displayed.".format(self.plugin_name))
|
||||
logger.debug(f"No max_width defined for the {self.plugin_name} plugin, it will not be displayed.")
|
||||
return ret
|
||||
|
||||
# Header
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -9,8 +8,6 @@
|
||||
|
||||
"""File system plugin."""
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import operator
|
||||
|
||||
import psutil
|
||||
@ -98,7 +95,7 @@ class PluginModel(GlancesPluginModel):
|
||||
|
||||
def __init__(self, args=None, config=None):
|
||||
"""Init the plugin."""
|
||||
super(PluginModel, self).__init__(
|
||||
super().__init__(
|
||||
args=args,
|
||||
config=config,
|
||||
items_history_list=items_history_list,
|
||||
@ -241,7 +238,7 @@ class PluginModel(GlancesPluginModel):
|
||||
def update_views(self):
|
||||
"""Update stats views."""
|
||||
# Call the father's method
|
||||
super(PluginModel, self).update_views()
|
||||
super().update_views()
|
||||
|
||||
# Add specifics information
|
||||
# Alert
|
||||
@ -264,7 +261,7 @@ class PluginModel(GlancesPluginModel):
|
||||
name_max_width = max_width - 13
|
||||
else:
|
||||
# No max_width defined, return an emptu curse message
|
||||
logger.debug("No max_width defined for the {} plugin, it will not be displayed.".format(self.plugin_name))
|
||||
logger.debug(f"No max_width defined for the {self.plugin_name} plugin, it will not be displayed.")
|
||||
return ret
|
||||
|
||||
# Build the string message
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -67,7 +66,7 @@ class PluginModel(GlancesPluginModel):
|
||||
|
||||
def __init__(self, args=None, config=None):
|
||||
"""Init the plugin."""
|
||||
super(PluginModel, self).__init__(
|
||||
super().__init__(
|
||||
args=args,
|
||||
config=config,
|
||||
items_history_list=items_history_list,
|
||||
@ -89,7 +88,7 @@ class PluginModel(GlancesPluginModel):
|
||||
self.amd.exit()
|
||||
|
||||
# Call the father exit method
|
||||
super(PluginModel, self).exit()
|
||||
super().exit()
|
||||
|
||||
def get_key(self):
|
||||
"""Return the key of the list."""
|
||||
@ -150,7 +149,7 @@ class PluginModel(GlancesPluginModel):
|
||||
def update_views(self):
|
||||
"""Update stats views."""
|
||||
# Call the father's method
|
||||
super(PluginModel, self).update_views()
|
||||
super().update_views()
|
||||
|
||||
# Add specifics information
|
||||
# Alert
|
||||
@ -190,7 +189,7 @@ class PluginModel(GlancesPluginModel):
|
||||
# Header
|
||||
header = ''
|
||||
if len(self.stats) > 1:
|
||||
header += '{}'.format(len(self.stats))
|
||||
header += f'{len(self.stats)}'
|
||||
if same_name:
|
||||
header += ' {}'.format(gpu_stats['name'])
|
||||
else:
|
||||
@ -213,7 +212,7 @@ class PluginModel(GlancesPluginModel):
|
||||
except TypeError:
|
||||
mean_proc_msg = '{:>4}'.format('N/A')
|
||||
else:
|
||||
mean_proc_msg = '{:>3.0f}%'.format(mean_proc)
|
||||
mean_proc_msg = f'{mean_proc:>3.0f}%'
|
||||
if len(self.stats) > 1:
|
||||
msg = '{:13}'.format('proc mean:')
|
||||
else:
|
||||
@ -232,7 +231,7 @@ class PluginModel(GlancesPluginModel):
|
||||
except TypeError:
|
||||
mean_mem_msg = '{:>4}'.format('N/A')
|
||||
else:
|
||||
mean_mem_msg = '{:>3.0f}%'.format(mean_mem)
|
||||
mean_mem_msg = f'{mean_mem:>3.0f}%'
|
||||
if len(self.stats) > 1:
|
||||
msg = '{:13}'.format('mem mean:')
|
||||
else:
|
||||
@ -255,7 +254,7 @@ class PluginModel(GlancesPluginModel):
|
||||
if args.fahrenheit:
|
||||
mean_temperature = to_fahrenheit(mean_temperature)
|
||||
unit = 'F'
|
||||
mean_temperature_msg = '{:>3.0f}{}'.format(mean_temperature, unit)
|
||||
mean_temperature_msg = f'{mean_temperature:>3.0f}{unit}'
|
||||
if len(self.stats) > 1:
|
||||
msg = '{:13}'.format('temp mean:')
|
||||
else:
|
||||
@ -283,7 +282,7 @@ class PluginModel(GlancesPluginModel):
|
||||
mem_msg = '{:>3.0f}%'.format(gpu_stats['mem'])
|
||||
except (ValueError, TypeError):
|
||||
mem_msg = '{:>4}'.format('N/A')
|
||||
msg = '{} {} mem {}'.format(id_msg, proc_msg, mem_msg)
|
||||
msg = f'{id_msg} {proc_msg} mem {mem_msg}'
|
||||
ret.append(self.curse_add_line(msg))
|
||||
|
||||
return ret
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -17,7 +16,7 @@ try:
|
||||
except Exception as e:
|
||||
nvidia_gpu_enable = False
|
||||
# Display debug message if import KeyError
|
||||
logger.warning("Missing Python Lib ({}), Nvidia GPU plugin is disabled".format(e))
|
||||
logger.warning(f"Missing Python Lib ({e}), Nvidia GPU plugin is disabled")
|
||||
else:
|
||||
nvidia_gpu_enable = True
|
||||
|
||||
@ -43,7 +42,7 @@ class NvidiaGPU:
|
||||
try:
|
||||
pynvml.nvmlShutdown()
|
||||
except Exception as e:
|
||||
logger.debug("pynvml failed to shutdown correctly ({})".format(e))
|
||||
logger.debug(f"pynvml failed to shutdown correctly ({e})")
|
||||
|
||||
def get_device_stats(self):
|
||||
"""Get Nvidia GPU stats."""
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -13,7 +12,6 @@ Help plugin.
|
||||
Just a stupid plugin to display the help screen.
|
||||
"""
|
||||
|
||||
import sys
|
||||
from itertools import chain
|
||||
|
||||
from glances import __version__, psutil_version
|
||||
@ -26,7 +24,7 @@ class PluginModel(GlancesPluginModel):
|
||||
|
||||
def __init__(self, args=None, config=None):
|
||||
"""Init the plugin."""
|
||||
super(PluginModel, self).__init__(args=args, config=config)
|
||||
super().__init__(args=args, config=config)
|
||||
|
||||
# Set the config instance
|
||||
self.config = config
|
||||
@ -36,12 +34,7 @@ class PluginModel(GlancesPluginModel):
|
||||
self.display_curse = True
|
||||
|
||||
# init data dictionary, to preserve insertion order
|
||||
if sys.version_info < (3, 6):
|
||||
from collections import OrderedDict
|
||||
|
||||
self.view_data = OrderedDict()
|
||||
else:
|
||||
self.view_data = {}
|
||||
self.view_data = {}
|
||||
self.generate_view_data()
|
||||
|
||||
def reset(self):
|
||||
@ -53,10 +46,10 @@ class PluginModel(GlancesPluginModel):
|
||||
def generate_view_data(self):
|
||||
"""Generate the views."""
|
||||
self.view_data['version'] = '{} {}'.format('Glances', __version__)
|
||||
self.view_data['psutil_version'] = ' with psutil {}'.format(psutil_version)
|
||||
self.view_data['psutil_version'] = f' with psutil {psutil_version}'
|
||||
|
||||
try:
|
||||
self.view_data['configuration_file'] = 'Configuration file: {}'.format(self.config.loaded_config_file)
|
||||
self.view_data['configuration_file'] = f'Configuration file: {self.config.loaded_config_file}'
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -23,7 +22,7 @@ try:
|
||||
import netifaces
|
||||
except ImportError as e:
|
||||
import_error_tag = True
|
||||
logger.warning("Missing Python Lib ({}), IP plugin is disabled".format(e))
|
||||
logger.warning(f"Missing Python Lib ({e}), IP plugin is disabled")
|
||||
else:
|
||||
import_error_tag = False
|
||||
|
||||
@ -66,7 +65,7 @@ class PluginModel(GlancesPluginModel):
|
||||
|
||||
def __init__(self, args=None, config=None):
|
||||
"""Init the plugin."""
|
||||
super(PluginModel, self).__init__(args=args, config=config, fields_description=fields_description)
|
||||
super().__init__(args=args, config=config, fields_description=fields_description)
|
||||
|
||||
# We want to display the stat in the curse interface
|
||||
self.display_curse = True
|
||||
@ -104,7 +103,7 @@ class PluginModel(GlancesPluginModel):
|
||||
try:
|
||||
default_gw = netifaces.gateways()['default'][netifaces.AF_INET]
|
||||
except (KeyError, AttributeError) as e:
|
||||
logger.debug("Cannot grab default gateway IP address ({})".format(e))
|
||||
logger.debug(f"Cannot grab default gateway IP address ({e})")
|
||||
return self.get_init_value()
|
||||
else:
|
||||
stats['gateway'] = default_gw[0]
|
||||
@ -113,7 +112,7 @@ class PluginModel(GlancesPluginModel):
|
||||
address = netifaces.ifaddresses(default_gw[1])[netifaces.AF_INET][0]['addr']
|
||||
mask = netifaces.ifaddresses(default_gw[1])[netifaces.AF_INET][0]['netmask']
|
||||
except (KeyError, AttributeError) as e:
|
||||
logger.debug("Cannot grab private IP address ({})".format(e))
|
||||
logger.debug(f"Cannot grab private IP address ({e})")
|
||||
return self.get_init_value()
|
||||
else:
|
||||
stats['address'] = address
|
||||
@ -129,7 +128,7 @@ class PluginModel(GlancesPluginModel):
|
||||
self.public_info = PublicIpInfo(self.public_api, self.public_username, self.public_password).get()
|
||||
self.public_address = self.public_info['ip']
|
||||
except (KeyError, AttributeError, TypeError) as e:
|
||||
logger.debug("Cannot grab public IP information ({})".format(e))
|
||||
logger.debug(f"Cannot grab public IP information ({e})")
|
||||
else:
|
||||
stats['public_address'] = (
|
||||
self.public_address if not self.args.hide_public_info else self.__hide_ip(self.public_address)
|
||||
@ -211,7 +210,7 @@ class PluginModel(GlancesPluginModel):
|
||||
return sum(bin(int(x)).count('1') for x in ip.split('.'))
|
||||
|
||||
|
||||
class PublicIpInfo(object):
|
||||
class PublicIpInfo:
|
||||
"""Get public IP information from online service."""
|
||||
|
||||
def __init__(self, url, username, password, timeout=2):
|
||||
@ -242,11 +241,11 @@ class PublicIpInfo(object):
|
||||
try:
|
||||
response = urlopen_auth(url, username, password).read()
|
||||
except Exception as e:
|
||||
logger.debug("IP plugin - Cannot get public IP information from {} ({})".format(url, e))
|
||||
logger.debug(f"IP plugin - Cannot get public IP information from {url} ({e})")
|
||||
queue_target.put(None)
|
||||
else:
|
||||
try:
|
||||
queue_target.put(loads(response))
|
||||
except (ValueError, KeyError) as e:
|
||||
logger.debug("IP plugin - Cannot load public IP information from {} ({})".format(url, e))
|
||||
logger.debug(f"IP plugin - Cannot load public IP information from {url} ({e})")
|
||||
queue_target.put(None)
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -42,9 +41,7 @@ class PluginModel(GlancesPluginModel):
|
||||
|
||||
def __init__(self, args=None, config=None):
|
||||
"""Init the plugin."""
|
||||
super(PluginModel, self).__init__(
|
||||
args=args, config=config, stats_init_value=[], fields_description=fields_description
|
||||
)
|
||||
super().__init__(args=args, config=config, stats_init_value=[], fields_description=fields_description)
|
||||
|
||||
# We want to display the stat in the curse interface
|
||||
self.display_curse = True
|
||||
@ -86,7 +83,7 @@ class PluginModel(GlancesPluginModel):
|
||||
def update_views(self):
|
||||
"""Update stats views."""
|
||||
# Call the father's method
|
||||
super(PluginModel, self).update_views()
|
||||
super().update_views()
|
||||
|
||||
def msg_curse(self, args=None, max_width=None):
|
||||
"""Return the dict to display in the curse interface."""
|
||||
@ -103,7 +100,7 @@ class PluginModel(GlancesPluginModel):
|
||||
name_max_width = max_width - 7
|
||||
else:
|
||||
# No max_width defined, return an emptu curse message
|
||||
logger.debug("No max_width defined for the {} plugin, it will not be displayed.".format(self.plugin_name))
|
||||
logger.debug(f"No max_width defined for the {self.plugin_name} plugin, it will not be displayed.")
|
||||
return ret
|
||||
|
||||
# Build the string message
|
||||
@ -123,7 +120,7 @@ class PluginModel(GlancesPluginModel):
|
||||
return ret
|
||||
|
||||
|
||||
class GlancesIRQ(object):
|
||||
class GlancesIRQ:
|
||||
"""This class manages the IRQ file."""
|
||||
|
||||
IRQ_FILE = '/proc/interrupts'
|
||||
@ -169,7 +166,7 @@ class GlancesIRQ(object):
|
||||
irq_line = splitted_line[0].replace(':', '')
|
||||
if irq_line.isdigit():
|
||||
# If the first column is a digit, use the alias (last column)
|
||||
irq_line += '_{}'.format(splitted_line[-1])
|
||||
irq_line += f'_{splitted_line[-1]}'
|
||||
return irq_line
|
||||
|
||||
def __sum(self, line):
|
||||
@ -216,7 +213,7 @@ class GlancesIRQ(object):
|
||||
}
|
||||
self.stats.append(irq_current)
|
||||
self.lasts[irq_line] = current_irqs
|
||||
except (OSError, IOError):
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
return self.stats
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -66,7 +65,7 @@ nb_phys_core = 1
|
||||
try:
|
||||
core = CorePluginModel().update()
|
||||
except Exception as e:
|
||||
logger.warning('Error: Can not retrieve the CPU core number (set it to 1) ({})'.format(e))
|
||||
logger.warning(f'Error: Can not retrieve the CPU core number (set it to 1) ({e})')
|
||||
else:
|
||||
if 'log' in core:
|
||||
nb_log_core = core['log']
|
||||
@ -82,7 +81,7 @@ class PluginModel(GlancesPluginModel):
|
||||
|
||||
def __init__(self, args=None, config=None):
|
||||
"""Init the plugin."""
|
||||
super(PluginModel, self).__init__(
|
||||
super().__init__(
|
||||
args=args, config=config, items_history_list=items_history_list, fields_description=fields_description
|
||||
)
|
||||
|
||||
@ -128,7 +127,7 @@ class PluginModel(GlancesPluginModel):
|
||||
def update_views(self):
|
||||
"""Update stats views."""
|
||||
# Call the father's method
|
||||
super(PluginModel, self).update_views()
|
||||
super().update_views()
|
||||
|
||||
# Add specifics information
|
||||
try:
|
||||
@ -164,17 +163,17 @@ class PluginModel(GlancesPluginModel):
|
||||
# Loop over 1min, 5min and 15min load
|
||||
for load_time in ['1', '5', '15']:
|
||||
ret.append(self.curse_new_line())
|
||||
msg = '{:7}'.format('{} min'.format(load_time))
|
||||
msg = '{:7}'.format(f'{load_time} min')
|
||||
ret.append(self.curse_add_line(msg))
|
||||
if args.disable_irix and get_nb_log_core() != 0:
|
||||
# Enable Irix mode for load (see issue #1554)
|
||||
load_stat = self.stats['min{}'.format(load_time)] / get_nb_log_core() * 100
|
||||
msg = '{:>5.1f}%'.format(load_stat)
|
||||
load_stat = self.stats[f'min{load_time}'] / get_nb_log_core() * 100
|
||||
msg = f'{load_stat:>5.1f}%'
|
||||
else:
|
||||
# Default mode for load
|
||||
load_stat = self.stats['min{}'.format(load_time)]
|
||||
msg = '{:>6.2f}'.format(load_stat)
|
||||
ret.append(self.curse_add_line(msg, self.get_views(key='min{}'.format(load_time), option='decoration')))
|
||||
load_stat = self.stats[f'min{load_time}']
|
||||
msg = f'{load_stat:>6.2f}'
|
||||
ret.append(self.curse_add_line(msg, self.get_views(key=f'min{load_time}', option='decoration')))
|
||||
|
||||
return ret
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -113,7 +112,7 @@ class PluginModel(GlancesPluginModel):
|
||||
|
||||
def __init__(self, args=None, config=None):
|
||||
"""Init the plugin."""
|
||||
super(PluginModel, self).__init__(
|
||||
super().__init__(
|
||||
args=args, config=config, items_history_list=items_history_list, fields_description=fields_description
|
||||
)
|
||||
|
||||
@ -219,7 +218,7 @@ class PluginModel(GlancesPluginModel):
|
||||
def update_views(self):
|
||||
"""Update stats views."""
|
||||
# Call the father's method
|
||||
super(PluginModel, self).update_views()
|
||||
super().update_views()
|
||||
|
||||
# Add specifics information
|
||||
# Alert and log
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -60,7 +59,7 @@ class PluginModel(GlancesPluginModel):
|
||||
|
||||
def __init__(self, args=None, config=None):
|
||||
"""Init the plugin."""
|
||||
super(PluginModel, self).__init__(
|
||||
super().__init__(
|
||||
args=args, config=config, items_history_list=items_history_list, fields_description=fields_description
|
||||
)
|
||||
|
||||
@ -145,7 +144,7 @@ class PluginModel(GlancesPluginModel):
|
||||
def update_views(self):
|
||||
"""Update stats views."""
|
||||
# Call the father's method
|
||||
super(PluginModel, self).update_views()
|
||||
super().update_views()
|
||||
|
||||
# Add specifics information
|
||||
# Alert and log
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -9,8 +8,6 @@
|
||||
|
||||
"""Network plugin."""
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import psutil
|
||||
|
||||
from glances.logger import logger
|
||||
@ -73,7 +70,7 @@ class PluginModel(GlancesPluginModel):
|
||||
|
||||
def __init__(self, args=None, config=None):
|
||||
"""Init the plugin."""
|
||||
super(PluginModel, self).__init__(
|
||||
super().__init__(
|
||||
args=args,
|
||||
config=config,
|
||||
items_history_list=items_history_list,
|
||||
@ -131,7 +128,7 @@ class PluginModel(GlancesPluginModel):
|
||||
try:
|
||||
net_io_counters = psutil.net_io_counters(pernic=True)
|
||||
except UnicodeDecodeError as e:
|
||||
logger.debug('Can not get network interface counters ({})'.format(e))
|
||||
logger.debug(f'Can not get network interface counters ({e})')
|
||||
return self.stats
|
||||
|
||||
# Grab interface's status (issue #765)
|
||||
@ -145,7 +142,7 @@ class PluginModel(GlancesPluginModel):
|
||||
net_status = psutil.net_if_stats()
|
||||
except OSError as e:
|
||||
# see psutil #797/glances #1106
|
||||
logger.debug('Can not get network interface status ({})'.format(e))
|
||||
logger.debug(f'Can not get network interface status ({e})')
|
||||
|
||||
for interface_name, interface_stat in net_io_counters.items():
|
||||
# Do not take hidden interface into account
|
||||
@ -181,7 +178,7 @@ class PluginModel(GlancesPluginModel):
|
||||
def update_views(self):
|
||||
"""Update stats views."""
|
||||
# Call the father's method
|
||||
super(PluginModel, self).update_views()
|
||||
super().update_views()
|
||||
|
||||
# Check if the stats should be hidden
|
||||
self.update_views_hidden()
|
||||
@ -227,7 +224,7 @@ class PluginModel(GlancesPluginModel):
|
||||
name_max_width = max_width - 12
|
||||
else:
|
||||
# No max_width defined, return an emptu curse message
|
||||
logger.debug("No max_width defined for the {} plugin, it will not be displayed.".format(self.plugin_name))
|
||||
logger.debug(f"No max_width defined for the {self.plugin_name} plugin, it will not be displayed.")
|
||||
return ret
|
||||
|
||||
# Header
|
||||
@ -301,16 +298,16 @@ class PluginModel(GlancesPluginModel):
|
||||
msg = '{:{width}}'.format(if_name, width=name_max_width)
|
||||
ret.append(self.curse_add_line(msg))
|
||||
if args.network_sum:
|
||||
msg = '{:>14}'.format(ax)
|
||||
msg = f'{ax:>14}'
|
||||
ret.append(self.curse_add_line(msg))
|
||||
else:
|
||||
msg = '{:>7}'.format(rx)
|
||||
msg = f'{rx:>7}'
|
||||
ret.append(
|
||||
self.curse_add_line(
|
||||
msg, self.get_views(item=i[self.get_key()], key='bytes_recv', option='decoration')
|
||||
)
|
||||
)
|
||||
msg = '{:>7}'.format(tx)
|
||||
msg = f'{tx:>7}'
|
||||
ret.append(
|
||||
self.curse_add_line(
|
||||
msg, self.get_views(item=i[self.get_key()], key='bytes_sent', option='decoration')
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -38,9 +37,7 @@ class PluginModel(GlancesPluginModel):
|
||||
|
||||
def __init__(self, args=None, config=None):
|
||||
"""Init the plugin."""
|
||||
super(PluginModel, self).__init__(
|
||||
args=args, config=config, fields_description=fields_description, stats_init_value={}
|
||||
)
|
||||
super().__init__(args=args, config=config, fields_description=fields_description, stats_init_value={})
|
||||
|
||||
# We want to display the stat in the curse interface
|
||||
self.display_curse = True
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -96,7 +95,7 @@ class PluginModel(GlancesPluginModel):
|
||||
|
||||
def __init__(self, args=None, config=None):
|
||||
"""Init the plugin."""
|
||||
super(PluginModel, self).__init__(
|
||||
super().__init__(
|
||||
args=args,
|
||||
config=config,
|
||||
items_history_list=items_history_list,
|
||||
@ -159,7 +158,7 @@ class PluginModel(GlancesPluginModel):
|
||||
for stat in header:
|
||||
if stat not in self.stats[0]:
|
||||
continue
|
||||
msg = '{:>7}'.format(stat)
|
||||
msg = f'{stat:>7}'
|
||||
ret.append(self.curse_add_line(msg))
|
||||
|
||||
# Manage the maximum number of CPU to display (related to enhancement request #2734)
|
||||
@ -176,9 +175,9 @@ class PluginModel(GlancesPluginModel):
|
||||
try:
|
||||
cpu_id = cpu[cpu['key']]
|
||||
if cpu_id < 10:
|
||||
msg = 'CPU{:1} '.format(cpu_id)
|
||||
msg = f'CPU{cpu_id:1} '
|
||||
else:
|
||||
msg = '{:4} '.format(cpu_id)
|
||||
msg = f'{cpu_id:4} '
|
||||
except TypeError:
|
||||
# TypeError: string indices must be integers (issue #1027)
|
||||
msg = '{:4} '.format('?')
|
||||
@ -187,7 +186,7 @@ class PluginModel(GlancesPluginModel):
|
||||
if stat not in self.stats[0]:
|
||||
continue
|
||||
try:
|
||||
msg = '{:6.1f}%'.format(cpu[stat])
|
||||
msg = f'{cpu[stat]:6.1f}%'
|
||||
except TypeError:
|
||||
msg = '{:>6}%'.format('?')
|
||||
ret.append(self.curse_add_line(msg, self.get_alert(cpu[stat], header=stat)))
|
||||
@ -204,7 +203,7 @@ class PluginModel(GlancesPluginModel):
|
||||
[i[stat] for i in percpu_list[0 : self.max_cpu_display]]
|
||||
)
|
||||
try:
|
||||
msg = '{:6.1f}%'.format(cpu_stat)
|
||||
msg = f'{cpu_stat:6.1f}%'
|
||||
except TypeError:
|
||||
msg = '{:>6}%'.format('?')
|
||||
ret.append(self.curse_add_line(msg, self.get_alert(cpu_stat, header=stat)))
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -43,7 +42,7 @@ fields_unit_type = {
|
||||
}
|
||||
|
||||
|
||||
class GlancesPluginModel(object):
|
||||
class GlancesPluginModel:
|
||||
"""Main class for Glances plugin model."""
|
||||
|
||||
def __init__(self, args=None, config=None, items_history_list=None, stats_init_value={}, fields_description=None):
|
||||
@ -77,7 +76,7 @@ class GlancesPluginModel(object):
|
||||
|
||||
if self.plugin_name.startswith('glances_'):
|
||||
self.plugin_name = self.plugin_name.split('glances_')[1]
|
||||
logger.debug("Init {} plugin".format(self.plugin_name))
|
||||
logger.debug(f"Init {self.plugin_name} plugin")
|
||||
|
||||
# Init the args
|
||||
self.args = args
|
||||
@ -96,7 +95,7 @@ class GlancesPluginModel(object):
|
||||
# Init the limits (configuration keys) dictionary
|
||||
self._limits = dict()
|
||||
if config is not None:
|
||||
logger.debug('Load section {} in {}'.format(self.plugin_name, config.config_file_paths()))
|
||||
logger.debug(f'Load section {self.plugin_name} in {config.config_file_paths()}')
|
||||
self.load_limits(config=config)
|
||||
|
||||
# Init the alias (dictionnary)
|
||||
@ -147,7 +146,7 @@ class GlancesPluginModel(object):
|
||||
|
||||
def exit(self):
|
||||
"""Just log an event when Glances exit."""
|
||||
logger.debug("Stop the {} plugin".format(self.plugin_name))
|
||||
logger.debug(f"Stop the {self.plugin_name} plugin")
|
||||
|
||||
def get_key(self):
|
||||
"""Return the key of the list."""
|
||||
@ -174,14 +173,14 @@ class GlancesPluginModel(object):
|
||||
"""Init the stats history (dict of GlancesAttribute)."""
|
||||
if self.history_enable():
|
||||
init_list = [a['name'] for a in self.get_items_history_list()]
|
||||
logger.debug("Stats history activated for plugin {} (items: {})".format(self.plugin_name, init_list))
|
||||
logger.debug(f"Stats history activated for plugin {self.plugin_name} (items: {init_list})")
|
||||
return GlancesHistory()
|
||||
|
||||
def reset_stats_history(self):
|
||||
"""Reset the stats history (dict of GlancesAttribute)."""
|
||||
if self.history_enable():
|
||||
reset_list = [a['name'] for a in self.get_items_history_list()]
|
||||
logger.debug("Reset history for plugin {} (items: {})".format(self.plugin_name, reset_list))
|
||||
logger.debug(f"Reset history for plugin {self.plugin_name} (items: {reset_list})")
|
||||
self.stats_history.reset()
|
||||
|
||||
def update_stats_history(self):
|
||||
@ -414,7 +413,7 @@ class GlancesPluginModel(object):
|
||||
try:
|
||||
return {value: [i for i in self.get_raw() if i[item] == value]}
|
||||
except (KeyError, ValueError) as e:
|
||||
logger.error("Cannot get item({})=value({}) ({})".format(item, value, e))
|
||||
logger.error(f"Cannot get item({item})=value({value}) ({e})")
|
||||
return None
|
||||
|
||||
def get_stats_value(self, item, value):
|
||||
@ -582,7 +581,7 @@ class GlancesPluginModel(object):
|
||||
self._limits[limit] = config.get_float_value(self.plugin_name, level)
|
||||
except ValueError:
|
||||
self._limits[limit] = config.get_value(self.plugin_name, level).split(",")
|
||||
logger.debug("Load limit: {} = {}".format(limit, self._limits[limit]))
|
||||
logger.debug(f"Load limit: {limit} = {self._limits[limit]}")
|
||||
|
||||
return True
|
||||
|
||||
@ -613,13 +612,13 @@ class GlancesPluginModel(object):
|
||||
|
||||
def set_limits(self, item, value):
|
||||
"""Set the limits object."""
|
||||
self._limits['{}_{}'.format(self.plugin_name, item)] = value
|
||||
self._limits[f'{self.plugin_name}_{item}'] = value
|
||||
|
||||
def get_limits(self, item=None):
|
||||
"""Return the limits object."""
|
||||
if item is None:
|
||||
return self._limits
|
||||
return self._limits.get('{}_{}'.format(self.plugin_name, item), None)
|
||||
return self._limits.get(f'{self.plugin_name}_{item}', None)
|
||||
|
||||
def get_stats_action(self):
|
||||
"""Return stats for the action.
|
||||
@ -1025,7 +1024,7 @@ class GlancesPluginModel(object):
|
||||
value = self.stats.get(key, None)
|
||||
|
||||
if width is None:
|
||||
msg_item = header + '{}'.format(key_name) + separator
|
||||
msg_item = header + f'{key_name}' + separator
|
||||
msg_template_float = '{:.1f}{}'
|
||||
msg_template = '{}{}'
|
||||
else:
|
||||
@ -1124,7 +1123,7 @@ class GlancesPluginModel(object):
|
||||
elif symbol in 'K':
|
||||
decimal_precision = 0
|
||||
return '{:.{decimal}f}{symbol}'.format(value, decimal=decimal_precision, symbol=symbol)
|
||||
return '{!s}'.format(number)
|
||||
return f'{number!s}'
|
||||
|
||||
def trend_msg(self, trend, significant=1):
|
||||
"""Return the trend message.
|
||||
@ -1170,11 +1169,9 @@ class GlancesPluginModel(object):
|
||||
counter = Counter()
|
||||
ret = fct(*args, **kw)
|
||||
duration = counter.get()
|
||||
logger.debug(
|
||||
"{} {} {} return {} in {} seconds".format(
|
||||
args[0].__class__.__name__, args[0].__class__.__module__, fct.__name__, ret, duration
|
||||
)
|
||||
)
|
||||
class_name = args[0].__class__.__name__
|
||||
class_module = args[0].__class__.__module__
|
||||
logger.debug(f"{class_name} {class_module} {fct.__name__} return {ret} in {duration} seconds")
|
||||
return ret
|
||||
|
||||
return wrapper
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -29,7 +28,7 @@ try:
|
||||
requests_tag = True
|
||||
except ImportError as e:
|
||||
requests_tag = False
|
||||
logger.warning("Missing Python Lib ({}), Ports plugin is limited to port scanning".format(e))
|
||||
logger.warning(f"Missing Python Lib ({e}), Ports plugin is limited to port scanning")
|
||||
|
||||
# Fields description
|
||||
# description: human readable description
|
||||
@ -72,9 +71,7 @@ class PluginModel(GlancesPluginModel):
|
||||
|
||||
def __init__(self, args=None, config=None):
|
||||
"""Init the plugin."""
|
||||
super(PluginModel, self).__init__(
|
||||
args=args, config=config, stats_init_value=[], fields_description=fields_description
|
||||
)
|
||||
super().__init__(args=args, config=config, stats_init_value=[], fields_description=fields_description)
|
||||
self.args = args
|
||||
self.config = config
|
||||
|
||||
@ -95,7 +92,7 @@ class PluginModel(GlancesPluginModel):
|
||||
if self._thread is not None:
|
||||
self._thread.stop()
|
||||
# Call the father class
|
||||
super(PluginModel, self).exit()
|
||||
super().exit()
|
||||
|
||||
def get_key(self):
|
||||
"""Return the key of the list."""
|
||||
@ -183,7 +180,7 @@ class PluginModel(GlancesPluginModel):
|
||||
name_max_width = max_width - 7
|
||||
else:
|
||||
# No max_width defined, return an emptu curse message
|
||||
logger.debug("No max_width defined for the {} plugin, it will not be displayed.".format(self.plugin_name))
|
||||
logger.debug(f"No max_width defined for the {self.plugin_name} plugin, it will not be displayed.")
|
||||
return ret
|
||||
|
||||
# Build the string message
|
||||
@ -199,11 +196,11 @@ class PluginModel(GlancesPluginModel):
|
||||
status = 'Timeout'
|
||||
else:
|
||||
# Convert second to ms
|
||||
status = '{0:.0f}ms'.format(p['status'] * 1000.0)
|
||||
status = '{:.0f}ms'.format(p['status'] * 1000.0)
|
||||
|
||||
msg = '{:{width}}'.format(p['description'][0:name_max_width], width=name_max_width)
|
||||
ret.append(self.curse_add_line(msg))
|
||||
msg = '{:>9}'.format(status)
|
||||
msg = f'{status:>9}'
|
||||
ret.append(self.curse_add_line(msg, self.get_ports_alert(p, header=p['indice'] + '_rtt')))
|
||||
ret.append(self.curse_new_line())
|
||||
elif 'url' in p:
|
||||
@ -215,7 +212,7 @@ class PluginModel(GlancesPluginModel):
|
||||
status = 'Scanning'
|
||||
else:
|
||||
status = p['status']
|
||||
msg = '{:>9}'.format(status)
|
||||
msg = f'{status:>9}'
|
||||
ret.append(self.curse_add_line(msg, self.get_web_alert(p, header=p['indice'] + '_rtt')))
|
||||
ret.append(self.curse_new_line())
|
||||
|
||||
@ -237,8 +234,8 @@ class ThreadScanner(threading.Thread):
|
||||
|
||||
def __init__(self, stats):
|
||||
"""Init the class."""
|
||||
logger.debug("ports plugin - Create thread for scan list {}".format(stats))
|
||||
super(ThreadScanner, self).__init__()
|
||||
logger.debug(f"ports plugin - Create thread for scan list {stats}")
|
||||
super().__init__()
|
||||
# Event needed to stop properly the thread
|
||||
self._stopper = threading.Event()
|
||||
# The class return the stats as a list of dict
|
||||
@ -283,7 +280,7 @@ class ThreadScanner(threading.Thread):
|
||||
|
||||
def stop(self, timeout=None):
|
||||
"""Stop the thread."""
|
||||
logger.debug("ports plugin - Close thread for scan list {}".format(self._stats))
|
||||
logger.debug(f"ports plugin - Close thread for scan list {self._stats}")
|
||||
self._stopper.set()
|
||||
|
||||
def stopped(self):
|
||||
@ -321,7 +318,7 @@ class ThreadScanner(threading.Thread):
|
||||
try:
|
||||
ip = socket.gethostbyname(hostname)
|
||||
except Exception as e:
|
||||
logger.debug("{}: Cannot convert {} to IP address ({})".format(self.plugin_name, hostname, e))
|
||||
logger.debug(f"{self.plugin_name}: Cannot convert {hostname} to IP address ({e})")
|
||||
return ip
|
||||
|
||||
def _port_scan_icmp(self, port):
|
||||
@ -379,7 +376,7 @@ class ThreadScanner(threading.Thread):
|
||||
socket.setdefaulttimeout(port['timeout'])
|
||||
_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
except Exception as e:
|
||||
logger.debug("{}: Error while creating scanning socket ({})".format(self.plugin_name, e))
|
||||
logger.debug(f"{self.plugin_name}: Error while creating scanning socket ({e})")
|
||||
|
||||
# Scan port
|
||||
ip = self._resolv_name(port['host'])
|
||||
@ -387,7 +384,7 @@ class ThreadScanner(threading.Thread):
|
||||
try:
|
||||
ret = _socket.connect_ex((ip, int(port['port'])))
|
||||
except Exception as e:
|
||||
logger.debug("{}: Error while scanning port {} ({})".format(self.plugin_name, port, e))
|
||||
logger.debug(f"{self.plugin_name}: Error while scanning port {port} ({e})")
|
||||
else:
|
||||
if ret == 0:
|
||||
port['status'] = counter.get()
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -58,7 +57,7 @@ class PluginModel(GlancesPluginModel):
|
||||
|
||||
def __init__(self, args=None, config=None):
|
||||
"""Init the plugin."""
|
||||
super(PluginModel, self).__init__(
|
||||
super().__init__(
|
||||
args=args, config=config, items_history_list=items_history_list, fields_description=fields_description
|
||||
)
|
||||
|
||||
@ -113,9 +112,9 @@ class PluginModel(GlancesPluginModel):
|
||||
if glances_processes.process_filter is not None:
|
||||
msg = 'Processes filter:'
|
||||
ret.append(self.curse_add_line(msg, "TITLE"))
|
||||
msg = ' {} '.format(glances_processes.process_filter)
|
||||
msg = f' {glances_processes.process_filter} '
|
||||
if glances_processes.process_filter_key is not None:
|
||||
msg += 'on column {} '.format(glances_processes.process_filter_key)
|
||||
msg += f'on column {glances_processes.process_filter_key} '
|
||||
ret.append(self.curse_add_line(msg, "FILTER"))
|
||||
msg = '(\'ENTER\' to edit, \'E\' to reset)'
|
||||
ret.append(self.curse_add_line(msg))
|
||||
@ -144,7 +143,7 @@ class PluginModel(GlancesPluginModel):
|
||||
msg = ' {} slp,'.format(self.stats['sleeping'])
|
||||
ret.append(self.curse_add_line(msg))
|
||||
|
||||
msg = ' {} oth '.format(other)
|
||||
msg = f' {other} oth '
|
||||
ret.append(self.curse_add_line(msg))
|
||||
|
||||
# Display sort information
|
||||
@ -156,9 +155,9 @@ class PluginModel(GlancesPluginModel):
|
||||
if glances_processes.auto_sort:
|
||||
msg += ' sorted automatically'
|
||||
ret.append(self.curse_add_line(msg))
|
||||
msg = ' by {}'.format(sort_human)
|
||||
msg = f' by {sort_human}'
|
||||
else:
|
||||
msg += ' sorted by {}'.format(sort_human)
|
||||
msg += f' sorted by {sort_human}'
|
||||
ret.append(self.curse_add_line(msg))
|
||||
|
||||
# Return the message with decoration
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -155,9 +154,7 @@ class PluginModel(GlancesPluginModel):
|
||||
|
||||
def __init__(self, args=None, config=None):
|
||||
"""Init the plugin."""
|
||||
super(PluginModel, self).__init__(
|
||||
args=args, config=config, fields_description=fields_description, stats_init_value=[]
|
||||
)
|
||||
super().__init__(args=args, config=config, fields_description=fields_description, stats_init_value=[])
|
||||
|
||||
# We want to display the stat in the curse interface
|
||||
self.display_curse = True
|
||||
@ -341,11 +338,11 @@ class PluginModel(GlancesPluginModel):
|
||||
else:
|
||||
hours, minutes, seconds = seconds_to_hms(user_system_time)
|
||||
if hours > 99:
|
||||
msg = '{:<7}h'.format(hours)
|
||||
msg = f'{hours:<7}h'
|
||||
elif 0 < hours < 100:
|
||||
msg = '{}h{}:{}'.format(hours, minutes, seconds)
|
||||
msg = f'{hours}h{minutes}:{seconds}'
|
||||
else:
|
||||
msg = '{}:{}'.format(minutes, seconds)
|
||||
msg = f'{minutes}:{seconds}'
|
||||
msg = self.layout_stat['time'].format(msg)
|
||||
if hours > 0:
|
||||
ret = self.curse_add_line(msg, decoration='CPU_TIME', optional=True)
|
||||
@ -502,7 +499,7 @@ class PluginModel(GlancesPluginModel):
|
||||
ret.append(self.curse_add_line(msg, decoration=process_decoration, splittable=True))
|
||||
except (TypeError, UnicodeEncodeError) as e:
|
||||
# Avoid crash after running fine for several hours #1335
|
||||
logger.debug("Can not decode command line '{}' ({})".format(cmdline, e))
|
||||
logger.debug(f"Can not decode command line '{cmdline}' ({e})")
|
||||
ret.append(self.curse_add_line('', splittable=True))
|
||||
|
||||
return ret
|
||||
@ -643,7 +640,7 @@ class PluginModel(GlancesPluginModel):
|
||||
# value is a number which goes from 0 to 7.
|
||||
# The higher the value, the lower the I/O priority of the process.
|
||||
if hasattr(p['ionice'], 'value') and p['ionice'].value != 0:
|
||||
msg += ' (value %s/7)' % str(p['ionice'].value)
|
||||
msg += ' (value {}/7)'.format(str(p['ionice'].value))
|
||||
ret.append(self.curse_add_line(msg, splittable=True))
|
||||
|
||||
# Second line is memory info
|
||||
@ -826,7 +823,7 @@ class PluginModel(GlancesPluginModel):
|
||||
msg = ' < {}'.format('current')
|
||||
ret.append(self.curse_add_line(msg, optional=True))
|
||||
else:
|
||||
msg = ' < {}'.format(mmm)
|
||||
msg = f' < {mmm}'
|
||||
ret.append(self.curse_add_line(msg, optional=True))
|
||||
msg = ' (\'M\' to reset)'
|
||||
ret.append(self.curse_add_line(msg, optional=True))
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -22,7 +21,7 @@ class PluginModel(GlancesPluginModel):
|
||||
|
||||
def __init__(self, args=None, config=None):
|
||||
"""Init the plugin."""
|
||||
super(PluginModel, self).__init__(args=args, config=config)
|
||||
super().__init__(args=args, config=config)
|
||||
|
||||
self.reset()
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -84,7 +83,7 @@ class PluginModel(GlancesPluginModel):
|
||||
|
||||
def __init__(self, args=None, config=None):
|
||||
"""Init the quicklook plugin."""
|
||||
super(PluginModel, self).__init__(
|
||||
super().__init__(
|
||||
args=args, config=config, items_history_list=items_history_list, fields_description=fields_description
|
||||
)
|
||||
|
||||
@ -97,7 +96,7 @@ class PluginModel(GlancesPluginModel):
|
||||
# Define the stats list
|
||||
self.stats_list = self.get_conf_value('list', default=self.DEFAULT_STATS_LIST)
|
||||
if not set(self.stats_list).issubset(self.AVAILABLE_STATS_LIST):
|
||||
logger.warning('Quicklook plugin: Invalid stats list: {}'.format(self.stats_list))
|
||||
logger.warning(f'Quicklook plugin: Invalid stats list: {self.stats_list}')
|
||||
self.stats_list = self.AVAILABLE_STATS_LIST
|
||||
|
||||
@GlancesPluginModel._check_decorator
|
||||
@ -152,7 +151,7 @@ class PluginModel(GlancesPluginModel):
|
||||
def update_views(self):
|
||||
"""Update stats views."""
|
||||
# Call the father's method
|
||||
super(PluginModel, self).update_views()
|
||||
super().update_views()
|
||||
|
||||
# Alert for CPU, MEM and SWAP
|
||||
for key in self.stats_list:
|
||||
@ -176,7 +175,7 @@ class PluginModel(GlancesPluginModel):
|
||||
|
||||
if not max_width:
|
||||
# No max_width defined, return an empty message
|
||||
logger.debug("No max_width defined for the {} plugin, it will not be displayed.".format(self.plugin_name))
|
||||
logger.debug(f"No max_width defined for the {self.plugin_name} plugin, it will not be displayed.")
|
||||
return ret
|
||||
|
||||
# Define the data: Bar (default behavior) or Sparkline
|
||||
@ -221,7 +220,7 @@ class PluginModel(GlancesPluginModel):
|
||||
else:
|
||||
# Bar only the last value
|
||||
data[key].percent = self.stats[key]
|
||||
msg = '{:4} '.format(key.upper())
|
||||
msg = f'{key.upper():4} '
|
||||
ret.extend(self._msg_create_line(msg, data[key], key))
|
||||
ret.append(self.curse_new_line())
|
||||
|
||||
@ -258,9 +257,9 @@ class PluginModel(GlancesPluginModel):
|
||||
# Bar will only display the last value
|
||||
data[key].percent = cpu['total']
|
||||
if cpu_id < 10:
|
||||
msg = '{:3}{} '.format(key.upper(), cpu_id)
|
||||
msg = f'{key.upper():3}{cpu_id} '
|
||||
else:
|
||||
msg = '{:4} '.format(cpu_id)
|
||||
msg = f'{cpu_id:4} '
|
||||
ret.extend(self._msg_create_line(msg, data[key], key))
|
||||
ret.append(self.curse_new_line())
|
||||
|
||||
@ -282,7 +281,7 @@ class PluginModel(GlancesPluginModel):
|
||||
sum_other.percent = sum([i['total'] for i in percpu_list[self.max_cpu_display :]]) / len(
|
||||
percpu_list[self.max_cpu_display :]
|
||||
)
|
||||
msg = msg = '{:3}* '.format(key.upper())
|
||||
msg = msg = f'{key.upper():3}* '
|
||||
ret.extend(self._msg_create_line(msg, sum_other, key))
|
||||
ret.append(self.curse_new_line())
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -18,7 +17,7 @@ try:
|
||||
from pymdstat import MdStat
|
||||
except ImportError as e:
|
||||
import_error_tag = True
|
||||
logger.warning("Missing Python Lib ({}), Raid plugin is disabled".format(e))
|
||||
logger.warning(f"Missing Python Lib ({e}), Raid plugin is disabled")
|
||||
else:
|
||||
import_error_tag = False
|
||||
|
||||
@ -31,7 +30,7 @@ class PluginModel(GlancesPluginModel):
|
||||
|
||||
def __init__(self, args=None, config=None):
|
||||
"""Init the plugin."""
|
||||
super(PluginModel, self).__init__(args=args, config=config)
|
||||
super().__init__(args=args, config=config)
|
||||
|
||||
# We want to display the stat in the curse interface
|
||||
self.display_curse = True
|
||||
@ -54,7 +53,7 @@ class PluginModel(GlancesPluginModel):
|
||||
# mds = MdStat(path='/home/nicolargo/dev/pymdstat/tests/mdstat.10')
|
||||
stats = mds.get_stats()['arrays']
|
||||
except Exception as e:
|
||||
logger.debug("Can not grab RAID stats (%s)" % e)
|
||||
logger.debug(f"Can not grab RAID stats ({e})")
|
||||
return self.stats
|
||||
|
||||
elif self.input_method == 'snmp':
|
||||
@ -81,7 +80,7 @@ class PluginModel(GlancesPluginModel):
|
||||
name_max_width = max_width - 12
|
||||
else:
|
||||
# No max_width defined, return an emptu curse message
|
||||
logger.debug("No max_width defined for the {} plugin, it will not be displayed.".format(self.plugin_name))
|
||||
logger.debug(f"No max_width defined for the {self.plugin_name} plugin, it will not be displayed.")
|
||||
return ret
|
||||
|
||||
# Header
|
||||
@ -108,7 +107,7 @@ class PluginModel(GlancesPluginModel):
|
||||
# Data: RAID type name | disk used | disk available
|
||||
array_type = self.stats[array]['type'].upper() if self.stats[array]['type'] is not None else 'UNKNOWN'
|
||||
# Build the full name = array type + array name
|
||||
full_name = '{} {}'.format(array_type, array)
|
||||
full_name = f'{array_type} {array}'
|
||||
msg = '{:{width}}'.format(full_name, width=name_max_width)
|
||||
ret.append(self.curse_add_line(msg))
|
||||
if self.stats[array]['type'] == 'raid0' and self.stats[array]['status'] == 'active':
|
||||
@ -134,7 +133,7 @@ class PluginModel(GlancesPluginModel):
|
||||
ret.append(self.curse_new_line())
|
||||
msg = ' {} disk {}: '.format(tree_char, self.stats[array]['components'][component])
|
||||
ret.append(self.curse_add_line(msg))
|
||||
msg = '{}'.format(component)
|
||||
msg = f'{component}'
|
||||
ret.append(self.curse_add_line(msg))
|
||||
if self.stats[array]['type'] != 'raid0' and (self.stats[array]['used'] < self.stats[array]['available']):
|
||||
# Display current array configuration
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -83,29 +82,27 @@ class PluginModel(GlancesPluginModel):
|
||||
|
||||
def __init__(self, args=None, config=None):
|
||||
"""Init the plugin."""
|
||||
super(PluginModel, self).__init__(
|
||||
args=args, config=config, stats_init_value=[], fields_description=fields_description
|
||||
)
|
||||
super().__init__(args=args, config=config, stats_init_value=[], fields_description=fields_description)
|
||||
start_duration = Counter()
|
||||
|
||||
# Init the sensor class
|
||||
start_duration.reset()
|
||||
glances_grab_sensors_cpu_temp = GlancesGrabSensors(SensorType.CPU_TEMP)
|
||||
logger.debug("CPU Temp sensor plugin init duration: {} seconds".format(start_duration.get()))
|
||||
logger.debug(f"CPU Temp sensor plugin init duration: {start_duration.get()} seconds")
|
||||
|
||||
start_duration.reset()
|
||||
glances_grab_sensors_fan_speed = GlancesGrabSensors(SensorType.FAN_SPEED)
|
||||
logger.debug("Fan speed sensor plugin init duration: {} seconds".format(start_duration.get()))
|
||||
logger.debug(f"Fan speed sensor plugin init duration: {start_duration.get()} seconds")
|
||||
|
||||
# Instance for the HDDTemp Plugin in order to display the hard disks temperatures
|
||||
start_duration.reset()
|
||||
hddtemp_plugin = HddTempPluginModel(args=args, config=config)
|
||||
logger.debug("HDDTemp sensor plugin init duration: {} seconds".format(start_duration.get()))
|
||||
logger.debug(f"HDDTemp sensor plugin init duration: {start_duration.get()} seconds")
|
||||
|
||||
# Instance for the BatPercent in order to display the batteries capacities
|
||||
start_duration.reset()
|
||||
batpercent_plugin = BatPercentPluginModel(args=args, config=config)
|
||||
logger.debug("Battery sensor plugin init duration: {} seconds".format(start_duration.get()))
|
||||
logger.debug(f"Battery sensor plugin init duration: {start_duration.get()} seconds")
|
||||
|
||||
self.sensors_grab_map: Dict[SensorType, Any] = {}
|
||||
|
||||
@ -214,7 +211,7 @@ class PluginModel(GlancesPluginModel):
|
||||
def update_views(self):
|
||||
"""Update stats views."""
|
||||
# Call the father's method
|
||||
super(PluginModel, self).update_views()
|
||||
super().update_views()
|
||||
|
||||
# Add specifics information
|
||||
# Alert
|
||||
@ -272,7 +269,7 @@ class PluginModel(GlancesPluginModel):
|
||||
name_max_width = max_width - 12
|
||||
else:
|
||||
# No max_width defined, return an emptu curse message
|
||||
logger.debug("No max_width defined for the {} plugin, it will not be displayed.".format(self.plugin_name))
|
||||
logger.debug(f"No max_width defined for the {self.plugin_name} plugin, it will not be displayed.")
|
||||
return ret
|
||||
|
||||
# Header
|
||||
@ -303,8 +300,8 @@ class PluginModel(GlancesPluginModel):
|
||||
value = i['value']
|
||||
unit = i['unit']
|
||||
try:
|
||||
msg = '{:.0f}{}{}'.format(value, unit, trend)
|
||||
msg = '{:>14}'.format(msg)
|
||||
msg = f'{value:.0f}{unit}{trend}'
|
||||
msg = f'{msg:>14}'
|
||||
ret.append(
|
||||
self.curse_add_line(
|
||||
msg, self.get_views(item=i[self.get_key()], key='value', option='decoration')
|
||||
@ -316,7 +313,7 @@ class PluginModel(GlancesPluginModel):
|
||||
return ret
|
||||
|
||||
|
||||
class GlancesGrabSensors(object):
|
||||
class GlancesGrabSensors:
|
||||
"""Get sensors stats."""
|
||||
|
||||
def __init__(self, sensor_type: Literal[SensorType.FAN_SPEED, SensorType.CPU_TEMP]):
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -31,7 +30,7 @@ psutil_tag = True
|
||||
try:
|
||||
psutil.sensors_battery()
|
||||
except Exception as e:
|
||||
logger.error("Cannot grab battery status {}.".format(e))
|
||||
logger.error(f"Cannot grab battery status {e}.")
|
||||
psutil_tag = False
|
||||
|
||||
|
||||
@ -43,13 +42,13 @@ class PluginModel(GlancesPluginModel):
|
||||
|
||||
def __init__(self, args=None, config=None):
|
||||
"""Init the plugin."""
|
||||
super(PluginModel, self).__init__(args=args, config=config, stats_init_value=[])
|
||||
super().__init__(args=args, config=config, stats_init_value=[])
|
||||
|
||||
# Init the sensor class
|
||||
try:
|
||||
self.glances_grab_bat = GlancesGrabBat()
|
||||
except Exception as e:
|
||||
logger.error("Can not init battery class ({})".format(e))
|
||||
logger.error(f"Can not init battery class ({e})")
|
||||
global batinfo_tag
|
||||
global psutil_tag
|
||||
batinfo_tag = False
|
||||
@ -82,7 +81,7 @@ class PluginModel(GlancesPluginModel):
|
||||
return self.stats
|
||||
|
||||
|
||||
class GlancesGrabBat(object):
|
||||
class GlancesGrabBat:
|
||||
"""Get batteries stats using the batinfo library."""
|
||||
|
||||
def __init__(self):
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -25,7 +24,7 @@ class PluginModel(GlancesPluginModel):
|
||||
|
||||
def __init__(self, args=None, config=None):
|
||||
"""Init the plugin."""
|
||||
super(PluginModel, self).__init__(args=args, config=config, stats_init_value=[])
|
||||
super().__init__(args=args, config=config, stats_init_value=[])
|
||||
|
||||
# Init the sensor class
|
||||
hddtemp_host = self.get_conf_value("host", default=["127.0.0.1"])[0]
|
||||
@ -58,7 +57,7 @@ class PluginModel(GlancesPluginModel):
|
||||
return self.stats
|
||||
|
||||
|
||||
class GlancesGrabHDDTemp(object):
|
||||
class GlancesGrabHDDTemp:
|
||||
"""Get hddtemp stats using a socket connection."""
|
||||
|
||||
def __init__(self, host='127.0.0.1', port=7634, args=None):
|
||||
@ -133,7 +132,7 @@ class GlancesGrabHDDTemp(object):
|
||||
break
|
||||
data += received
|
||||
except Exception as e:
|
||||
logger.debug("Cannot connect to an HDDtemp server ({}:{} => {})".format(self.host, self.port, e))
|
||||
logger.debug(f"Cannot connect to an HDDtemp server ({self.host}:{self.port} => {e})")
|
||||
logger.debug("Disable the HDDtemp module. Use the --disable-hddtemp to hide the previous message.")
|
||||
if self.args is not None:
|
||||
self.args.disable_hddtemp = True
|
||||
@ -141,7 +140,7 @@ class GlancesGrabHDDTemp(object):
|
||||
finally:
|
||||
sck.close()
|
||||
if data != "":
|
||||
logger.debug("Received data from the HDDtemp server: {}".format(data))
|
||||
logger.debug(f"Received data from the HDDtemp server: {data}")
|
||||
|
||||
return data
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -44,7 +43,7 @@ try:
|
||||
from pySMART import DeviceList
|
||||
except ImportError as e:
|
||||
import_error_tag = True
|
||||
logger.warning("Missing Python Lib ({}), HDD Smart plugin is disabled".format(e))
|
||||
logger.warning(f"Missing Python Lib ({e}), HDD Smart plugin is disabled")
|
||||
else:
|
||||
import_error_tag = False
|
||||
|
||||
@ -89,7 +88,7 @@ def get_smart_data():
|
||||
devlist = DeviceList()
|
||||
except TypeError as e:
|
||||
# Catch error (see #1806)
|
||||
logger.debug('Smart plugin error - Can not grab device list ({})'.format(e))
|
||||
logger.debug(f'Smart plugin error - Can not grab device list ({e})')
|
||||
global import_error_tag
|
||||
import_error_tag = True
|
||||
return stats
|
||||
@ -97,7 +96,7 @@ def get_smart_data():
|
||||
for dev in devlist.devices:
|
||||
stats.append(
|
||||
{
|
||||
'DeviceName': '{} {}'.format(dev.name, dev.model),
|
||||
'DeviceName': f'{dev.name} {dev.model}',
|
||||
}
|
||||
)
|
||||
for attribute in dev.attributes:
|
||||
@ -112,7 +111,7 @@ def get_smart_data():
|
||||
assert num is not None
|
||||
except Exception as e:
|
||||
# we should never get here, but if we do, continue to next iteration and skip this attribute
|
||||
logger.debug('Smart plugin error - Skip the attribute {} ({})'.format(attribute, e))
|
||||
logger.debug(f'Smart plugin error - Skip the attribute {attribute} ({e})')
|
||||
continue
|
||||
|
||||
stats[-1][num] = attrib_dict
|
||||
@ -129,7 +128,7 @@ class PluginModel(GlancesPluginModel):
|
||||
disable(args, "smart")
|
||||
logger.debug("Current user is not admin, HDD SMART plugin disabled.")
|
||||
|
||||
super(PluginModel, self).__init__(args=args, config=config)
|
||||
super().__init__(args=args, config=config)
|
||||
|
||||
# We want to display the stat in the curse interface
|
||||
self.display_curse = True
|
||||
@ -172,7 +171,7 @@ class PluginModel(GlancesPluginModel):
|
||||
name_max_width = max_width - 6
|
||||
else:
|
||||
# No max_width defined, return an emptu curse message
|
||||
logger.debug("No max_width defined for the {} plugin, it will not be displayed.".format(self.plugin_name))
|
||||
logger.debug(f"No max_width defined for the {self.plugin_name} plugin, it will not be displayed.")
|
||||
return ret
|
||||
|
||||
# Header
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -9,10 +8,10 @@
|
||||
|
||||
"""System plugin."""
|
||||
|
||||
import builtins
|
||||
import os
|
||||
import platform
|
||||
import re
|
||||
from io import open
|
||||
|
||||
from glances.globals import iteritems
|
||||
from glances.logger import logger
|
||||
@ -92,12 +91,12 @@ def _linux_os_release():
|
||||
ashtray = {}
|
||||
keys = ['NAME', 'VERSION_ID']
|
||||
try:
|
||||
with open(os.path.join('/etc', 'os-release')) as f:
|
||||
with builtins.open(os.path.join('/etc', 'os-release')) as f:
|
||||
for line in f:
|
||||
for key in keys:
|
||||
if line.startswith(key):
|
||||
ashtray[key] = re.sub(r'^"|"$', '', line.strip().split('=')[1])
|
||||
except (OSError, IOError):
|
||||
except OSError:
|
||||
return pretty_name
|
||||
|
||||
if ashtray:
|
||||
@ -117,7 +116,7 @@ class PluginModel(GlancesPluginModel):
|
||||
|
||||
def __init__(self, args=None, config=None):
|
||||
"""Init the plugin."""
|
||||
super(PluginModel, self).__init__(args=args, config=config, fields_description=fields_description)
|
||||
super().__init__(args=args, config=config, fields_description=fields_description)
|
||||
|
||||
# We want to display the stat in the curse interface
|
||||
self.display_curse = True
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -27,7 +26,7 @@ class PluginModel(GlancesPluginModel):
|
||||
|
||||
def __init__(self, args=None, config=None):
|
||||
"""Init the plugin."""
|
||||
super(PluginModel, self).__init__(args=args, config=config)
|
||||
super().__init__(args=args, config=config)
|
||||
|
||||
# We want to display the stat in the curse interface
|
||||
self.display_curse = True
|
||||
@ -83,4 +82,4 @@ class PluginModel(GlancesPluginModel):
|
||||
if not self.stats or self.is_disabled():
|
||||
return ret
|
||||
|
||||
return [self.curse_add_line('Uptime: {}'.format(self.stats))]
|
||||
return [self.curse_add_line(f'Uptime: {self.stats}')]
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -23,7 +22,7 @@ class PluginModel(GlancesPluginModel):
|
||||
|
||||
def __init__(self, args=None, config=None):
|
||||
"""Init the plugin."""
|
||||
super(PluginModel, self).__init__(args=args, config=config)
|
||||
super().__init__(args=args, config=config)
|
||||
|
||||
self.reset()
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -29,7 +28,7 @@ WIRELESS_FILE = '/proc/net/wireless'
|
||||
wireless_file_exists = file_exists(WIRELESS_FILE)
|
||||
|
||||
if not wireless_file_exists:
|
||||
logger.debug("Wifi plugin is disabled (no %s file found)" % (WIRELESS_FILE))
|
||||
logger.debug(f"Wifi plugin is disabled (no {WIRELESS_FILE} file found)")
|
||||
|
||||
# Fields description
|
||||
# description: human readable description
|
||||
@ -58,7 +57,7 @@ class PluginModel(GlancesPluginModel):
|
||||
|
||||
def __init__(self, args=None, config=None):
|
||||
"""Init the plugin."""
|
||||
super(PluginModel, self).__init__(args=args, config=config, stats_init_value=[])
|
||||
super().__init__(args=args, config=config, stats_init_value=[])
|
||||
|
||||
# We want to display the stat in the curse interface
|
||||
self.display_curse = True
|
||||
@ -71,7 +70,7 @@ class PluginModel(GlancesPluginModel):
|
||||
if self._thread is not None:
|
||||
self._thread.stop()
|
||||
# Call the father class
|
||||
super(PluginModel, self).exit()
|
||||
super().exit()
|
||||
|
||||
def get_key(self):
|
||||
"""Return the key of the list.
|
||||
@ -98,7 +97,7 @@ class PluginModel(GlancesPluginModel):
|
||||
|
||||
if self.input_method == 'local' and wireless_file_exists:
|
||||
# As a backup solution, use the /proc/net/wireless file
|
||||
with open(WIRELESS_FILE, 'r') as f:
|
||||
with open(WIRELESS_FILE) as f:
|
||||
# The first two lines are header
|
||||
f.readline()
|
||||
f.readline()
|
||||
@ -154,7 +153,7 @@ class PluginModel(GlancesPluginModel):
|
||||
def update_views(self):
|
||||
"""Update stats views."""
|
||||
# Call the father's method
|
||||
super(PluginModel, self).update_views()
|
||||
super().update_views()
|
||||
|
||||
# Add specifics information
|
||||
# Alert on quality_level thresholds
|
||||
@ -175,7 +174,7 @@ class PluginModel(GlancesPluginModel):
|
||||
if_name_max_width = max_width - 5
|
||||
else:
|
||||
# No max_width defined, return an emptu curse message
|
||||
logger.debug("No max_width defined for the {} plugin, it will not be displayed.".format(self.plugin_name))
|
||||
logger.debug(f"No max_width defined for the {self.plugin_name} plugin, it will not be displayed.")
|
||||
return ret
|
||||
|
||||
# Build the string message
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -26,7 +25,7 @@ else:
|
||||
netifaces_tag = False
|
||||
|
||||
|
||||
class GlancesPortsList(object):
|
||||
class GlancesPortsList:
|
||||
"""Manage the ports list for the ports plugin."""
|
||||
|
||||
_section = "ports"
|
||||
@ -46,9 +45,9 @@ class GlancesPortsList(object):
|
||||
if config is None:
|
||||
logger.debug("No configuration file available. Cannot load ports list.")
|
||||
elif not config.has_section(self._section):
|
||||
logger.debug("No [%s] section in the configuration file. Cannot load ports list." % self._section)
|
||||
logger.debug(f"No [{self._section}] section in the configuration file. Cannot load ports list.")
|
||||
else:
|
||||
logger.debug("Start reading the [%s] section in the configuration file" % self._section)
|
||||
logger.debug(f"Start reading the [{self._section}] section in the configuration file")
|
||||
|
||||
refresh = int(config.get_value(self._section, 'refresh', default=self._default_refresh))
|
||||
timeout = int(config.get_value(self._section, 'timeout', default=self._default_timeout))
|
||||
@ -68,26 +67,26 @@ class GlancesPortsList(object):
|
||||
new_port['timeout'] = timeout
|
||||
new_port['status'] = None
|
||||
new_port['rtt_warning'] = None
|
||||
new_port['indice'] = str('port_0')
|
||||
logger.debug("Add default gateway %s to the static list" % (new_port['host']))
|
||||
new_port['indice'] = 'port_0'
|
||||
logger.debug("Add default gateway {} to the static list".format(new_port['host']))
|
||||
ports_list.append(new_port)
|
||||
|
||||
# Read the scan list
|
||||
for i in range(1, 256):
|
||||
new_port = {}
|
||||
postfix = 'port_%s_' % str(i)
|
||||
postfix = f'port_{str(i)}_'
|
||||
|
||||
# Read mandatory configuration key: host
|
||||
new_port['host'] = config.get_value(self._section, '%s%s' % (postfix, 'host'))
|
||||
new_port['host'] = config.get_value(self._section, '{}{}'.format(postfix, 'host'))
|
||||
|
||||
if new_port['host'] is None:
|
||||
continue
|
||||
|
||||
# Read optionals configuration keys
|
||||
# Port is set to 0 by default. 0 mean ICMP check instead of TCP check
|
||||
new_port['port'] = config.get_value(self._section, '%s%s' % (postfix, 'port'), 0)
|
||||
new_port['port'] = config.get_value(self._section, '{}{}'.format(postfix, 'port'), 0)
|
||||
new_port['description'] = config.get_value(
|
||||
self._section, '%sdescription' % postfix, default="%s:%s" % (new_port['host'], new_port['port'])
|
||||
self._section, f'{postfix}description', default="{}:{}".format(new_port['host'], new_port['port'])
|
||||
)
|
||||
|
||||
# Default status
|
||||
@ -97,10 +96,10 @@ class GlancesPortsList(object):
|
||||
new_port['refresh'] = refresh
|
||||
|
||||
# Timeout in second
|
||||
new_port['timeout'] = int(config.get_value(self._section, '%stimeout' % postfix, default=timeout))
|
||||
new_port['timeout'] = int(config.get_value(self._section, f'{postfix}timeout', default=timeout))
|
||||
|
||||
# RTT warning
|
||||
new_port['rtt_warning'] = config.get_value(self._section, '%srtt_warning' % postfix, default=None)
|
||||
new_port['rtt_warning'] = config.get_value(self._section, f'{postfix}rtt_warning', default=None)
|
||||
if new_port['rtt_warning'] is not None:
|
||||
# Convert to second
|
||||
new_port['rtt_warning'] = int(new_port['rtt_warning']) / 1000.0
|
||||
@ -109,11 +108,11 @@ class GlancesPortsList(object):
|
||||
new_port['indice'] = 'port_' + str(i)
|
||||
|
||||
# Add the server to the list
|
||||
logger.debug("Add port %s:%s to the static list" % (new_port['host'], new_port['port']))
|
||||
logger.debug("Add port {}:{} to the static list".format(new_port['host'], new_port['port']))
|
||||
ports_list.append(new_port)
|
||||
|
||||
# Ports list loaded
|
||||
logger.debug("Ports list loaded: %s" % ports_list)
|
||||
logger.debug(f"Ports list loaded: {ports_list}")
|
||||
|
||||
return ports_list
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
@ -34,7 +33,7 @@ sort_for_human = {
|
||||
}
|
||||
|
||||
|
||||
class GlancesProcesses(object):
|
||||
class GlancesProcesses:
|
||||
"""Get processed stats using the psutil library."""
|
||||
|
||||
def __init__(self, cache_timeout=60):
|
||||
@ -83,7 +82,7 @@ class GlancesProcesses(object):
|
||||
p = psutil.Process()
|
||||
p.io_counters()
|
||||
except Exception as e:
|
||||
logger.warning('PsUtil can not grab processes io_counters ({})'.format(e))
|
||||
logger.warning(f'PsUtil can not grab processes io_counters ({e})')
|
||||
self.disable_io_counters = True
|
||||
else:
|
||||
logger.debug('PsUtil can grab processes io_counters')
|
||||
@ -94,7 +93,7 @@ class GlancesProcesses(object):
|
||||
p = psutil.Process()
|
||||
p.gids()
|
||||
except Exception as e:
|
||||
logger.warning('PsUtil can not grab processes gids ({})'.format(e))
|
||||
logger.warning(f'PsUtil can not grab processes gids ({e})')
|
||||
self.disable_gids = True
|
||||
else:
|
||||
logger.debug('PsUtil can grab processes gids')
|
||||
@ -183,7 +182,7 @@ class GlancesProcesses(object):
|
||||
try:
|
||||
with open('/proc/sys/kernel/pid_max', 'rb') as f:
|
||||
return int(f.read())
|
||||
except (OSError, IOError):
|
||||
except OSError:
|
||||
return None
|
||||
else:
|
||||
return None
|
||||
@ -310,7 +309,7 @@ class GlancesProcesses(object):
|
||||
# Get number of TCP and UDP network connections for the selected process
|
||||
ret['tcp'], ret['udp'] = self.__get_extended_connections(selected_process)
|
||||
except (psutil.NoSuchProcess, ValueError, AttributeError) as e:
|
||||
logger.error('Can not grab extended stats ({})'.format(e))
|
||||
logger.error(f'Can not grab extended stats ({e})')
|
||||
self.extended_process = None
|
||||
ret['extended_stats'] = False
|
||||
else:
|
||||
@ -595,11 +594,9 @@ class GlancesProcesses(object):
|
||||
p = psutil.Process(pid)
|
||||
try:
|
||||
p.nice(p.nice() - 1)
|
||||
logger.info('Set nice level of process {} to {} (higher the priority)'.format(pid, p.nice()))
|
||||
logger.info(f'Set nice level of process {pid} to {p.nice()} (higher the priority)')
|
||||
except psutil.AccessDenied:
|
||||
logger.warning(
|
||||
'Can not decrease (higher the priority) the nice level of process {} (access denied)'.format(pid)
|
||||
)
|
||||
logger.warning(f'Can not decrease (higher the priority) the nice level of process {pid} (access denied)')
|
||||
|
||||
def nice_increase(self, pid):
|
||||
"""Increase nice level
|
||||
@ -608,17 +605,15 @@ class GlancesProcesses(object):
|
||||
p = psutil.Process(pid)
|
||||
try:
|
||||
p.nice(p.nice() + 1)
|
||||
logger.info('Set nice level of process {} to {} (lower the priority)'.format(pid, p.nice()))
|
||||
logger.info(f'Set nice level of process {pid} to {p.nice()} (lower the priority)')
|
||||
except psutil.AccessDenied:
|
||||
logger.warning(
|
||||
'Can not increase (lower the priority) the nice level of process {} (access denied)'.format(pid)
|
||||
)
|
||||
logger.warning(f'Can not increase (lower the priority) the nice level of process {pid} (access denied)')
|
||||
|
||||
def kill(self, pid, timeout=3):
|
||||
"""Kill process with pid"""
|
||||
assert pid != os.getpid(), "Glances can kill itself..."
|
||||
p = psutil.Process(pid)
|
||||
logger.debug('Send kill signal to process: {}'.format(p))
|
||||
logger.debug(f'Send kill signal to process: {p}')
|
||||
p.kill()
|
||||
return p.wait(timeout)
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user