Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ Modules write to a shared config dict that is accessible by other modules.

> The main module, mostly pulls basic binaries and pulls the `core`, `mounts`, and `cpio` module.

* `switch_root_target` Set the target filesystem for `switch_root`, defaults to the root mountpoint if not set.
* `init_target` Sets the init target for `switch_root`.
* `autodetect_init` (true) Automatically set the init target based `which init`.
* `loglevel` (5) Sets the kernel log level in the init script.
Expand Down
2 changes: 2 additions & 0 deletions examples/livegui.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
modules = [ "ugrd.fs.livecd" ]
livecd_label = "gentoo-amd64-livegui"
39 changes: 23 additions & 16 deletions src/ugrd/base/base.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
__author__ = "desultory"
__version__ = "5.1.4"
__version__ = "5.2.0"

from importlib.metadata import version
from pathlib import Path
Expand Down Expand Up @@ -46,12 +46,20 @@ def autodetect_init(self) -> None:
raise FileNotFoundError("init_target is not specified and could not be detected.")


def export_switch_root_target(self) -> None:
"""Adds SWITCH_ROOT_TARGET to exports.
Uses switch_root_target if set, otherwise uses the rootfs."""
switch_root_target = self["switch_root_target"]
if str(switch_root_target) == ".": # Handle empty Path
switch_root_target = self["mounts"]["root"]["destination"]
self["exports"]["SWITCH_ROOT_TARGET"] = switch_root_target

