Skip to content

Commit

Permalink
storage: generate physical volumes config
Browse files Browse the repository at this point in the history
  • Loading branch information
joseivanlopez committed Oct 4, 2024
1 parent a9e9321 commit 9e452b7
Show file tree
Hide file tree
Showing 6 changed files with 198 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
# find current contact information at www.suse.com.

require "agama/storage/config_conversions/from_json_conversions/base"
require "agama/storage/config_conversions/from_json_conversions/encryption"
require "agama/storage/config_conversions/from_json_conversions/logical_volume"
require "agama/storage/configs/volume_group"

Expand All @@ -43,10 +44,12 @@ def convert
# @return [Hash]
def conversions
{
name: volume_group_json[:name],
extent_size: convert_extent_size,
physical_volumes: volume_group_json[:physicalVolumes],
logical_volumes: convert_logical_volumes
name: volume_group_json[:name],
extent_size: convert_extent_size,
physical_volumes_devices: convert_physical_volumes_devices,
physical_volumes_encryption: convert_physical_volumes_encryption,
physical_volumes: convert_physical_volumes,
logical_volumes: convert_logical_volumes
}
end

Expand All @@ -58,6 +61,40 @@ def convert_extent_size
Y2Storage::DiskSize.new(value)
end

# @return [Array<String>, nil]
def convert_physical_volumes_devices
generate_json = physical_volume_generate_json
return unless generate_json

generate_json.dig(:generate, :targetDevices)
end

# @return [Configs::Encryption, nil]
def convert_physical_volumes_encryption
encryption_json = physical_volume_generate_json&.dig(:generate, :encryption)
return unless encryption_json

FromJSONConversions::Encryption.new(encryption_json).convert
end

# JSON of the physical volume with a 'generate'.
#
# @return [Hash, nil]
def physical_volume_generate_json
physical_volumes_json = volume_group_json[:physicalVolumes]
return unless physical_volumes_json

physical_volumes_json.find { |p| p.is_a?(Hash) }
end

# @return [Array<String>, nil]
def convert_physical_volumes
physical_volumes_json = volume_group_json[:physicalVolumes]
return unless physical_volumes_json

physical_volumes_json.select { |c| c.is_a?(String) }
end

# @return [Array<Configs::LogicalVolume>, nil]
def convert_logical_volumes
logical_volumes_json = volume_group_json[:logicalVolumes]
Expand Down
23 changes: 22 additions & 1 deletion service/lib/agama/storage/config_encryption_solver.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ def initialize(product_config)
def solve(config)
@config = config

configs_with_encryption.each { |c| solve_encryption(c) }
solve_encryptions
solve_physical_volumes_encryptions
end

private
Expand All @@ -52,6 +53,10 @@ def solve(config)
# @return [Config]
attr_reader :config

def solve_encryptions
configs_with_encryption.each { |c| solve_encryption(c) }
end

# @param config [#encryption]
def solve_encryption(config)
return unless config.encryption
Expand All @@ -64,6 +69,22 @@ def solve_encryption(config)
solve_encryption_values(encryption) if encryption.method == default_encryption.method
end

def solve_physical_volumes_encryptions
config.volume_groups.each { |c| solve_physical_volumes_encryption(c) }
end

# @param config [Configs::VolumeGroup]
def solve_physical_volumes_encryption(config)
return unless config.physical_volumes_encryption

encryption = config.physical_volumes_encryption
encryption.method ||= default_encryption.method

# Recovering values from the default encryption only makes sense if the encryption method is
# the same.
solve_encryption_values(encryption) if encryption.method == default_encryption.method
end

# @param config [Configs::Encryption]
def solve_encryption_values(config)
config.password ||= default_encryption.password
Expand Down
13 changes: 13 additions & 0 deletions service/lib/agama/storage/configs/volume_group.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,26 @@ class VolumeGroup
# @return [Y2Storage::DiskSize, nil]
attr_accessor :extent_size

# Aliases of the devices used for automatically creating new physical volumes.
#
# @return [Array<String>]
attr_accessor :physical_volumes_devices

# Encryption for the new physical volumes created at the {physical_volume_devices}.
#
# @return [Encryption, nil]
attr_accessor :physical_volumes_encryption

# Aliases of the devices used as physical volumes.
#
# @return [Array<String>]
attr_accessor :physical_volumes

# @return [Array<LogicalVolume>]
attr_accessor :logical_volumes

