Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adapt storage UI #724

Merged
3 changes: 3 additions & 0 deletions service/etc/agama.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ ALP-Dolomite:
patterns: null

storage:
space_policy: delete
encryption:
method: luks2
pbkd_function: pbkdf2
Expand Down Expand Up @@ -150,6 +151,7 @@ Tumbleweed:
patterns: null

storage:
space_policy: delete
volumes:
- "/"
- "swap"
Expand Down Expand Up @@ -274,6 +276,7 @@ Leap16:
patterns: null

storage:
space_policy: delete
encryption:
method: luks2
pbkd_function: pbkdf2
Expand Down
13 changes: 3 additions & 10 deletions service/lib/agama/dbus/storage/manager.rb
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ def initialize(backend, logger)
register_progress_callbacks
register_service_status_callbacks
register_iscsi_callbacks
register_software_callbacks

add_s390_interfaces if Yast::Arch.s390
end
Expand Down Expand Up @@ -149,7 +148,7 @@ def calculate_proposal(dbus_settings)
logger.info(
"Calculating storage proposal from D-Bus.\n " \
"D-Bus settings: #{dbus_settings}\n" \
"Agama settings: #{settings}"
"Agama settings: #{settings.inspect}"
)

success = proposal.calculate(settings)
Expand All @@ -164,8 +163,8 @@ def calculate_proposal(dbus_settings)

dbus_reader :result, "o"

dbus_method :DefaultVolume, "in mount_path:s , out volume:a{sv}" do |mount_path|
default_volume(mount_path)
dbus_method :DefaultVolume, "in mount_path:s, out volume:a{sv}" do |mount_path|
[default_volume(mount_path)]
end

# result: 0 success; 1 error
Expand Down Expand Up @@ -298,12 +297,6 @@ def register_iscsi_callbacks
end
end

def register_software_callbacks
backend.software.on_product_selected do |_product|
backend.proposal.invalidate
end
end

def storage_properties_changed
properties = interfaces_and_properties[STORAGE_INTERFACE]
dbus_properties_changed(STORAGE_INTERFACE, properties, [])
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ def convert
# @param target [Agama::Storage::ProposalSettings]
# @param value [String]
def boot_device_conversion(target, value)
target.boot_device = value
target.boot_device = value.empty? ? nil : value
end

# @param target [Agama::Storage::ProposalSettings]
Expand Down
14 changes: 2 additions & 12 deletions service/lib/agama/storage/manager.rb
Original file line number Diff line number Diff line change
Expand Up @@ -188,22 +188,12 @@ def probe_devices
self.deprecated_system = false
end

# Calculates the proposal
#
# It reuses the settings from the previous proposal, if any.
# Calculates the proposal using the settings from the config file.
def calculate_proposal
settings = proposal.settings || read_proposal_settings

settings = ProposalSettingsReader.new(config).read
proposal.calculate(settings)
end

# Reads the default proposal settings from the config file.
#
# @return [ProposalSettings]
def read_proposal_settings
ProposalSettingsReader.new(config).read
end

# Adds the required packages to the list of resolvables to install
def add_packages
devicegraph = Y2Storage::StorageManager.instance.staging
Expand Down
37 changes: 9 additions & 28 deletions service/lib/agama/storage/proposal.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,34 +38,11 @@ def initialize(config, logger: nil)

# Whether the proposal was successfully calculated.
#
# @note: The proposal must not be invalidated.
#
# @return [Boolean]
def success?
calculated? && !proposal.failed?
end

# Whether the proposal was already calculated.
#
# @note: The proposal must not be invalidated.
#
# @return [Boolean]
def calculated?
!invalidated? && !proposal.nil?
end

# Whether the proposal was invalidated.
#
# @return [Boolean]
def invalidated?
!!@invalidated
end

# Invalidates the current proposal.
def invalidate
@invalidated = true
end

# Stores callbacks to be call after calculating a proposal.
def on_calculate(&block)
@on_calculate_callbacks << block
Expand All @@ -91,7 +68,6 @@ def calculate(settings)
calculate_proposal(settings)

