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
8 changes: 4 additions & 4 deletions src/ugrd/base/banner.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
__author__ = 'desultory'
__version__ = '0.1.0'
__author__ = "desultory"
__version__ = "0.1.0"


def print_banner(self) -> list[str]:
""" Prints the banner. Prints the kernel version if set """
"""Prints the banner. Prints the kernel version if set"""
banner = [self.banner]
if kver := self.get('kernel_version'):
if kver := self.get("kernel_version"):
banner.append(f"einfo 'Kernel version: {kver}'")
return banner
26 changes: 11 additions & 15 deletions src/ugrd/base/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,17 +153,15 @@ def setvar(self) -> str:


def readvar(self) -> str:
"""
Returns a bash function that reads a variable from /run/vars/{name}.
"""Returns a bash function that reads a variable from /run/vars/{name}.
The second arg can be a default value.
If no default is supplied, and the variable is not found, it returns an empty string.
"""
return 'cat "/run/vars/${1}" 2>/dev/null || echo "${2}"'


def check_var(self) -> str:
"""
Returns a bash function that checks the value of a variable.
def check_var(self) -> list[str]:
"""Returns a bash function that checks the value of a variable.
if it's not set, tries to read the cmdline.
"""
return [
Expand All @@ -181,9 +179,8 @@ def check_var(self) -> str:
]


def prompt_user(self) -> str:
"""
Returns a bash function that pauses until the user presses enter.
def prompt_user(self) -> list[str]:
"""Returns a bash function that pauses until the user presses enter.
The first argument is the prompt message.
The second argument is the timeout in seconds.
Expand All @@ -210,9 +207,8 @@ def prompt_user(self) -> str:
return output


def retry(self) -> str:
"""
Returns a bash function that retries a command some number of times.
def retry(self) -> list[str]:
"""Returns a bash function that retries a command some number of times.
The first argument is the number of retries. if 0, it retries 100 times.
The second argument is the timeout in seconds.
The remaining arguments represent the command to run.
Expand Down Expand Up @@ -241,7 +237,7 @@ def retry(self) -> str:


# To feel more at home
def edebug(self) -> str:
def edebug(self) -> list[str]:
"""Returns a bash function like edebug."""
return [
"if check_var quiet; then",
Expand All @@ -254,12 +250,12 @@ def edebug(self) -> str:
]


def einfo(self) -> str:
def einfo(self) -> list[str]:
"""Returns a bash function like einfo."""
return ["if check_var quiet; then", " return", "fi", r'echo -e "\e[1;32m *\e[0m ${*}"']


def ewarn(self) -> str:
def ewarn(self) -> list[str]:
"""Returns a bash function like ewarn.
If plymouth is running, it displays a message instead of echoing.
"""
Expand Down Expand Up @@ -290,7 +286,7 @@ def eerror(self) -> str:
' plymouth display-message --text="Error: ${*}"',
" return",
"fi",
r'echo -e "\e[1;31m *\e[0m ${*}"'
r'echo -e "\e[1;31m *\e[0m ${*}"',
]
else:
return [r'echo -e "\e[1;31m *\e[0m ${*}"']
21 changes: 10 additions & 11 deletions src/ugrd/base/checks.py
Original file line number Diff line number Diff line change
@@ -1,34 +1,33 @@
__version__ = '0.2.1'
__version__ = "0.2.1"

from zenlib.util import contains


@contains('check_included_funcs', 'Skipping included funcs check', log_level=30)
@contains("check_included_funcs", "Skipping included funcs check", log_level=30)
def check_included_funcs(self):
""" Ensures required functions are included in the build dir. """
bash_func_names = [func + '() {\n' for func in self.included_functions]
_check_in_file(self, '/etc/profile', bash_func_names)
"""Ensures required functions are included in the build dir."""
bash_func_names = [func + "() {\n" for func in self.included_functions]
_check_in_file(self, "/etc/profile", bash_func_names)
return "All functions found in the build dir."


