Skip to content

Commit

Permalink
Merge pull request #2324 from OSInside/btrfs_no_hardcoded_toplevel_vo…
Browse files Browse the repository at this point in the history
…lume

Evaluate the @root volume name also for btrfs
  • Loading branch information
Conan-Kudo committed Jul 31, 2023
2 parents 5598493 + fcf6b6e commit 60d7b1f
Show file tree
Hide file tree
Showing 22 changed files with 661 additions and 147 deletions.
7 changes: 6 additions & 1 deletion build-tests/x86/fedora/test-image-live-disk/appliance.kiwi
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,11 @@
</type>
</preferences>
<preferences profiles="Virtual">
<type image="oem" filesystem="ext4" kernelcmdline="console=ttyS0" firmware="uefi" format="qcow2">
<type image="oem" filesystem="btrfs" kernelcmdline="console=ttyS0" firmware="uefi" format="qcow2" btrfs_root_is_subvolume="true" btrfs_set_default_volume="false" rootfs_label="fedora" bootpartition="true" bootfilesystem="ext4">
<systemdisk name="fedora">
<volume name="@root=root"/>
<volume name="home" parent="/"/>
</systemdisk>
<oemconfig>
<oem-resize>false</oem-resize>
</oemconfig>
Expand Down Expand Up @@ -67,6 +71,7 @@
<package name="vim"/>
<package name="tzdata"/>
<package name="NetworkManager"/>
<package name="btrfs-progs"/>
</packages>
<packages type="image" profiles="Live,Disk">
<package name="syslinux"/>
Expand Down
22 changes: 22 additions & 0 deletions doc/source/image_description/elements.rst
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,28 @@ btrfs_quota_groups="true|false":
Boolean parameter to activate filesystem quotas if
the filesystem is `btrfs`. By default quotas are inactive.

btrfs_set_default_volume="true|false":
Tell kiwi to explicitly make a volume the default volume
This can be either `/` or the root subvolume or the root
snapshot depending on the specified btrfs configuration
attributes. By default btrfs_set_default_volume is set to: true
If no default volume should be set, this attribute can be
used to turn it off

btrfs_root_is_subvolume="true|false":
Tell kiwi to create a root volume to host (/) inside.
The name of this subvolume is by default set to: `@`.
The name of the subvolume can be changed via a volume entry
of the form:

.. code:: xml
<systemdisk>
<volume name="@root=TOPLEVEL_NAME"/>
</systemdisk>
By default the creation of a toplevel volume is set to: `true`

btrfs_root_is_snapshot="true|false":
Boolean parameter that tells {kiwi} to install
the system into a btrfs snapshot. The snapshot layout is compatible with
Expand Down
8 changes: 6 additions & 2 deletions kiwi/bootloader/config/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -501,7 +501,8 @@ def get_gfxmode(self, target):
return gfxmode

