Page MenuHomeVyOS Platform

No OneTemporary

Size
10 KB
Referenced Files
None
Subscribers
None
diff --git a/python/vyos/utils/convert.py b/python/vyos/utils/convert.py
index 9a8a1ff7d..c02f0071e 100644
--- a/python/vyos/utils/convert.py
+++ b/python/vyos/utils/convert.py
@@ -1,197 +1,200 @@
# Copyright 2023 VyOS maintainers and contributors <maintainers@vyos.io>
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library. If not, see <http://www.gnu.org/licenses/>.
def seconds_to_human(s, separator=""):
""" Converts number of seconds passed to a human-readable
interval such as 1w4d18h35m59s
"""
s = int(s)
week = 60 * 60 * 24 * 7
day = 60 * 60 * 24
hour = 60 * 60
remainder = 0
result = ""
weeks = s // week
if weeks > 0:
result = "{0}w".format(weeks)
s = s % week
days = s // day
if days > 0:
result = "{0}{1}{2}d".format(result, separator, days)
s = s % day
hours = s // hour
if hours > 0:
result = "{0}{1}{2}h".format(result, separator, hours)
s = s % hour
minutes = s // 60
if minutes > 0:
result = "{0}{1}{2}m".format(result, separator, minutes)
s = s % 60
seconds = s
if seconds > 0:
result = "{0}{1}{2}s".format(result, separator, seconds)
return result
-def bytes_to_human(bytes, initial_exponent=0, precision=2):
+def bytes_to_human(bytes, initial_exponent=0, precision=2,
+ int_below_exponent=0):
""" Converts a value in bytes to a human-readable size string like 640 KB
The initial_exponent parameter is the exponent of 2,
e.g. 10 (1024) for kilobytes, 20 (1024 * 1024) for megabytes.
"""
if bytes == 0:
return "0 B"
from math import log2
bytes = bytes * (2**initial_exponent)
# log2 is a float, while range checking requires an int
exponent = int(log2(bytes))
+ if exponent < int_below_exponent:
+ precision = 0
if exponent < 10:
value = bytes
suffix = "B"
elif exponent in range(10, 20):
value = bytes / 1024
suffix = "KB"
elif exponent in range(20, 30):
value = bytes / 1024**2
suffix = "MB"
elif exponent in range(30, 40):
value = bytes / 1024**3
suffix = "GB"
else:
value = bytes / 1024**4
suffix = "TB"
# Add a new case when the first machine with petabyte RAM
# hits the market.
size_string = "{0:.{1}f} {2}".format(value, precision, suffix)
return size_string
def human_to_bytes(value):
""" Converts a data amount with a unit suffix to bytes, like 2K to 2048 """
from re import match as re_match
res = re_match(r'^\s*(\d+(?:\.\d+)?)\s*([a-zA-Z]+)\s*$', value)
if not res:
raise ValueError(f"'{value}' is not a valid data amount")
else:
amount = float(res.group(1))
unit = res.group(2).lower()
if unit == 'b':
res = amount
elif (unit == 'k') or (unit == 'kb'):
res = amount * 1024
elif (unit == 'm') or (unit == 'mb'):
res = amount * 1024**2
elif (unit == 'g') or (unit == 'gb'):
res = amount * 1024**3
elif (unit == 't') or (unit == 'tb'):
res = amount * 1024**4
else:
raise ValueError(f"Unsupported data unit '{unit}'")
# There cannot be fractional bytes, so we convert them to integer.
# However, truncating causes problems with conversion back to human unit,
# so we round instead -- that seems to work well enough.
return round(res)
def mac_to_eui64(mac, prefix=None):
"""
Convert a MAC address to a EUI64 address or, with prefix provided, a full
IPv6 address.
Thankfully copied from https://gist.github.com/wido/f5e32576bb57b5cc6f934e177a37a0d3
"""
import re
from ipaddress import ip_network
# http://tools.ietf.org/html/rfc4291#section-2.5.1
eui64 = re.sub(r'[.:-]', '', mac).lower()
eui64 = eui64[0:6] + 'fffe' + eui64[6:]
eui64 = hex(int(eui64[0:2], 16) ^ 2)[2:].zfill(2) + eui64[2:]
if prefix is None:
return ':'.join(re.findall(r'.{4}', eui64))
else:
try:
net = ip_network(prefix, strict=False)
euil = int('0x{0}'.format(eui64), 16)
return str(net[euil])
except: # pylint: disable=bare-except
return
def convert_data(data) -> dict | list | tuple | str | int | float | bool | None:
"""Filter and convert multiple types of data to types usable in CLI/API
WARNING: Must not be used for anything except formatting output for API or CLI
On the output allowed everything supported in JSON.
Args:
data (Any): input data
Returns:
dict | list | tuple | str | int | float | bool | None: converted data
"""
from base64 import b64encode
# return original data for types which do not require conversion
if isinstance(data, str | int | float | bool | None):
return data
if isinstance(data, list):
list_tmp = []
for item in data:
list_tmp.append(convert_data(item))
return list_tmp
if isinstance(data, tuple):
list_tmp = list(data)
tuple_tmp = tuple(convert_data(list_tmp))
return tuple_tmp
if isinstance(data, bytes | bytearray):
try:
return data.decode()
except UnicodeDecodeError:
return b64encode(data).decode()
if isinstance(data, set | frozenset):
list_tmp = convert_data(list(data))
return list_tmp
if isinstance(data, dict):
dict_tmp = {}
for key, value in data.items():
dict_tmp[key] = convert_data(value)
return dict_tmp
# do not return anything for other types
# which cannot be converted to JSON
# for example: complex | range | memoryview
return
diff --git a/src/op_mode/image_info.py b/src/op_mode/image_info.py
index ae0677196..14dca7476 100755
--- a/src/op_mode/image_info.py
+++ b/src/op_mode/image_info.py
@@ -1,108 +1,112 @@
#!/usr/bin/env python3
#
# Copyright 2022 VyOS maintainers and contributors <maintainers@vyos.io>
#
# This file is part of VyOS.
#
# VyOS is free software: you can redistribute it and/or modify it under the
# terms of the GNU General Public License as published by the Free Software
# Foundation, either version 3 of the License, or (at your option) any later
# version.
#
# VyOS is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along with
# VyOS. If not, see <https://www.gnu.org/licenses/>.
import sys
from typing import List, Union
-from hurry.filesize import size
from tabulate import tabulate
from vyos import opmode
from vyos.system import disk, grub, image
+from vyos.utils.convert import bytes_to_human
def _format_show_images_summary(images_summary: image.BootDetails) -> str:
headers: list[str] = ['Name', 'Default boot', 'Running']
table_data: list[list[str]] = list()
for image_item in images_summary.get('images_available', []):
name: str = image_item
if images_summary.get('image_default') == name:
default: str = 'Yes'
else:
default: str = ''
if images_summary.get('image_running') == name:
running: str = 'Yes'
else:
running: str = ''
table_data.append([name, default, running])
tabulated: str = tabulate(table_data, headers)
return tabulated
def _format_show_images_details(
images_details: list[image.ImageDetails]) -> str:
headers: list[str] = [
'Name', 'Version', 'Storage Read-Only', 'Storage Read-Write',
'Storage Total'
]
table_data: list[list[Union[str, int]]] = list()
for image_item in images_details:
name: str = image_item.get('name')
version: str = image_item.get('version')
- disk_ro: int = size(image_item.get('disk_ro'))
- disk_rw: int = size(image_item.get('disk_rw'))
- disk_total: int = size(image_item.get('disk_total'))
+ disk_ro: str = bytes_to_human(image_item.get('disk_ro'),
+ precision=1, int_below_exponent=30)
+ disk_rw: str = bytes_to_human(image_item.get('disk_rw'),
+ precision=1, int_below_exponent=30)
+ disk_total: str = bytes_to_human(image_item.get('disk_total'),
+ precision=1, int_below_exponent=30)
table_data.append([name, version, disk_ro, disk_rw, disk_total])
- tabulated: str = tabulate(table_data, headers)
+ tabulated: str = tabulate(table_data, headers,
+ colalign=('left', 'left', 'right', 'right', 'right'))
return tabulated
def show_images_summary(raw: bool) -> Union[image.BootDetails, str]:
images_available: list[str] = grub.version_list()
root_dir: str = disk.find_persistence()
boot_vars: dict = grub.vars_read(f'{root_dir}/{image.CFG_VYOS_VARS}')
images_summary: image.BootDetails = dict()
images_summary['image_default'] = image.get_default_image()
images_summary['image_running'] = image.get_running_image()
images_summary['images_available'] = images_available
images_summary['console_type'] = boot_vars.get('console_type')
images_summary['console_num'] = boot_vars.get('console_num')
if raw:
return images_summary
else:
return _format_show_images_summary(images_summary)
def show_images_details(raw: bool) -> Union[list[image.ImageDetails], str]:
images: list[str] = grub.version_list()
images_details: list[image.ImageDetails] = list()
for image_name in images:
images_details.append(image.get_details(image_name))
if raw:
return images_details
else:
return _format_show_images_details(images_details)
if __name__ == '__main__':
try:
res = opmode.run(sys.modules[__name__])
if res:
print(res)
except (ValueError, opmode.Error) as e:
print(e)
sys.exit(1)

File Metadata

Mime Type
text/x-diff
Expires
Fri, Nov 6, 9:50 AM (1 h, 24 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
4654054
Default Alt Text
(10 KB)

Event Timeline