Skip to content

Commit

Permalink
Fix snap boot kernel path (Bugfix) (#884)
Browse files Browse the repository at this point in the history
As describe in this snap doc[1], to access to host’s snap-related files, it's now have to access via /var/lib/snapd/hostfs. This system-backup interface gives privileged read-only access to system data. The change can be traced back to snapd 2.36.

[1] https://snapcraft.io/docs/the-system-backup-interface

* fix snap boot kernel path

* add comment for reference

* add unit test for boot_mode_test_snappy.py

* amend for flake8 check

* remove unnecessary test data

Co-authored-by: Pierre Equoy <pierre.equoy@canonical.com>

---------

Co-authored-by: Pierre Equoy <pierre.equoy@canonical.com>
  • Loading branch information
nancyc12 and pieqq authored Jan 10, 2024
1 parent e5349d7 commit 45f1137
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 17 deletions.
50 changes: 33 additions & 17 deletions providers/base/bin/boot_mode_test_snappy.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,18 +61,8 @@ def fitdumpimage(filename):
return objects


def main():
if len(sys.argv) != 3:
raise SystemExit('ERROR: please supply gadget & kernel name')
gadget = sys.argv[1]
kernel = sys.argv[2]

gadget_yaml = os.path.join('/snap', gadget, 'current/meta/gadget.yaml')

if not os.path.exists(gadget_yaml):
raise SystemExit(
'ERROR: failed to find gadget.yaml at {}'.format(gadget_yaml))

def get_bootloader(gadget_yaml):
"""Parse gadget.yaml to get bootloader"""
with open(gadget_yaml) as f:
data = yaml.load(f, Loader=yaml.SafeLoader)
for k in data['volumes'].keys():
Expand All @@ -84,16 +74,42 @@ def main():

if bootloader not in ('u-boot', 'grub', 'lk'):
raise SystemExit(
'ERROR: Unexpected bootloader name {}'.format(bootloader))
'ERROR: Unexpected bootloader name {}'.format(bootloader)
)
print('Bootloader is {}\n'.format(bootloader))
return bootloader


def get_uboot_kernel(kernel):
"""Get u-boot kernel path"""
kernel_rev = os.path.basename(
os.path.realpath('/snap/{}/current'.format(kernel))
)
# update boot kernel path according to
# https://snapcraft.io/docs/the-system-backup-interface
return '/var/lib/snapd/hostfs/boot/uboot/{}_{}.snap/kernel.img'.format(
kernel, kernel_rev
)


def main():
if len(sys.argv) != 3:
raise SystemExit('ERROR: please supply gadget & kernel name')
gadget = sys.argv[1]
kernel = sys.argv[2]

gadget_yaml = os.path.join('/snap', gadget, 'current/meta/gadget.yaml')

if not os.path.exists(gadget_yaml):
raise SystemExit(
'ERROR: failed to find gadget.yaml at {}'.format(gadget_yaml))

bootloader = get_bootloader(gadget_yaml)

if bootloader == 'u-boot':
print('Parsing FIT image information...\n')

kernel_rev = os.path.basename(
os.path.realpath('/snap/{}/current'.format(kernel)))
boot_kernel = '/boot/uboot/{}_{}.snap/kernel.img'.format(
kernel, kernel_rev)
boot_kernel = get_uboot_kernel(kernel)
boot_objects = fitdumpimage(boot_kernel)

for obj, attrs in boot_objects.items():
Expand Down
39 changes: 39 additions & 0 deletions providers/base/tests/test_boot_mode_test_snappy.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#!/usr/bin/env python3
# Copyright 2023 Canonical Ltd.
# Written by:
# Nancy Chen <nancy.chen@canonical.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 3,
# as published by the Free Software Foundation.
#
# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.

import unittest
import os
from boot_mode_test_snappy import get_bootloader, get_uboot_kernel


class TestBootModeTestSnappy(unittest.TestCase):
def test_get_bootloader(self):
"""Test for get_bootloader function"""
kdrp_kdrp_k4500_gadget_yaml = os.path.join(
os.path.dirname(os.path.abspath(__file__)),
"test_data/kdrp-kdrp-k4500-gadget.yaml",
)
self.assertEqual("u-boot", get_bootloader(kdrp_kdrp_k4500_gadget_yaml))

def test_get_uboot_kernel(self):
"""
Test if system-backup interface is included in kernel.img file path
https://snapcraft.io/docs/the-system-backup-interface
"""
self.assertIn(
"/var/lib/snapd/hostfs/boot/uboot/", get_uboot_kernel("kernel")
)
40 changes: 40 additions & 0 deletions providers/base/tests/test_data/kdrp-kdrp-k4500-gadget.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
volumes:
kdrp-k4500:
schema: mbr
bootloader: u-boot
structure:
- name: ubuntu-seed
role: system-seed
filesystem: vfat
type: 0C
size: 2400M
content:
- source: $kernel:boot-assets/boot-assets/
target: /
- source: $kernel:dtbs/dtbs/bcm2710-rpi-custom-keurig.dtb
target: /
- source: $kernel:dtbs/dtbs/dt-blob-keurig.dtb
target: /dt-blob.bin
- source: $kernel:dtbs/dtbs/overlays/
target: /overlays
- name: ubuntu-boot
role: system-boot
filesystem: vfat
type: 0C
# whats the appropriate size?
size: 750M
content:
# TODO:UC20: install the boot.sel via snapd instead of via the gadget
- source: boot.sel
target: uboot/ubuntu/boot.sel
- name: ubuntu-save
role: system-save
filesystem: ext4
type: 83,0FC63DAF-8483-4772-8E79-3D69D8477DE4
size: 16M
- name: ubuntu-data
role: system-data
filesystem: ext4
type: 83,0FC63DAF-8483-4772-8E79-3D69D8477DE4
# XXX: make auto-grow to partition
size: 2500M

0 comments on commit 45f1137

Please sign in to comment.