From e491682340e19c7e92efad5132e87c20c9f3adbf Mon Sep 17 00:00:00 2001 From: Leos Stejskal Date: Tue, 18 Jun 2024 13:06:21 +0200 Subject: [PATCH 1/2] EFI & Secure Boot Co-authored-by: Ewoud Kohl van Wijngaarden --- .rubocop.yml | 4 ++ lib/fog/libvirt/models/compute/server.rb | 18 +++++++- tests/libvirt/models/compute/server_tests.rb | 43 ++++++++++++++++++++ 3 files changed, 64 insertions(+), 1 deletion(-) diff --git a/.rubocop.yml b/.rubocop.yml index a0874b8..c3b6657 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -17,3 +17,7 @@ Style/SignalException: Metrics/ClassLength: Enabled: false + +Metrics/BlockLength: + Exclude: + - tests/**/*.rb diff --git a/lib/fog/libvirt/models/compute/server.rb b/lib/fog/libvirt/models/compute/server.rb index 531e631..7832700 100644 --- a/lib/fog/libvirt/models/compute/server.rb +++ b/lib/fog/libvirt/models/compute/server.rb @@ -13,6 +13,8 @@ class Server < Fog::Compute::Server attribute :cpus attribute :cputime + attribute :os_firmware + attribute :os_firmware_features attribute :os_type attribute :memory_size attribute :max_memory_size @@ -287,14 +289,28 @@ def to_xml end xml.vcpu(cpus) - xml.os do + os_tags = {} + + # Set firmware only if it's EFI, BIOS don't need to be set + os_tags[:firmware] = "efi" if os_firmware == "efi" + + xml.os(**os_tags) do type = xml.type(os_type, :arch => arch) type[:machine] = "q35" if ["i686", "x86_64"].include?(arch) boot_order.each do |dev| xml.boot(:dev => dev) end + + if os_firmware == "efi" + xml.firmware do + os_firmware_features.each_pair do |key, value| + xml.feature(:name => key, :enabled => value) + end + end + end end + xml.features do xml.acpi xml.apic diff --git a/tests/libvirt/models/compute/server_tests.rb b/tests/libvirt/models/compute/server_tests.rb index 30d45f2..f9d6b0b 100644 --- a/tests/libvirt/models/compute/server_tests.rb +++ b/tests/libvirt/models/compute/server_tests.rb @@ -32,6 +32,8 @@ attributes = [ :id, :cpus, :cputime, + :os_firmware, + :os_firmware_features, :os_type, :memory_size, :max_memory_size, @@ -67,6 +69,7 @@ test('be a kind of Fog::Libvirt::Compute::Server') { server.kind_of? Fog::Libvirt::Compute::Server } tests("serializes to xml") do + test("without firmware") { server.to_xml.include?("") } test("with memory") { server.to_xml.match?(%r{\d+}) } test("with disk of type file") do xml = server.to_xml @@ -86,5 +89,45 @@ end test("with q35 machine type on x86_64") { server.to_xml.match?(%r{hvm}) } end + test("with efi firmware") do + server = Fog::Libvirt::Compute::Server.new( + { + :os_firmware => "efi", + :os_firmware_features => { + "secure-boot" => "no", + "enrolled-keys" => "no" + }, + :nics => [], + :volumes => [] + } + ) + xml = server.to_xml + + os_firmware = xml.include?('') + secure_boot = !xml.include?('') + enrolled_keys = !xml.include?('') + + os_firmware && secure_boot && enrolled_keys + end + test("with secure boot") do + server = Fog::Libvirt::Compute::Server.new( + { + :os_firmware => "efi", + :os_firmware_features => { + "secure-boot" => "yes", + "enrolled-keys" => "yes" + }, + :nics => [], + :volumes => [] + } + ) + xml = server.to_xml + + os_firmware = xml.include?('') + secure_boot = xml.include?('') + enrolled_keys = xml.include?('') + + os_firmware && secure_boot && enrolled_keys + end end end From ba8b95cd1925fe3fcfd54bfe0a93bc11ebad717f Mon Sep 17 00:00:00 2001 From: nofaralfasi Date: Mon, 22 Jul 2024 18:14:20 +0300 Subject: [PATCH 2/2] Refactor Secure Boot Support and Firmware Handling - Renamed firmware-related attributes to align with VMware conventions. - Added the `loader` attribute to determine if SB is enabled. --- lib/fog/libvirt/models/compute/server.rb | 18 ++++++++---- .../libvirt/requests/compute/list_domains.rb | 22 ++++++++++++++- tests/libvirt/models/compute/server_tests.rb | 28 +++++++++---------- 3 files changed, 47 insertions(+), 21 deletions(-) diff --git a/lib/fog/libvirt/models/compute/server.rb b/lib/fog/libvirt/models/compute/server.rb index 7832700..d9f0bce 100644 --- a/lib/fog/libvirt/models/compute/server.rb +++ b/lib/fog/libvirt/models/compute/server.rb @@ -13,8 +13,10 @@ class Server < Fog::Compute::Server attribute :cpus attribute :cputime - attribute :os_firmware - attribute :os_firmware_features + attribute :firmware + attribute :firmware_features + attribute :secure_boot + attribute :loader attribute :os_type attribute :memory_size attribute :max_memory_size @@ -291,8 +293,7 @@ def to_xml xml.vcpu(cpus) os_tags = {} - # Set firmware only if it's EFI, BIOS don't need to be set - os_tags[:firmware] = "efi" if os_firmware == "efi" + os_tags[:firmware] = firmware if firmware == 'efi' xml.os(**os_tags) do type = xml.type(os_type, :arch => arch) @@ -302,9 +303,13 @@ def to_xml xml.boot(:dev => dev) end - if os_firmware == "efi" + loader&.each do |key, value| + xml.loader(key => value) + end + + if firmware == "efi" && firmware_features&.any? xml.firmware do - os_firmware_features.each_pair do |key, value| + firmware_features.each_pair do |key, value| xml.feature(:name => key, :enabled => value) end end @@ -555,6 +560,7 @@ def defaults :guest_agent => true, :video => {:type => "cirrus", :vram => 9216, :heads => 1}, :virtio_rng => {}, + :firmware_features => { "secure-boot" => "no" }, } end diff --git a/lib/fog/libvirt/requests/compute/list_domains.rb b/lib/fog/libvirt/requests/compute/list_domains.rb index 25b02a4..2dc7f99 100644 --- a/lib/fog/libvirt/requests/compute/list_domains.rb +++ b/lib/fog/libvirt/requests/compute/list_domains.rb @@ -46,6 +46,24 @@ def boot_order xml xml_elements(xml, "domain/os/boot", "dev") end + def firmware(xml) + firmware_from_loader = xml_elements(xml, "domain/os/loader", "type").first + + case firmware_from_loader + when 'pflash' + 'efi' + when 'rom' + 'bios' + else + xml_elements(xml, "domain/os", "firmware").first || 'bios' + end + end + + # we rely on the fact that the secure attribute is only present when secure boot is enabled + def secure_boot_enabled?(xml) + xml_elements(xml, "domain/os/loader", "secure").first == 'yes' + end + def domain_interfaces xml ifs = xml_elements(xml, "domain/devices/interface") ifs.map { |i| @@ -78,7 +96,9 @@ def domain_to_attributes(dom) :boot_order => boot_order(dom.xml_desc), :nics => domain_interfaces(dom.xml_desc), :volumes_path => domain_volumes(dom.xml_desc), - :state => states[dom.info.state] + :state => states[dom.info.state], + :firmware => firmware(dom.xml_desc), + :secure_boot => secure_boot_enabled?(dom.xml_desc), } rescue ::Libvirt::RetrieveError, ::Libvirt::Error # Catch libvirt exceptions to avoid race conditions involving diff --git a/tests/libvirt/models/compute/server_tests.rb b/tests/libvirt/models/compute/server_tests.rb index f9d6b0b..2ee7a03 100644 --- a/tests/libvirt/models/compute/server_tests.rb +++ b/tests/libvirt/models/compute/server_tests.rb @@ -32,8 +32,10 @@ attributes = [ :id, :cpus, :cputime, - :os_firmware, - :os_firmware_features, + :firmware, + :firmware_features, + :secure_boot, + :loader, :os_type, :memory_size, :max_memory_size, @@ -92,11 +94,7 @@ test("with efi firmware") do server = Fog::Libvirt::Compute::Server.new( { - :os_firmware => "efi", - :os_firmware_features => { - "secure-boot" => "no", - "enrolled-keys" => "no" - }, + :firmware => "efi", :nics => [], :volumes => [] } @@ -104,19 +102,20 @@ xml = server.to_xml os_firmware = xml.include?('') - secure_boot = !xml.include?('') - enrolled_keys = !xml.include?('') + secure_boot = xml.include?('') + loader = !xml.include?('') - os_firmware && secure_boot && enrolled_keys + os_firmware && secure_boot && loader end - test("with secure boot") do + test("with secure boot enabled") do server = Fog::Libvirt::Compute::Server.new( { - :os_firmware => "efi", - :os_firmware_features => { + :firmware => "efi", + :firmware_features => { "secure-boot" => "yes", "enrolled-keys" => "yes" }, + :loader => { "secure" => "yes" }, :nics => [], :volumes => [] } @@ -126,8 +125,9 @@ os_firmware = xml.include?('') secure_boot = xml.include?('') enrolled_keys = xml.include?('') + loader = xml.include?('') - os_firmware && secure_boot && enrolled_keys + os_firmware && secure_boot && enrolled_keys && loader end end end