def _find_init(self) -> str:
"""Returns bash to find the init_target."""
return [
'for init_path in "/sbin/init" "/bin/init" "/init"; do',
' if [ -e "$(readvar MOUNTS_ROOT_TARGET)$init_path" ] ; then',
' einfo "Found init at: $(readvar MOUNTS_ROOT_TARGET)$init_path"',
' if [ -e "$(readvar SWITCH_ROOT_TARGET)$init_path" ] ; then',
' einfo "Found init at: $(readvar SWITCH_ROOT_TARGET)$init_path"',
' setvar init "$init_path"',
" return",
" fi",
Expand All @@ -68,9 +76,8 @@ def set_loglevel(self) -> list[str]:

@contains("init_target", "init_target must be set.", raise_exception=True)
def do_switch_root(self) -> list[str]:
"""
Should be the final statement, switches root.
Checks if the root mount is mounted and that it contains an init.
"""Should be the final statement, switches root.
Checks if the switch_root target is mounted, and that it contains an init.
If not, it restarts UGRD.
"""
return [
Expand All @@ -79,21 +86,21 @@ def do_switch_root(self) -> list[str]:
" exit 1",
"fi",
'init_target=$(readvar init) || rd_fail "init_target not set."', # should be set, if unset, checks fail
'einfo "Checking root mount: $(readvar MOUNTS_ROOT_TARGET)"',
'if ! grep -q " $(readvar MOUNTS_ROOT_TARGET) " /proc/mounts ; then',
' rd_fail "Root not found at: $(readvar MOUNTS_ROOT_TARGET)"',
'elif [ ! -e "$(readvar MOUNTS_ROOT_TARGET)${init_target}" ] ; then',
' ewarn "$init_target not found at: $(readvar MOUNTS_ROOT_TARGET)"',
r' einfo "Target root contents:\n$(ls -l "$(readvar MOUNTS_ROOT_TARGET)")"',
'einfo "Checking root mount: $(readvar SWITCH_ROOT_TARGET)"',
'if ! grep -q " $(readvar SWITCH_ROOT_TARGET) " /proc/mounts ; then',
' rd_fail "Root not found at: $(readvar SWITCH_ROOT_TARGET)"',
'elif [ ! -e "$(readvar SWITCH_ROOT_TARGET)${init_target}" ] ; then',
' ewarn "$init_target not found at: $(readvar SWITCH_ROOT_TARGET)"',
r' einfo "Target root contents:\n$(ls -l "$(readvar SWITCH_ROOT_TARGET)")"',
" if _find_init ; then", # This redefineds the var, so readvar instaed of using $init_target
' einfo "Switching root to: $(readvar MOUNTS_ROOT_TARGET) $(readvar init)"',
' exec switch_root "$(readvar MOUNTS_ROOT_TARGET)" "$(readvar init)"',
' einfo "Switching root to: $(readvar SWITCH_ROOT_TARGET) $(readvar init)"',
' exec switch_root "$(readvar SWITCH_ROOT_TARGET)" "$(readvar init)"',
" fi",
' rd_fail "Unable to find init."',
"else",
f' einfo "Completed UGRD v{version("ugrd")}."',
' einfo "Switching root to: $(readvar MOUNTS_ROOT_TARGET) $init_target"',
' exec switch_root "$(readvar MOUNTS_ROOT_TARGET)" "$init_target"',
' einfo "Switching root to: $(readvar SWITCH_ROOT_TARGET) $init_target"',
' exec switch_root "$(readvar SWITCH_ROOT_TARGET)" "$init_target"',
"fi",
]

Expand Down
4 changes: 4 additions & 0 deletions src/ugrd/base/base.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ autodetect_init = true
[imports.build_enum]
"ugrd.base.base" = [ "autodetect_init" ]

[imports.build_tasks]
"ugrd.base.base" = [ "export_switch_root_target" ]

[imports.init_early]
"ugrd.base.base" = [ "set_loglevel" ]

Expand All @@ -32,6 +35,7 @@ autodetect_init = true
"rd_fail", "rd_restart", "_find_init" ]

[custom_parameters]
switch_root_target = "Path" # Specifies the location of the new root filesystem
init_target = "Path" # Specifies the location of the system init file
autodetect_init = "bool" # If set to true, the init_target will be autodetected based on the system's init system
loglevel = "int" # Set the kernel log level at /proc/sys/kernel/printk
Expand Down
33 changes: 19 additions & 14 deletions src/ugrd/fs/livecd.py
Original file line number Diff line number Diff line change
@@ -1,24 +1,29 @@
__author__ = "desultory"
__version__ = "0.3.0"
__version__ = "0.5.0"

from zenlib.util import contains


@contains("livecd_label", "livecd_label must be set to the label of the livecd.", raise_exception=True)
def generate_livecd_mount(self):
""" Makes the mounts entry for livecd base. """
self['mounts'] = {'livecd': {'label': self.livecd_label, 'no_validate': True}}
"""Makes the mounts entry for livecd base."""
self["mounts"] = {"livecd": {"label": self.livecd_label, "no_validate": True}}


def prepare_squashfs_mount(self) -> str:
"""Create the folder for the squashfs mount in /run"""
return "edebug $(mkdir -pv /run/squashfs)"


@contains("squashfs_image", "squashfs_image must be set to the path of the squashfs image to mount.", raise_exception=True)
def mount_squashfs(self):
"""
Returns bash lines to mount squashfs image.
Creates /run/squashfs directory to mount squashfs image.
Creates /run/upperdir and /run/workdir directories for overlayfs.
"""
return ["einfo $(mkdir -pv /run/squashfs)",
f"mount -t squashfs -o loop /livecd/{self.squashfs_image} /run/squashfs || rd_fail 'Failed to mount squashfs image: {self.squashfs_image}'",
"edebug $(mkdir -pv /run/upperdir)",
"edebug $(mkdir -pv /run/workdir)",
f"mount -t overlay overlay -o lowerdir=/run/squashfs,upperdir=/run/upperdir,workdir=/run/workdir {self.mounts['root']['destination']} || rd_fail 'Failed to mount overlayfs'"]
def set_squashfs_mount(self):
"""Updates the root mount entry to use the squashfs image."""
self["mounts"] = {
"root": {
"type": "squashfs",
"options": ["loop"],
"path": f"/livecd/{self.squashfs_image}",
"destination": "/run/squashfs",
"no_validate": True,
}
}
18 changes: 7 additions & 11 deletions src/ugrd/fs/livecd.toml
Original file line number Diff line number Diff line change
@@ -1,20 +1,16 @@
autodetect_root = false
autodetect_root_dm = false
modules = ["ugrd.fs.overlayfs"]

squashfs_image = 'image.squashfs'
lowerdir = "/run/squashfs"
hostonly = false

kmod_init = ['hfsplus', 'nls_utf8', 'squashfs', 'overlay', 'isofs', 'loop']
kmod_init = ['hfsplus', 'nls_utf8', 'squashfs', 'isofs', 'loop']

[imports.build_pre]
"ugrd.fs.livecd" = ["generate_livecd_mount"]
"ugrd.fs.livecd" = ["generate_livecd_mount", "set_squashfs_mount"]

[imports.init_mount]
"ugrd.fs.livecd" = ["mount_squashfs"]

[masks]
init_mount = "mount_cmdline_root" # Don't use the normal mount process
build_tasks = "export_mount_info"
functions = "mount_root"
[imports.init_early]
"ugrd.fs.livecd" = ["prepare_squashfs_mount"]

[custom_parameters]
squashfs_image = "Path" # the path to the squashfs image (at runtime)
Expand Down
8 changes: 2 additions & 6 deletions src/ugrd/fs/mounts.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
__author__ = "desultory"
__version__ = "5.4.0"
__version__ = "5.4.2"

from pathlib import Path

Expand Down Expand Up @@ -216,7 +216,7 @@ def umount_fstab(self) -> list[str]:
for mount_info in self["mounts"].values():
if mount_info.get("base_mount"):
continue
if str(mount_info.get("destination")) == "/target_rootfs":
if str(mount_info.get("destination")) == str(self["mounts"]["root"]["destination"]):
continue

mountpoints.append(str(mount_info["destination"]))
Expand Down Expand Up @@ -729,10 +729,6 @@ def export_mount_info(self) -> None:
self["exports"]["MOUNTS_ROOT_SOURCE"] = _get_mount_str(self, self["mounts"]["root"])
self["exports"]["MOUNTS_ROOT_TYPE"] = self["mounts"]["root"].get("type", "auto")
self["exports"]["MOUNTS_ROOT_OPTIONS"] = ",".join(self["mounts"]["root"]["options"])


def export_root_target(self) -> None:
"""Exports the root target path to /run/MOUNTS_ROOT_TARGET"""
self["exports"]["MOUNTS_ROOT_TARGET"] = self["mounts"]["root"]["destination"]


Expand Down
2 changes: 1 addition & 1 deletion src/ugrd/fs/mounts.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ late_fstab = "/etc/fstab.late"
"autodetect_root", "autodetect_mounts", "autodetect_root_dm", "autodetect_init_mount" ]

[imports.build_tasks]
"ugrd.fs.mounts" = [ "export_mount_info", "export_root_target" ]
"ugrd.fs.mounts" = [ "export_mount_info" ]

[imports.build_final]
"ugrd.fs.mounts" = [ "check_mounts", "generate_fstab" ]
Expand Down
22 changes: 22 additions & 0 deletions src/ugrd/fs/overlayfs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
from zenlib.util import unset

@unset('lowerdir', "lowerdir is already set, skipping detection.")
def detect_lowerdir(self):
"""Detect the lowerdir using the mounts['root']['destination']"""
self['lowerdir'] = self.mounts['root']['destination']
self.logger.info("Detected lowerdir: %s" % self['lowerdir'])


def init_overlayfs(self) -> list[str]:
"""Returns bash lines to create the upperdir and workdir
Uses /run/upperdir and /run/workdir."""
return ["edebug $(mkdir -pv /run/upperdir /run/workdir)"]

def mount_overlayfs(self) -> list[str]:
"""Returns bash lines to mount the overlayfs based on the lowerdir"""
return [
"einfo $(mount -t overlay overlay -o lowerdir=%s,upperdir=/run/upperdir,workdir=/run/workdir $(readvar SWITCH_ROOT_TARGET))" % self['lowerdir']
]



13 changes: 13 additions & 0 deletions src/ugrd/fs/overlayfs.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
kmod_init = ["overlay"]

[imports.build_pre]
"ugrd.fs.overlayfs" = ["detect_lowerdir"]

[imports.init_early]
"ugrd.fs.overlayfs" = ["init_overlayfs"]

[imports.init_mount]
"ugrd.fs.overlayfs" = ["mount_overlayfs"]

[custom_parameters]
lowerdir = "Path"
4 changes: 2 additions & 2 deletions src/ugrd/kmod/kmod.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
__author__ = 'desultory'
__version__ = '2.16.1'
__version__ = '2.16.2'

from pathlib import Path
from subprocess import run
Expand Down Expand Up @@ -124,7 +124,7 @@ def _autodetect_modules_lsmod(self) -> None:


@unset('no_kmod', "no_kmod is enabled, skipping.", log_level=30)
@contains('hostonly', "hostonly is not enabled, skipping.", log_level=30)
@contains('hostonly', "Skipping kmod autodetection, hostonly is disabled.", log_level=30)
def autodetect_modules(self) -> None:
""" Autodetects kernel modules from lsmod and/or lspci -k. """
if not self['kmod_autodetect_lsmod'] and not self['kmod_autodetect_lspci']:
Expand Down