Skip to content

Commit

Permalink
rubocop
Browse files Browse the repository at this point in the history
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 8ab6946 commit 89f6d73
Show file tree
Hide file tree
Showing 9 changed files with 718 additions and 1,070 deletions.
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.
34 changes: 13 additions & 21 deletions src/lib/bootloader/autoyast_converter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,21 +34,17 @@ def import(data)
return bootloader if bootloader.name == "none"

case bootloader.name
when "grub2"
import_grub2(data, bootloader)
import_grub2efi(data, bootloader)
import_stage1(data, bootloader)
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)
when "grub2", "grub2-efi", "grub2-bls"
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
when "grub2-bls"
import_default(data, bootloader.grub_default)
cpu_mitigations = data.global.cpu_mitigations
if cpu_mitigations
Expand Down Expand Up @@ -78,15 +74,11 @@ def export(config)
res["global"] = {}

case config.name
when "grub2", "grub2-efi"
when "grub2", "grub2-efi", "grub2-bls"
global = res["global"]
export_grub2(global, config) if config.name == "grub2"
export_grub2efi(global, config) if config.name == "grub2-efi"
export_default(global, config.grub_default)
export_password(global, config.password)
res["global"]["cpu_mitigations"] = config.cpu_mitigations.value.to_s
when "grub2-bls"
global = res["global"]
export_password(global, config.password) if ["grub2", "grub2-efi"].include?(config.name)
export_default(global, config.grub_default)
res["global"]["cpu_mitigations"] = config.cpu_mitigations.value.to_s
when "systemd-boot"
Expand Down Expand Up @@ -116,7 +108,7 @@ def import_grub2(data, bootloader)
end

def import_grub2efi(data, bootloader)
return unless bootloader.name=="grub2-efi"
return unless bootloader.name == "grub2-efi"

GRUB2EFI_BOOLEAN_MAPPING.each do |key, method|
val = data.global.public_send(key)
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
2 changes: 1 addition & 1 deletion src/lib/bootloader/grub2bls.rb
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ 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])
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
166 changes: 166 additions & 0 deletions test/grub2_bls_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
# frozen_string_literal: true

require_relative "test_helper"

require "bootloader/grub2bls"

describe Bootloader::Grub2Bls do
subject do
sub = described_class.new
sub
end

let(:destdir) { File.expand_path("data/", __dir__) }
let(:cmdline_content) { "splash=silent quiet security=apparmor mitigations=off" }

before do
allow(Yast::Arch).to receive(:architecture).and_return("x86_64")
end

describe "#read" do
before do
allow(Yast::Misc).to receive(:CustomSysconfigRead)
.with("ID_LIKE", "openSUSE", "/etc/os-release")
.and_return("openSUSE")
allow(Yast::Misc).to receive(:CustomSysconfigRead)
.with("timeout", "", "/boot/efi/EFI/openSUSE/grubenv")
.and_return("10")
allow(Yast::Misc).to receive(:CustomSysconfigRead)
.with("default", "", "/boot/efi/EFI/openSUSE/grubenv")
.and_return("")
allow(Yast::Installation).to receive(:destdir).and_return(destdir)
end

it "reads menu timeout" do
subject.read

expect(subject.grub_default.timeout).to eq "10"
end

it "reads entries from /etc/kernel/cmdline" do
subject.read

expect(subject.cpu_mitigations.to_human_string).to eq "Off"
expect(subject.grub_default.kernel_params.serialize).to eq cmdline_content
end
end

describe "#write" do
before do
allow(Yast::Stage).to receive(:initial).and_return(false)
allow(Yast::Installation).to receive(:destdir).and_return(destdir)
subject.grub_default.kernel_params.replace(cmdline_content)
subject.grub_default.timeout = 10
end