@on_calculate_callbacks.each(&:call)
@invalidated = false

success?
end
Expand All @@ -101,8 +77,7 @@ def calculate(settings)
# Note that this settings might differ from the {#original_settings}. For example, the sizes
# of some volumes could be adjusted if auto size is set.
#
# @return [ProposalSettings, nil] nil if no proposal has been calculated yet or the proposal
# was invalidated.
# @return [ProposalSettings, nil] nil if no proposal has been calculated yet.
def settings
return nil unless calculated?

Expand Down Expand Up @@ -154,11 +129,16 @@ def issues

# @return [Y2Storage::MinGuidedProposal, nil]
def proposal
return nil if invalidated?

storage_manager.proposal
end

# Whether the proposal was already calculated.
#
# @return [Boolean]
def calculated?
!proposal.nil?
end

# Instantiates and executes a Y2Storage proposal with the given settings
#
# @param settings [Y2Storage::ProposalSettings]
Expand Down Expand Up @@ -205,6 +185,7 @@ def boot_device_issue
# @return [Issue, nil]
def missing_devices_issue
# At this moment, only the boot device is checked.
return unless settings.boot_device
return if available_devices.map(&:name).include?(settings.boot_device)

Issue.new("Selected device is not found in the system",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ def lvm_conversion(target)

target.lvm = lvm
target.separate_vgs = lvm
# Prevent VG reuse
target.lvm_vg_reuse = false
end

# @param target [Y2Storage::ProposalSettings]
Expand Down Expand Up @@ -135,8 +137,12 @@ def missing_volumes
# @param target [Y2Storage::ProposalSettings]
def fallbacks_conversion(target)
target.volumes.each do |spec|
spec.fallback_for_min_size = find_min_size_fallback(spec.mount_point)
spec.fallback_for_max_size = find_max_size_fallback(spec.mount_point)
min_size_fallback = find_min_size_fallback(spec.mount_point)
max_size_fallback = find_max_size_fallback(spec.mount_point)

spec.fallback_for_min_size = min_size_fallback
spec.fallback_for_max_size = max_size_fallback
spec.fallback_for_max_size_lvm = max_size_fallback
end
end

Expand Down
8 changes: 6 additions & 2 deletions service/lib/agama/storage/volume_conversion/to_y2storage.rb
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,12 @@ def sizes_conversion(target)
# And note that the final range of sizes used by the Y2Storage proposal is calculated by
# Y2Storage according the range configured here and other sizes like fallback sizes or
# the size for snapshots.
target.min_size = auto ? volume.outline.base_min_size : volume.min_size
target.max_size = auto ? volume.outline.base_max_size : volume.max_size
min_size = auto ? volume.outline.base_min_size : volume.min_size
max_size = auto ? volume.outline.base_max_size : volume.max_size

target.min_size = min_size
target.max_size = max_size
target.max_size_lvm = max_size
end

# @param target [Y2Storage::VolumeSpecification]
Expand Down
5 changes: 4 additions & 1 deletion service/lib/agama/storage/volume_templates_builder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,10 @@ def btrfs(data)
def subvolume(data)
return Y2Storage::SubvolSpecification.new(data) if data.is_a?(String)

attrs = { copy_on_write: fetch(data, :copy_on_write), archs: fetch(data, :archs) }.compact
archs = fetch(data, :archs, "").gsub(/\s+/, "").split(",")
archs = nil if archs.none?

attrs = { copy_on_write: fetch(data, :copy_on_write), archs: archs }.compact
Y2Storage::SubvolSpecification.new(fetch(data, :path), **attrs)
end

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,16 @@
end
end

context "when an empty boot device is provided from D-Bus" do
let(:dbus_settings) { { "BootDevice" => "" } }

it "sets the boot device to nil" do
settings = subject.convert

expect(settings.boot_device).to be_nil
end
end

context "when volumes are not provided from D-Bus" do
let(:dbus_settings) { { "Volumes" => [] } }

Expand Down
36 changes: 8 additions & 28 deletions service/test/agama/storage/manager_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,9 @@
allow(y2storage_manager).to receive(:activate)
allow(iscsi).to receive(:probe)
allow(y2storage_manager).to receive(:probe)

allow_any_instance_of(Agama::Storage::ProposalSettingsReader).to receive(:read)
.and_return(config_settings)
end

let(:raw_devicegraph) do
Expand All @@ -168,7 +171,9 @@
let(:iscsi) { Agama::Storage::ISCSI::Manager.new }

let(:devices) { [disk1, disk2] }
let(:settings) { nil }

let(:settings) { Agama::Storage::ProposalSettings.new }
let(:config_settings) { Agama::Storage::ProposalSettings.new }

let(:disk1) { instance_double(Y2Storage::Disk, name: "/dev/vda") }
let(:disk2) { instance_double(Y2Storage::Disk, name: "/dev/vdb") }
Expand All @@ -179,15 +184,15 @@

let(:callback) { proc {} }

it "probes the storage devices and calculates a proposal" do
it "probes the storage devices and calculates a proposal with the default settings" do
expect(config).to receive(:pick_product).with("ALP")
expect(iscsi).to receive(:activate)
expect(y2storage_manager).to receive(:activate) do |callbacks|
expect(callbacks).to be_a(Agama::Storage::Callbacks::Activate)
end
expect(iscsi).to receive(:probe)
expect(y2storage_manager).to receive(:probe)
expect(proposal).to receive(:calculate)
expect(proposal).to receive(:calculate).with(config_settings)
storage.probe
end

Expand Down Expand Up @@ -245,31 +250,6 @@
)
end
end