@contains('check_in_file', 'Skipping in file check')
@contains("check_in_file", "Skipping in file check")
def check_in_file(self):
""" Runs all 'check_in_file' checks. """
for file, lines in self['check_in_file'].items():
"""Runs all 'check_in_file' checks."""
for file, lines in self["check_in_file"].items():
_check_in_file(self, file, lines)
return "All 'check_in_file' checks passed"


def _check_in_file(self, file, lines):
""" Checks that all lines are in the file. """
"""Checks that all lines are in the file."""
file = self._get_build_path(file)
if not file.exists():
raise ValueError("File '%s' does not exist" % file)

with open(file, 'r') as f:
with open(file, "r") as f:
file_lines = f.readlines()

for check_line in lines:
if check_line not in file_lines:
raise ValueError("Failed to find line '%s' in file '%s'" % (check_line, file))

103 changes: 55 additions & 48 deletions src/ugrd/base/cmdline.py
Original file line number Diff line number Diff line change
@@ -1,64 +1,71 @@
__author__ = 'desultory'
__version__ = '2.4.0'
__author__ = "desultory"
__version__ = "2.5.0"


def parse_cmdline_bool(self) -> str:
"""
Returns a bash script to parse a boolean value from /proc/cmdline
def parse_cmdline_bool(self) -> list[str]:
"""Returns a bash script to parse a boolean value from /proc/cmdline
The only argument is the name of the variable to be read/set
"""
return ['edebug "Parsing cmdline bool: $1"',
r'setvar "$1" "$(grep -qE "(^|\s)$1(\s|$)" /proc/cmdline && echo 1 || echo 0)"']
return [
'edebug "Parsing cmdline bool: $1"',
r'setvar "$1" "$(grep -qE "(^|\s)$1(\s|$)" /proc/cmdline && echo 1 || echo 0)"',
]


def parse_cmdline_str(self) -> str:
"""
Returns a bash script to parse a string value from /proc/cmdline
def parse_cmdline_str(self) -> list[str]:
"""Returns a bash script to parse a string value from /proc/cmdline
The only argument is the name of the variable to be read/set
"""
return ['edebug "Parsing cmdline string: $1"',
r'val=$(grep -oP "(?<=$1=)[^\s]+" /proc/cmdline)',
'if [ -n "$val" ]; then',
' edebug "Parsed $1: $val"',
' setvar "$1" "$val"',
'fi']
return [
'edebug "Parsing cmdline string: $1"',
r'val=$(grep -oP "(?<=$1=)[^\s]+" /proc/cmdline)',
'if [ -n "$val" ]; then',
' edebug "Parsed $1: $val"',
' setvar "$1" "$val"',
"fi",
]


def parse_cmdline(self) -> list[str]:
"""Returns bash script to parse /proc/cmdline"""
return [
r"""cmdline=$(awk -F '--' '{print $1}' /proc/cmdline)""", # Get everything before '--'
r'''setvar INIT_ARGS "$(awk -F '--' '{print $2}' /proc/cmdline)"''', # Get everything after '--'
f"""for bool in {" ".join([f'"{bool}"' for bool in self['cmdline_bools']])}; do""",
' parse_cmdline_bool "$bool"',
"done",
f"""for string in {" ".join([f'"{string}"' for string in self['cmdline_strings']])}; do""",
' parse_cmdline_str "$string"',
"done",
'einfo "Parsed cmdline: $cmdline"',
]

def parse_cmdline(self) -> str:
""" Returns bash script to parse /proc/cmdline """
return [r'''cmdline=$(awk -F '--' '{print $1}' /proc/cmdline)''', # Get everything before '--'
r'''setvar INIT_ARGS "$(awk -F '--' '{print $2}' /proc/cmdline)"''', # Get everything after '--'
f'''for bool in {" ".join([f'"{bool}"' for bool in self['cmdline_bools']])}; do''',
' parse_cmdline_bool "$bool"',
'done',
f'''for string in {" ".join([f'"{string}"' for string in self['cmdline_strings']])}; do''',
' parse_cmdline_str "$string"',
'done',
'einfo "Parsed cmdline: $cmdline"']