it "installs the bootloader" do
allow(Yast::Execute).to receive(:on_target)
.with("/usr/bin/sdbootutil", "set-timeout",
subject.grub_default.timeout,
allowed_exitstatus: [0, 1])
allow(Yast::Execute).to receive(:on_target!)
.with("/usr/bin/sdbootutil", "set-default", subject.sections.default)

# install bootloader
expect(Yast::Execute).to receive(:on_target!)
.with("/usr/bin/sdbootutil", "--verbose", "install")

# create menu entries
expect(Yast::Execute).to receive(:on_target!)
.with("/usr/bin/sdbootutil", "--verbose", "add-all-kernels")

subject.write
end

it "writes kernel cmdline" do
allow(Yast::Execute).to receive(:on_target)
.with("/usr/bin/sdbootutil", "set-timeout",
subject.grub_default.timeout,
allowed_exitstatus: [0, 1])
allow(Yast::Execute).to receive(:on_target!)
.with("/usr/bin/sdbootutil", "set-default", subject.sections.default)
allow(Yast::Execute).to receive(:on_target!)
.with("/usr/bin/sdbootutil", "--verbose", "install")
allow(Yast::Execute).to receive(:on_target!)
.with("/usr/bin/sdbootutil", "--verbose", "add-all-kernels")

subject.write
# Checking written kernel parameters
subject.read
expect(subject.cpu_mitigations.to_human_string).to eq "Off"
expect(subject.grub_default.kernel_params.serialize).to include cmdline_content
end

it "saves menu timeout" do
allow(Yast::Execute).to receive(:on_target!)
.with("/usr/bin/sdbootutil", "set-default", subject.sections.default)
allow(Yast::Execute).to receive(:on_target!)
.with("/usr/bin/sdbootutil", "--verbose", "install")
allow(Yast::Execute).to receive(:on_target!)
.with("/usr/bin/sdbootutil", "--verbose", "add-all-kernels")

# Saving menu timeout
expect(Yast::Execute).to receive(:on_target)
.with("/usr/bin/sdbootutil", "set-timeout",
subject.grub_default.timeout,
allowed_exitstatus: [0, 1])
subject.write
end
end

describe "#packages" do
it "adds grub2* and sdbootutil packages" do
allow(Yast::Arch).to receive(:architecture).and_return("x86_64")
allow(Yast::Package).to receive(:Available).with("os-prober").and_return(true)
expect(subject.packages).to include("grub2-" + Yast::Arch.architecture + "-efi-bls")
expect(subject.packages).to include("sdbootutil")
expect(subject.packages).to include("grub2")
end
end

describe "#summary" do
it "returns line with boot loader type specified" do
expect(subject.summary).to include("Boot Loader Type: GRUB2 BLS")
end

end

describe "#merge" do
it "overwrite mitigations and menu timeout if specified in merged one" do
other_cmdline = "splash=silent quiet mitigations=auto"
other = described_class.new
other.grub_default.timeout = 12
other.grub_default.kernel_params.replace(other_cmdline)

subject.grub_default.timeout = 10
subject.grub_default.kernel_params.replace(cmdline_content)

subject.merge(other)

expect(subject.grub_default.timeout).to eq 12
expect(subject.cpu_mitigations.to_human_string).to eq "Auto"
expect(subject.grub_default.kernel_params.serialize).to include "security=apparmor splash=silent quiet mitigations=auto"
end
end

describe "#propose" do
before do
allow(Yast::BootStorage).to receive(:available_swap_partitions).and_return({})
end

it "proposes timeout to product/role default" do
allow(Yast::ProductFeatures).to receive(:GetIntegerFeature)
.with("globals", "boot_timeout").and_return(2)
subject.propose

expect(subject.grub_default.timeout).to eq 2
end

it "proposes kernel cmdline" do
expect(Yast::BootArch).to receive(:DefaultKernelParams).and_return(cmdline_content)

subject.propose
expect(subject.grub_default.kernel_params.serialize).to eq cmdline_content
end
end
end

0 comments on commit 89f6d73

Please sign in to comment.