context "when there are settings from a previous proposal" do
let(:settings) { Agama::Storage::ProposalSettings.new }

it "calculates a proposal using the previous settings" do
expect(proposal).to receive(:calculate).with(settings)
storage.probe
end
end

context "when there are no settings from a previous proposal" do
let(:settings) { nil }

let(:new_settings) { Agama::Storage::ProposalSettings.new }

before do
allow_any_instance_of(Agama::Storage::ProposalSettingsReader).to receive(:read)
.and_return(new_settings)
end

it "calculates a proposal using default settings from the config file" do
expect(proposal).to receive(:calculate).with(new_settings)
storage.probe
end
end
end

describe "#install" do
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
root_device: "/dev/sda",
lvm: true,
separate_vgs: true,
lvm_vg_reuse: false,
encryption_password: "notsecret",
encryption_method: Y2Storage::EncryptionMethod::LUKS2,
encryption_pbkdf: Y2Storage::PbkdFunction::ARGON2ID,
Expand Down Expand Up @@ -269,24 +270,28 @@

expect(y2storage_settings.volumes).to contain_exactly(
an_object_having_attributes(
mount_point: "/",
fallback_for_min_size: nil,
fallback_for_max_size: nil
mount_point: "/",
fallback_for_min_size: nil,
fallback_for_max_size: nil,
fallback_for_max_size_lvm: nil
),
an_object_having_attributes(
mount_point: "/home",
fallback_for_min_size: "/test",
fallback_for_max_size: nil
mount_point: "/home",
fallback_for_min_size: "/test",
fallback_for_max_size: nil,
fallback_for_max_size_lvm: nil
),
an_object_having_attributes(
mount_point: "swap",
fallback_for_min_size: "/test",
fallback_for_max_size: "/test"
mount_point: "swap",
fallback_for_min_size: "/test",
fallback_for_max_size: "/test",
fallback_for_max_size_lvm: "/test"
),
an_object_having_attributes(
mount_point: "/test",
fallback_for_min_size: nil,
fallback_for_max_size: nil
mount_point: "/test",
fallback_for_min_size: nil,
fallback_for_max_size: nil,
fallback_for_max_size_lvm: nil
)
)
end
Expand Down
Loading
Loading