def mount_cmdline_root(self) -> list[str]:
"""Returns bash script to mount root partition based on /proc/cmdline"""
return [
"root=$(readvar root)",
'if [ -z "$root" ]; then',
' edebug "No root partition specified in /proc/cmdline, falling back to mount_root"',
" mount_root",
" return",
"fi",
'roottype="$(readvar roottype auto)"',
'''rootflags="$(readvar rootflags 'defaults,ro')"''',
'einfo "Mounting root partition based on /proc/cmdline: $root -t $roottype -o $rootflags"',
'if ! mount "$root" "$(readvar MOUNTS_ROOT_TARGET)" -t "$roottype" -o "$rootflags"; then',
' eerror "Failed to mount the root partition using /proc/cmdline: $root -t $roottype -o $rootflags"',
" mount_root",
"fi",
]

def mount_cmdline_root(self) -> str:
""" Returns bash script to mount root partition based on /proc/cmdline """
return ['root=$(readvar root)',
'if [ -z "$root" ]; then',
' edebug "No root partition specified in /proc/cmdline, falling back to mount_root"',
' mount_root',
' return',
'fi',
'roottype="$(readvar roottype auto)"',
'''rootflags="$(readvar rootflags 'defaults,ro')"''',
'einfo "Mounting root partition based on /proc/cmdline: $root -t $roottype -o $rootflags"',
'if ! mount "$root" "$(readvar MOUNTS_ROOT_TARGET)" -t "$roottype" -o "$rootflags"; then',
' eerror "Failed to mount the root partition using /proc/cmdline: $root -t $roottype -o $rootflags"',
' mount_root',
'fi']

def export_exports(self) -> list[str]:
"""Returns a bash script exporting all exports defined in the exports key."""
from importlib.metadata import PackageNotFoundError, version

def export_exports(self) -> list:
""" Returns a bash script exporting all exports defined in the exports key. """
from importlib.metadata import version, PackageNotFoundError
try:
self['exports']['VERSION'] = version(__package__.split('.')[0])
self["exports"]["VERSION"] = version(__package__.split(".")[0])
except PackageNotFoundError:
self['exports']['VERSION'] = 9999
return [f'setvar {key} "{value}"' for key, value in self['exports'].items()]
self["exports"]["VERSION"] = 9999
return [f'setvar {key} "{value}"' for key, value in self["exports"].items()]
34 changes: 17 additions & 17 deletions src/ugrd/base/console.py
Original file line number Diff line number Diff line change
@@ -1,38 +1,38 @@
__author__ = "desultory"
__version__ = "1.2.0"
__version__ = "1.3.0"


def custom_init(self) -> str:
"""
init override for the console module.
def custom_init(self) -> list[str]:
""" init override for the console module.
Adds the shebang to the top of the file, runs the banner, followed by
most of the main init runlevels
Write the main init runlevels to self._custom_init_file.
Returns the output of console_init which is the command to start agetty.
"""
custom_init_contents = [self['shebang'],
f'einfo "Starting console module v{__version__}"',
'print_banner',
*self.generate_init_main()]
custom_init_contents = [
self["shebang"],
f'einfo "Starting console module v{__version__}"',
"print_banner",
*self.generate_init_main(),
]

return console_init(self), custom_init_contents


def console_init(self) -> str:
"""
Start agetty on the primary console.
Tell it to execute the _custom_init_file
def console_init(self) -> list[str]:
""" Returns the command to start agetty on the primary console.
If the console is a serial port, set the baud rate.
"""
name = self['primary_console']
console = self['console'][name]
name = self["primary_console"]
console = self["console"][name]

out_str = f"agetty --autologin root --login-program {self['_custom_init_file']}"

console_type = console.get('type', 'tty')
if console_type != 'tty':
console_type = console.get("type", "tty")
if console_type != "tty":
# This differs from usage in the man page but seems to work?
out_str += f" --local-line {console['baud']}"

out_str += f" {name} {console_type} || rd_restart"

return out_str

Loading