diff --git a/service/lib/agama/dbus/storage/manager.rb b/service/lib/agama/dbus/storage/manager.rb index c6742718eb..ccc8616691 100644 --- a/service/lib/agama/dbus/storage/manager.rb +++ b/service/lib/agama/dbus/storage/manager.rb @@ -119,6 +119,18 @@ def recover_config JSON.pretty_generate(json) end + # Applies the given serialized config model according to the JSON schema. + # + # @param serialized_model [String] Serialized storage config model. + # @return [Integer] 0 success; 1 error + def apply_config_model(serialized_model) + logger.info("Setting storage config model from D-Bus: #{serialized_model}") + + model_json = JSON.parse(serialized_model, symbolize_names: true) + proposal.calculate_from_model(model_json) + proposal.success? ? 0 : 1 + end + # Gets and serializes the storage config model. # # @return [String] @@ -148,6 +160,9 @@ def deprecated_system busy_while { apply_config(serialized_config) } end dbus_method(:GetConfig, "out serialized_config:s") { recover_config } + dbus_method(:SetConfigModel, "in serialized_model:s, out result:u") do |serialized_model| + busy_while { apply_config_model(serialized_model) } + end dbus_method(:GetConfigModel, "out serialized_model:s") { recover_model } dbus_method(:Install) { install } dbus_method(:Finish) { finish } diff --git a/service/lib/agama/storage/proposal.rb b/service/lib/agama/storage/proposal.rb index 74531aaf1e..fff8bd40ad 100644 --- a/service/lib/agama/storage/proposal.rb +++ b/service/lib/agama/storage/proposal.rb @@ -21,9 +21,7 @@ require "agama/issue" require "agama/storage/actions_generator" -require "agama/storage/config_conversions/from_json" -require "agama/storage/config_conversions/to_json" -require "agama/storage/config_conversions/to_model" +require "agama/storage/config_conversions" require "agama/storage/proposal_settings" require "agama/storage/proposal_strategies" require "json" @@ -129,6 +127,15 @@ def calculate_from_json(source_json) success? end + # Calculates a new proposal from a config model. + # + # @param model_json [Hash] Source config model according to the JSON schema. + # @return [Boolean] Whether the proposal successes. + def calculate_from_model(model_json) + config = ConfigConversions::FromModel.new(model_json).convert + calculate_agama(config) + end + # Calculates a new proposal using the guided strategy. # # @param settings [Agama::Storage::ProposalSettings] diff --git a/service/test/agama/dbus/storage/manager_test.rb b/service/test/agama/dbus/storage/manager_test.rb index 7381474efb..8a423168e3 100644 --- a/service/test/agama/dbus/storage/manager_test.rb +++ b/service/test/agama/dbus/storage/manager_test.rb @@ -557,6 +557,37 @@ end end + describe "#apply_config_model" do + let(:serialized_model) { model_json.to_json } + + let(:model_json) do + { + drives: [ + name: "/dev/vda", + partitions: [ + { mountPath: "/" } + ] + ] + } + end + + it "calculates an agama proposal with the given config" do + expect(proposal).to receive(:calculate_agama) do |config| + expect(config).to be_a(Agama::Storage::Config) + expect(config.drives.size).to eq(1) + + drive = config.drives.first + expect(drive.search.name).to eq("/dev/vda") + expect(drive.partitions.size).to eq(1) + + partition = drive.partitions.first + expect(partition.filesystem.path).to eq("/") + end + + subject.apply_config_model(serialized_model) + end + end + describe "#recover_config" do def serialize(value) JSON.pretty_generate(value) diff --git a/service/test/agama/storage/proposal_test.rb b/service/test/agama/storage/proposal_test.rb index 97c13326af..a5dda91ee3 100644 --- a/service/test/agama/storage/proposal_test.rb +++ b/service/test/agama/storage/proposal_test.rb @@ -692,6 +692,34 @@ def drive(partitions) end end + describe "#calculate_from_model" do + let(:model_json) do + { + drives: [ + { + name: "/dev/vda", + filesystem: { + type: "xfs" + } + } + ] + } + end + + it "calculates a proposal with the agama strategy and with the expected config" do + expect(subject).to receive(:calculate_agama) do |config| + expect(config).to be_a(Agama::Storage::Config) + expect(config.drives.size).to eq(1) + + drive = config.drives.first + expect(drive.search.name).to eq("/dev/vda") + expect(drive.filesystem.type.fs_type).to eq(Y2Storage::Filesystems::Type::XFS) + end + + subject.calculate_from_model(model_json) + end + end + describe "#actions" do it "returns an empty list if calculate has not been called yet" do expect(subject.actions).to eq([])