summaryrefslogtreecommitdiff
path: root/src
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 /src
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 'src')
-rwxr-xr-xsrc/op_mode/image_info.py7
-rwxr-xr-xsrc/op_mode/image_installer.py17
-rwxr-xr-xsrc/op_mode/image_manager.py7
-rw-r--r--src/system/grub_update.py141
4 files changed, 36 insertions, 136 deletions
diff --git a/src/op_mode/image_info.py b/src/op_mode/image_info.py
index 14dca7476..791001e00 100755
--- a/src/op_mode/image_info.py
+++ b/src/op_mode/image_info.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
#
-# Copyright 2022 VyOS maintainers and contributors <maintainers@vyos.io>
+# Copyright 2023 VyOS maintainers and contributors <maintainers@vyos.io>
#
# This file is part of VyOS.
#
@@ -91,10 +91,7 @@ def show_images_summary(raw: bool) -> Union[image.BootDetails, str]:
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))
+ images_details = image.get_images_details()
if raw:
return images_details
diff --git a/src/op_mode/image_installer.py b/src/op_mode/image_installer.py
index 12d32968c..2d998f5e1 100755
--- a/src/op_mode/image_installer.py
+++ b/src/op_mode/image_installer.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
#
-# Copyright 2022 VyOS maintainers and contributors <maintainers@vyos.io>
+# Copyright 2023 VyOS maintainers and contributors <maintainers@vyos.io>
#
# This file is part of VyOS.
#
@@ -28,7 +28,7 @@ from psutil import disk_partitions
from vyos.configtree import ConfigTree
from vyos.remote import download
-from vyos.system import disk, grub, image
+from vyos.system import disk, grub, image, compat, SYSTEM_CFG_VER
from vyos.template import render
from vyos.utils.io import ask_input, ask_yes_no
from vyos.utils.file import chmod_2775
@@ -462,6 +462,7 @@ def install_image() -> None:
exit(1)
+@compat.grub_cfg_update
def add_image(image_path: str) -> None:
"""Add a new image
@@ -488,10 +489,16 @@ def add_image(image_path: str) -> None:
Path(DIR_ROOTFS_SRC).mkdir(mode=0o755, parents=True)
disk.partition_mount(f'{DIR_ISO_MOUNT}/live/filesystem.squashfs',
DIR_ROOTFS_SRC, 'squashfs')
- version_file: str = Path(
- f'{DIR_ROOTFS_SRC}/opt/vyatta/etc/version').read_text()
+
+ cfg_ver: str = image.get_image_tools_version(DIR_ROOTFS_SRC)
+ version_name: str = image.get_image_version(DIR_ROOTFS_SRC)
+
disk.partition_umount(f'{DIR_ISO_MOUNT}/live/filesystem.squashfs')
- version_name: str = version_file.lstrip('Version: ').strip()
+
+ if cfg_ver < SYSTEM_CFG_VER:
+ raise compat.DowngradingImageTools(
+ f'Adding image would downgrade image tools to v.{cfg_ver}; disallowed')
+
image_name: str = ask_input(MSG_INPUT_IMAGE_NAME, version_name)
set_as_default: bool = ask_yes_no(MSG_INPUT_IMAGE_DEFAULT, default=True)
diff --git a/src/op_mode/image_manager.py b/src/op_mode/image_manager.py
index 76fc4367f..725c40613 100755
--- a/src/op_mode/image_manager.py
+++ b/src/op_mode/image_manager.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
#
-# Copyright 2022 VyOS maintainers and contributors <maintainers@vyos.io>
+# Copyright 2023 VyOS maintainers and contributors <maintainers@vyos.io>
#
# This file is part of VyOS.
#
@@ -22,10 +22,11 @@ from pathlib import Path
from shutil import rmtree
from sys import exit
-from vyos.system import disk, grub, image
+from vyos.system import disk, grub, image, compat
from vyos.utils.io import ask_yes_no
+@compat.grub_cfg_update
def delete_image(image_name: str) -> None:
"""Remove installed image files and boot entry
@@ -57,6 +58,7 @@ def delete_image(image_name: str) -> None:
exit(f'Unable to remove the image "{image_name}": {err}')
+@compat.grub_cfg_update
def set_image(image_name: str) -> None:
"""Set default boot image
@@ -86,6 +88,7 @@ def set_image(image_name: str) -> None:
exit(f'Unable to set default image "{image_name}": {err}')
+@compat.grub_cfg_update
def rename_image(name_old: str, name_new: str) -> None:
"""Rename installed image
diff --git a/src/system/grub_update.py b/src/system/grub_update.py
index 1ae66464b..da1986e9d 100644
--- a/src/system/grub_update.py
+++ b/src/system/grub_update.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
#
-# Copyright 2022 VyOS maintainers and contributors <maintainers@vyos.io>
+# Copyright 2023 VyOS maintainers and contributors <maintainers@vyos.io>
#
# This file is part of VyOS.
#
@@ -18,23 +18,11 @@
# VyOS. If not, see <https://www.gnu.org/licenses/>.
from pathlib import Path
-from re import compile, MULTILINE, DOTALL
from sys import exit
-from vyos.system import disk, grub, image
+from vyos.system import disk, grub, image, compat, SYSTEM_CFG_VER
from vyos.template import render
-# define configuration version
-CFG_VER = 1
-
-# define regexes and variables
-REGEX_VERSION = r'^menuentry "[^\n]*{\n[^}]*\s+linux /boot/(?P<version>\S+)/[^}]*}'
-REGEX_MENUENTRY = r'^menuentry "[^\n]*{\n[^}]*\s+linux /boot/(?P<version>\S+)/vmlinuz (?P<options>[^\n]+)\n[^}]*}'
-REGEX_CONSOLE = r'^.*console=(?P<console_type>[^\s\d]+)(?P<console_num>[\d]+).*$'
-REGEX_SANIT_CONSOLE = r'\ ?console=[^\s\d]+[\d]+(,\d+)?\ ?'
-REGEX_SANIT_INIT = r'\ ?init=\S*\ ?'
-PW_RESET_OPTION = 'init=/opt/vyatta/sbin/standalone_root_pw_reset'
-
def cfg_check_update() -> bool:
"""Check if GRUB structure update is required
@@ -43,111 +31,10 @@ def cfg_check_update() -> bool:
bool: False if not required, True if required
"""
current_ver = grub.get_cfg_ver()
- if current_ver and current_ver >= CFG_VER:
+ if current_ver and current_ver >= SYSTEM_CFG_VER:
return False
- else:
- return True
-
-
-def find_versions(menu_entries: list) -> list:
- """Find unique VyOS versions from menu entries
-
- Args:
- menu_entries (list): a list with menu entries
-
- Returns:
- list: List of installed versions
- """
- versions = []
- for vyos_ver in menu_entries:
- versions.append(vyos_ver.get('version'))
- # remove duplicates
- versions = list(set(versions))
- return versions
-
-def filter_unparsed(grub_path: str) -> str:
- """Find currently installed VyOS version
-
- Args:
- grub_path (str): a path to the grub.cfg file
-
- Returns:
- str: unparsed grub.cfg items
- """
- config_text = Path(grub_path).read_text()
- regex_filter = compile(REGEX_VERSION, MULTILINE | DOTALL)
- filtered = regex_filter.sub('', config_text)
- regex_filter = compile(grub.REGEX_GRUB_VARS, MULTILINE)
- filtered = regex_filter.sub('', filtered)
- regex_filter = compile(grub.REGEX_GRUB_MODULES, MULTILINE)
- filtered = regex_filter.sub('', filtered)
- # strip extra new lines
- filtered = filtered.strip()
- return filtered
-
-
-def sanitize_boot_opts(boot_opts: str) -> str:
- """Sanitize boot options from console and init
-
- Args:
- boot_opts (str): boot options
-
- Returns:
- str: sanitized boot options
- """
- regex_filter = compile(REGEX_SANIT_CONSOLE)
- boot_opts = regex_filter.sub('', boot_opts)
- regex_filter = compile(REGEX_SANIT_INIT)
- boot_opts = regex_filter.sub('', boot_opts)
-
- return boot_opts
-
-
-def parse_entry(entry: tuple) -> dict:
- """Parse GRUB menuentry
-
- Args:
- entry (tuple): tuple of (version, options)
-
- Returns:
- dict: dictionary with parsed options
- """
- # save version to dict
- entry_dict = {'version': entry[0]}
- # detect boot mode type
- if PW_RESET_OPTION in entry[1]:
- entry_dict['bootmode'] = 'pw_reset'
- else:
- entry_dict['bootmode'] = 'normal'
- # find console type and number
- regex_filter = compile(REGEX_CONSOLE)
- entry_dict.update(regex_filter.match(entry[1]).groupdict())
- entry_dict['boot_opts'] = sanitize_boot_opts(entry[1])
-
- return entry_dict
-
-
-def parse_menuntries(grub_path: str) -> list:
- """Parse all GRUB menuentries
-
- Args:
- grub_path (str): a path to GRUB config file
-
- Returns:
- list: list with menu items (each item is a dict)
- """
- menuentries = []
- # read configuration file
- config_text = Path(grub_path).read_text()
- # parse menuentries to tuples (version, options)
- regex_filter = compile(REGEX_MENUENTRY, MULTILINE)
- filter_results = regex_filter.findall(config_text)
- # parse each entry
- for entry in filter_results:
- menuentries.append(parse_entry(entry))
-
- return menuentries
+ return True
if __name__ == '__main__':
@@ -162,12 +49,12 @@ if __name__ == '__main__':
root_dir = disk.find_persistence()
# read current GRUB config
- grub_cfg_main = f'{root_dir}/{image.GRUB_DIR_MAIN}/grub.cfg'
+ grub_cfg_main = f'{root_dir}/{grub.GRUB_CFG_MAIN}'
vars = grub.vars_read(grub_cfg_main)
modules = grub.modules_read(grub_cfg_main)
- vyos_menuentries = parse_menuntries(grub_cfg_main)
- vyos_versions = find_versions(vyos_menuentries)
- unparsed_items = filter_unparsed(grub_cfg_main)
+ vyos_menuentries = compat.parse_menuentries(grub_cfg_main)
+ vyos_versions = compat.find_versions(vyos_menuentries)
+ unparsed_items = compat.filter_unparsed(grub_cfg_main)
# find default values
default_entry = vyos_menuentries[int(vars['default'])]
@@ -185,13 +72,12 @@ if __name__ == '__main__':
# print(f'unparsed_items: {unparsed_items}')
# create new files
- grub_cfg_vars = f'{root_dir}/{image.CFG_VYOS_VARS}'
+ grub_cfg_vars = f'{root_dir}/{grub.CFG_VYOS_VARS}'
grub_cfg_modules = f'{root_dir}/{grub.CFG_VYOS_MODULES}'
grub_cfg_platform = f'{root_dir}/{grub.CFG_VYOS_PLATFORM}'
grub_cfg_menu = f'{root_dir}/{grub.CFG_VYOS_MENU}'
grub_cfg_options = f'{root_dir}/{grub.CFG_VYOS_OPTIONS}'
- render(grub_cfg_main, grub.TMPL_GRUB_MAIN, {})
Path(image.GRUB_DIR_VYOS).mkdir(exist_ok=True)
grub.vars_write(grub_cfg_vars, vars)
grub.modules_write(grub_cfg_modules, modules)
@@ -210,5 +96,12 @@ if __name__ == '__main__':
grub.version_add(vyos_ver, root_dir, boot_opts)
# update structure version
- grub.write_cfg_ver(CFG_VER, root_dir)
+ cfg_ver = compat.update_cfg_ver(root_dir)
+ grub.write_cfg_ver(cfg_ver, root_dir)
+
+ if compat.mode():
+ compat.render_grub_cfg(root_dir)
+ else:
+ render(grub_cfg_main, grub.TMPL_GRUB_MAIN, {})
+
exit(0)