Skip to content

Commit

Permalink
rubocop
Browse files Browse the repository at this point in the history
grub2bls

grub2bls

grub2bls

sync text about secure boot on s390 to be correct (bsc#1219989)

make rubocop happy

rubocop

rubocop

fixed test cases

fixed test cases

grub2bls

grub2bls

grub2bls

grub2bls

grub2bls

rubocop

rubocop

rubocop

rubocop

rubocop

docu

added yast-bootloader

added yast-bootloader
  • Loading branch information
schubi2 committed Nov 13, 2024
1 parent 36e4ed4 commit 14aac63
Show file tree
Hide file tree
Showing 14 changed files with 746 additions and 1,080 deletions.
2 changes: 1 addition & 1 deletion .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ Metrics/BlockLength:

# Configuration parameters: CountComments.
Metrics/MethodLength:
Max: 30 # TODO this should be lower for new code
Max: 31 # TODO this should be lower for new code
Include:
- 'src/lib/**/*.rb' # be more strict for new code in lib

Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ that holds and also can propose the bootloader implementation. So now let's expl

- [GRUB2](https://www.rubydoc.info/github/yast/yast-bootloader/master/Bootloader/Grub2) for legacy booting or emulated grub2 boot like s390x.
- [GRUB2-EFI](https://www.rubydoc.info/github/yast/yast-bootloader/master/Bootloader/Grub2EFI) for EFI variant of GRUB2 bootloader
- [GRUB2-BLS](https://www.rubydoc.info/github/yast/yast-bootloader/master/Bootloader/Grub2Bls) bootloader based on Boot Loader Specification(BLS) (for EFI only)
- [systemd-boot](https://www.rubydoc.info/github/yast/yast-bootloader/master/Bootloader/SystemdBoot) systemd bootloader (for EFI only)
- [None](https://www.rubydoc.info/github/yast/yast-bootloader/master/Bootloader/NoneBootloader) when YaST does not manage booting
- [GRUB2 base](https://www.rubydoc.info/github/yast/yast-bootloader/master/Bootloader/Grub2Base) is the shared functionality for both GRUB2 implementations
Expand Down
1,490 changes: 446 additions & 1,044 deletions doc/bootloader_backend.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
24 changes: 13 additions & 11 deletions src/lib/bootloader/autoyast_converter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,17 @@ def import(data)

case bootloader.name
when "grub2", "grub2-efi", "grub2-bls"
import_grub2(data, bootloader)
import_grub2efi(data, bootloader)
import_stage1(data, bootloader)
if ["grub2", "grub2-efi"].include?(bootloader.name)
import_grub2(data, bootloader)
import_grub2efi(data, bootloader)
import_stage1(data, bootloader)
import_device_map(data, bootloader)
import_password(data, bootloader)
# always nil pmbr as autoyast does not support it yet,
# so use nil to always use proposed value (bsc#1081967)
bootloader.pmbr_action = nil
end
import_default(data, bootloader.grub_default)
import_device_map(data, bootloader)
import_password(data, bootloader)
# always nil pmbr as autoyast does not support it yet,
# so use nil to always use proposed value (bsc#1081967)
bootloader.pmbr_action = nil
cpu_mitigations = data.global.cpu_mitigations
if cpu_mitigations
bootloader.cpu_mitigations = CpuMitigations.from_string(cpu_mitigations)
Expand Down Expand Up @@ -75,9 +77,9 @@ def export(config)
when "grub2", "grub2-efi", "grub2-bls"
global = res["global"]
export_grub2(global, config) if config.name == "grub2"
export_grub2efi(global, config) if ["grub2-efi", "grub2-bls"].include?(config.name)
export_grub2efi(global, config) if config.name == "grub2-efi"
export_password(global, config.password) if ["grub2", "grub2-efi"].include?(config.name)
export_default(global, config.grub_default)
export_password(global, config.password)
res["global"]["cpu_mitigations"] = config.cpu_mitigations.value.to_s
when "systemd-boot"
res["global"]["timeout"] = config.menu_timeout
Expand Down Expand Up @@ -106,7 +108,7 @@ def import_grub2(data, bootloader)
end

def import_grub2efi(data, bootloader)
return unless ["grub2-efi", "grub2-bls"].include?(bootloader.name)
return unless bootloader.name == "grub2-efi"

GRUB2EFI_BOOLEAN_MAPPING.each do |key, method|
val = data.global.public_send(key)
Expand Down
10 changes: 6 additions & 4 deletions src/lib/bootloader/bls_sections.rb
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,12 @@ def write_default
ret = Yast::Execute.on_target("/usr/bin/sdbootutil",
"set-default", @default,
allowed_exitstatus: [0, 1])
if ret != 0 # fallback directly over grub2-editenv
Yast::Execute.on_target("/usr/bin/grub2-editenv", grubenv_path,
"set", "default=" + @default)
end

return unless ret != 0

# fallback directly over grub2-editenv
Yast::Execute.on_target("/usr/bin/grub2-editenv", grubenv_path,
"set", "default=" + @default)
end

# @return [Array] return array of entries or []
Expand Down
4 changes: 4 additions & 0 deletions src/lib/bootloader/bootloader_base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@
module Bootloader
# Represents base for all kinds of bootloaders
class BootloaderBase
include Yast::I18n

def initialize
textdomain "bootloader"

@read = false
@proposed = false
@initial_sysconfig = Sysconfig.from_system
Expand Down
1 change: 0 additions & 1 deletion src/lib/bootloader/generic_widgets.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ def localized_names(name)
names[name] or raise "Unknown supported bootloader '#{name}'"
end

# It will be reduced again if systemd-boot is not anymore in beta phase.
def handle
old_bl = BootloaderFactory.current.name
new_bl = value
Expand Down
24 changes: 13 additions & 11 deletions src/lib/bootloader/grub2bls.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ class Grub2Bls < Grub2Base
CMDLINE = "/etc/kernel/cmdline"

def initialize
super
textdomain "bootloader"

@grub_default = ::CFA::Grub2::Default.new
@sections = ::Bootloader::BlsSections.new
@is_read = false
@is_proposed = false
Expand Down Expand Up @@ -84,9 +84,7 @@ def proposed?
end

# writes configuration to target disk
# @param etc_only [Boolean] true on transactional systems
# because /boot is read-only there
def write(etc_only: false)
def write(*)
install_bootloader if Yast::Stage.initial # while new installation only (currently)
create_menu_entries
install_bootloader
Expand All @@ -100,6 +98,7 @@ def write(etc_only: false)

# merges other bootloader configuration into this one.
# It have to be same bootloader type.
# rubocop:disable Metrics/AbcSize
def merge(other)
raise "Invalid merge argument #{other.name} for #{name}" if name != other.name

Expand All @@ -116,6 +115,7 @@ def merge(other)
log.info " mitigations: #{cpu_mitigations.to_human_string}"
log.info " kernel_params: #{grub_default.kernel_params.serialize}"
end
# rubocop:enable Metrics/AbcSize

# @return [Array<String>] packages required to configure given bootloader
def packages
Expand Down Expand Up @@ -147,14 +147,16 @@ def read_menu_timeout
end

def write_menu_timeout
ret = Yast::Execute.on_target("/usr/bin/sdbootutil",
ret = Yast::Execute.on_target(SDBOOTUTIL,
"set-timeout",
grub_default.timeout,
allowed_exitstatus: [0, 1])
if ret != 0 # fallback directly over grub2-editenv
Yast::Execute.on_target("/usr/bin/grub2-editenv", grubenv_path,
"set", "timeout=#{grub_default.timeout}")
end

return unless ret != 0

# fallback directly over grub2-editenv
Yast::Execute.on_target("/usr/bin/grub2-editenv", grubenv_path,
"set", "timeout=#{grub_default.timeout}")
end

def merge_sections(other)
Expand All @@ -168,7 +170,7 @@ def create_menu_entries
rescue Cheetah::ExecutionFailed => e
Yast::Report.Error(
format(_(
"Cannot create systemd-boot menu entry:\n" \
"Cannot create grub2-bls menu entry:\n" \
"Command `%{command}`.\n" \
"Error output: %{stderr}"
), command: e.commands.inspect, stderr: e.stderr)
Expand All @@ -181,7 +183,7 @@ def install_bootloader
rescue Cheetah::ExecutionFailed => e
Yast::Report.Error(
format(_(
"Cannot install systemd bootloader:\n" \
"Cannot install grub2-bls bootloader:\n" \
"Command `%{command}`.\n" \
"Error output: %{stderr}"
), command: e.commands.inspect, stderr: e.stderr)
Expand Down
11 changes: 8 additions & 3 deletions src/lib/bootloader/proposal_client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -381,10 +381,15 @@ def single_click_action(option, value)
bootloader.secure_boot = value
if value && Yast::Arch.s390
Yast2::Popup.show(
# text is identical like one in grub2_widgets. Keep in sync!
# TRANSLATORS: IPL stands for Initial Program Load, IBM speak for system boot
_(
"The new secure-boot enabled boot data format works only on z15 " \
"and later and only for zFCP disks.\n\n" \
"The system does not boot if these requirements are not met."
"Secure boot IPL has the following minimum system requirements,\n" \
"depending on the boot device to be IPLed:\n" \
"NVMe disk: IBM LinuxONE III or newer.\n" \
"FC-attached SCSI disk: IBM LinuxONE III, IBM z15 or newer.\n" \
"ECKD DASD with CDL layout: IBM z16, LinuxONE 4 or newer.\n" \
"If these requirements are not met, the system can be IPLed in non-secure mode only."
),
headline: :warning, buttons: :ok
)
Expand Down
2 changes: 1 addition & 1 deletion src/lib/bootloader/sysconfig.rb
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ def pre_write
bootloader: "\n" \
"## Path:\tSystem/Bootloader\n" \
"## Description:\tBootloader configuration\n" \
"## Type:\tlist(grub,grub2,grub2-efi,systemd-boot,none)\n" \
"## Type:\tlist(grub,grub2,grub2-efi,grub2-bls,systemd-boot,none)\n" \
"## Default:\tgrub2\n" \
"#\n" \
"# Type of bootloader in use.\n" \
Expand Down
76 changes: 76 additions & 0 deletions test/bls_sections_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
#! /usr/bin/env rspec --format doc
# frozen_string_literal: true

require_relative "./test_helper"

require "bootloader/bls_sections"
require "cfa/memory_file"

describe Bootloader::BlsSections do

before do
allow(Yast::Misc).to receive(:CustomSysconfigRead)
.with("ID_LIKE", "openSUSE", "/etc/os-release")
.and_return("openSUSE")
end

describe "#read" do
before do
allow(Yast::Execute).to receive(:on_target)
.with("/usr/bin/bootctl", "--json=short", "list", stdout: :capture)
.and_return("[{\"title\" : \"openSUSE Tumbleweed\", \"isDefault\" : true }," \
"{\"title\" : \"Snapper: *openSUSE Tumbleweed 20241107\", \"isDefault\" : false}]")
allow(Yast::Misc).to receive(:CustomSysconfigRead)
.with("default", "", "/boot/efi/EFI/openSUSE/grubenv")
.and_return("openSUSE Tumbleweed")
subject.read
end

it "returns list of all available sections" do
expect(subject.all).to eq(["openSUSE Tumbleweed", "Snapper: *openSUSE Tumbleweed 20241107"])
end

it "reads default menu entry" do
expect(subject.default).to eq("openSUSE Tumbleweed")
end
end

describe "#default=" do
before do
allow(Yast::Execute).to receive(:on_target)
.with("/usr/bin/bootctl", "--json=short", "list", stdout: :capture)
.and_return("[{\"title\" : \"openSUSE Tumbleweed\", \"isDefault\" : true }," \
"{\"title\" : \"Snapper: *openSUSE Tumbleweed 20241107\", \"isDefault\" : false}]")
allow(Yast::Misc).to receive(:CustomSysconfigRead)
.with("default", "", "/boot/efi/EFI/openSUSE/grubenv")
.and_return("openSUSE Tumbleweed")
subject.read
end
it "sets new value for default" do
subject.default = "Snapper: *openSUSE Tumbleweed 20241107"
expect(subject.default).to eq "Snapper: *openSUSE Tumbleweed 20241107"
end

it "sets default to empty if section do not exists" do
subject.default = "non-exist"
expect(subject.default).to eq ""
end
end

describe "#write" do
it "writes default value if set" do
subject.default = "Snapper: *openSUSE Tumbleweed 20241107"
expect(Yast::Execute).to receive(:on_target)
.with("/usr/bin/sdbootutil", "set-default", subject.default, { :allowed_exitstatus=>[0, 1] })
subject.write
end

it "does not write default value if not set" do
subject.default = ""
expect(Yast::Execute).to_not receive(:on_target)
.with("/usr/bin/sdbootutil", "set-default", subject.default, { :allowed_exitstatus=>[0, 1] })
subject.write
end

end
end
7 changes: 7 additions & 0 deletions test/boot_support_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,13 @@
expect(subject.SystemSupported).to eq false
end

it "returns false if grub2-bls is used and UEFI is not supported" do
Bootloader::BootloaderFactory.current_name = "grub2-bls"
allow(subject).to receive(:efi?).and_return(false)

expect(subject.SystemSupported).to eq false
end

it "returns false if systemd-boot is used and UEFI is not supported" do
Bootloader::BootloaderFactory.current_name = "systemd-boot"
allow(subject).to receive(:efi?).and_return(false)
Expand Down
8 changes: 4 additions & 4 deletions test/bootloader_factory_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,15 @@
allow(Yast::ProductFeatures).to receive(:GetBooleanFeature).with("globals", "enable_systemd_boot").and_return(true)
end
it "returns systemd-boot in the list" do
expect(Bootloader::BootloaderFactory.supported_names).to eq ["grub2", "grub2-efi", "systemd-boot", "none"]
expect(Bootloader::BootloaderFactory.supported_names).to eq ["grub2", "grub2-efi", "grub2-bls", "systemd-boot", "none"]
end
end
context "product does not support systemd-boot" do
before do
allow(Yast::ProductFeatures).to receive(:GetBooleanFeature).with("globals", "enable_systemd_boot").and_return(false)
end
it "does not include systemd-boot in the list" do
expect(Bootloader::BootloaderFactory.supported_names).to eq ["grub2", "grub2-efi", "none"]
expect(Bootloader::BootloaderFactory.supported_names).to eq ["grub2", "grub2-efi", "grub2-bls", "none"]
end
end
end
Expand All @@ -61,15 +61,15 @@
allow(Yast::ProductFeatures).to receive(:GetBooleanFeature).with("globals", "enable_systemd_boot").and_return(true)
end
it "does not include grub2 in the list" do
expect(Bootloader::BootloaderFactory.supported_names).to eq ["grub2-efi", "systemd-boot", "none"]
expect(Bootloader::BootloaderFactory.supported_names).to eq ["grub2-efi", "grub2-bls", "systemd-boot", "none"]
end
end
context "product does not support systemd-boot" do
before do
allow(Yast::ProductFeatures).to receive(:GetBooleanFeature).with("globals", "enable_systemd_boot").and_return(false)
end
it "does not include systemd-boot and grub2 in the list" do
expect(Bootloader::BootloaderFactory.supported_names).to eq ["grub2-efi", "none"]
expect(Bootloader::BootloaderFactory.supported_names).to eq ["grub2-efi", "grub2-bls", "none"]
end
end
end
Expand Down
Loading

0 comments on commit 14aac63

Please sign in to comment.