diff --git a/rust/agama-lib/src/manager.rs b/rust/agama-lib/src/manager.rs index a43b23a4c5..da7fa8b393 100644 --- a/rust/agama-lib/src/manager.rs +++ b/rust/agama-lib/src/manager.rs @@ -1,4 +1,4 @@ -// Copyright (c) [2024] SUSE LLC +// Copyright (c) [2024-2025] SUSE LLC // // All Rights Reserved. // @@ -146,6 +146,12 @@ impl<'a> ManagerClient<'a> { Ok(self.manager_proxy.probe().await?) } + /// Starts the reprobing process. + pub async fn reprobe(&self) -> Result<(), ServiceError> { + self.wait().await?; + Ok(self.manager_proxy.reprobe().await?) + } + /// Starts the installation. pub async fn install(&self) -> Result<(), ServiceError> { Ok(self.manager_proxy.commit().await?) diff --git a/rust/agama-lib/src/manager/http_client.rs b/rust/agama-lib/src/manager/http_client.rs index 06bbbe532b..51dc016abd 100644 --- a/rust/agama-lib/src/manager/http_client.rs +++ b/rust/agama-lib/src/manager/http_client.rs @@ -1,4 +1,4 @@ -// Copyright (c) [2024] SUSE LLC +// Copyright (c) [2024-2025] SUSE LLC // // All Rights Reserved. // @@ -52,6 +52,13 @@ impl ManagerHTTPClient { Ok(self.client.post_void("/manager/probe_sync", &()).await?) } + /// Starts a "reprobing". + pub async fn reprobe(&self) -> Result<(), ManagerHTTPClientError> { + // BaseHTTPClient did not anticipate POST without request body + // so we pass () which is rendered as `null` + Ok(self.client.post_void("/manager/reprobe_sync", &()).await?) + } + /// Starts the installation. pub async fn install(&self) -> Result<(), ManagerHTTPClientError> { Ok(self.client.post_void("/manager/install", &()).await?) diff --git a/rust/agama-lib/src/product/store.rs b/rust/agama-lib/src/product/store.rs index fc6d086937..19b96440a7 100644 --- a/rust/agama-lib/src/product/store.rs +++ b/rust/agama-lib/src/product/store.rs @@ -1,4 +1,4 @@ -// Copyright (c) [2024] SUSE LLC +// Copyright (c) [2024-2025] SUSE LLC // // All Rights Reserved. // @@ -78,6 +78,7 @@ impl ProductStore { pub async fn store(&self, settings: &ProductSettings) -> ProductStoreResult<()> { let mut probe = false; + let mut reprobe = false; if let Some(product) = &settings.id { let existing_product = self.product_client.product().await?; if *product != existing_product { @@ -94,7 +95,7 @@ impl ProductStore { self.product_client.register(reg_code, email).await?; // TODO: avoid reprobing if the system has been already registered with the same code? - probe = true; + reprobe = true; } // register the addons in the order specified in the profile if let Some(addons) = &settings.addons { @@ -105,6 +106,8 @@ impl ProductStore { if probe { self.manager_client.probe().await?; + } else if reprobe { + self.manager_client.reprobe().await?; } Ok(()) diff --git a/rust/agama-lib/src/proxies/manager1.rs b/rust/agama-lib/src/proxies/manager1.rs index 3ac0d73397..f852a7fa26 100644 --- a/rust/agama-lib/src/proxies/manager1.rs +++ b/rust/agama-lib/src/proxies/manager1.rs @@ -41,6 +41,9 @@ pub trait Manager1 { /// Probe method fn probe(&self) -> zbus::Result<()>; + /// Reprobe method + fn reprobe(&self) -> zbus::Result<()>; + /// BusyServices property #[zbus(property)] fn busy_services(&self) -> zbus::Result>; diff --git a/rust/agama-server/src/manager/web.rs b/rust/agama-server/src/manager/web.rs index e5bbf4e3ca..ad37553a91 100644 --- a/rust/agama-server/src/manager/web.rs +++ b/rust/agama-server/src/manager/web.rs @@ -1,4 +1,4 @@ -// Copyright (c) [2024] SUSE LLC +// Copyright (c) [2024-2025] SUSE LLC // // All Rights Reserved. // @@ -104,6 +104,7 @@ pub async fn manager_service( Ok(Router::new() .route("/probe", post(probe_action)) .route("/probe_sync", post(probe_sync_action)) + .route("/reprobe_sync", post(reprobe_sync_action)) .route("/install", post(install_action)) .route("/finish", post(finish_action)) .route("/installer", get(installer_status)) @@ -162,6 +163,20 @@ async fn probe_sync_action(State(state): State>) -> Result<(), Ok(()) } +/// Starts the reprobing process and waits until it is done. +#[utoipa::path( + post, + path = "/reprobe_sync", + context_path = "/api/manager", + responses( + (status = 200, description = "Re-probing done.") + ) +)] +async fn reprobe_sync_action(State(state): State>) -> Result<(), Error> { + state.manager.reprobe().await?; + Ok(()) +} + /// Starts the installation process. #[utoipa::path( post, diff --git a/rust/package/agama.changes b/rust/package/agama.changes index 7fc207a871..6206bb6aa1 100644 --- a/rust/package/agama.changes +++ b/rust/package/agama.changes @@ -1,3 +1,9 @@ +------------------------------------------------------------------- +Fri Jul 4 11:33:44 UTC 2025 - José Iván López González + +- Reprobe the system after registering the product + (gh#agama-project/agama#2532, bsc#1245400). + ------------------------------------------------------------------- Wed Jul 2 16:02:07 UTC 2025 - Imobach Gonzalez Sosa diff --git a/service/lib/agama/dbus/clients/storage.rb b/service/lib/agama/dbus/clients/storage.rb index c2d4363f65..fcab970a98 100644 --- a/service/lib/agama/dbus/clients/storage.rb +++ b/service/lib/agama/dbus/clients/storage.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -# Copyright (c) [2022-2024] SUSE LLC +# Copyright (c) [2022-2025] SUSE LLC # # All Rights Reserved. # @@ -53,6 +53,11 @@ def probe(&done) dbus_object[STORAGE_IFACE].Probe(&done) end + # Reprobes (keeps the current settings). + def reprobe + dbus_object.Reprobe + end + # Performs the packages installation def install dbus_object.Install diff --git a/service/lib/agama/dbus/manager.rb b/service/lib/agama/dbus/manager.rb index f6a8d7b50e..e847339478 100644 --- a/service/lib/agama/dbus/manager.rb +++ b/service/lib/agama/dbus/manager.rb @@ -64,6 +64,7 @@ def initialize(backend, logger) dbus_interface MANAGER_INTERFACE do dbus_method(:Probe, "") { config_phase } + dbus_method(:Reprobe, "") { config_phase(reprobe: true) } dbus_method(:Commit, "") { install_phase } dbus_method(:CanInstall, "out result:b") { can_install? } dbus_method(:CollectLogs, "out tarball_filesystem_path:s") { collect_logs } @@ -75,9 +76,9 @@ def initialize(backend, logger) end # Runs the config phase - def config_phase + def config_phase(reprobe: false) safe_run do - busy_while { backend.config_phase } + busy_while { backend.config_phase(reprobe: reprobe) } end end diff --git a/service/lib/agama/dbus/manager_service.rb b/service/lib/agama/dbus/manager_service.rb index 1b8a3bc456..d13eb9b873 100644 --- a/service/lib/agama/dbus/manager_service.rb +++ b/service/lib/agama/dbus/manager_service.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -# Copyright (c) [2022] SUSE LLC +# Copyright (c) [2022-2025] SUSE LLC # # All Rights Reserved. # @@ -69,8 +69,6 @@ def initialize(config, logger = nil) # @note The service runs its startup phase def start export - # We need locale for data from users - locale_client = Clients::Locale.instance manager.on_progress_change { dispatch } # make single thread more responsive manager.startup_phase end diff --git a/service/lib/agama/manager.rb b/service/lib/agama/manager.rb index 260cb3da45..811a09a1b5 100644 --- a/service/lib/agama/manager.rb +++ b/service/lib/agama/manager.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -# Copyright (c) [2022-2023] SUSE LLC +# Copyright (c) [2022-2025] SUSE LLC # # All Rights Reserved. # @@ -90,33 +90,22 @@ def startup_phase end # Runs the config phase - def config_phase - service_status.busy - first_time = installation_phase.startup? + def config_phase(reprobe: false) installation_phase.config - - start_progress_with_descriptions( - _("Analyze disks"), _("Configure software") - ) - # FIXME: hot-fix for bsc#1234711, see {#probe_and_recover_storage}. In autoinstallation, the - # storage config could be applied before probing. In that case, the config has to be - # recovered. - progress.step { first_time ? probe_and_recover_storage : storage.probe } + start_progress_with_descriptions(_("Analyze disks"), _("Configure software")) + progress.step { reprobe ? storage.reprobe : storage.probe } progress.step { software.probe } - logger.info("Config phase done") rescue StandardError => e logger.error "Startup error: #{e.inspect}. Backtrace: #{e.backtrace}" # TODO: report errors ensure - service_status.idle finish_progress end # Runs the install phase # rubocop:disable Metrics/AbcSize, Metrics/MethodLength def install_phase - service_status.busy @ipmi.started installation_phase.install @@ -155,14 +144,12 @@ def install_phase @ipmi.failed logger.error "Installation error: #{e.inspect}. Backtrace: #{e.backtrace}" ensure - service_status.idle installation_phase.finish finish_progress end # rubocop:enable Metrics/AbcSize, Metrics/MethodLength def locale=(locale) - service_status.busy change_process_locale(locale) users.update_issues start_progress_with_descriptions( @@ -172,7 +159,6 @@ def locale=(locale) progress.step { software.locale = locale } progress.step { storage.locale = locale } ensure - service_status.idle finish_progress end @@ -322,13 +308,6 @@ def finish_cmd(method) # @return [ServiceStatusRecorder] attr_reader :service_status_recorder - # Probes storage and recover the current config, if any. - def probe_and_recover_storage - storage_config = storage.config - storage.probe - storage.config = storage_config if storage_config - end - # Runs post partitioning scripts def run_post_partitioning_scripts client = Agama::HTTP::Clients::Scripts.new(logger) diff --git a/service/package/rubygem-agama-yast.changes b/service/package/rubygem-agama-yast.changes index b9811bd67d..e90f985567 100644 --- a/service/package/rubygem-agama-yast.changes +++ b/service/package/rubygem-agama-yast.changes @@ -1,3 +1,9 @@ +------------------------------------------------------------------- +Fri Jul 4 11:31:21 UTC 2025 - José Iván López González + +- Extend D-Bus API to allow reprobing the system + (gh#agama-project/agama#2532, bsc#1245400). + ------------------------------------------------------------------- Wed Jul 2 10:50:56 UTC 2025 - José Iván López González @@ -19,7 +25,7 @@ Mon Jun 30 11:23:03 UTC 2025 - Martin Vidner Fri Jun 27 14:02:57 UTC 2025 - Michal Filka - jsc#PED-11193 - - do not create the "after install" snapshot + - do not create the "after install" snapshot ------------------------------------------------------------------- Fri Jun 27 12:07:35 UTC 2025 - Imobach Gonzalez Sosa diff --git a/service/test/agama/manager_test.rb b/service/test/agama/manager_test.rb index d7c71695d5..ac6a3028f3 100644 --- a/service/test/agama/manager_test.rb +++ b/service/test/agama/manager_test.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -# Copyright (c) [2022-2023] SUSE LLC +# Copyright (c) [2022-2025] SUSE LLC # # All Rights Reserved. # @@ -56,7 +56,7 @@ let(:network) { instance_double(Agama::Network, install: nil, startup: nil) } let(:storage) do instance_double( - Agama::DBus::Clients::Storage, probe: nil, install: nil, finish: nil, + Agama::DBus::Clients::Storage, probe: nil, reprobe: nil, install: nil, finish: nil, on_service_status_change: nil, errors?: false ) end @@ -124,6 +124,18 @@ expect(software).to receive(:probe) subject.config_phase end + + context "if reprobe is requested" do + it "calls #reprobe method of the storage module" do + expect(storage).to receive(:reprobe) + subject.config_phase(reprobe: true) + end + + it "calls #probe method of the software module" do + expect(software).to receive(:probe) + subject.config_phase(reprobe: true) + end + end end describe "#install_phase" do diff --git a/web/package/agama-web-ui.changes b/web/package/agama-web-ui.changes index 176685de74..cbf1d7b8e9 100644 --- a/web/package/agama-web-ui.changes +++ b/web/package/agama-web-ui.changes @@ -1,3 +1,9 @@ +------------------------------------------------------------------- +Fri Jul 4 11:34:59 UTC 2025 - José Iván López González + +- Reprobe the system after registering the product + (gh#agama-project/agama#2532, bsc#1245400). + ------------------------------------------------------------------- Tue Jul 1 12:57:50 UTC 2025 - Lubos Kocman diff --git a/web/src/api/manager.ts b/web/src/api/manager.ts index b2fe97c316..d02d1f6d83 100644 --- a/web/src/api/manager.ts +++ b/web/src/api/manager.ts @@ -1,5 +1,5 @@ /* - * Copyright (c) [2024] SUSE LLC + * Copyright (c) [2024-2025] SUSE LLC * * All Rights Reserved. * @@ -32,6 +32,11 @@ const startProbing = () => post("/api/manager/probe"); */ const probe = () => post("/api/manager/probe_sync"); +/** + * Triggers a synchronous reprobing process. + */ +const reprobe = () => post("/api/manager/reprobe_sync"); + /** * Starts the installation process. * @@ -49,4 +54,4 @@ const finishInstallation = () => post("/api/manager/finish"); */ const fetchLogs = () => get("/api/manager/logs/store"); -export { startProbing, probe, startInstallation, finishInstallation, fetchLogs }; +export { startProbing, probe, reprobe, startInstallation, finishInstallation, fetchLogs }; diff --git a/web/src/queries/software.ts b/web/src/queries/software.ts index 699f6abbea..d74ecd3b8a 100644 --- a/web/src/queries/software.ts +++ b/web/src/queries/software.ts @@ -1,5 +1,5 @@ /* - * Copyright (c) [2024] SUSE LLC + * Copyright (c) [2024-2025] SUSE LLC * * All Rights Reserved. * @@ -62,7 +62,7 @@ import { updateConfig, } from "~/api/software"; import { QueryHookOptions } from "~/types/queries"; -import { probe as systemProbe } from "~/api/manager"; +import { probe as systemProbe, reprobe as systemReprobe } from "~/api/manager"; /** * Query to retrieve software configuration @@ -180,7 +180,7 @@ const useRegisterMutation = () => { const query = { mutationFn: register, onSuccess: async () => { - await systemProbe(); + await systemReprobe(); queryClient.invalidateQueries({ queryKey: ["software", "registration"] }); queryClient.invalidateQueries({ queryKey: ["storage"] }); },