Skip to content

Commit

Permalink
[sonic_installer]Add --skip-platform-check option for sonic_installer…
Browse files Browse the repository at this point in the history
… when image mismatch (sonic-net#1791)

What I did
Add --skip-platform-check option for sonic_installer;

How I did it
Add --skip-platform-check option for sonic_installer when image ASIC mismatch;
Split verify_binary_image to verify_secureboot_image and verify_image_platform to handle
image verification more accurately.

How to verify it
Installing a bin file which differs the running platform's ASIC will fail. 

Previous command output (if the output of a command-line utility has changed)
sudo sonic-installer install --help
Usage: sonic-installer install [OPTIONS] URL
Install image from local binary or URL
Options:
-y, --yes
-f, --force_install Force installation of an image of a type which
differs from that of the current running image
--skip_migration Do not migrate current configuration to the newly
installed image
--skip-package-migration Do not migrate current packages to the newly
installed image
--help Show this message and exit.

New command output (if the output of a command-line utility has changed)
Options:
-y, --yes
-f, --force, --skip-secure-check
Force installation of an image of a non-
secure type than secure running image
--skip-platform-check Force installation of an image of a type
which is not of the same platform
--skip_migration Do not migrate current configuration to the
newly installed image
--skip-package-migration Do not migrate current packages to the newly
installed image
--help Show this message and exit.
  • Loading branch information
wen587 authored Sep 14, 2021
1 parent c007d65 commit f1086ee
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 10 deletions.
5 changes: 4 additions & 1 deletion sonic_installer/bootloader/aboot.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,10 @@ def get_binary_image_version(self, image_path):
return None
return IMAGE_PREFIX + version.strip()

def verify_binary_image(self, image_path):
def verify_image_platform(self, image_path):
return os.path.isfile(image_path)

def verify_secureboot_image(self, image_path):
try:
subprocess.check_call(['/usr/bin/unzip', '-tq', image_path])
return self._verify_secureboot_image(image_path)
Expand Down
8 changes: 6 additions & 2 deletions sonic_installer/bootloader/bootloader.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,12 @@ def get_binary_image_version(self, image_path):
"""returns the version of the image"""
raise NotImplementedError

def verify_binary_image(self, image_path):
"""verify that the image is supported by the bootloader"""
def verify_image_platform(self, image_path):
"""verify that the image is of the same platform than running platform"""
raise NotImplementedError

def verify_secureboot_image(self, image_path):
"""verify that the image is secure running image"""
raise NotImplementedError

def verify_next_image(self):
Expand Down
34 changes: 34 additions & 0 deletions sonic_installer/bootloader/grub.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,17 @@

import click

from sonic_py_common import device_info
from ..common import (
HOST_PATH,
IMAGE_DIR_PREFIX,
IMAGE_PREFIX,
run_command,
)
from .onie import OnieInstallerBootloader
from .onie import default_sigpipe

MACHINE_CONF = "installer/machine.conf"

class GrubBootloader(OnieInstallerBootloader):

Expand Down Expand Up @@ -81,6 +85,36 @@ def remove_image(self, image):
run_command('grub-set-default --boot-directory=' + HOST_PATH + ' 0')
click.echo('Image removed')

def verify_image_platform(self, image_path):
if not os.path.isfile(image_path):
return False

# Get running platform's ASIC
try:
version_info = device_info.get_sonic_version_info()
if version_info:
asic_type = version_info['asic_type']
else:
asic_type = None
except (KeyError, TypeError) as e:
click.echo("Caught an exception: " + str(e))

# Get installing image's ASIC
p1 = subprocess.Popen(["sed", "-e", "1,/^exit_marker$/d", image_path], stdout=subprocess.PIPE, preexec_fn=default_sigpipe)
p2 = subprocess.Popen(["tar", "xf", "-", MACHINE_CONF, "-O"], stdin=p1.stdout, stdout=subprocess.PIPE, preexec_fn=default_sigpipe)
p3 = subprocess.Popen(["sed", "-n", r"s/^machine=\(.*\)/\1/p"], stdin=p2.stdout, stdout=subprocess.PIPE, preexec_fn=default_sigpipe, text=True)

stdout = p3.communicate()[0]
image_asic = stdout.rstrip('\n')

# Return false if machine is not found or unexpected issue occur
if not image_asic:
return False

if asic_type == image_asic:
return True
return False

@classmethod
def detect(cls):
return os.path.isfile(os.path.join(HOST_PATH, 'grub/grub.cfg'))
2 changes: 1 addition & 1 deletion sonic_installer/bootloader/onie.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,5 +44,5 @@ def get_binary_image_version(self, image_path):

return IMAGE_PREFIX + version_num

def verify_binary_image(self, image_path):
def verify_secureboot_image(self, image_path):
return os.path.isfile(image_path)
3 changes: 3 additions & 0 deletions sonic_installer/bootloader/uboot.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@ def remove_image(self, image):
subprocess.call(['rm','-rf', HOST_PATH + '/' + image_dir])
click.echo('Done')

def verify_image_platform(self, image_path):
return os.path.isfile(image_path)

@classmethod
def detect(cls):
arch = platform.machine()
Expand Down
21 changes: 15 additions & 6 deletions sonic_installer/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -480,8 +480,10 @@ def sonic_installer():
@sonic_installer.command('install')
@click.option('-y', '--yes', is_flag=True, callback=abort_if_false,
expose_value=False, prompt='New image will be installed, continue?')
@click.option('-f', '--force', is_flag=True,
help="Force installation of an image of a type which differs from that of the current running image")
@click.option('-f', '--force', '--skip-secure-check', is_flag=True,
help="Force installation of an image of a non-secure type than secure running image")
@click.option('--skip-platform-check', is_flag=True,
help="Force installation of an image of a type which is not of the same platform")
@click.option('--skip_migration', is_flag=True,
help="Do not migrate current configuration to the newly installed image")
@click.option('--skip-package-migration', is_flag=True,
Expand All @@ -500,7 +502,7 @@ def sonic_installer():
cls=clicommon.MutuallyExclusiveOption, mutually_exclusive=['skip_setup_swap'],
callback=validate_positive_int)
@click.argument('url')
def install(url, force, skip_migration=False, skip_package_migration=False,
def install(url, force, skip_platform_check=False, skip_migration=False, skip_package_migration=False,
skip_setup_swap=False, swap_mem_size=None, total_mem_threshold=None, available_mem_threshold=None):
""" Install image from local binary or URL"""
bootloader = get_bootloader()
Expand Down Expand Up @@ -530,10 +532,17 @@ def install(url, force, skip_migration=False, skip_package_migration=False,
echo_and_log('Error: Failed to set image as default', LOG_ERR)
raise click.Abort()
else:
# Verify that the binary image is of the same type as the running image
if not bootloader.verify_binary_image(image_path) and not force:
# Verify not installing non-secure image in a secure running image
if not bootloader.verify_secureboot_image(image_path) and not force:
echo_and_log("Image file '{}' is of a different type than running image.\n".format(url) +
"If you are sure you want to install this image, use -f|--force.\n" +
"If you are sure you want to install this image, use -f|--force|--skip-secure-check.\n" +
"Aborting...", LOG_ERR)
raise click.Abort()

# Verify that the binary image is of the same platform type as running platform
if not bootloader.verify_image_platform(image_path) and not skip_platform_check:
echo_and_log("Image file '{}' is of a different platform type than running platform.\n".format(url) +
"If you are sure you want to install this image, use --skip-platform-check.\n" +
"Aborting...", LOG_ERR)
raise click.Abort()

Expand Down

0 comments on commit f1086ee

Please sign in to comment.