def initialize
@physical_volumes_devices = []
@physical_volumes = []
@logical_volumes = []
end
Expand Down
93 changes: 92 additions & 1 deletion service/test/agama/storage/config_conversions/from_json_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -924,10 +924,20 @@
context "with an empty list" do
let(:physical_volumes) { [] }

it "sets #physical_volumes to empty" do
it "sets #physical_volumes to the expected value" do
vg = vg_proc.call(subject.convert)
expect(vg.physical_volumes).to eq([])
end

it "sets #physical_volumes_devices to the expected value" do
vg = vg_proc.call(subject.convert)
expect(vg.physical_volumes_devices).to eq([])
end

it "sets #physical_volumes_encryption to the expected value" do
vg = vg_proc.call(subject.convert)
expect(vg.physical_volumes_encryption).to be_nil
end
end

context "with a list of aliases" do
Expand All @@ -937,6 +947,87 @@
vg = vg_proc.call(subject.convert)
expect(vg.physical_volumes).to contain_exactly("pv1", "pv2")
end

it "sets #physical_volumes_devices to the expected value" do
vg = vg_proc.call(subject.convert)
expect(vg.physical_volumes_devices).to eq([])
end

it "sets #physical_volumes_encryption to the expected value" do
vg = vg_proc.call(subject.convert)
expect(vg.physical_volumes_encryption).to be_nil
end
end

context "with a list including a physical volume with 'generate'" do
let(:physical_volumes) do
[
"pv1",
{
generate: {
targetDevices: target_devices,
encryption: encryption
}
},
"pv2"
]
end

let(:target_devices) { nil }

let(:encryption) { nil }

it "sets #physical_volumes to the expected value" do
vg = vg_proc.call(subject.convert)
expect(vg.physical_volumes).to contain_exactly("pv1", "pv2")
end

context "if the physical volume does not specify 'targetDevices'" do
let(:target_devices) { nil }

it "sets #physical_volumes_devices to the expected value" do
vg = vg_proc.call(subject.convert)
expect(vg.physical_volumes_devices).to eq([])
end
end

context "if the physical volume does not specify 'encryption'" do
let(:target_devices) { nil }

it "does not set #physical_volumes_encryption" do
vg = vg_proc.call(subject.convert)
expect(vg.physical_volumes_encryption).to be_nil
end
end

context "if the physical volume specifies 'targetDevices'" do
let(:target_devices) { ["disk1"] }

it "sets #physical_volumes_devices to the expected value" do
vg = vg_proc.call(subject.convert)
expect(vg.physical_volumes_devices).to contain_exactly("disk1")
end
end

context "if the physical volume specifies 'encryption'" do
let(:encryption) do
{
luks1: { password: "12345" }
}
end

it "sets #physical_volumes_encryption to the expected value" do
vg = vg_proc.call(subject.convert)
encryption = vg.physical_volumes_encryption
expect(encryption).to be_a(Agama::Storage::Configs::Encryption)
expect(encryption.method).to eq(Y2Storage::EncryptionMethod::LUKS1)
expect(encryption.password).to eq("12345")
expect(encryption.pbkd_function).to be_nil
expect(encryption.label).to be_nil
expect(encryption.cipher).to be_nil
expect(encryption.key_size).to be_nil
end
end
end
end

Expand Down
30 changes: 30 additions & 0 deletions service/test/agama/storage/config_solver_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,36 @@
end
end

context "if a volume group does not specify all the pv encryption properties" do
let(:config_json) do
{
volumeGroups: [
{
physicalVolumes: [
{
generate: {
encryption: {
luks2: { password: "12345" }
}
}
}
]
}
]
}
end

it "completes the encryption config according to the product info" do
subject.solve(config)

volume_group = config.volume_groups.first
encryption = volume_group.physical_volumes_encryption
expect(encryption.method).to eq(Y2Storage::EncryptionMethod::LUKS2)
expect(encryption.password).to eq("12345")
expect(encryption.pbkd_function).to eq(Y2Storage::PbkdFunction::ARGON2I)
end
end

context "if a config does not specify all the filesystem properties" do
let(:config_json) do
{
Expand Down
1 change: 0 additions & 1 deletion service/test/y2storage/agama_proposal_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,6 @@ def partition_config(name: nil, filesystem: nil, size: nil)

describe Y2Storage::AgamaProposal do
include Agama::RSpec::StorageHelpers
using Y2Storage::Refinements::SizeCasts

subject(:proposal) do
described_class.new(config, product_config: product_config, issues_list: issues_list)
Expand Down

0 comments on commit 9e452b7

Please sign in to comment.