Merge branch 'issue2518' into develop

This commit is contained in:
nicolargo 2023-08-19 17:51:42 +02:00
commit 723e0617bc
8 changed files with 59 additions and 61 deletions

View File

@ -13,22 +13,9 @@ from __future__ import unicode_literals
import os
from glances.timer import Timer
from glances.globals import nativestr
from glances.globals import nativestr, folder_size
from glances.logger import logger
# Use the built-in version of scandir/walk if possible, otherwise
# use the scandir module version
scandir_tag = True
try:
# For Python 3.5 or higher
from os import scandir
except ImportError:
# For others...
try:
from scandir import scandir
except ImportError:
scandir_tag = False
class FolderList(object):
@ -62,12 +49,9 @@ class FolderList(object):
self.first_grab = True
if self.config is not None and self.config.has_section('folders'):
if scandir_tag:
# Process monitoring list
logger.debug("Folder list configuration detected")
self.__set_folder_list('folders')
else:
logger.error('Scandir not found. Please use Python 3.5+ or install the scandir lib')
else:
self.__folder_list = []
@ -132,23 +116,6 @@ class FolderList(object):
else:
return None
def __folder_size(self, path):
"""Return the size of the directory given by path
path: <string>"""
ret = 0
for f in scandir(path):
if f.is_dir(follow_symlinks=False) and (f.name != '.' or f.name != '..'):
ret += self.__folder_size(os.path.join(path, f.name))
else:
try:
ret += f.stat().st_size
except OSError:
pass
return ret
def update(self, key='path'):
"""Update the command result attributed."""
# Only continue if monitor list is not empty
@ -163,15 +130,12 @@ class FolderList(object):
# Set the key (see issue #2327)
self.__folder_list[i]['key'] = key
# Get folder size
try:
self.__folder_list[i]['size'] = self.__folder_size(self.path(i))
except OSError as e:
logger.debug('Cannot get folder size ({}). Error: {}'.format(self.path(i), e))
if e.errno == 13:
# Permission denied
self.__folder_list[i]['size'] = '!'
else:
self.__folder_list[i]['size'] = '?'
self.__folder_list[i]['size'], self.__folder_list[i]['errno'] = folder_size(self.path(i))
if self.__folder_list[i]['errno'] != 0:
logger.debug('Folder size ({} ~ {}) may not be correct. Error: {}'.format(
self.path(i),
self.__folder_list[i]['size'],
self.__folder_list[i]['errno']))
# Reset the timer
self.timer_folders[i].reset()

View File

@ -372,3 +372,29 @@ def string_value_to_float(s):
def file_exists(filename):
"""Return True if the file exists and is readable."""
return os.path.isfile(filename) and os.access(filename, os.R_OK)
def folder_size(path, errno=0):
"""Return a tuple with the size of the directory given by path and the errno.
If an error occurs (for example one file or subfolder is not accessible),
errno is set to the error number.
path: <string>
errno: <int> Should always be 0 when calling the function"""
ret_size = 0
ret_err = errno
try:
f_list = os.scandir(path)
except OSError as e:
return 0, e.errno
for f in f_list:
if f.is_dir(follow_symlinks=False) and (f.name != '.' or f.name != '..'):
ret = folder_size(os.path.join(path, f.name), ret_err)
ret_size += ret[0]
ret_err = ret[1]
else:
try:
ret_size += f.stat().st_size
except OSError as e:
ret_err = e.errno
return ret_size, ret_err

View File

@ -330,6 +330,7 @@ class _GlancesCurses(object):
'PASSWORD': curses.A_PROTECT,
'SELECTED': self.selected_color,
'INFO': self.ifINFO_color,
'ERROR': self.selected_color,
}
def set_cursor(self, value):

View File

@ -110,6 +110,10 @@ body {
color: white;
font-weight: bold;
}
.error {
color: #EE6600;
font-weight: bold;
}
/* Plugins */
#processlist-plugin .table-cell {

View File

@ -9,6 +9,9 @@
<div class="table-cell text-left">{{ folder.path }}</div>
<div class="table-cell"></div>
<div class="table-cell" :class="getDecoration(folder)">
<span v-if="folder.errno > 0" class="visible-lg-inline">
?
</span>
{{ $filters.bytes(folder.size) }}
</div>
</div>
@ -31,6 +34,7 @@ export default {
return {
path: folderData['path'],
size: folderData['size'],
errno: folderData['errno'],
careful: folderData['careful'],
warning: folderData['warning'],
critical: folderData['critical']
@ -40,8 +44,8 @@ export default {
},
methods: {
getDecoration(folder) {
if (!Number.isInteger(folder.size)) {
return;
if (folder.errno > 0) {
return 'error';
}
if (folder.critical !== null && folder.size > folder.critical * 1000000) {
return 'critical';

File diff suppressed because one or more lines are too long

View File

@ -64,8 +64,8 @@ class PluginModel(GlancesPluginModel):
def get_alert(self, stat, header=""):
"""Manage limits of the folder list."""
if not isinstance(stat['size'], numbers.Number):
ret = 'DEFAULT'
if stat['errno'] != 0:
ret = 'ERROR'
else:
ret = 'OK'
@ -113,10 +113,10 @@ class PluginModel(GlancesPluginModel):
path = i['path']
msg = '{:{width}}'.format(nativestr(path), width=name_max_width)
ret.append(self.curse_add_line(msg))
try:
if i['errno'] != 0:
msg = '?{:>8}'.format(self.auto_unit(i['size']))
else:
msg = '{:>9}'.format(self.auto_unit(i['size']))
except (TypeError, ValueError):
msg = '{:>9}'.format(i['size'])
ret.append(self.curse_add_line(msg, self.get_alert(i, header='folder_' + i['indice'])))
return ret

View File

@ -9,8 +9,8 @@ from io import open
from setuptools import setup, Command
if sys.version_info < (3, 4):
print('Glances requires at least Python 3.4 to run.')
if sys.version_info < (3, 8):
print('Glances requires at least Python 3.8 to run.')
sys.exit(1)
# Global functions
@ -60,7 +60,6 @@ def get_install_extras_require():
'graphitesender', 'influxdb>=1.0.0', 'influxdb-client', 'pymongo',
'kafka-python', 'pika', 'paho-mqtt', 'potsdb', 'prometheus_client',
'pyzmq', 'statsd'],
'folders': ['scandir'],
'gpu': ['py3nvml'],
'graph': ['pygal'],
'ip': ['netifaces'],