def _mount_system(
self, root_device, boot_device, efi_device=None, volumes=None
self, root_device, boot_device, efi_device=None,
volumes=None, root_volume_name=None
):
self.root_mount = MountManager(
device=root_device
Expand All @@ -522,7 +523,10 @@ def _mount_system(
mountpoint=self.root_mount.mountpoint + '/boot/efi'
)

self.root_mount.mount()
custom_root_mount_args = []
if root_volume_name and root_volume_name != '/':
custom_root_mount_args += [f'subvol={root_volume_name}']
self.root_mount.mount(options=custom_root_mount_args)

if not self.root_mount.device == self.boot_mount.device:
self.boot_mount.mount()
Expand Down
64 changes: 40 additions & 24 deletions kiwi/bootloader/config/grub2.py
Original file line number Diff line number Diff line change
Expand Up @@ -233,14 +233,18 @@ def setup_disk_image_config(
'root_device': string,
'boot_device': string,
'efi_device': string,
'system_volumes': volume_manager_instance.get_volumes()
'system_volumes':
volume_manager_instance.get_volumes(),
'system_root_volume':
volume_manager_instance.get_root_volume_name()
}
"""
self._mount_system(
boot_options.get('root_device'),
boot_options.get('boot_device'),
boot_options.get('efi_device'),
boot_options.get('system_volumes')
boot_options.get('system_volumes'),
boot_options.get('system_root_volume')
)
config_file = os.sep.join(
[
Expand Down Expand Up @@ -809,35 +813,47 @@ def _setup_secure_boot_efi_image(
# a grub image that got signed by the shim. The shim image
# is the one that gets loaded by the firmware which itself
# loads the second stage grub image
log.info(
f'--> Using shim image: {shim_image.filename}'
)
log.info(
f'--> Using grub image: {grub_image.filename}'
)
Command.run(
['cp', shim_image.filename, self._get_efi_image_name()]
)
Command.run(
[
'cp', grub_image.filename,
os.sep.join([self.efi_boot_path, grub_image.binaryname])
]
target_efi_image_name = self._get_efi_image_name()
target_grub_image_name = os.sep.join(
[self.efi_boot_path, grub_image.binaryname]
)
if not os.path.isfile(target_efi_image_name):
log.info(
f'--> Using shim image: {shim_image.filename}'
)
Command.run(
['cp', shim_image.filename, target_efi_image_name]
)
if not os.path.isfile(target_grub_image_name):
log.info(
f'--> Using grub image: {grub_image.filename}'
)
Command.run(
['cp', grub_image.filename, target_grub_image_name]
)
mok_manager = Defaults.get_mok_manager(lookup_path)
if mok_manager:
Command.run(
['cp', mok_manager, self.efi_boot_path]
target_mok_manager = os.sep.join(
[self.efi_boot_path, os.path.basename(mok_manager)]
)
if not os.path.isfile(target_mok_manager):
log.info(
f'--> Using mok image: {mok_manager}'
)
Command.run(
['cp', mok_manager, self.efi_boot_path]
)
else:
# Without shim a self signed grub image is used that
# gets loaded by the firmware
log.info(
f'--> No shim image, using grub image: {grub_image.filename}'
)
Command.run(
['cp', grub_image.filename, self._get_efi_image_name()]
)
target_efi_image_name = self._get_efi_image_name()
if not os.path.isfile(target_efi_image_name):
log.info(
f'--> No shim image, using grub image: {grub_image.filename}'
)
Command.run(
['cp', grub_image.filename, target_efi_image_name]
)
self._create_efi_config_search(uuid, mbrid)

def _setup_efi_image(
Expand Down
9 changes: 8 additions & 1 deletion kiwi/bootloader/install/grub2.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ def post_init(self, custom_args):
{
'target_removable': bool,
'system_volumes': list_of_volumes,
'system_root_volume': root volume name if required
'firmware': FirmWare_instance,
'efi_device': string,
'boot_device': string,
Expand All @@ -71,12 +72,15 @@ def post_init(self, custom_args):
self.proc_mount = None
self.sysfs_mount = None
self.volumes = None
self.root_volume_name = None
self.volumes_mount = []
self.target_removable = None
if custom_args and 'target_removable' in custom_args:
self.target_removable = custom_args['target_removable']
if custom_args and 'system_volumes' in custom_args:
self.volumes = custom_args['system_volumes']
if custom_args and 'system_root_volume' in custom_args:
self.root_volume_name = custom_args['system_root_volume']
if custom_args and 'firmware' in custom_args:
self.firmware = custom_args['firmware']
if custom_args and 'install_options' in custom_args:
Expand Down Expand Up @@ -302,7 +306,10 @@ def _mount_device_and_volumes(self):
self.root_mount = MountManager(
device=self.custom_args['root_device']
)
self.root_mount.mount()
custom_root_mount_args = []
if self.root_volume_name and self.root_volume_name != '/':
custom_root_mount_args += [f'subvol={self.root_volume_name}']
self.root_mount.mount(options=custom_root_mount_args)

if self.boot_mount is None:
if 's390' in self.arch:
Expand Down
34 changes: 31 additions & 3 deletions kiwi/builder/disk.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,8 @@ def __init__(
self.target_removable = xml_state.build_type.get_target_removable()
self.root_filesystem_is_multipath = \
xml_state.get_oemconfig_oem_multipath_scan()
self.btrfs_set_default_volume = \
xml_state.build_type.get_btrfs_set_default_volume()
self.oem_systemsize = xml_state.get_oemconfig_oem_systemsize()
self.oem_resize = xml_state.get_oemconfig_oem_resize()
self.disk_resize_requested = \
Expand Down Expand Up @@ -417,6 +419,11 @@ def create_disk(self) -> Result:
'root_is_readonly_snapshot':
self.xml_state.build_type.
get_btrfs_root_is_readonly_snapshot(),
'root_is_subvolume':
self.xml_state.build_type.
get_btrfs_root_is_subvolume(),
'set_default_volume':
self.btrfs_set_default_volume,
'quota_groups':
self.xml_state.build_type.get_btrfs_quota_groups(),
'resize_on_boot':
Expand Down Expand Up @@ -523,7 +530,9 @@ def create_disk(self) -> Result:
# create second stage metadata to system image
self._copy_first_boot_files_to_system_image()

self._write_bootloader_meta_data_to_system_image(device_map, disk)
self._write_bootloader_meta_data_to_system_image(
device_map, disk, system
)

self.mbrid.write_to_disk(
disk.storage_provider
Expand Down Expand Up @@ -1116,6 +1125,13 @@ def _write_generic_fstab(
custom_root_mount_args += ['ro']
fs_check_interval = '0 0'

if self.volume_manager_name and self.volume_manager_name == 'btrfs':
root_volume_name = system.get_root_volume_name()
if root_volume_name != '/':
custom_root_mount_args += [
f'defaults,subvol={root_volume_name}'
]

self._add_fstab_entry(
device_map['root'].get_device(), '/',
custom_root_mount_args, fs_check_interval
Expand Down Expand Up @@ -1234,13 +1250,20 @@ def _write_recovery_metadata_to_boot_image(self) -> None:
)

def _write_bootloader_meta_data_to_system_image(
self, device_map: Dict, disk: Disk
self, device_map: Dict, disk: Disk, system: Any
) -> None:
if self.bootloader != 'custom':
log.info('Creating %s bootloader configuration', self.bootloader)
boot_options = []
if self.mdraid:
boot_options.append('rd.auto')
if self.volume_manager_name \
and self.volume_manager_name == 'btrfs' \
and self.btrfs_set_default_volume is False \
and system.get_root_volume_name() != '/':
boot_options.append(
f'rootflags=subvol={system.get_root_volume_name()}'
)
ro_device = device_map.get('readonly')
root_device = device_map['root']
boot_device = root_device
Expand Down Expand Up @@ -1524,7 +1547,12 @@ def _install_bootloader(
if self.volume_manager_name:
system.umount_volumes()
custom_install_arguments.update(
{'system_volumes': system.get_volumes()}
{
'system_volumes': system.get_volumes(),
'system_root_volume':
system.get_root_volume_name()
if self.volume_manager_name == 'btrfs' else None
}
)

if self.bootloader != 'custom':
Expand Down
17 changes: 15 additions & 2 deletions kiwi/mount_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@
import time
import logging
from textwrap import dedent
from typing import List
from typing import (
List, Dict
)

# project
from kiwi.path import Path
Expand All @@ -41,9 +43,14 @@ class MountManager:
* :param string device: device node name
* :param string mountpoint: mountpoint directory name
* :param dict attributes: optional attributes to store
"""
def __init__(self, device: str, mountpoint: str = ''):
def __init__(
self, device: str, mountpoint: str = '',
attributes: Dict[str, str] = {}
):
self.device = device
self.attributes = attributes
if not mountpoint:
self.mountpoint_tempdir = Temporary(
prefix='kiwi_mount_manager.'
Expand All @@ -53,6 +60,12 @@ def __init__(self, device: str, mountpoint: str = ''):
Path.create(mountpoint)
self.mountpoint = mountpoint

def get_attributes(self) -> Dict[str, str]:
"""
Return attributes dict for this mount manager
"""
return self.attributes

def bind_mount(self) -> None:
"""
Bind mount the device to the mountpoint
Expand Down
33 changes: 33 additions & 0 deletions kiwi/schema/kiwi.rnc
Original file line number Diff line number Diff line change
Expand Up @@ -1433,6 +1433,29 @@ div {
sch:param [ name = "attr" value = "btrfs_quota_groups" ]
sch:param [ name = "types" value = "oem" ]
]
k.type.btrfs_set_default_volume.attribute =
## Tell kiwi to explicitly make a volume the default volume
## This can be either (/) or the root subvolume or the root
## snapshot depending on the specified btrfs configuration
## attributes. By default btrfs_set_default_volume is set to: true
## If no default volume should be set, this attribute can be
## used to turn it off
attribute btrfs_set_default_volume { xsd:boolean }
>> sch:pattern [ id = "btrfs_set_default_volume" is-a = "image_type"
sch:param [ name = "attr" value = "btrfs_set_default_volume" ]
sch:param [ name = "types" value = "oem" ]
]
k.type.btrfs_root_is_subvolume.attribute =
## Tell kiwi to create a root volume to host (/) inside.
## The name of this subvolume is by default set to: '@'
## The name of the subvolume can be changed via
## a volume entry of the form '<volume name="@root=NAME"/>'
## By default the creation of a root subvolume is set to: true
attribute btrfs_root_is_subvolume { xsd:boolean }
>> sch:pattern [ id = "btrfs_root_is_subvolume" is-a = "image_type"
sch:param [ name = "attr" value = "btrfs_root_is_subvolume" ]
sch:param [ name = "types" value = "oem" ]
]
k.type.btrfs_root_is_snapshot.attribute =
## Tell kiwi to install the system into a btrfs snapshot
## The snapshot layout is compatible with the snapper management
Expand Down Expand Up @@ -2218,6 +2241,8 @@ div {
k.type.bootprofile.attribute? &
k.type.btrfs_quota_groups.attribute? &
k.type.btrfs_root_is_snapshot.attribute? &
k.type.btrfs_root_is_subvolume.attribute? &
k.type.btrfs_set_default_volume.attribute? &
k.type.btrfs_root_is_readonly_snapshot.attribute? &
k.type.compressed.attribute? &
k.type.devicepersistency.attribute? &
Expand Down Expand Up @@ -2552,6 +2577,13 @@ div {
## not specified the name specifies a path which has to
## exist inside the root directory.
attribute name { text }
k.volume.parent.attribute =
## The name/path of the parent volume.
## Evaluated only for the btrfs volume manager to allow
## specifying the parent subvolume to nest this volume in.
## If not specified the parent is always the volume set
## as the default volume
attribute parent { text }
k.volume.mountpoint.attribute =
## volume path. The mountpoint specifies a path which has to
## exist inside the root directory.
Expand Down Expand Up @@ -2584,6 +2616,7 @@ div {
k.volume.mountpoint.attribute? &
k.volume.label.attribute? &
k.volume.name.attribute &
k.volume.parent.attribute? &
k.volume.size.attribute?
k.volume =
## Specify which parts of the filesystem should be
Expand Down

0 comments on commit 60d7b1f

Please sign in to comment.