Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package agama for openSUSE:Factory checked in at 2026-07-17 18:47:24 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/agama (Old) and /work/SRC/openSUSE:Factory/.agama.new.24530 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "agama" Fri Jul 17 18:47:24 2026 rev:50 rq:1366193 version:0 Changes: -------- --- /work/SRC/openSUSE:Factory/agama/agama.changes 2026-07-15 16:29:51.994467897 +0200 +++ /work/SRC/openSUSE:Factory/.agama.new.24530/agama.changes 2026-07-17 18:47:46.869815176 +0200 @@ -1,0 +2,27 @@ +Thu Jul 16 11:26:26 UTC 2026 - Imobach Gonzalez Sosa <[email protected]> + +- Limit the number of Tokio worker threads to 4 + (gh#agama-project/agama#3729, related to bsc#1265451). + +------------------------------------------------------------------- +Thu Jul 16 11:01:05 UTC 2026 - Michal Filka <[email protected]> + +- Fixed issues when fetching AutoYast XML profile. + Agama cares about YAST_SKIP_PROFILE_FETCH_ERROR now. + agama-autoyast doesn't end with error when no profile found. + +------------------------------------------------------------------- +Wed Jul 15 10:13:10 UTC 2026 - Imobach Gonzalez Sosa <[email protected]> + +- Do not crash when running "lshw" fails or the output cannot be + parsed (bsc#1269367). +- Fix the detection of model and CPU in s390x (bsc#1270639). +- Fix the detection of the memory when lshw does not report a + node with id "memory", but "memory:0" (bsc#1271190). + +------------------------------------------------------------------- +Wed Jul 15 09:16:44 UTC 2026 - Josef Reidinger <[email protected]> + +- Fix setting security kernel parameter (bsc#1269581) + +------------------------------------------------------------------- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ agama.obscpio ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/agama/agama-bootloader/src/client.rs new/agama/agama-bootloader/src/client.rs --- old/agama/agama-bootloader/src/client.rs 2026-07-14 10:45:10.000000000 +0200 +++ new/agama/agama-bootloader/src/client.rs 2026-07-16 14:18:35.000000000 +0200 @@ -50,12 +50,16 @@ /// Retrieves the bootloader resolvables. async fn get_resolvables(&self) -> ClientResult<Vec<Resolvable>>; /// Sets the bootloader configuration. - async fn set_config(&self, config: &Config) -> ClientResult<BoxFuture<Result<(), Error>>>; + async fn set_config(&mut self, config: &Config) -> ClientResult<BoxFuture<Result<(), Error>>>; /// Sets the extra kernel args for given scope. /// /// * `id`: identifier of the kernel argument so it can be later changed. /// * `value`: plaintext value that will be appended to kernel commandline. - async fn set_kernel_arg(&mut self, id: String, value: String); + async fn set_kernel_arg( + &mut self, + id: String, + value: String, + ) -> ClientResult<BoxFuture<Result<(), Error>>>; } // full config used on dbus which beside public config passes @@ -74,16 +78,30 @@ #[derive(Clone)] pub struct Client { storage_client: Handler<storage_client::Service>, - kernel_args: HashMap<String, String>, + // full config, so we can replace only modified part + full_config: FullConfig, } impl Client { pub async fn new(storage_client: Handler<storage_client::Service>) -> ClientResult<Client> { Ok(Self { storage_client, - kernel_args: HashMap::new(), + full_config: FullConfig::default(), }) } + + async fn send_config(&self) -> ClientResult<BoxFuture<Result<(), Error>>> { + let full_config = self.full_config.clone(); + tracing::info!("sending bootloader config {:?}", full_config); + // ignore return value as currently it does not fail and who knows what future brings + // but it should not be part of result and instead transformed to Issue + let value = serde_json::to_value(&full_config)?; + let rx = self + .storage_client + .call(message::bootloader::SetConfig::new(value)) + .await?; + Ok(Box::pin(async move { rx.await.map_err(Error::from) })) + } } #[async_trait] @@ -109,23 +127,17 @@ .await?) } - async fn set_config(&self, config: &Config) -> ClientResult<BoxFuture<Result<(), Error>>> { - let full_config = FullConfig { - config: config.clone(), - kernel_args: self.kernel_args.clone(), - }; - tracing::info!("sending bootloader config {:?}", full_config); - // ignore return value as currently it does not fail and who knows what future brings - // but it should not be part of result and instead transformed to Issue - let value = serde_json::to_value(&full_config)?; - let rx = self - .storage_client - .call(message::bootloader::SetConfig::new(value)) - .await?; - Ok(Box::pin(async move { rx.await.map_err(Error::from) })) + async fn set_config(&mut self, config: &Config) -> ClientResult<BoxFuture<Result<(), Error>>> { + self.full_config.config = config.clone(); + self.send_config().await } - async fn set_kernel_arg(&mut self, id: String, value: String) { - self.kernel_args.insert(id, value); + async fn set_kernel_arg( + &mut self, + id: String, + value: String, + ) -> ClientResult<BoxFuture<Result<(), Error>>> { + self.full_config.kernel_args.insert(id, value); + self.send_config().await } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/agama/agama-bootloader/src/service.rs new/agama/agama-bootloader/src/service.rs --- old/agama/agama-bootloader/src/service.rs 2026-07-14 10:45:10.000000000 +0200 +++ new/agama/agama-bootloader/src/service.rs 2026-07-16 14:18:35.000000000 +0200 @@ -132,7 +132,9 @@ #[async_trait] impl MessageHandler<message::SetKernelArg> for Service { async fn handle(&mut self, message: message::SetKernelArg) -> Result<(), Error> { - self.client.set_kernel_arg(message.id, message.value).await; + if let Err(err) = self.client.set_kernel_arg(message.id, message.value).await { + tracing::error!("Failed to set kernel args {:?}", err); + } Ok(()) } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/agama/agama-bootloader/src/test_utils.rs new/agama/agama-bootloader/src/test_utils.rs --- old/agama/agama-bootloader/src/test_utils.rs 2026-07-14 10:45:10.000000000 +0200 +++ new/agama/agama-bootloader/src/test_utils.rs 2026-07-16 14:18:35.000000000 +0200 @@ -91,13 +91,19 @@ Ok(vec![]) } - async fn set_config(&self, config: &Config) -> Result<BoxFuture<Result<(), Error>>, Error> { + async fn set_config(&mut self, config: &Config) -> Result<BoxFuture<Result<(), Error>>, Error> { let mut state = self.state.lock().await; state.config = config.clone(); Ok(Box::pin(async { Ok(()) })) } - async fn set_kernel_arg(&mut self, _id: String, _value: String) {} + async fn set_kernel_arg( + &mut self, + _id: String, + _value: String, + ) -> Result<BoxFuture<Result<(), Error>>, Error> { + Ok(Box::pin(async { Ok(()) })) + } } /// Starts a testing storage service. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/agama/agama-manager/src/hardware.rs new/agama/agama-manager/src/hardware.rs --- old/agama/agama-manager/src/hardware.rs 2026-07-14 10:45:10.000000000 +0200 +++ new/agama/agama-manager/src/hardware.rs 2026-07-16 14:18:35.000000000 +0200 @@ -18,7 +18,7 @@ // To contact SUSE LLC about this file by physical or electronic mail, you may // find current contact information at www.suse.com. -use agama_utils::api::manager::HardwareInfo; +use agama_utils::{api::manager::HardwareInfo, arch::Arch}; use serde::Deserialize; use serde_with::{formats::PreferMany, serde_as, OneOrMany}; use std::{ @@ -68,7 +68,14 @@ pub async fn read(&mut self) -> Result<(), Error> { match &self.source { - Source::System => self.read_from_system().await, + Source::System => { + self.read_from_system().await?; + // On s390x, enrich the system node with model info from read_values if needed + if Arch::is_s390() { + self.read_s390_model().await.ok(); + } + Ok(()) + } Source::File(ref path) => self.read_from_file(path.clone()), } } @@ -98,6 +105,50 @@ Ok(()) } + /// Enriches the s390x system node with model info from read_values command. + async fn read_s390_model(&mut self) -> Result<(), Error> { + let Some(ref mut root) = self.root else { + return Ok(()); + }; + + let Some(system) = root.find_first_by_class_mut("system") else { + return Ok(()); + }; + + let output = tokio::process::Command::new("read_values") + .arg("-c") + .output() + .await?; + + if !output.status.success() { + return Ok(()); + } + + let model = String::from_utf8_lossy(&output.stdout); + system.vendor = Some("IBM".to_string()); + system.version = Self::parse_s390_version(&model); + + Ok(()) + } + + /// Parses the s390x model from read_values output. + /// + /// Extracts "eServer zSeries 900" from "z900 IBM eServer zSeries 900". + /// or "LinuxONE III LT1" from "IBM LinuxONE III LT1". + /// + /// Expected format: "8561 = IBM LinuxONE III LT1" + fn parse_s390_version(output: &str) -> Option<String> { + let line = output + .lines() + .find_map(|l| l.split_once('=').map(|(_id, model)| model.to_string()))?; + + if let Some((_, version)) = line.split_once("IBM") { + Some(version.trim().to_string()) + } else { + None + } + } + /// Converts the information to a HardwareInfo struct. pub fn to_hardware_info(&self) -> HardwareInfo { let Some(root) = &self.root else { @@ -191,16 +242,39 @@ children.search_by_class(class, results); } } + + /// Searches and returns the first hardware node by class (mutable version). + /// + /// * `class`: class to search for (e.g., "disk", "processor", etc.). + pub fn find_first_by_class_mut(&mut self, class: &str) -> Option<&mut HardwareNode> { + if self.class == class { + return Some(self); + } + + for children in &mut self.children { + let result = children.find_first_by_class_mut(class); + if result.is_some() { + return result; + } + } + + None + } } impl From<&HardwareNode> for HardwareInfo { fn from(value: &HardwareNode) -> Self { + // Find the first "processor" node to get the CPU. Use the "product" key. If not present, + // fallback to "vendor" (like in s390x). let cpu = value .find_by_class("processor") .first() - .and_then(|c| c.product.clone()); + .and_then(|c| c.product.clone().or(c.vendor.clone())); - let memory = value.find_by_id("memory").and_then(|m| m.size); + let memory = value + .find_by_id("memory") + .or_else(|| value.find_by_id("memory:0")) + .and_then(|m| m.size); let model = if let Some(system) = value.find_by_class("system").first() { let model_str = format!( @@ -323,6 +397,34 @@ )); } + #[test] + fn test_parse_s390_version() { + let output = "8561 = IBM LinuxONE III LT1"; + let model = Registry::parse_s390_version(output); + assert_eq!(model, Some("LinuxONE III LT1".to_string())); + + let output_with_extra_spaces = "8561 = IBM LinuxONE III LT1 "; + let model = Registry::parse_s390_version(output_with_extra_spaces); + assert_eq!(model, Some("LinuxONE III LT1".to_string())); + + let multiline_output = "SomeOtherLine\n8561 = IBM LinuxONE III LT1\nAnotherLine"; + let model = Registry::parse_s390_version(multiline_output); + assert_eq!(model, Some("LinuxONE III LT1".to_string())); + + // Test format with machine type prefix before IBM + let output_with_prefix = "2064 = z900 IBM eServer zSeries 900"; + let model = Registry::parse_s390_version(output_with_prefix); + assert_eq!(model, Some("eServer zSeries 900".to_string())); + + let invalid_output = "No equals sign here"; + let model = Registry::parse_s390_version(invalid_output); + assert_eq!(model, None); + + let empty_output = ""; + let model = Registry::parse_s390_version(empty_output); + assert_eq!(model, None); + } + #[tokio::test] async fn test_to_hardware_incomplete() -> Result<(), Box<dyn Error>> { let fixtures = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../test/share"); @@ -334,4 +436,105 @@ assert_eq!(node.model, None); Ok(()) } + + #[tokio::test] + async fn test_to_hardware_s390x() -> Result<(), Box<dyn Error>> { + let fixtures = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../test/share"); + let mut registry = Registry::new_from_file(fixtures.join("lshw-s390x.json")); + registry.read().await?; + let node = registry.to_hardware_info(); + assert_eq!(node.cpu, Some("IBM/S390".to_string())); + assert_eq!(node.memory, Some(8589934592)); + // Model is not available from lshw on s390x + assert_eq!(node.model, None); + Ok(()) + } + + #[tokio::test] + async fn test_s390x_model_enrichment() -> Result<(), Box<dyn Error>> { + let fixtures = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../test/share"); + let mut registry = Registry::new_from_file(fixtures.join("lshw-s390x.json")); + registry.read().await?; + + // Simulate enriching the system node with s390 model data + if let Some(ref mut root) = registry.root { + if let Some(system) = root.find_first_by_class_mut("system") { + system.vendor = Some("IBM".to_string()); + system.version = Some("LinuxONE III LT1".to_string()); + } + } + + let node = registry.to_hardware_info(); + assert_eq!(node.cpu, Some("IBM/S390".to_string())); + assert_eq!(node.memory, Some(8589934592)); + // Model should now be available from the enriched system node + assert_eq!(node.model, Some("IBM LinuxONE III LT1".to_string())); + Ok(()) + } + + #[tokio::test] + async fn test_s390x_enrich_with_different_formats() -> Result<(), Box<dyn Error>> { + let fixtures = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../test/share"); + + // Test "IBM LinuxONE III LT1" format - should split into vendor="IBM" and version="LinuxONE III LT1" + let mut registry = Registry::new_from_file(fixtures.join("lshw-s390x.json")); + registry.read().await?; + if let Some(ref mut root) = registry.root { + if let Some(system) = root.find_first_by_class_mut("system") { + system.vendor = Some("IBM".to_string()); + system.version = Some("LinuxONE III LT1".to_string()); + } + } + let info = registry.to_hardware_info(); + assert_eq!(info.model, Some("IBM LinuxONE III LT1".to_string())); + + // Test "IBM eServer zSeries 900" format - should split into vendor="IBM" and version="eServer zSeries 900" + let mut registry = Registry::new_from_file(fixtures.join("lshw-s390x.json")); + registry.read().await?; + if let Some(ref mut root) = registry.root { + if let Some(system) = root.find_first_by_class_mut("system") { + system.vendor = Some("IBM".to_string()); + system.version = Some("eServer zSeries 900".to_string()); + } + } + let info = registry.to_hardware_info(); + assert_eq!(info.model, Some("IBM eServer zSeries 900".to_string())); + + // Test "IBM LinuxONE Rockhopper" format - should split into vendor="IBM" and version="LinuxONE Rockhopper" + let mut registry = Registry::new_from_file(fixtures.join("lshw-s390x.json")); + registry.read().await?; + if let Some(ref mut root) = registry.root { + if let Some(system) = root.find_first_by_class_mut("system") { + system.vendor = Some("IBM".to_string()); + system.version = Some("LinuxONE Rockhopper".to_string()); + } + } + let info = registry.to_hardware_info(); + assert_eq!(info.model, Some("IBM LinuxONE Rockhopper".to_string())); + + // Test non-IBM format - everything should go to version + let mut registry = Registry::new_from_file(fixtures.join("lshw-s390x.json")); + registry.read().await?; + if let Some(ref mut root) = registry.root { + if let Some(system) = root.find_first_by_class_mut("system") { + system.version = Some("SomeOther Vendor Model".to_string()); + } + } + let info = registry.to_hardware_info(); + assert_eq!(info.model, Some("SomeOther Vendor Model".to_string())); + + // Test "z900 IBM eServer zSeries 900" format with machine type prefix + let mut registry = Registry::new_from_file(fixtures.join("lshw-s390x.json")); + registry.read().await?; + if let Some(ref mut root) = registry.root { + if let Some(system) = root.find_first_by_class_mut("system") { + system.vendor = Some("IBM".to_string()); + system.version = Some("eServer zSeries 900".to_string()); + } + } + let info = registry.to_hardware_info(); + assert_eq!(info.model, Some("IBM eServer zSeries 900".to_string())); + + Ok(()) + } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/agama/agama-manager/src/service.rs new/agama/agama-manager/src/service.rs --- old/agama/agama-manager/src/service.rs 2026-07-14 10:45:10.000000000 +0200 +++ new/agama/agama-manager/src/service.rs 2026-07-16 14:18:35.000000000 +0200 @@ -482,7 +482,9 @@ async fn read_system_info(&mut self) -> Result<(), Error> { self.licenses.read()?; self.products.read()?; - self.hardware.read().await?; + if let Err(error) = self.hardware.read().await { + tracing::warn!("Failed to read hardware information: {error}"); + } self.system.licenses = self.licenses.licenses().into_iter().cloned().collect(); self.system.products = self.products.products(); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/agama/agama-utils/src/runtime.rs new/agama/agama-utils/src/runtime.rs --- old/agama/agama-utils/src/runtime.rs 2026-07-14 10:45:10.000000000 +0200 +++ new/agama/agama-utils/src/runtime.rs 2026-07-16 14:18:35.000000000 +0200 @@ -23,7 +23,7 @@ use std::future::Future; /// Maximum number of worker threads for the Tokio runtime. -const MAX_WORKER_THREADS: usize = 32; +const MAX_WORKER_THREADS: usize = 4; /// Creates a multi-threaded Tokio runtime with a capped number of worker threads. /// diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/agama/package/agama.changes new/agama/package/agama.changes --- old/agama/package/agama.changes 2026-07-14 10:45:10.000000000 +0200 +++ new/agama/package/agama.changes 2026-07-16 14:18:35.000000000 +0200 @@ -1,4 +1,31 @@ ------------------------------------------------------------------- +Thu Jul 16 11:26:26 UTC 2026 - Imobach Gonzalez Sosa <[email protected]> + +- Limit the number of Tokio worker threads to 4 + (gh#agama-project/agama#3729, related to bsc#1265451). + +------------------------------------------------------------------- +Thu Jul 16 11:01:05 UTC 2026 - Michal Filka <[email protected]> + +- Fixed issues when fetching AutoYast XML profile. + Agama cares about YAST_SKIP_PROFILE_FETCH_ERROR now. + agama-autoyast doesn't end with error when no profile found. + +------------------------------------------------------------------- +Wed Jul 15 10:13:10 UTC 2026 - Imobach Gonzalez Sosa <[email protected]> + +- Do not crash when running "lshw" fails or the output cannot be + parsed (bsc#1269367). +- Fix the detection of model and CPU in s390x (bsc#1270639). +- Fix the detection of the memory when lshw does not report a + node with id "memory", but "memory:0" (bsc#1271190). + +------------------------------------------------------------------- +Wed Jul 15 09:16:44 UTC 2026 - Josef Reidinger <[email protected]> + +- Fix setting security kernel parameter (bsc#1269581) + +------------------------------------------------------------------- Mon Jul 13 16:17:18 UTC 2026 - José Iván López González <[email protected]> - Do not start config tasks until pre-scripts have finished diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/agama/test/share/lshw-s390x.json new/agama/test/share/lshw-s390x.json --- old/agama/test/share/lshw-s390x.json 1970-01-01 01:00:00.000000000 +0100 +++ new/agama/test/share/lshw-s390x.json 2026-07-16 14:18:35.000000000 +0200 @@ -0,0 +1,40 @@ +{ + "id": "s390x", + "class": "system", + "claimed": true, + "description": "System", + "children": [ + { + "id": "memory", + "class": "memory", + "claimed": true, + "description": "System memory", + "physid": "0", + "size": 8589934592 + }, + { + "id": "cpu:0", + "class": "processor", + "claimed": true, + "product": "IBM/S390", + "physid": "1", + "businfo": "cpu@0", + "configuration": { + "cores": "2", + "enabledcores": "2" + } + }, + { + "id": "cpu:1", + "class": "processor", + "claimed": true, + "product": "IBM/S390", + "physid": "2", + "businfo": "cpu@1", + "configuration": { + "cores": "2", + "enabledcores": "2" + } + } + ] +} ++++++ agama.obsinfo ++++++ --- /var/tmp/diff_new_pack.pP4phw/_old 2026-07-17 18:47:49.197893669 +0200 +++ /var/tmp/diff_new_pack.pP4phw/_new 2026-07-17 18:47:49.225894613 +0200 @@ -1,5 +1,5 @@ name: agama -version: 22+398.d23cf880d -mtime: 1784018710 -commit: d23cf880d8ccae5e227b611b1b1ece43b8dc3d72 +version: 22+456.ce0fb8baf +mtime: 1784204315 +commit: ce0fb8baf906e6dc037106481ae0640cc743cee2
