mirror of
https://github.com/freedombox/FreedomBox.git
synced 2026-03-11 09:04:54 +00:00
storage: simplified use of df to get disk information
- Use df --block-size=1 instead --human-readable to fix locale issue #1043. - Code cleanup: get available space directly, better variable/module names. Signed-off-by: Johannes Keyser <johanneskeyser@posteo.de> Reviewed-by: James Valleroy <jvalleroy@mailbox.org>
This commit is contained in:
parent
1247f2ef93
commit
10df3004ac
@ -64,8 +64,8 @@ def get_disks():
|
||||
def _get_disks_from_df():
|
||||
"""Return the list of disks and free space available using 'df'."""
|
||||
command = ['df', '--exclude-type=tmpfs', '--exclude-type=devtmpfs',
|
||||
'--output=source,target,fstype,size,used,pcent',
|
||||
'--human-readable']
|
||||
'--block-size=1',
|
||||
'--output=source,target,fstype,size,used,avail,pcent']
|
||||
try:
|
||||
process = subprocess.run(command, stdout=subprocess.PIPE, check=True)
|
||||
except subprocess.CalledProcessError as exception:
|
||||
@ -78,9 +78,15 @@ def _get_disks_from_df():
|
||||
for line in output.splitlines()[1:]:
|
||||
parts = line.split()
|
||||
keys = ('device', 'mount_point', 'file_system_type', 'size', 'used',
|
||||
'percentage_used')
|
||||
'free', 'percent_used')
|
||||
disk = dict(zip(keys, parts))
|
||||
disk['percentage_used'] = int(disk['percentage_used'].rstrip('%'))
|
||||
disk['percent_used'] = int(disk['percent_used'].rstrip('%'))
|
||||
disk['size'] = int(disk['size'])
|
||||
disk['used'] = int(disk['used'])
|
||||
disk['free'] = int(disk['free'])
|
||||
disk['size_str'] = format_bytes(disk['size'])
|
||||
disk['used_str'] = format_bytes(disk['used'])
|
||||
disk['free_str'] = format_bytes(disk['free'])
|
||||
disks.append(disk)
|
||||
|
||||
return disks
|
||||
@ -130,3 +136,27 @@ def is_expandable(device):
|
||||
def expand_partition(device):
|
||||
"""Expand a partition."""
|
||||
actions.superuser_run('storage', ['expand-partition', device])
|
||||
|
||||
|
||||
def format_bytes(size):
|
||||
"""Return human readable disk size from bytes."""
|
||||
if not size:
|
||||
return size
|
||||
|
||||
if size < 1024:
|
||||
return _('{disk_size:.1f} bytes').format(disk_size=size)
|
||||
|
||||
if size < 1024 ** 2:
|
||||
size /= 1024
|
||||
return _('{disk_size:.1f} KiB').format(disk_size=size)
|
||||
|
||||
if size < 1024 ** 3:
|
||||
size /= 1024 ** 2
|
||||
return _('{disk_size:.1f} MiB').format(disk_size=size)
|
||||
|
||||
if size < 1024 ** 4:
|
||||
size /= 1024 ** 3
|
||||
return _('{disk_size:.1f} GiB').format(disk_size=size)
|
||||
|
||||
size /= 1024 ** 4
|
||||
return _('{disk_size:.1f} TiB').format(disk_size=size)
|
||||
|
||||
@ -52,20 +52,20 @@
|
||||
<td>{{ disk.file_system_type }}</td>
|
||||
<td>
|
||||
<div class="progress">
|
||||
{% if disk.percentage_used < 75 %}
|
||||
{% if disk.percent_used < 75 %}
|
||||
<div class="progress-bar progress-bar-striped progress-bar-success"
|
||||
{% elif disk.percentage_used < 90 %}
|
||||
{% elif disk.percent_used < 90 %}
|
||||
<div class="progress-bar progress-bar-striped progress-bar-warning"
|
||||
{% else %}
|
||||
<div class="progress-bar progress-bar-striped progress-bar-danger"
|
||||
{% endif %}
|
||||
role="progressbar" aria-valuenow="disk.percentage_used"
|
||||
role="progressbar" aria-valuenow="disk.percent_used"
|
||||
aria-valuemin="0" aria-valuemax="100"
|
||||
style="width: {{ disk.percentage_used }}%;">
|
||||
{{ disk.percentage_used }}%
|
||||
style="width: {{ disk.percent_used }}%;">
|
||||
{{ disk.percent_used }}%
|
||||
</div>
|
||||
</div>
|
||||
<div>{{ disk.used }} / {{ disk.size }}</div>
|
||||
<div>{{ disk.used_str }} / {{ disk.size_str }}</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
||||
@ -25,7 +25,7 @@ from django.shortcuts import redirect
|
||||
from django.template.response import TemplateResponse
|
||||
from django.urls import reverse
|
||||
from django.utils.translation import ugettext as _
|
||||
from plinth.modules import storage as storage_module
|
||||
from plinth.modules import storage
|
||||
from plinth.utils import format_lazy, is_user_admin
|
||||
|
||||
|
||||
@ -34,10 +34,10 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
def index(request):
|
||||
"""Show connection list."""
|
||||
disks = storage_module.get_disks()
|
||||
root_device = storage_module.get_root_device(disks)
|
||||
expandable_root_size = storage_module.is_expandable(root_device)
|
||||
expandable_root_size = _format_bytes(expandable_root_size)
|
||||
disks = storage.get_disks()
|
||||
root_device = storage.get_root_device(disks)
|
||||
expandable_root_size = storage.is_expandable(root_device)
|
||||
expandable_root_size = storage.format_bytes(expandable_root_size)
|
||||
|
||||
warn_about_low_disk_space(request)
|
||||
|
||||
@ -49,15 +49,15 @@ def index(request):
|
||||
|
||||
def expand(request):
|
||||
"""Warn and expand the root partition."""
|
||||
disks = storage_module.get_disks()
|
||||
root_device = storage_module.get_root_device(disks)
|
||||
disks = storage.get_disks()
|
||||
root_device = storage.get_root_device(disks)
|
||||
|
||||
if request.method == 'POST':
|
||||
expand_partition(request, root_device)
|
||||
return redirect(reverse('storage:index'))
|
||||
|
||||
expandable_root_size = storage_module.is_expandable(root_device)
|
||||
expandable_root_size = _format_bytes(expandable_root_size)
|
||||
expandable_root_size = storage.is_expandable(root_device)
|
||||
expandable_root_size = storage.format_bytes(expandable_root_size)
|
||||
return TemplateResponse(request, 'storage_expand.html',
|
||||
{'title': _('Expand Root Partition'),
|
||||
'expandable_root_size': expandable_root_size})
|
||||
@ -66,7 +66,7 @@ def expand(request):
|
||||
def expand_partition(request, device):
|
||||
"""Expand the partition."""
|
||||
try:
|
||||
storage_module.expand_partition(device)
|
||||
storage.expand_partition(device)
|
||||
except Exception as exception:
|
||||
messages.error(request, _('Error expanding partition: {exception}')
|
||||
.format(exception=exception))
|
||||
@ -79,71 +79,26 @@ def warn_about_low_disk_space(request):
|
||||
if not is_user_admin(request, cached=True):
|
||||
return
|
||||
|
||||
disks = storage_module.get_disks()
|
||||
disks = storage.get_disks()
|
||||
list_root = [disk for disk in disks if disk['mountpoint'] == '/']
|
||||
if not list_root:
|
||||
logger.error('Error getting information about root partition.')
|
||||
return
|
||||
|
||||
perc_used = list_root[0]['percentage_used']
|
||||
size_bytes = _interpret_size_string(list_root[0]['size'])
|
||||
free_bytes = size_bytes * (100 - perc_used) / 100
|
||||
percent_used = list_root[0]['percent_used']
|
||||
size_bytes = list_root[0]['size']
|
||||
free_bytes = list_root[0]['free']
|
||||
free_gib = free_bytes / (1024 ** 3)
|
||||
|
||||
message = format_lazy(
|
||||
# Translators: xgettext:no-python-format
|
||||
_('Warning: Low space on system partition ({percent_used}% used, '
|
||||
'{free_space} free).'),
|
||||
percent_used=perc_used, free_space=_format_bytes(free_bytes))
|
||||
percent_used=percent_used,
|
||||
free_space=storage.format_bytes(free_bytes))
|
||||
|
||||
free_gib = free_bytes / (1024 ** 3)
|
||||
if perc_used > 90 or free_gib < 1:
|
||||
if percent_used > 90 or free_gib < 1:
|
||||
messages.error(request, message)
|
||||
elif perc_used > 75 or free_gib < 2:
|
||||
elif percent_used > 75 or free_gib < 2:
|
||||
messages.warning(request, message)
|
||||
|
||||
|
||||
def _interpret_size_string(size_str):
|
||||
"""Convert size string to number of bytes."""
|
||||
# TODO: Drop --human-readable from df command (github issue #1043)
|
||||
size_str = size_str.replace(',', '.') # some locales use commas
|
||||
size_str = size_str.replace('٫', '.') # arabic decimal separator
|
||||
if size_str[-1] in '0123456789':
|
||||
return float(size_str[:-1])
|
||||
|
||||
if size_str[-1] == 'K':
|
||||
return float(size_str[:-1]) * 1024
|
||||
|
||||
if size_str[-1] == 'M':
|
||||
return float(size_str[:-1]) * 1024 ** 2
|
||||
|
||||
if size_str[-1] == 'G':
|
||||
return float(size_str[:-1]) * 1024 ** 3
|
||||
|
||||
if size_str[-1] == 'T':
|
||||
return float(size_str[:-1]) * 1024 ** 4
|
||||
|
||||
return -1
|
||||
|
||||
|
||||
def _format_bytes(size):
|
||||
"""Return human readable disk size from bytes."""
|
||||
if not size:
|
||||
return size
|
||||
|
||||
if size < 1024:
|
||||
return _('{disk_size:.1f} bytes').format(disk_size=size)
|
||||
|
||||
if size < 1024 ** 2:
|
||||
size /= 1024
|
||||
return _('{disk_size:.1f} KiB').format(disk_size=size)
|
||||
|
||||
if size < 1024 ** 3:
|
||||
size /= 1024 ** 2
|
||||
return _('{disk_size:.1f} MiB').format(disk_size=size)
|
||||
|
||||
if size < 1024 ** 4:
|
||||
size /= 1024 ** 3
|
||||
return _('{disk_size:.1f} GiB').format(disk_size=size)
|
||||
|
||||
size /= 1024 ** 4
|
||||
return _('{disk_size:.1f} TiB').format(disk_size=size)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user