Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package agama for openSUSE:Factory checked in at 2025-06-11 16:24:07 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/agama (Old) and /work/SRC/openSUSE:Factory/.agama.new.19631 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "agama" Wed Jun 11 16:24:07 2025 rev:21 rq:1284539 version:0 Changes: -------- --- /work/SRC/openSUSE:Factory/agama/agama.changes 2025-05-27 18:43:16.415286509 +0200 +++ /work/SRC/openSUSE:Factory/.agama.new.19631/agama.changes 2025-06-11 16:25:58.163079938 +0200 @@ -1,0 +2,12 @@ +Tue Jun 3 08:35:58 UTC 2025 - Knut Anderssen <kanders...@suse.com> + +- Added support for moving the connections from memory only to disk + (gh#agama-project/agama#2402). + +------------------------------------------------------------------- +Wed May 28 09:00:00 UTC 2025 - Clemens Famulla-Conrad <cfamullacon...@suse.com> + +- Fix bridge port config (bridge-port.priority and + brdige-port.path_cost) + +------------------------------------------------------------------- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ agama.obscpio ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/agama/agama-network/src/model.rs new/agama/agama-network/src/model.rs --- old/agama/agama-network/src/model.rs 2025-05-27 09:55:53.000000000 +0200 +++ new/agama/agama-network/src/model.rs 2025-06-03 17:34:25.000000000 +0200 @@ -463,6 +463,7 @@ pub struct GeneralState { pub hostname: String, pub connectivity: bool, + pub copy_network: bool, pub wireless_enabled: bool, pub networking_enabled: bool, // pub network_state: NMSTATE } @@ -520,6 +521,9 @@ pub ieee_8021x_config: Option<IEEE8021XConfig>, pub autoconnect: bool, pub state: ConnectionState, + pub keep: bool, + pub filename: String, + pub flags: u32, } impl Connection { @@ -552,10 +556,19 @@ self.status == Status::Up } + pub fn is_down(&self) -> bool { + self.status == Status::Down + } + pub fn set_up(&mut self) { self.status = Status::Up } + pub fn set_keep(&mut self, keep: bool) { + self.keep = keep; + self.status = Status::Keep + } + pub fn set_down(&mut self) { self.status = Status::Down } @@ -593,6 +606,9 @@ ieee_8021x_config: Default::default(), autoconnect: true, state: Default::default(), + keep: true, + filename: Default::default(), + flags: Default::default(), } } } @@ -648,6 +664,7 @@ connection.interface = conn.interface; connection.mtu = conn.mtu; connection.autoconnect = conn.autoconnect; + connection.keep = conn.keep; Ok(connection) } @@ -675,6 +692,8 @@ .ieee_8021x_config .and_then(|x| IEEE8021XSettings::try_from(x).ok()); let autoconnect = conn.autoconnect; + let keep = conn.keep; + let filename = Some(conn.filename); let mut connection = NetworkConnection { id, @@ -692,6 +711,8 @@ mtu, ieee_8021x, autoconnect, + keep, + filename, ..Default::default() }; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/agama/agama-network/src/nm/adapter.rs new/agama/agama-network/src/nm/adapter.rs --- old/agama/agama-network/src/nm/adapter.rs 2025-05-27 09:55:53.000000000 +0200 +++ new/agama/agama-network/src/nm/adapter.rs 2025-06-03 17:34:25.000000000 +0200 @@ -111,7 +111,6 @@ .map_err(|e| NetworkAdapterError::Checkpoint(anyhow!(e)))?; tracing::info!("Updating the general state {:?}", &network.general_state); - let result = self .client .update_general_state(&network.general_state) @@ -134,6 +133,11 @@ for conn in ordered_connections(network) { if let Some(old_conn) = old_state.get_connection_by_uuid(conn.uuid) { if old_conn == conn { + tracing::info!( + "No change detected for connection {} ({})", + conn.id, + conn.uuid + ); continue; } } else if conn.is_removed() { @@ -194,8 +198,11 @@ conns: &mut Vec<&'b Connection>, ) { if let Some(uuid) = conn.controller { - let controller = network.get_connection_by_uuid(uuid).unwrap(); - add_ordered_connections(controller, network, conns); + if let Some(controller) = network.get_connection_by_uuid(uuid) { + add_ordered_connections(controller, network, conns); + } else { + tracing::error!("Could not found the controller {}", &uuid); + } } if !conns.contains(&conn) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/agama/agama-network/src/nm/client.rs new/agama/agama-network/src/nm/client.rs --- old/agama/agama-network/src/nm/client.rs 2025-05-27 09:55:53.000000000 +0200 +++ new/agama/agama-network/src/nm/client.rs 2025-06-03 17:34:25.000000000 +0200 @@ -20,6 +20,8 @@ //! NetworkManager client. use std::collections::HashMap; +use std::fs::{self, OpenOptions}; +use std::path::Path; use super::builder::DeviceFromProxyBuilder; use super::dbus::{ @@ -70,18 +72,21 @@ // let global_dns_configuration = self.nm_proxy.global_dns_configuration().await?; // Fixme: save as NMConnectivityState enum let connectivity = self.nm_proxy.connectivity().await? == 4; + let copy_network = !Path::new("/run/agama/not_copy_network").exists(); Ok(GeneralState { hostname, wireless_enabled, networking_enabled, connectivity, + copy_network, }) } /// Updates the general state pub async fn update_general_state(&self, state: &GeneralState) -> Result<(), NmError> { let wireless_enabled = self.nm_proxy.wireless_enabled().await?; + let copy_network = !Path::new("/run/agama/not_copy_network").exists(); if wireless_enabled != state.wireless_enabled { self.nm_proxy @@ -89,6 +94,19 @@ .await?; }; + if copy_network != state.copy_network { + let path = Path::new("/run/agama/not_copy_network"); + if state.copy_network { + if let Err(error) = fs::remove_file(path) { + tracing::error!("Cannot remove /run/agama/not_copy_network file {:?}", error); + } + } else { + if let Err(error) = OpenOptions::new().create(true).write(true).open(path) { + tracing::error!("Cannot write /run/agama/not_copy_network file {:?}", error); + } + }; + }; + Ok(()) } @@ -182,7 +200,7 @@ /// Returns the list of network connections. pub async fn connections(&self) -> Result<Vec<Connection>, NmError> { let mut controlled_by: HashMap<Uuid, String> = HashMap::new(); - let mut uuids_map: HashMap<Uuid, String> = HashMap::new(); + let mut uuids_map: HashMap<String, Uuid> = HashMap::new(); let proxy = SettingsProxy::new(&self.connection).await?; let paths = proxy.list_connections().await?; @@ -213,11 +231,15 @@ } Self::add_secrets(&mut connection.config, &proxy).await?; + connection.filename = proxy.filename().await?; + connection.flags = flags; + connection.keep = if flags != 0 { false } else { true }; + if let Some(controller) = controller { controlled_by.insert(connection.uuid, controller); } if let Some(iname) = &connection.interface { - uuids_map.insert(connection.uuid, iname.to_string()); + uuids_map.insert(iname.to_string(), connection.uuid); } if self.settings_active_connection(path).await?.is_none() { connection.set_down() @@ -231,8 +253,11 @@ } for conn in connections.iter_mut() { - if controlled_by.contains_key(&conn.uuid) { - conn.controller = Some(conn.uuid); + // FIXME: Is this OK? + if let Some(controller) = controlled_by.get(&conn.uuid) { + if let Some(iface) = uuids_map.get(controller) { + conn.controller = Some(iface.to_owned()); + } }; } @@ -266,18 +291,33 @@ let path = if let Ok(proxy) = self.get_connection_proxy(conn.uuid).await { let original = proxy.get_settings().await?; let merged = merge_dbus_connections(&original, &new_conn)?; - proxy.update(merged).await?; + // https://networkmanager.dev/docs/api/latest/nm-dbus-types.html#NMSettingsConnectionFlags + // 0x1 persist to disk, 0x8 memory only + let persist = if conn.keep { 0x1 } else { 0x8 }; + proxy.update2(merged, persist, Default::default()).await?; OwnedObjectPath::from(proxy.inner().path().to_owned()) } else { let proxy = SettingsProxy::new(&self.connection).await?; + // https://networkmanager.dev/docs/api/latest/nm-dbus-types.html#NMSettingsConnectionFlags + // 0x1 persist to disk, 0x2 memory only + let persist = if conn.keep { 0x1 } else { 0x2 }; cleanup_dbus_connection(&mut new_conn); - proxy.add_connection(new_conn).await? + let (path, _) = proxy + .add_connection2(new_conn, persist, Default::default()) + .await?; + path }; + // FIXME: Do not like that an activation/deactivation could not apply the changes because of + // a roolback when calling this method with an error. if conn.is_up() { + // FIXME: If it is a wireless and wireless is disabled it will fail, and if it is a + // device which is not available it will also fail. self.activate_connection(path).await?; } else { - self.deactivate_connection(path).await?; + if conn.is_down() || conn.is_removed() { + self.deactivate_connection(path).await?; + } } Ok(()) } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/agama/agama-network/src/nm/dbus.rs new/agama/agama-network/src/nm/dbus.rs --- old/agama/agama-network/src/nm/dbus.rs 2025-05-27 09:55:53.000000000 +0200 +++ new/agama/agama-network/src/nm/dbus.rs 2025-06-03 17:34:25.000000000 +0200 @@ -260,11 +260,11 @@ Ok(merged) } -fn is_bridge(conn: NestedHash) -> bool { +fn is_bridge_port(conn: &NestedHash) -> bool { if let Some(connection) = conn.get("connection") { if let Some(port_type) = connection.get("port-type") { - if port_type.to_string().as_str() == "bridge" { - return true; + if let Ok(s) = TryInto::<&str>::try_into(port_type) { + return s == "bridge"; } } } @@ -284,7 +284,7 @@ /// /// * `conn`: connection represented as a NestedHash. pub fn cleanup_dbus_connection(conn: &mut NestedHash) { - if !is_bridge(conn.to_owned()) { + if !is_bridge_port(conn) { conn.remove("bridge-port"); } @@ -1595,7 +1595,6 @@ #[test] fn test_connection_from_dbus_bridge() -> anyhow::Result<()> { - dbg!("TESTING BRIDGE"); let uuid = Uuid::new_v4().to_string(); let connection_section = HashMap::from([hi("id", "br0")?, hi("uuid", uuid)?]); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/agama/agama-network/src/settings.rs new/agama/agama-network/src/settings.rs --- old/agama/agama-network/src/settings.rs 2025-05-27 09:55:53.000000000 +0200 +++ new/agama/agama-network/src/settings.rs 2025-06-03 17:34:25.000000000 +0200 @@ -262,6 +262,11 @@ /// Specifies if the connection should automatically connect #[serde(default = "default_true")] pub autoconnect: bool, + /// Specifies whether the connection should be keep after the installation + #[serde(default = "default_true")] + pub keep: bool, + #[serde(skip_serializing_if = "Option::is_none")] + pub filename: Option<String>, } fn is_zero<T: PartialEq + From<u16>>(u: &T) -> bool { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/agama/agama-network/src/system.rs new/agama/agama-network/src/system.rs --- old/agama/agama-network/src/system.rs 2025-05-27 09:55:53.000000000 +0200 +++ new/agama/agama-network/src/system.rs 2025-06-03 17:34:25.000000000 +0200 @@ -427,7 +427,12 @@ /// Writes the network configuration. pub async fn write(&mut self) -> Result<(), NetworkAdapterError> { self.adapter.write(&self.state).await?; - self.state = self.adapter.read(StateConfig::default()).await?; + self.state = self + .adapter + .read(StateConfig { + ..Default::default() + }) + .await?; Ok(()) } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/agama/agama-network/src/types.rs new/agama/agama-network/src/types.rs --- old/agama/agama-network/src/types.rs 2025-05-27 09:55:53.000000000 +0200 +++ new/agama/agama-network/src/types.rs 2025-06-03 17:34:25.000000000 +0200 @@ -150,6 +150,8 @@ Up, Down, Removed, + // Workaound for not modify the connection status + Keep, } impl fmt::Display for Status { @@ -157,6 +159,7 @@ let name = match &self { Status::Up => "up", Status::Down => "down", + Status::Keep => "keep", Status::Removed => "removed", }; write!(f, "{}", name) @@ -174,6 +177,7 @@ match value { "up" => Ok(Status::Up), "down" => Ok(Status::Down), + "keep" => Ok(Status::Keep), "removed" => Ok(Status::Removed), _ => Err(InvalidStatus(value.to_string())), } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/agama/agama-server/src/network/web.rs new/agama/agama-server/src/network/web.rs --- old/agama/agama-server/src/network/web.rs 2025-05-27 09:55:53.000000000 +0200 +++ new/agama/agama-server/src/network/web.rs 2025-06-03 17:34:25.000000000 +0200 @@ -27,7 +27,7 @@ extract::{Path, State}, http::StatusCode, response::{IntoResponse, Response}, - routing::{delete, get, patch, post}, + routing::{delete, get, post}, Json, Router, }; use uuid::Uuid; @@ -121,8 +121,10 @@ .put(update_connection) .get(connection), ) - .route("/connections/:id/connect", patch(connect)) - .route("/connections/:id/disconnect", patch(disconnect)) + .route("/connections/:id/connect", post(connect)) + .route("/connections/:id/disconnect", post(disconnect)) + .route("/connections/:id/keep", post(keep)) + .route("/connections/:id/unkeep", post(unkeep)) .route("/devices", get(devices)) .route("/system/apply", post(apply)) .route("/wifi", get(wifi_networks)) @@ -214,6 +216,7 @@ let network_connections = connections .iter() + .filter(|c| c.controller.is_none()) .map(|c| { let state = c.state; let mut conn = NetworkConnection::try_from(c.clone()).unwrap(); @@ -344,12 +347,8 @@ let bridge = conn.bridge.clone(); let mut conn = Connection::try_from(conn)?; - if orig_conn.id != id { - // FIXME: why? - return Err(NetworkError::UnknownConnection(id)); - } else { - conn.uuid = orig_conn.uuid; - } + conn.uuid = orig_conn.uuid; + conn.filename = orig_conn.filename; state.network.update_connection(conn.clone()).await?; @@ -364,7 +363,7 @@ } #[utoipa::path( - patch, + post, path = "/connections/:id/connect", context_path = "/api/network", responses( @@ -396,7 +395,7 @@ } #[utoipa::path( - patch, + post, path = "/connections/:id/disconnect", context_path = "/api/network", responses( @@ -420,6 +419,100 @@ state .network + .apply() + .await + .map_err(|_| NetworkError::CannotApplyConfig)?; + + Ok(StatusCode::NO_CONTENT) +} + +#[utoipa::path( + post, + path = "/connections/:id/keep", + context_path = "/api/network", + responses( + (status = 204, description = "Keep the given connection after the installation", body = String) + ) +)] +async fn keep( + State(state): State<NetworkServiceState>, + Path(id): Path<String>, +) -> Result<impl IntoResponse, NetworkError> { + if id == "all" { + let mut connections = state.network.get_connections().await?; + + for conn in connections.iter_mut() { + conn.set_keep(true); + + state + .network + .update_connection(conn.to_owned()) + .await + .map_err(|_| NetworkError::CannotApplyConfig)?; + } + } else { + let Some(mut conn) = state.network.get_connection(&id).await? else { + return Err(NetworkError::UnknownConnection(id)); + }; + + conn.set_keep(true); + + state + .network + .update_connection(conn) + .await + .map_err(|_| NetworkError::CannotApplyConfig)?; + } + + state + .network + .apply() + .await + .map_err(|_| NetworkError::CannotApplyConfig)?; + + Ok(StatusCode::NO_CONTENT) +} + +#[utoipa::path( + post, + path = "/connections/:id/unkeep", + context_path = "/api/network", + responses( + (status = 204, description = "Do not keep the given connection after the installation", body = String) + ) +)] +async fn unkeep( + State(state): State<NetworkServiceState>, + Path(id): Path<String>, +) -> Result<impl IntoResponse, NetworkError> { + if id == "all" { + let mut connections = state.network.get_connections().await?; + + for conn in connections.iter_mut() { + conn.set_keep(false); + + state + .network + .update_connection(conn.to_owned()) + .await + .map_err(|_| NetworkError::CannotApplyConfig)?; + } + } else { + let Some(mut conn) = state.network.get_connection(&id).await? else { + return Err(NetworkError::UnknownConnection(id)); + }; + + conn.set_keep(false); + + state + .network + .update_connection(conn) + .await + .map_err(|_| NetworkError::CannotApplyConfig)?; + } + + state + .network .apply() .await .map_err(|_| NetworkError::CannotApplyConfig)?; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/agama/agama-server/tests/network_service.rs new/agama/agama-server/tests/network_service.rs --- old/agama/agama-server/tests/network_service.rs 2025-05-27 09:55:53.000000000 +0200 +++ new/agama/agama-server/tests/network_service.rs 2025-06-03 17:34:25.000000000 +0200 @@ -232,7 +232,6 @@ let response = network_service.clone().oneshot(request).await?; assert_eq!(response.status(), StatusCode::OK); let body = body_to_string(response.into_body()).await; - assert!(body.contains(r#""id":"eth0""#)); assert!(body.contains(r#""id":"bond0""#)); assert!(body.contains(r#""mode":"active-backup""#)); assert!(body.contains(r#""primary=eth0""#)); @@ -278,7 +277,6 @@ let response = network_service.clone().oneshot(request).await?; assert_eq!(response.status(), StatusCode::OK); let body = body_to_string(response.into_body()).await; - assert!(body.contains(r#""id":"eth0""#)); assert!(body.contains(r#""id":"br0""#)); assert!(body.contains(r#""ports":["eth0"]"#)); assert!(body.contains(r#""stp":false"#)); 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 2025-05-27 09:55:53.000000000 +0200 +++ new/agama/package/agama.changes 2025-06-03 17:34:25.000000000 +0200 @@ -1,4 +1,16 @@ ------------------------------------------------------------------- +Tue Jun 3 08:35:58 UTC 2025 - Knut Anderssen <kanders...@suse.com> + +- Added support for moving the connections from memory only to disk + (gh#agama-project/agama#2402). + +------------------------------------------------------------------- +Wed May 28 09:00:00 UTC 2025 - Clemens Famulla-Conrad <cfamullacon...@suse.com> + +- Fix bridge port config (bridge-port.priority and + brdige-port.path_cost) + +------------------------------------------------------------------- Mon May 26 19:51:52 UTC 2025 - Imobach Gonzalez Sosa <igonzalezs...@suse.com> - Version 15 ++++++ agama.obsinfo ++++++ --- /var/tmp/diff_new_pack.ExBfSR/_old 2025-06-11 16:25:59.607140198 +0200 +++ /var/tmp/diff_new_pack.ExBfSR/_new 2025-06-11 16:25:59.611140365 +0200 @@ -1,5 +1,5 @@ name: agama -version: 15+6.b2172efdc -mtime: 1748332553 -commit: b2172efdc433f1c573c639dcfc38102fac18fbfe +version: 15+54.8e10affb2 +mtime: 1748964865 +commit: 8e10affb228ff198651e5338d8ad91b481a86be0