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
1 change: 1 addition & 0 deletions rust/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions rust/agama-manager/src/actions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,12 @@ impl SetConfigAction {
self.progress
.call(progress::message::Next::new(Scope::Manager))
.await?;
// Ensure storage was already probed before configuring s390. Otherwise, probing could
// fail later if DASD is formatting in a background process (bsc#1259354).
let storage_system = self.storage.call(storage::message::GetSystem).await?;
if storage_system.is_none() {
self.storage.call(storage::message::Probe).await?
}
s390.call(s390::message::SetConfig::new(config.s390.clone()))
.await?;
}
Expand Down
1 change: 1 addition & 0 deletions rust/agama-storage-client/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ zbus = "5.7.1"
tokio = { version = "1.47.1", features = ["macros", "rt-multi-thread", "sync"] }
serde = { version = "1.0.228" }
serde_json = "1.0.140"
tracing = "0.1.41"

7 changes: 5 additions & 2 deletions rust/agama-storage-client/src/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ impl MessageHandler<message::SetStorageConfig> for Service {
message: message::SetStorageConfig,
) -> Result<BoxFuture<Result<(), Error>>, Error> {
let proxy = self.storage_proxy.clone();
let result = run_in_background(async move {
let response = run_in_background(async move {
let product = message.product.read().await;
let product_json = serde_json::to_string(&*product)?;
let config = message.config.filter(|c| c.has_value());
Expand All @@ -232,7 +232,7 @@ impl MessageHandler<message::SetStorageConfig> for Service {
Ok(())
});
Ok(Box::pin(async move {
result
response
.await
.map_err(|_| Error::Actor(actor::Error::Response(Self::name())))?
}))
Expand Down Expand Up @@ -419,6 +419,9 @@ where
let (tx, rx) = oneshot::channel::<Result<(), Error>>();
tokio::spawn(async move {
let result = func.await;
if let Err(error) = &result {
tracing::error!("Failed to run background action: {error}");
}
_ = tx.send(result);
});
rx
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 @@
-------------------------------------------------------------------
Mon Mar 16 16:52:49 UTC 2026 - José Iván López González <jlopez@suse.com>

- Ensure storage system is probed before configuring DASD
(bsc#1259354).

-------------------------------------------------------------------
Mon Mar 16 13:17:33 UTC 2026 - Knut Anderssen <kanderssen@suse.com>

Expand Down
44 changes: 20 additions & 24 deletions service/lib/agama/dbus/storage/dasd.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,13 @@ class DASD < BaseObject
private_constant :PATH

# @param manager [Agama::Storage::DASD::Manager]
# @param task_runner [Agama::TaskRunner]
# @param logger [Logger, nil]
def initialize(manager, logger: nil)
def initialize(manager, task_runner, logger: nil)
textdomain "agama"
super(PATH, logger: logger)
@manager = manager
@task_runner = task_runner
@serialized_system = serialize_system
@serialized_config = serialize_config
register_callbacks
Expand Down Expand Up @@ -72,6 +74,7 @@ def probe
# Applies the given serialized DASD config.
#
# @todo Raise error if the config is not valid.
# @raise [Agama::TaskRunner::BusyError] If an async task is running, see {TaskRunner}.
#
# @param serialized_config [String] Serialized DASD config according to the JSON schema.
def configure(serialized_config)
Expand All @@ -83,14 +86,29 @@ def configure(serialized_config)
# Do not configure if there is nothing to change.
return if manager.configured?(config_json)

perform_configuration(config_json)
# The configuration could take long time (e.g., formatting devices). It is important to
# not block the service in order to make possible to attend other requests.
task_runner.async_run("Configure DASD") do
logger.info("Configuring DASD")

start_progress(1, _("Configuring DASD"))
manager.configure(config_json)

update_serialized_system
update_serialized_config

finish_progress
end
end

private

# @return [Agama::Storage::DASD::Manager]
attr_reader :manager

# @return [Agama::TaskRunner]
attr_reader :task_runner

def register_callbacks
on_progress_change { self.ProgressChanged(serialize_progress) }
on_progress_finish { self.ProgressFinished }
Expand All @@ -102,28 +120,6 @@ def register_callbacks
manager.on_format_finish { |process_status| self.FormatFinished(process_status.to_s) }
end

# Performs the configuration process in a separate thread.
#
# The configuration could take long time (e.g., formatting devices). It is important to not
# block the service in order to make possible to attend other requests.
#
# @raise if there is an unfinished configuration.
#
# @param config_json [Hash]
def perform_configuration(config_json)
raise "Previous configuration is not finished yet" if @configuration_thread&.alive?

logger.info("Configuring DASD")

@configuration_thread = Thread.new do
start_progress(1, _("Configuring DASD"))
manager.configure(config_json)
update_serialized_system
update_serialized_config
finish_progress
end
end

# Updates the system info if needed.
def update_serialized_system
serialized_system = serialize_system
Expand Down
Loading
Loading