From 668c116731df715ffec4551c7c17d3faf738ff82 Mon Sep 17 00:00:00 2001 From: Nazarii Hnydyn Date: Tue, 24 Mar 2020 13:06:31 +0200 Subject: [PATCH] [fwutil]: Use overlay driver when mounting next image filesystem (#825) * [fwutil]: Use overlay driver when mounting next image filesystem. Signed-off-by: Nazarii Hnydyn * [fwutil]: Update command reference. Signed-off-by: Nazarii Hnydyn --- doc/Command-Reference.md | 2 +- fwutil/lib.py | 51 ++++++++++++++++++++++++++++++---------- fwutil/log.py | 3 +++ fwutil/main.py | 12 ++++++---- 4 files changed, 50 insertions(+), 18 deletions(-) diff --git a/doc/Command-Reference.md b/doc/Command-Reference.md index c6f3fbfd636f..5c41983cb068 100644 --- a/doc/Command-Reference.md +++ b/doc/Command-Reference.md @@ -4117,7 +4117,7 @@ Supported options: 2. -f|--force - install FW regardless the current version 3. -i|--image - update FW using current/next SONiC image -Note: the default option is --image=current +Note: the default option is --image=current (current/next values are taken from `sonic_installer list`) Go Back To [Beginning of the document](#) or [Beginning of this section](#platform-component-firmware) diff --git a/fwutil/lib.py b/fwutil/lib.py index 60377c283a75..b065c9eefa67 100755 --- a/fwutil/lib.py +++ b/fwutil/lib.py @@ -201,43 +201,67 @@ class SquashFs(object): OS_PREFIX = "SONiC-OS-" FS_PATH_TEMPLATE = "/host/image-{}/fs.squashfs" + FS_RW_TEMPLATE = "/host/image-{}/rw" + FS_WORK_TEMPLATE = "/host/image-{}/work" FS_MOUNTPOINT_TEMPLATE = "/tmp/image-{}-fs" - def __init__(self): - current_image = self.__get_current_image() - next_image = self.__get_next_image() - - if current_image == next_image: - raise RuntimeError("Next boot image is not set") + OVERLAY_MOUNTPOINT_TEMPLATE = "/tmp/image-{}-overlay" - image_stem = next_image.lstrip(self.OS_PREFIX) + def __init__(self): + image_stem = self.next_image.lstrip(self.OS_PREFIX) self.fs_path = self.FS_PATH_TEMPLATE.format(image_stem) + self.fs_rw = self.FS_RW_TEMPLATE.format(image_stem) + self.fs_work = self.FS_WORK_TEMPLATE.format(image_stem) self.fs_mountpoint = self.FS_MOUNTPOINT_TEMPLATE.format(image_stem) - def __get_current_image(self): + self.overlay_mountpoint = self.OVERLAY_MOUNTPOINT_TEMPLATE.format(image_stem) + + def get_current_image(self): cmd = "sonic_installer list | grep 'Current: ' | cut -f2 -d' '" output = subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True) return output.rstrip(NEWLINE) - def __get_next_image(self): + def get_next_image(self): cmd = "sonic_installer list | grep 'Next: ' | cut -f2 -d' '" output = subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True) return output.rstrip(NEWLINE) + def is_next_boot_set(self): + return self.current_image != self.next_image + def mount_next_image_fs(self): - if os.path.ismount(self.fs_mountpoint): + if os.path.ismount(self.fs_mountpoint) or os.path.ismount(self.overlay_mountpoint): self.umount_next_image_fs() os.mkdir(self.fs_mountpoint) - cmd = "mount -t squashfs {} {}".format(self.fs_path, self.fs_mountpoint) + cmd = "mount -t squashfs {} {}".format( + self.fs_path, + self.fs_mountpoint + ) subprocess.check_call(cmd, shell=True) - return self.fs_mountpoint + os.mkdir(self.overlay_mountpoint) + cmd = "mount -n -r -t overlay -o lowerdir={},upperdir={},workdir={} overlay {}".format( + self.fs_mountpoint, + self.fs_rw, + self.fs_work, + self.overlay_mountpoint + ) + subprocess.check_call(cmd, shell=True) + + return self.overlay_mountpoint def umount_next_image_fs(self): + if os.path.ismount(self.overlay_mountpoint): + cmd = "umount -rf {}".format(self.overlay_mountpoint) + subprocess.check_call(cmd, shell=True) + + if os.path.exists(self.overlay_mountpoint): + os.rmdir(self.overlay_mountpoint) + if os.path.ismount(self.fs_mountpoint): cmd = "umount -rf {}".format(self.fs_mountpoint) subprocess.check_call(cmd, shell=True) @@ -245,6 +269,9 @@ def umount_next_image_fs(self): if os.path.exists(self.fs_mountpoint): os.rmdir(self.fs_mountpoint) + current_image = property(fget=get_current_image) + next_image = property(fget=get_next_image) + class PlatformComponentsParser(object): """ diff --git a/fwutil/log.py b/fwutil/log.py index 0580e4bb279f..a686c437ef08 100755 --- a/fwutil/log.py +++ b/fwutil/log.py @@ -124,3 +124,6 @@ def log_fw_install_end(self, component, firmware, status, exception=None): def print_error(self, msg): click.echo("Error: {}.".format(msg)) + + def print_warning(self, msg): + click.echo("Warning: {}.".format(msg)) diff --git a/fwutil/main.py b/fwutil/main.py index c1443627c199..7f03e54ab00e 100755 --- a/fwutil/main.py +++ b/fwutil/main.py @@ -227,14 +227,16 @@ def update(ctx, yes, force, image): squashfs = None try: - cup = None + cup = ComponentUpdateProvider() if image == IMAGE_NEXT: squashfs = SquashFs() - fs_path = squashfs.mount_next_image_fs() - cup = ComponentUpdateProvider(fs_path) - else: - cup = ComponentUpdateProvider() + + if squashfs.is_next_boot_set(): + fs_path = squashfs.mount_next_image_fs() + cup = ComponentUpdateProvider(fs_path) + else: + log_helper.print_warning("Next boot is set to current: fallback to defaults") click.echo(cup.get_status(force))