summaryrefslogtreecommitdiff
path: root/python/vyos/system/image.py
diff options
context:
space:
mode:
authorJohn Estabrook <jestabro@vyos.io>2023-10-21 13:33:37 -0500
committerJohn Estabrook <jestabro@vyos.io>2023-11-15 11:29:04 -0600
commit96b65e90fbfa1fe63d97929ac86fc910abb0caa9 (patch)
tree467b257caea8c6118dfef5eb3ac54c79b7712167 /python/vyos/system/image.py
parent8efab9ee8cdb0e65dddb9d3ba97de8ddcf3666dc (diff)
downloadvyos-1x-96b65e90fbfa1fe63d97929ac86fc910abb0caa9.tar.gz
vyos-1x-96b65e90fbfa1fe63d97929ac86fc910abb0caa9.zip
image: T4516: support for interoperability of legacy/new image tools
This commit allows management of system images with either new or legacy tools: 'add/delete/rename system image' and 'set default' are translated appropriately on booting between images with the old and new tools. Consequently, the warning of the initial commit of T4516 is dropped.
Diffstat (limited to 'python/vyos/system/image.py')
-rw-r--r--python/vyos/system/image.py88
1 files changed, 77 insertions, 11 deletions
diff --git a/python/vyos/system/image.py b/python/vyos/system/image.py
index b77c3563f..6c4e3bba5 100644
--- a/python/vyos/system/image.py
+++ b/python/vyos/system/image.py
@@ -1,4 +1,4 @@
-# Copyright 2022 VyOS maintainers and contributors <maintainers@vyos.io>
+# 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
@@ -28,12 +28,14 @@ CFG_VYOS_VARS: str = f'{GRUB_DIR_VYOS}/20-vyos-defaults-autoload.cfg'
GRUB_DIR_VYOS_VERS: str = f'{GRUB_DIR_VYOS}/vyos-versions'
# prepare regexes
REGEX_KERNEL_CMDLINE: str = r'^BOOT_IMAGE=/(?P<boot_type>boot|live)/((?P<image_version>.+)/)?vmlinuz.*$'
+REGEX_SYSTEM_CFG_VER: str = r'(\r\n|\r|\n)SYSTEM_CFG_VER\s*=\s*(?P<cfg_ver>\d+)(\r\n|\r|\n)'
# structures definitions
class ImageDetails(TypedDict):
name: str
version: str
+ tools_version: int
disk_ro: int
disk_rw: int
disk_total: int
@@ -59,26 +61,73 @@ def bootmode_detect() -> str:
return 'bios'
-def get_version(image_name: str, root_dir: str) -> str:
- """Extract version name from rootfs based on image name
+def get_image_version(mount_path: str) -> str:
+ """Extract version name from rootfs mounted at mount_path
Args:
- image_name (str): a name of image (from boot menu)
- root_dir (str): a root directory of persistence storage
+ mount_path (str): mount path of rootfs
Returns:
str: version name
"""
+ version_file: str = Path(
+ f'{mount_path}/opt/vyatta/etc/version').read_text()
+ version_name: str = version_file.lstrip('Version: ').strip()
+
+ return version_name
+
+
+def get_image_tools_version(mount_path: str) -> int:
+ """Extract image-tools version from rootfs mounted at mount_path
+
+ Args:
+ mount_path (str): mount path of rootfs
+
+ Returns:
+ str: image-tools version
+ """
+ try:
+ version_file: str = Path(
+ f'{mount_path}/usr/lib/python3/dist-packages/vyos/system/__init__.py').read_text()
+ except FileNotFoundError:
+ system_cfg_ver: int = 0
+ else:
+ res = re_compile(REGEX_SYSTEM_CFG_VER).search(version_file)
+ system_cfg_ver: int = int(res.groupdict().get('cfg_ver', 0))
+
+ return system_cfg_ver
+
+
+def get_versions(image_name: str, root_dir: str = '') -> dict[str, str]:
+ """Return versions of image and image-tools
+
+ Args:
+ image_name (str): a name of an image
+ root_dir (str, optional): an optional path to the root directory.
+ Defaults to ''.
+
+ Returns:
+ dict[str, int]: a dictionary with versions of image and image-tools
+ """
+ if not root_dir:
+ root_dir = disk.find_persistence()
+
squashfs_file: str = next(
Path(f'{root_dir}/boot/{image_name}').glob('*.squashfs')).as_posix()
with TemporaryDirectory() as squashfs_mounted:
disk.partition_mount(squashfs_file, squashfs_mounted, 'squashfs')
- version_file: str = Path(
- f'{squashfs_mounted}/opt/vyatta/etc/version').read_text()
+
+ image_version: str = get_image_version(squashfs_mounted)
+ image_tools_version: int = get_image_tools_version(squashfs_mounted)
+
disk.partition_umount(squashfs_file)
- version_name: str = version_file.lstrip('Version: ').strip()
- return version_name
+ versions: dict[str, int] = {
+ 'image': image_version,
+ 'image-tools': image_tools_version
+ }
+
+ return versions
def get_details(image_name: str, root_dir: str = '') -> ImageDetails:
@@ -95,7 +144,9 @@ def get_details(image_name: str, root_dir: str = '') -> ImageDetails:
if not root_dir:
root_dir = disk.find_persistence()
- image_version: str = get_version(image_name, root_dir)
+ versions = get_versions(image_name, root_dir)
+ image_version: str = versions.get('image', '')
+ image_tools_version: int = versions.get('image-tools', 0)
image_path: Path = Path(f'{root_dir}/boot/{image_name}')
image_path_rw: Path = Path(f'{root_dir}/boot/{image_name}/rw')
@@ -113,6 +164,7 @@ def get_details(image_name: str, root_dir: str = '') -> ImageDetails:
image_details: ImageDetails = {
'name': image_name,
'version': image_version,
+ 'tools_version': image_tools_version,
'disk_ro': image_disk_ro,
'disk_rw': image_disk_rw,
'disk_total': image_disk_ro + image_disk_rw
@@ -121,6 +173,20 @@ def get_details(image_name: str, root_dir: str = '') -> ImageDetails:
return image_details
+def get_images_details() -> list[ImageDetails]:
+ """Return information about all images
+
+ Returns:
+ list[ImageDetails]: a list of dictionaries with details about images
+ """
+ images: list[str] = grub.version_list()
+ images_details: list[ImageDetails] = list()
+ for image_name in images:
+ images_details.append(get_details(image_name))
+
+ return images_details
+
+
def get_running_image() -> str:
"""Find currently running image name
@@ -134,7 +200,7 @@ def get_running_image() -> str:
if running_image_result:
running_image: str = running_image_result.groupdict().get(
'image_version', '')
- # we need to have a fallbak for live systems
+ # we need to have a fallback for live systems
if not running_image:
running_image: str = version.get_version()