Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion rust/agama-lib/src/manager.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) [2024] SUSE LLC
// Copyright (c) [2024-2025] SUSE LLC
//
// All Rights Reserved.
//
Expand Down Expand Up @@ -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?)
Expand Down
9 changes: 8 additions & 1 deletion rust/agama-lib/src/manager/http_client.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) [2024] SUSE LLC
// Copyright (c) [2024-2025] SUSE LLC
//
// All Rights Reserved.
//
Expand Down Expand Up @@ -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?)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤯

}

/// Starts the installation.
pub async fn install(&self) -> Result<(), ManagerHTTPClientError> {
Ok(self.client.post_void("/manager/install", &()).await?)
Expand Down
7 changes: 5 additions & 2 deletions rust/agama-lib/src/product/store.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) [2024] SUSE LLC
// Copyright (c) [2024-2025] SUSE LLC
//
// All Rights Reserved.
//
Expand Down Expand Up @@ -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 {
Expand All @@ -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 {
Expand All @@ -105,6 +106,8 @@ impl ProductStore {

if probe {
self.manager_client.probe().await?;
} else if reprobe {
self.manager_client.reprobe().await?;
}

Ok(())
Expand Down
3 changes: 3 additions & 0 deletions rust/agama-lib/src/proxies/manager1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Vec<String>>;
Expand Down
17 changes: 16 additions & 1 deletion rust/agama-server/src/manager/web.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) [2024] SUSE LLC
// Copyright (c) [2024-2025] SUSE LLC
//
// All Rights Reserved.
//
Expand Down Expand Up @@ -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))
Expand Down Expand Up @@ -162,6 +163,20 @@ async fn probe_sync_action(State(state): State<ManagerState<'_>>) -> 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<ManagerState<'_>>) -> Result<(), Error> {
state.manager.reprobe().await?;
Ok(())
}

/// Starts the installation process.
#[utoipa::path(
post,
Expand Down
6 changes: 6 additions & 0 deletions rust/package/agama.changes
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
-------------------------------------------------------------------
Fri Jul 4 11:33:44 UTC 2025 - José Iván López González <[email protected]>

- 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 <[email protected]>

Expand Down
7 changes: 6 additions & 1 deletion service/lib/agama/dbus/clients/storage.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# frozen_string_literal: true

# Copyright (c) [2022-2024] SUSE LLC
# Copyright (c) [2022-2025] SUSE LLC
#
# All Rights Reserved.
#
Expand Down Expand Up @@ -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
Expand Down
5 changes: 3 additions & 2 deletions service/lib/agama/dbus/manager.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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 }
Expand All @@ -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

Expand Down
4 changes: 1 addition & 3 deletions service/lib/agama/dbus/manager_service.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# frozen_string_literal: true

# Copyright (c) [2022] SUSE LLC
# Copyright (c) [2022-2025] SUSE LLC
#
# All Rights Reserved.
#
Expand Down Expand Up @@ -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
Expand Down
29 changes: 4 additions & 25 deletions service/lib/agama/manager.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# frozen_string_literal: true

# Copyright (c) [2022-2023] SUSE LLC
# Copyright (c) [2022-2025] SUSE LLC
#
# All Rights Reserved.
#
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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(
Expand All @@ -172,7 +159,6 @@ def locale=(locale)
progress.step { software.locale = locale }
progress.step { storage.locale = locale }
ensure
service_status.idle
finish_progress
end

Expand Down Expand Up @@ -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)
Expand Down
8 changes: 7 additions & 1 deletion service/package/rubygem-agama-yast.changes
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
-------------------------------------------------------------------
Fri Jul 4 11:31:21 UTC 2025 - José Iván López González <[email protected]>

- 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 <[email protected]>

Expand All @@ -19,7 +25,7 @@ Mon Jun 30 11:23:03 UTC 2025 - Martin Vidner <[email protected]>
Fri Jun 27 14:02:57 UTC 2025 - Michal Filka <[email protected]>

- 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 <[email protected]>
Expand Down
16 changes: 14 additions & 2 deletions service/test/agama/manager_test.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# frozen_string_literal: true

# Copyright (c) [2022-2023] SUSE LLC
# Copyright (c) [2022-2025] SUSE LLC
#
# All Rights Reserved.
#
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
6 changes: 6 additions & 0 deletions web/package/agama-web-ui.changes
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
-------------------------------------------------------------------
Fri Jul 4 11:34:59 UTC 2025 - José Iván López González <[email protected]>

- Reprobe the system after registering the product
(gh#agama-project/agama#2532, bsc#1245400).

-------------------------------------------------------------------
Tue Jul 1 12:57:50 UTC 2025 - Lubos Kocman <[email protected]>

Expand Down
9 changes: 7 additions & 2 deletions web/src/api/manager.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) [2024] SUSE LLC
* Copyright (c) [2024-2025] SUSE LLC
*
* All Rights Reserved.
*
Expand Down Expand Up @@ -32,6 +32,11 @@ const startProbing = () => post("/api/manager/probe");
*/
const probe = () => post("/api/manager/probe_sync");

/**
* Triggers a synchronous reprobing process.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Jus a question, does Agama server provide their async counterparts? Asking because I also see in manager "probe_sync" and "probe".

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, an async version is not needed yet.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Anyway, all this about sync/async probing/reprobing is something to revisit. For now, just following the current approach.

Copy link
Contributor

@dgdavid dgdavid Jul 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Anyway, all this about sync/async probing/reprobing is something to revisit.

Great then.

Thank you

*/
const reprobe = () => post("/api/manager/reprobe_sync");

/**
* Starts the installation process.
*
Expand All @@ -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 };
6 changes: 3 additions & 3 deletions web/src/queries/software.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) [2024] SUSE LLC
* Copyright (c) [2024-2025] SUSE LLC
*
* All Rights Reserved.
*
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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"] });
},
Expand Down