diff --git a/service/lib/agama/storage/finisher.rb b/service/lib/agama/storage/finisher.rb index 6d97f1d88e..291ca6d5d0 100644 --- a/service/lib/agama/storage/finisher.rb +++ b/service/lib/agama/storage/finisher.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -# Copyright (c) [2023] SUSE LLC +# Copyright (c) [2023-2025] SUSE LLC # # All Rights Reserved. # @@ -20,6 +20,7 @@ # find current contact information at www.suse.com. require "yast" +require "yast/i18n" require "yast2/execute" require "yast2/systemd/service" require "bootloader/finish_client" @@ -82,6 +83,7 @@ def possible_steps SecurityStep.new(logger, security), CopyFilesStep.new(logger), StorageStep.new(logger), + IscsiStep.new(logger), BootloaderStep.new(logger), IguanaStep.new(logger), SnapshotsStep.new(logger), @@ -94,8 +96,11 @@ def possible_steps # Base class for the Finisher steps containing some shared logic class Step + include Yast::I18n + # Base constructor def initialize(logger) + textdomain "agama" @logger = logger end @@ -137,7 +142,7 @@ class CopyFilesStep < Step ].freeze def label - "Copying important installation files to the target system" + _("Copying important installation files to the target system") end def run? @@ -178,7 +183,7 @@ def initialize(logger, security) end def label - "Writing Linux Security Modules configuration" + _("Writing Linux Security Modules configuration") end def run @@ -189,7 +194,7 @@ def run # Step to write the bootloader configuration class BootloaderStep < Step def label - "Installing bootloader" + _("Installing bootloader") end def run @@ -206,7 +211,7 @@ def cio_ignore_finish # Step to finish the Y2Storage configuration class StorageStep < Step def label - "Adjusting storage configuration" + _("Adjusting storage configuration") end def run @@ -214,10 +219,21 @@ def run end end + # Step to finish the iSCSI configuration + class IscsiStep < Step + def label + _("Adjusting iSCSI configuration") + end + + def run + wfm_write("iscsi-client_finish") + end + end + # Step to configure the file-system snapshots class SnapshotsStep < Step def label - "Configuring file systems snapshots" + _("Configuring file systems snapshots") end def run @@ -230,7 +246,7 @@ class CopyLogsStep < Step SCRIPTS_DIR = "/run/agama/scripts" def label - "Copying logs" + _("Copying logs") end def run @@ -264,7 +280,7 @@ def logs_dir # Executes post-installation scripts class PostScripts < Step def label - "Running user-defined scripts" + _("Running user-defined scripts") end def run @@ -303,7 +319,7 @@ def enable_init_scripts # Executes post-installation scripts class FilesStep < Step def label - "Deploying user-defined files" + _("Deploying user-defined files") end def run @@ -322,7 +338,7 @@ def deploy_files # Step to unmount the target file-systems class UnmountStep < Step def label - "Unmounting storage devices" + _("Unmounting storage devices") end def run @@ -338,7 +354,7 @@ class IguanaStep < Step private_constant :IGUANA_MOUNTLIST def label - "Configuring Iguana" + _("Configuring Iguana") end def run? diff --git a/service/lib/agama/storage/iscsi/adapter.rb b/service/lib/agama/storage/iscsi/adapter.rb index 13e3c8913f..a49ba0d907 100644 --- a/service/lib/agama/storage/iscsi/adapter.rb +++ b/service/lib/agama/storage/iscsi/adapter.rb @@ -25,6 +25,7 @@ require "y2iscsi_client/authentication" Yast.import "IscsiClientLib" +Yast.import "Service" module Agama module Storage @@ -33,6 +34,7 @@ module ISCSI class Adapter # Performs actions for activating iSCSI. def activate + start_services Yast::IscsiClientLib.getiBFT # Check initiator name, creating one if missing. return false unless Yast::IscsiClientLib.checkInitiatorName(silent: true) @@ -137,6 +139,13 @@ def update_node(node, startup:) private + # Starts the iSCSI services. + def start_services + Yast::Service.start("iscsi") + Yast::Service.start("iscsid") + Yast::Service.start("iscsiuio") + end + # Creates an iSCSI authentication object. # # @param credentials [Hash] diff --git a/service/lib/agama/storage/iscsi/manager.rb b/service/lib/agama/storage/iscsi/manager.rb index 0064f59bb1..8a1dfd491b 100644 --- a/service/lib/agama/storage/iscsi/manager.rb +++ b/service/lib/agama/storage/iscsi/manager.rb @@ -37,6 +37,7 @@ class Manager include Yast::I18n STARTUP_OPTIONS = ["onboot", "manual", "automatic"].freeze + PACKAGES = ["open-iscsi", "iscsiuio"].freeze # Config according to the JSON schema. # @@ -61,7 +62,15 @@ def initialize(progress_manager: nil, logger: nil) @nodes = [] @on_activate_callbacks = [] @on_probe_callbacks = [] - @on_sessions_change_callbacks = [] + # Sets iSCSI as configured after any change on the sessions. + @on_sessions_change_callbacks = [proc { @configured = true }] + end + + # Whether iSCSI was configured. + # + # @return [Boolean] + def configured? + !!@configured end # Performs actions for activating iSCSI. diff --git a/service/lib/agama/storage/manager.rb b/service/lib/agama/storage/manager.rb index 1815746072..a33230d66b 100644 --- a/service/lib/agama/storage/manager.rb +++ b/service/lib/agama/storage/manager.rb @@ -256,14 +256,28 @@ def probe_devices # Adds the required packages to the list of resolvables to install def add_packages - devicegraph = Y2Storage::StorageManager.instance.staging packages = devicegraph.used_features.pkg_list + packages += ISCSI::Manager::PACKAGES if need_iscsi? return if packages.empty? logger.info "Selecting these packages for installation: #{packages}" Yast::PackagesProposal.SetResolvables(PROPOSAL_ID, :package, packages) end + # Whether iSCSI is needed in the target system. + # + # @return [Boolean] + def need_iscsi? + iscsi.configured? || devicegraph.used_features.any? { |f| f.id == :UF_ISCSI } + end + + # Staging devicegraph + # + # @return [Y2Storage::Devicegraph] + def devicegraph + Y2Storage::StorageManager.instance.staging + end + # Prepares the storage devices for installation # # @return [Boolean] true if the all actions were successful diff --git a/service/package/rubygem-agama-yast.changes b/service/package/rubygem-agama-yast.changes index 822086afae..38e2abbecb 100644 --- a/service/package/rubygem-agama-yast.changes +++ b/service/package/rubygem-agama-yast.changes @@ -1,3 +1,9 @@ +------------------------------------------------------------------- +Thu Jun 19 10:21:13 UTC 2025 - José Iván López González + +- Add missing steps for iSCSI installation + (gh#agama-project/agama#2473). + ------------------------------------------------------------------- Wed Jun 18 12:28:14 UTC 2025 - Ladislav Slezák diff --git a/service/test/agama/storage/iscsi/manager_test.rb b/service/test/agama/storage/iscsi/manager_test.rb index bf82acdbf0..19f2bc2d7d 100644 --- a/service/test/agama/storage/iscsi/manager_test.rb +++ b/service/test/agama/storage/iscsi/manager_test.rb @@ -50,6 +50,7 @@ allow(Yast::IscsiClientLib).to receive(:iBFT?) allow(Yast::IscsiClientLib).to receive(:find_session) allow(Yast::IscsiClientLib).to receive(:getStartupStatus) + allow(Yast::Service).to receive(:start) allow(subject).to receive(:adapter).and_return(adapter) allow(subject).to receive(:sleep) end @@ -69,6 +70,14 @@ subject.activate end + it "enables the iSCSI services" do + expect(Yast::Service).to receive(:start).with("iscsi").ordered + expect(Yast::Service).to receive(:start).with("iscsid").ordered + expect(Yast::Service).to receive(:start).with("iscsiuio").ordered + + subject.activate + end + it "runs the callbacks" do callback = proc {} subject.on_activate(&callback) @@ -230,25 +239,20 @@ end describe "#login" do - let(:node) { Agama::Storage::ISCSI::Node.new } - before do allow(Yast::IscsiClientLib).to receive(:default_startup_status).and_return("onboot") - allow(Yast::IscsiClientLib).to receive(:login_into_current) - allow(Yast::IscsiClientLib).to receive(:setStartupStatus) - end - - let(:startup) { "automatic" } - - before do allow(Yast::IscsiClientLib).to receive(:login_into_current).and_return(login_success) allow(Yast::IscsiClientLib).to receive(:setStartupStatus).and_return(startup_success) end + let(:node) { Agama::Storage::ISCSI::Node.new } + let(:login_success) { nil } let(:startup_success) { nil } + let(:startup) { "automatic" } + it "tries to login without credentials" do expect(Yast::IscsiClientLib).to receive(:login_into_current) do |auth, _| expect(auth).to be_a(Y2IscsiClient::Authentication) @@ -685,4 +689,50 @@ end end end + + describe "#configured?" do + context "if no session has been configured yet" do + it "returns false" do + expect(subject.configured?).to eq(false) + end + end + + context "if a session was configured by loading a config" do + let(:config_json) do + { + targets: [ + { + address: "192.168.100.152", + port: 3260, + name: "iqn.2025-01.com.example:becda24e8804c6580bd1", + interface: "default" + } + ] + } + end + + before do + allow(adapter).to receive(:login).and_return(true) + subject.apply_config_json(config_json) + end + + it "returns true" do + expect(subject.configured?).to eq(true) + end + end + + context "if a session was manually configured" do + before do + allow(Yast::IscsiClientLib).to receive(:default_startup_status).and_return("onboot") + allow(Yast::IscsiClientLib).to receive(:login_into_current).and_return(true) + allow(Yast::IscsiClientLib).to receive(:setStartupStatus).and_return(true) + node = Agama::Storage::ISCSI::Node.new + subject.login(node) + end + + it "returns true" do + expect(subject.configured?).to eq(true) + end + end + end end diff --git a/service/test/agama/storage/manager_test.rb b/service/test/agama/storage/manager_test.rb index ede0ba078e..744287587a 100644 --- a/service/test/agama/storage/manager_test.rb +++ b/service/test/agama/storage/manager_test.rb @@ -319,7 +319,11 @@ end let(:used_features) do - instance_double(Y2Storage::StorageFeaturesList, pkg_list: ["btrfsprogs", "snapper"]) + instance_double( + Y2Storage::StorageFeaturesList, + pkg_list: ["btrfsprogs", "snapper"], + any?: false + ) end let(:bootloader_proposal) { instance_double(Bootloader::ProposalClient, make_proposal: nil) } @@ -343,6 +347,40 @@ storage.install end + + context "if iSCSI was configured" do + before do + allow_any_instance_of(Agama::Storage::ISCSI::Manager) + .to receive(:configured?).and_return(true) + end + + it "adds the iSCSI software to install" do + expect(Yast::PackagesProposal).to receive(:SetResolvables) do |_, _, packages| + expect(packages).to include("open-iscsi", "iscsiuio") + end + + storage.install + end + end + + context "if iSCSI was used" do + before do + allow_any_instance_of(Agama::Storage::ISCSI::Manager) + .to receive(:configured?).and_return(false) + end + + let(:used_features) do + instance_double(Y2Storage::StorageFeaturesList, pkg_list: [], any?: true) + end + + it "adds the iSCSI software to install" do + expect(Yast::PackagesProposal).to receive(:SetResolvables) do |_, _, packages| + expect(packages).to include("open-iscsi", "iscsiuio") + end + + storage.install + end + end end describe "#proposal" do @@ -372,6 +410,7 @@ expect(copy_files).to receive(:run) expect(bootloader_finish).to receive(:write) expect(Yast::WFM).to receive(:CallFunction).with("storage_finish", ["Write"]) + expect(Yast::WFM).to receive(:CallFunction).with("iscsi-client_finish", ["Write"]) expect(Yast::WFM).to receive(:CallFunction).with("snapshots_finish", ["Write"]) expect(network).to receive(:link_resolv) expect(scripts_client).to receive(:run).with("post")