diff --git a/rust/agama-lib/src/network/client.rs b/rust/agama-lib/src/network/client.rs index 20f4f7930b..1f2131e227 100644 --- a/rust/agama-lib/src/network/client.rs +++ b/rust/agama-lib/src/network/client.rs @@ -1,5 +1,4 @@ -use super::settings::{BondSettings, MatchSettings, NetworkConnection, WirelessSettings}; -use super::types::{Device, DeviceState, DeviceType, SSID}; +use super::{settings::NetworkConnection, types::Device}; use crate::error::ServiceError; use reqwest::{Client, Response}; use serde_json; diff --git a/rust/agama-server/src/agama-dbus-server.rs b/rust/agama-server/src/agama-dbus-server.rs index 7643d6e0ec..0637a90a2d 100644 --- a/rust/agama-server/src/agama-dbus-server.rs +++ b/rust/agama-server/src/agama-dbus-server.rs @@ -1,6 +1,6 @@ use agama_server::{ l10n::{self, helpers}, - network, questions, + questions, }; use agama_lib::connection_to; @@ -41,8 +41,6 @@ async fn main() -> Result<(), Box> { log::info!("Started questions interface"); l10n::export_dbus_objects(&connection, &locale).await?; log::info!("Started locale interface"); - network::export_dbus_objects(&connection).await?; - log::info!("Started network interface"); connection .request_name(SERVICE_NAME) diff --git a/rust/agama-server/src/network.rs b/rust/agama-server/src/network.rs index 633397a3b6..9c9d6abee7 100644 --- a/rust/agama-server/src/network.rs +++ b/rust/agama-server/src/network.rs @@ -40,7 +40,6 @@ mod action; mod adapter; -pub mod dbus; pub mod error; pub mod model; mod nm; @@ -49,17 +48,6 @@ pub mod web; pub use action::Action; pub use adapter::{Adapter, NetworkAdapterError}; -pub use dbus::NetworkService; pub use model::NetworkState; pub use nm::NetworkManagerAdapter; pub use system::NetworkSystem; -use zbus::Connection; - -pub async fn export_dbus_objects( - connection: &Connection, -) -> Result<(), Box> { - let adapter = NetworkManagerAdapter::from_system() - .await - .expect("Could not connect to NetworkManager to read the configuration."); - NetworkService::start(connection, adapter).await -} diff --git a/rust/agama-server/src/network/action.rs b/rust/agama-server/src/network/action.rs index 057b5fff68..8885098b3b 100644 --- a/rust/agama-server/src/network/action.rs +++ b/rust/agama-server/src/network/action.rs @@ -2,7 +2,6 @@ use crate::network::model::{AccessPoint, Connection, Device}; use agama_lib::network::types::DeviceType; use tokio::sync::oneshot; use uuid::Uuid; -use zbus::zvariant::OwnedObjectPath; use super::{error::NetworkStateError, model::GeneralState, NetworkAdapterError}; @@ -16,11 +15,7 @@ pub type ControllerConnection = (Connection, Vec); #[derive(Debug)] pub enum Action { /// Add a new connection with the given name and type. - AddConnection( - String, - DeviceType, - Responder>, - ), + AddConnection(String, DeviceType, Responder>), /// Add a new connection NewConnection(Box, Responder>), /// Gets a connection by its id @@ -29,12 +24,6 @@ pub enum Action { GetConnectionByUuid(Uuid, Responder>), /// Gets a connection GetConnections(Responder>), - /// Gets a connection path - GetConnectionPath(Uuid, Responder>), - /// Gets a connection path by id - GetConnectionPathById(String, Responder>), - /// Get connections paths - GetConnectionsPaths(Responder>), /// Gets a controller connection GetController( Uuid, @@ -52,10 +41,6 @@ pub enum Action { GetDevice(String, Responder>), /// Gets all the existent devices GetDevices(Responder>), - /// Gets a device path - GetDevicePath(String, Responder>), - /// Get devices paths - GetDevicesPaths(Responder>), GetGeneralState(Responder), /// Sets a controller's ports. It uses the Uuid of the controller and the IDs or interface names /// of the ports. diff --git a/rust/agama-server/src/network/dbus.rs b/rust/agama-server/src/network/dbus.rs deleted file mode 100644 index 30fe51b7aa..0000000000 --- a/rust/agama-server/src/network/dbus.rs +++ /dev/null @@ -1,11 +0,0 @@ -//! D-Bus service and interfaces. -//! -//! This module contains a [D-Bus network service](NetworkService) which expose the network -//! configuration for Agama. - -mod interfaces; -pub mod service; -mod tree; - -pub use service::NetworkService; -pub(crate) use tree::Tree; diff --git a/rust/agama-server/src/network/dbus/interfaces.rs b/rust/agama-server/src/network/dbus/interfaces.rs deleted file mode 100644 index be287a5776..0000000000 --- a/rust/agama-server/src/network/dbus/interfaces.rs +++ /dev/null @@ -1,14 +0,0 @@ -//! Network D-Bus interfaces. -//! -//! This module contains the set of D-Bus interfaces that are exposed by [D-Bus network -//! service](crate::NetworkService). - -mod common; -mod connection_configs; -mod connections; -mod devices; -mod ip_config; -pub use connection_configs::{Bond, Wireless}; -pub use connections::{Connection, Connections, Match}; -pub use devices::{Device, Devices}; -pub use ip_config::Ip; diff --git a/rust/agama-server/src/network/dbus/interfaces/common.rs b/rust/agama-server/src/network/dbus/interfaces/common.rs deleted file mode 100644 index a0faeebb1f..0000000000 --- a/rust/agama-server/src/network/dbus/interfaces/common.rs +++ /dev/null @@ -1,86 +0,0 @@ -//! Traits to build network D-Bus interfaces. -//! -//! There are a set of operations that are shared by many D-Bus interfaces (retrieving or updating a connection, a configuration etc.). -//! The traits in this module implements the common pieces to make it easier to build new -//! interfaces and reduce code duplication. -//! -//! Note: it is not clear to us whether using traits or simple structs is better for this use case. -//! We could change the approach in the future. -use crate::network::{ - error::NetworkStateError, - model::{Connection as NetworkConnection, ConnectionConfig}, - Action, -}; -use async_trait::async_trait; -use tokio::sync::{mpsc::UnboundedSender, oneshot, MutexGuard}; -use uuid::Uuid; - -#[async_trait] -pub trait ConnectionInterface { - fn uuid(&self) -> Uuid; - - async fn actions(&self) -> MutexGuard>; - - async fn get_connection(&self) -> Result { - let actions = self.actions().await; - let (tx, rx) = oneshot::channel(); - actions - .send(Action::GetConnectionByUuid(self.uuid(), tx)) - .unwrap(); - rx.await - .unwrap() - .ok_or(NetworkStateError::UnknownConnection( - self.uuid().to_string(), - )) - } - - /// Updates the connection data in the NetworkSystem. - /// - /// * `func`: function to update the connection. - async fn update_connection(&self, func: F) -> Result<(), NetworkStateError> - where - F: FnOnce(&mut NetworkConnection) + std::marker::Send, - { - let (tx, rx) = oneshot::channel(); - let mut connection = self.get_connection().await?; - func(&mut connection); - let actions = self.actions().await; - actions - .send(Action::UpdateConnection(Box::new(connection), tx)) - .unwrap(); - - rx.await.unwrap() - } -} - -#[async_trait] -pub trait ConnectionConfigInterface: ConnectionInterface { - async fn get_config(&self) -> Result - where - T: TryFrom, - { - let connection = self.get_connection().await?; - connection.config.try_into() - } - - async fn update_config(&self, func: F) -> Result<(), NetworkStateError> - where - F: FnOnce(&mut T) + std::marker::Send, - T: Into - + TryFrom - + std::marker::Send, - { - let mut connection = self.get_connection().await?; - let mut config: T = connection.config.clone().try_into()?; - func(&mut config); - connection.config = config.into(); - let actions = self.actions().await; - - let (tx, rx) = oneshot::channel(); - actions - .send(Action::UpdateConnection(Box::new(connection), tx)) - .unwrap(); - - rx.await.unwrap() - } -} diff --git a/rust/agama-server/src/network/dbus/interfaces/connection_configs.rs b/rust/agama-server/src/network/dbus/interfaces/connection_configs.rs deleted file mode 100644 index f35d82f489..0000000000 --- a/rust/agama-server/src/network/dbus/interfaces/connection_configs.rs +++ /dev/null @@ -1,228 +0,0 @@ -use agama_lib::network::types::SSID; -use async_trait::async_trait; -use std::sync::Arc; -use tokio::sync::{mpsc::UnboundedSender, oneshot, Mutex, MutexGuard}; -use uuid::Uuid; -use zbus::dbus_interface; - -use crate::network::{ - action::Action, - error::NetworkStateError, - model::{BondConfig, SecurityProtocol, WirelessConfig, WirelessMode}, -}; - -use super::common::{ConnectionConfigInterface, ConnectionInterface}; - -/// D-Bus interface for Bond settings. -pub struct Bond { - actions: Arc>>, - uuid: Uuid, -} - -impl Bond { - /// Creates a Bond interface object. - /// - /// * `actions`: sending-half of a channel to send actions. - /// * `uuid`: connection UUID. - pub fn new(actions: UnboundedSender, uuid: Uuid) -> Self { - Self { - actions: Arc::new(Mutex::new(actions)), - uuid, - } - } -} - -#[dbus_interface(name = "org.opensuse.Agama1.Network.Connection.Bond")] -impl Bond { - /// Bonding mode. - #[dbus_interface(property)] - pub async fn mode(&self) -> zbus::fdo::Result { - let config = self.get_config::().await?; - Ok(config.mode.to_string()) - } - - #[dbus_interface(property)] - pub async fn set_mode(&mut self, mode: &str) -> zbus::fdo::Result<()> { - let mode = mode.try_into()?; - self.update_config::(|c| c.mode = mode) - .await?; - Ok(()) - } - - /// List of bonding options. - #[dbus_interface(property)] - pub async fn options(&self) -> zbus::fdo::Result { - let config = self.get_config::().await?; - Ok(config.options.to_string()) - } - - #[dbus_interface(property)] - pub async fn set_options(&mut self, opts: &str) -> zbus::fdo::Result<()> { - let opts = opts.try_into()?; - self.update_config::(|c| c.options = opts) - .await?; - Ok(()) - } - - /// List of bond ports. - /// - /// For the port names, it uses the interface name (preferred) or, as a fallback, - /// the connection ID of the port. - #[dbus_interface(property)] - pub async fn ports(&self) -> zbus::fdo::Result> { - let actions = self.actions.lock().await; - let (tx, rx) = oneshot::channel(); - actions.send(Action::GetController(self.uuid, tx)).unwrap(); - - let (_, ports) = rx.await.unwrap()?; - Ok(ports) - } - - #[dbus_interface(property)] - pub async fn set_ports(&mut self, ports: Vec) -> zbus::fdo::Result<()> { - let actions = self.actions.lock().await; - let (tx, rx) = oneshot::channel(); - actions - .send(Action::SetPorts(self.uuid, Box::new(ports), tx)) - .unwrap(); - let result = rx.await.unwrap(); - Ok(result?) - } -} - -#[async_trait] -impl ConnectionInterface for Bond { - fn uuid(&self) -> Uuid { - self.uuid - } - - async fn actions(&self) -> MutexGuard> { - self.actions.lock().await - } -} - -impl ConnectionConfigInterface for Bond {} - -/// D-Bus interface for wireless settings -pub struct Wireless { - actions: Arc>>, - uuid: Uuid, -} - -impl Wireless { - /// Creates a Wireless interface object. - /// - /// * `actions`: sending-half of a channel to send actions. - /// * `uuid`: connection UUID. - pub fn new(actions: UnboundedSender, uuid: Uuid) -> Self { - Self { - actions: Arc::new(Mutex::new(actions)), - uuid, - } - } -} - -#[dbus_interface(name = "org.opensuse.Agama1.Network.Connection.Wireless")] -impl Wireless { - /// Network SSID. - #[dbus_interface(property, name = "SSID")] - pub async fn ssid(&self) -> zbus::fdo::Result> { - let config = self.get_config::().await?; - Ok(config.ssid.into()) - } - - #[dbus_interface(property, name = "SSID")] - pub async fn set_ssid(&mut self, ssid: Vec) -> zbus::fdo::Result<()> { - self.update_config::(|c| c.ssid = SSID(ssid)) - .await?; - Ok(()) - } - - /// Wireless connection mode. - /// - /// Possible values: "unknown", "adhoc", "infrastructure", "ap" or "mesh". - /// - /// See [crate::network::model::WirelessMode]. - #[dbus_interface(property)] - pub async fn mode(&self) -> zbus::fdo::Result { - let config = self.get_config::().await?; - Ok(config.mode.to_string()) - } - - #[dbus_interface(property)] - pub async fn set_mode(&mut self, mode: &str) -> zbus::fdo::Result<()> { - let mode: WirelessMode = mode.try_into()?; - self.update_config::(|c| c.mode = mode) - .await?; - Ok(()) - } - - /// Password to connect to the wireless network. - #[dbus_interface(property)] - pub async fn password(&self) -> zbus::fdo::Result { - let config = self.get_config::().await?; - Ok(config.password.unwrap_or_default()) - } - - #[dbus_interface(property)] - pub async fn set_password(&mut self, password: String) -> zbus::fdo::Result<()> { - self.update_config::(|c| { - c.password = if password.is_empty() { - None - } else { - Some(password) - }; - }) - .await?; - Ok(()) - } - - /// Wireless security protocol. - /// - /// Possible values: "none", "owe", "ieee8021x", "wpa-psk", "sae", "wpa-eap", - /// "wpa-eap-suite-b192". - /// - /// See [crate::network::model::SecurityProtocol]. - #[dbus_interface(property)] - pub async fn security(&self) -> zbus::fdo::Result { - let config = self.get_config::().await?; - Ok(config.security.to_string()) - } - - #[dbus_interface(property)] - pub async fn set_security(&mut self, security: &str) -> zbus::fdo::Result<()> { - let security: SecurityProtocol = security - .try_into() - .map_err(|_| NetworkStateError::InvalidSecurityProtocol(security.to_string()))?; - self.update_config::(|c| c.security = security) - .await?; - Ok(()) - } - - /// Whether the network is hidden or not. - #[dbus_interface(property)] - pub async fn hidden(&self) -> zbus::fdo::Result { - let config = self.get_config::().await?; - Ok(config.hidden) - } - - #[dbus_interface(property)] - pub async fn set_hidden(&mut self, hidden: bool) -> zbus::fdo::Result<()> { - self.update_config::(|c| c.hidden = hidden) - .await?; - Ok(()) - } -} - -#[async_trait] -impl ConnectionInterface for Wireless { - fn uuid(&self) -> Uuid { - self.uuid - } - - async fn actions(&self) -> MutexGuard> { - self.actions.lock().await - } -} - -impl ConnectionConfigInterface for Wireless {} diff --git a/rust/agama-server/src/network/dbus/interfaces/connections.rs b/rust/agama-server/src/network/dbus/interfaces/connections.rs deleted file mode 100644 index 56a2e11363..0000000000 --- a/rust/agama-server/src/network/dbus/interfaces/connections.rs +++ /dev/null @@ -1,330 +0,0 @@ -use async_trait::async_trait; -use std::{str::FromStr, sync::Arc}; -use tokio::sync::{mpsc::UnboundedSender, oneshot, Mutex, MutexGuard}; -use uuid::Uuid; -use zbus::{ - dbus_interface, - zvariant::{ObjectPath, OwnedObjectPath}, - SignalContext, -}; - -use super::common::ConnectionInterface; -use crate::network::{error::NetworkStateError, model::MacAddress, Action}; - -/// D-Bus interface for the set of connections. -/// -/// It offers an API to query the connections collection. -pub struct Connections { - actions: Arc>>, -} - -impl Connections { - /// Creates a Connections interface object. - /// - /// * `actions`: sending-half of a channel to send actions. - pub fn new(actions: UnboundedSender) -> Self { - Self { - actions: Arc::new(Mutex::new(actions)), - } - } -} - -#[dbus_interface(name = "org.opensuse.Agama1.Network.Connections")] -impl Connections { - /// Returns the D-Bus paths of the network connections. - pub async fn get_connections(&self) -> zbus::fdo::Result> { - let actions = self.actions.lock().await; - let (tx, rx) = oneshot::channel(); - actions.send(Action::GetConnectionsPaths(tx)).unwrap(); - let result = rx.await.unwrap(); - Ok(result) - } - - /// Adds a new network connection. - /// - /// * `id`: connection name. - /// * `ty`: connection type (see [agama_lib::network::types::DeviceType]). - pub async fn add_connection( - &mut self, - id: String, - ty: u8, - #[zbus(signal_context)] ctxt: SignalContext<'_>, - ) -> zbus::fdo::Result { - let actions = self.actions.lock().await; - let (tx, rx) = oneshot::channel(); - actions - .send(Action::AddConnection(id.clone(), ty.try_into()?, tx)) - .unwrap(); - let path = rx.await.unwrap()?; - Self::connection_added(&ctxt, &id, &path).await?; - Ok(path) - } - - /// Returns the D-Bus path of the network connection by its UUID. - /// - /// * `uuid`: connection UUID. - pub async fn get_connection(&self, uuid: &str) -> zbus::fdo::Result { - let uuid: Uuid = uuid - .parse() - .map_err(|_| NetworkStateError::InvalidUuid(uuid.to_string()))?; - let actions = self.actions.lock().await; - let (tx, rx) = oneshot::channel(); - actions.send(Action::GetConnectionPath(uuid, tx)).unwrap(); - let path = rx - .await - .unwrap() - .ok_or(NetworkStateError::UnknownConnection(uuid.to_string()))?; - Ok(path) - } - - /// Returns the D-Bus path of the network connection by its ID. - /// - /// * `id`: connection ID. - pub async fn get_connection_by_id(&self, id: &str) -> zbus::fdo::Result { - let actions = self.actions.lock().await; - let (tx, rx) = oneshot::channel(); - actions - .send(Action::GetConnectionPathById(id.to_string(), tx)) - .unwrap(); - let path = rx - .await - .unwrap() - .ok_or(NetworkStateError::UnknownConnection(id.to_string()))?; - Ok(path) - } - - /// Removes a network connection. - /// - /// * `uuid`: connection UUID.. - pub async fn remove_connection(&mut self, uuid: &str) -> zbus::fdo::Result<()> { - let uuid = uuid - .parse() - .map_err(|_| NetworkStateError::InvalidUuid(uuid.to_string()))?; - let actions = self.actions.lock().await; - let (tx, rx) = oneshot::channel(); - actions.send(Action::RemoveConnection(uuid, tx)).unwrap(); - - rx.await.unwrap()?; - Ok(()) - } - - /// Applies the network configuration. - /// - /// It includes adding, updating and removing connections as needed. - pub async fn apply(&self) -> zbus::fdo::Result<()> { - let actions = self.actions.lock().await; - let (tx, rx) = oneshot::channel(); - actions.send(Action::Apply(tx)).unwrap(); - rx.await.unwrap()?; - Ok(()) - } - - /// Notifies than a new interface has been added. - #[dbus_interface(signal)] - pub async fn connection_added( - ctxt: &SignalContext<'_>, - id: &str, - path: &ObjectPath<'_>, - ) -> zbus::Result<()>; -} - -/// D-Bus interface for a network connection -/// -/// It offers an API to query a connection. -pub struct Connection { - actions: Arc>>, - uuid: Uuid, -} - -impl Connection { - /// Creates a Connection interface object. - /// - /// * `actions`: sending-half of a channel to send actions. - /// * `uuid`: network connection's UUID. - pub fn new(actions: UnboundedSender, uuid: Uuid) -> Self { - Self { - actions: Arc::new(Mutex::new(actions)), - uuid, - } - } -} - -#[dbus_interface(name = "org.opensuse.Agama1.Network.Connection")] -impl Connection { - /// Connection ID. - /// - /// Unique identifier of the network connection. It may or not be the same that the used by the - /// backend. For instance, when using NetworkManager (which is the only supported backend by - /// now), it uses the original ID but appending a number in case the ID is duplicated. - #[dbus_interface(property)] - pub async fn id(&self) -> zbus::fdo::Result { - let connection = self.get_connection().await?; - Ok(connection.id) - } - - /// Connection UUID. - /// - /// Unique identifier of the network connection. It may or not be the same that the used by the - /// backend. - #[dbus_interface(property)] - pub async fn uuid(&self) -> String { - self.uuid.to_string() - } - - #[dbus_interface(property)] - pub async fn controller(&self) -> zbus::fdo::Result { - let connection = self.get_connection().await?; - let result = match connection.controller { - Some(uuid) => uuid.to_string(), - None => "".to_string(), - }; - Ok(result) - } - - #[dbus_interface(property)] - pub async fn interface(&self) -> zbus::fdo::Result { - let connection = self.get_connection().await?; - Ok(connection.interface.unwrap_or_default()) - } - - #[dbus_interface(property)] - pub async fn set_interface(&mut self, name: &str) -> zbus::fdo::Result<()> { - let interface = Some(name.to_string()); - self.update_connection(|c| c.interface = interface).await?; - Ok(()) - } - - /// Custom mac-address - #[dbus_interface(property)] - pub async fn mac_address(&self) -> zbus::fdo::Result { - let connection = self.get_connection().await?; - Ok(connection.mac_address.to_string()) - } - - #[dbus_interface(property)] - pub async fn set_mac_address(&mut self, mac_address: &str) -> zbus::fdo::Result<()> { - let mac_address = MacAddress::from_str(mac_address)?; - self.update_connection(|c| c.mac_address = mac_address) - .await?; - Ok(()) - } - - /// Whether the network interface should be active or not - #[dbus_interface(property)] - pub async fn active(&self) -> zbus::fdo::Result { - let connection = self.get_connection().await?; - Ok(connection.is_up()) - } - - #[dbus_interface(property)] - pub async fn set_active(&mut self, active: bool) -> zbus::fdo::Result<()> { - self.update_connection(|c| { - if active { - c.set_up(); - } else { - c.set_down(); - } - }) - .await?; - Ok(()) - } -} - -#[async_trait] -impl ConnectionInterface for Connection { - fn uuid(&self) -> Uuid { - self.uuid - } - - async fn actions(&self) -> MutexGuard> { - self.actions.lock().await - } -} - -/// D-Bus interface for Match settings -pub struct Match { - actions: Arc>>, - uuid: Uuid, -} - -impl Match { - /// Creates a Match Settings interface object. - /// - /// * `actions`: sending-half of a channel to send actions. - /// * `uuid`: nework connection's UUID. - pub fn new(actions: UnboundedSender, uuid: Uuid) -> Self { - Self { - actions: Arc::new(Mutex::new(actions)), - uuid, - } - } -} - -#[dbus_interface(name = "org.opensuse.Agama1.Network.Connection.Match")] -impl Match { - /// List of driver names to match. - #[dbus_interface(property)] - pub async fn driver(&self) -> zbus::fdo::Result> { - let connection = self.get_connection().await?; - Ok(connection.match_config.driver) - } - - #[dbus_interface(property)] - pub async fn set_driver(&mut self, driver: Vec) -> zbus::fdo::Result<()> { - self.update_connection(|c| c.match_config.driver = driver) - .await?; - Ok(()) - } - - /// List of paths to match agains the ID_PATH udev property of devices. - #[dbus_interface(property)] - pub async fn path(&self) -> zbus::fdo::Result> { - let connection = self.get_connection().await?; - Ok(connection.match_config.path) - } - - #[dbus_interface(property)] - pub async fn set_path(&mut self, path: Vec) -> zbus::fdo::Result<()> { - self.update_connection(|c| c.match_config.path = path) - .await?; - Ok(()) - } - /// List of interface names to match. - #[dbus_interface(property)] - pub async fn interface(&self) -> zbus::fdo::Result> { - let connection = self.get_connection().await?; - Ok(connection.match_config.interface) - } - - #[dbus_interface(property)] - pub async fn set_interface(&mut self, interface: Vec) -> zbus::fdo::Result<()> { - self.update_connection(|c| c.match_config.interface = interface) - .await?; - Ok(()) - } - - /// List of kernel options to match. - #[dbus_interface(property)] - pub async fn kernel(&self) -> zbus::fdo::Result> { - let connection = self.get_connection().await?; - Ok(connection.match_config.kernel) - } - - #[dbus_interface(property)] - pub async fn set_kernel(&mut self, kernel: Vec) -> zbus::fdo::Result<()> { - self.update_connection(|c| c.match_config.kernel = kernel) - .await?; - Ok(()) - } -} - -#[async_trait] -impl ConnectionInterface for Match { - fn uuid(&self) -> Uuid { - self.uuid - } - - async fn actions(&self) -> MutexGuard> { - self.actions.lock().await - } -} diff --git a/rust/agama-server/src/network/dbus/interfaces/devices.rs b/rust/agama-server/src/network/dbus/interfaces/devices.rs deleted file mode 100644 index 8f29d84f35..0000000000 --- a/rust/agama-server/src/network/dbus/interfaces/devices.rs +++ /dev/null @@ -1,71 +0,0 @@ -use crate::network::{model::Device as NetworkDevice, Action}; -use std::sync::Arc; -use tokio::sync::{mpsc::UnboundedSender, oneshot, Mutex}; -use zbus::{dbus_interface, zvariant::OwnedObjectPath}; - -/// D-Bus interface for the network devices collection -/// -/// It offers an API to query the devices collection. -pub struct Devices { - actions: Arc>>, -} - -impl Devices { - /// Creates a Devices interface object. - /// - /// * `objects`: Objects paths registry. - pub fn new(actions: UnboundedSender) -> Self { - Self { - actions: Arc::new(Mutex::new(actions)), - } - } -} - -#[dbus_interface(name = "org.opensuse.Agama1.Network.Devices")] -impl Devices { - /// Returns the D-Bus paths of the network devices. - pub async fn get_devices(&self) -> zbus::fdo::Result> { - let actions = self.actions.lock().await; - let (tx, rx) = oneshot::channel(); - actions.send(Action::GetDevicesPaths(tx)).unwrap(); - let result = rx.await.unwrap(); - Ok(result) - } -} - -/// D-Bus interface for a network device -/// -/// It offers an API to query basic networking devices information (e.g., the name). -pub struct Device { - device: NetworkDevice, -} - -impl Device { - /// Creates an interface object. - /// - /// * `device`: network device. - pub fn new(device: NetworkDevice) -> Self { - Self { device } - } -} - -#[dbus_interface(name = "org.opensuse.Agama1.Network.Device")] -impl Device { - /// Device name. - /// - /// Kernel device name, e.g., eth0, enp1s0, etc. - #[dbus_interface(property)] - pub fn name(&self) -> &str { - &self.device.name - } - - /// Device type. - /// - /// Possible values: 0 = loopback, 1 = ethernet, 2 = wireless. - /// - /// See [agama_lib::network::types::DeviceType]. - #[dbus_interface(property, name = "Type")] - pub fn device_type(&self) -> u8 { - self.device.type_ as u8 - } -} diff --git a/rust/agama-server/src/network/dbus/interfaces/ip_config.rs b/rust/agama-server/src/network/dbus/interfaces/ip_config.rs deleted file mode 100644 index dfbfd6ad30..0000000000 --- a/rust/agama-server/src/network/dbus/interfaces/ip_config.rs +++ /dev/null @@ -1,226 +0,0 @@ -//! Network D-Bus interfaces for IP configuration. -//! -//! This module contains the D-Bus interfaces to deal with IPv4 and IPv6 configuration. -//! The `dbus_interface` macro should be applied to structs, that's the reason there are -//! two different structs for IPv4 and IPv6 settings. The common code have been moved -//! to the `Ip` struct. -use crate::network::{ - action::Action, - error::NetworkStateError, - model::{IpConfig, Ipv4Method, Ipv6Method}, -}; -use async_trait::async_trait; -use cidr::IpInet; -use std::{net::IpAddr, sync::Arc}; -use tokio::sync::mpsc::UnboundedSender; -use tokio::sync::{Mutex, MutexGuard}; -use uuid::Uuid; -use zbus::dbus_interface; - -use super::common::ConnectionInterface; - -/// D-Bus interface for IPv4 and IPv6 settings -pub struct Ip { - actions: Arc>>, - uuid: Uuid, -} - -impl Ip { - /// Creates an IP interface object. - /// - /// * `actions`: sending-half of a channel to send actions. - /// * `uuid`: connection UUID.. - pub fn new(actions: UnboundedSender, uuid: Uuid) -> Self { - Self { - actions: Arc::new(Mutex::new(actions)), - uuid, - } - } - - /// Returns the IpConfig struct. - async fn get_ip_config(&self) -> Result { - self.get_connection().await.map(|c| c.ip_config) - } - - /// Updates the IpConfig struct. - /// - /// * `func`: function to update the configuration. - async fn update_ip_config(&self, func: F) -> zbus::fdo::Result<()> - where - F: Fn(&mut IpConfig) + std::marker::Send, - { - self.update_connection(move |c| func(&mut c.ip_config)) - .await?; - Ok(()) - } -} - -#[dbus_interface(name = "org.opensuse.Agama1.Network.Connection.IP")] -impl Ip { - /// List of IP addresses. - /// - /// When the method is 'auto', these addresses are used as additional addresses. - #[dbus_interface(property)] - pub async fn addresses(&self) -> zbus::fdo::Result> { - let ip_config = self.get_ip_config().await?; - let addresses = ip_config.addresses.iter().map(|a| a.to_string()).collect(); - Ok(addresses) - } - - #[dbus_interface(property)] - pub async fn set_addresses(&mut self, addresses: Vec) -> zbus::fdo::Result<()> { - let addresses = helpers::parse_addresses::(addresses); - self.update_ip_config(|ip| ip.addresses = addresses.clone()) - .await - } - - /// IPv4 configuration method. - /// - /// Possible values: "disabled", "auto", "manual" or "link-local". - /// - /// See [crate::network::model::Ipv4Method]. - #[dbus_interface(property)] - pub async fn method4(&self) -> zbus::fdo::Result { - let ip_config = self.get_ip_config().await?; - Ok(ip_config.method4.to_string()) - } - - #[dbus_interface(property)] - pub async fn set_method4(&mut self, method: &str) -> zbus::fdo::Result<()> { - let method: Ipv4Method = method.parse()?; - self.update_ip_config(|ip| ip.method4 = method).await - } - - /// IPv6 configuration method. - /// - /// Possible values: "disabled", "auto", "manual", "link-local", "ignore" or "dhcp". - /// - /// See [crate::network::model::Ipv6Method]. - #[dbus_interface(property)] - pub async fn method6(&self) -> zbus::fdo::Result { - let ip_config = self.get_ip_config().await?; - Ok(ip_config.method6.to_string()) - } - - #[dbus_interface(property)] - pub async fn set_method6(&mut self, method: &str) -> zbus::fdo::Result<()> { - let method: Ipv6Method = method.parse()?; - self.update_ip_config(|ip| ip.method6 = method).await - } - - /// Name server addresses. - #[dbus_interface(property)] - pub async fn nameservers(&self) -> zbus::fdo::Result> { - let ip_config = self.get_ip_config().await?; - let nameservers = ip_config - .nameservers - .iter() - .map(IpAddr::to_string) - .collect(); - Ok(nameservers) - } - - #[dbus_interface(property)] - pub async fn set_nameservers(&mut self, addresses: Vec) -> zbus::fdo::Result<()> { - let addresses = helpers::parse_addresses::(addresses); - self.update_ip_config(|ip| ip.nameservers = addresses.clone()) - .await - } - - /// Network gateway for IPv4. - /// - /// An empty string removes the current value. - #[dbus_interface(property)] - pub async fn gateway4(&self) -> zbus::fdo::Result { - let ip_config = self.get_ip_config().await?; - let gateway = match ip_config.gateway4 { - Some(ref address) => address.to_string(), - None => "".to_string(), - }; - Ok(gateway) - } - - #[dbus_interface(property)] - pub async fn set_gateway4(&mut self, gateway: String) -> zbus::fdo::Result<()> { - let gateway = helpers::parse_gateway(gateway)?; - self.update_ip_config(|ip| ip.gateway4 = gateway).await - } - - /// Network gateway for IPv6. - /// - /// An empty string removes the current value. - #[dbus_interface(property)] - pub async fn gateway6(&self) -> zbus::fdo::Result { - let ip_config = self.get_ip_config().await?; - let result = match ip_config.gateway6 { - Some(ref address) => address.to_string(), - None => "".to_string(), - }; - Ok(result) - } - - #[dbus_interface(property)] - pub async fn set_gateway6(&mut self, gateway: String) -> zbus::fdo::Result<()> { - let gateway = helpers::parse_gateway(gateway)?; - self.update_ip_config(|ip| ip.gateway6 = gateway).await - } -} - -mod helpers { - use crate::network::error::NetworkStateError; - use log; - use std::{ - fmt::{Debug, Display}, - str::FromStr, - }; - - /// Parses a set of addresses in textual form into T. - /// - /// * `addresses`: addresses to parse. - pub fn parse_addresses(addresses: Vec) -> Vec - where - T: FromStr, - ::Err: Display, - { - addresses - .into_iter() - .filter_map(|ip| match ip.parse::() { - Ok(address) => Some(address), - Err(error) => { - log::error!("Ignoring the invalid IP address: {} ({})", ip, error); - None - } - }) - .collect() - } - - /// Sets the gateway for an IP configuration. - /// - /// * `ip`: IpConfig object. - /// * `gateway`: IP in textual form. - pub fn parse_gateway(gateway: String) -> Result, NetworkStateError> - where - T: FromStr, - ::Err: Debug + Display, - { - if gateway.is_empty() { - Ok(None) - } else { - let parsed = gateway - .parse() - .map_err(|_| NetworkStateError::InvalidIpAddr(gateway))?; - Ok(Some(parsed)) - } - } -} - -#[async_trait] -impl ConnectionInterface for Ip { - fn uuid(&self) -> Uuid { - self.uuid - } - - async fn actions(&self) -> MutexGuard> { - self.actions.lock().await - } -} diff --git a/rust/agama-server/src/network/dbus/service.rs b/rust/agama-server/src/network/dbus/service.rs deleted file mode 100644 index 64785fc85c..0000000000 --- a/rust/agama-server/src/network/dbus/service.rs +++ /dev/null @@ -1,24 +0,0 @@ -//! Network D-Bus service. -//! -//! This module defines a D-Bus service which exposes Agama's network configuration. -use crate::network::{Adapter, NetworkSystem}; -use std::error::Error; -use zbus::Connection; - -/// Represents the Agama networking D-Bus service. -/// -/// It is responsible for starting the [NetworkSystem] on a different thread. -/// TODO: this struct might not be needed anymore. -pub struct NetworkService; - -impl NetworkService { - /// Starts listening and dispatching events on the D-Bus connection. - pub async fn start( - connection: &Connection, - adapter: T, - ) -> Result<(), Box> { - let network = NetworkSystem::new(connection.clone(), adapter); - network.start().await?; - Ok(()) - } -} diff --git a/rust/agama-server/src/network/dbus/tree.rs b/rust/agama-server/src/network/dbus/tree.rs deleted file mode 100644 index 76674d9a90..0000000000 --- a/rust/agama-server/src/network/dbus/tree.rs +++ /dev/null @@ -1,273 +0,0 @@ -use agama_lib::error::ServiceError; -use uuid::Uuid; -use zbus::zvariant::{ObjectPath, OwnedObjectPath}; - -use crate::network::{action::Action, dbus::interfaces, model::*}; -use log; -use std::collections::HashMap; -use tokio::sync::mpsc::UnboundedSender; - -const CONNECTIONS_PATH: &str = "/org/opensuse/Agama1/Network/connections"; -const DEVICES_PATH: &str = "/org/opensuse/Agama1/Network/devices"; - -/// Handle the objects in the D-Bus tree for the network state -pub struct Tree { - connection: zbus::Connection, - actions: UnboundedSender, - objects: ObjectsRegistry, -} - -impl Tree { - /// Creates a new tree handler. - /// - /// * `connection`: D-Bus connection to use. - /// * `actions`: sending-half of a channel to send actions. - pub fn new(connection: zbus::Connection, actions: UnboundedSender) -> Self { - Self { - connection, - actions, - objects: Default::default(), - } - } - - /// Refreshes the list of connections. - /// - /// TODO: re-creating the tree is kind of brute-force and it sends signals about - /// adding/removing interfaces. We should add/update/delete objects as needed. - /// - /// * `connections`: list of connections. - pub async fn set_connections( - &mut self, - connections: &mut [Connection], - ) -> Result<(), ServiceError> { - self.remove_connections().await?; - self.add_connections(connections).await?; - Ok(()) - } - - /// Refreshes the list of devices. - /// - /// * `devices`: list of devices. - pub async fn set_devices(&mut self, devices: &[Device]) -> Result<(), ServiceError> { - self.remove_devices().await?; - self.add_devices(devices).await?; - Ok(()) - } - - /// Adds devices to the D-Bus tree. - /// - /// * `devices`: list of devices. - pub async fn add_devices(&mut self, devices: &[Device]) -> Result<(), ServiceError> { - for (i, dev) in devices.iter().enumerate() { - let path = format!("{}/{}", DEVICES_PATH, i); - let path = ObjectPath::try_from(path.as_str()).unwrap(); - self.add_interface(&path, interfaces::Device::new(dev.clone())) - .await?; - self.objects.register_device(&dev.name, path); - } - - self.add_interface(DEVICES_PATH, interfaces::Devices::new(self.actions.clone())) - .await?; - - Ok(()) - } - - /// Adds a connection to the D-Bus tree and returns the D-Bus path. - /// - /// * `conn`: connection to add. - /// * `notify`: whether to notify the added connection - pub async fn add_connection( - &mut self, - conn: &Connection, - ) -> Result { - let uuid = conn.uuid; - let path: OwnedObjectPath = self.objects.register_connection(conn.uuid).into(); - log::info!( - "Publishing network connection '{}' on '{}'", - &conn.id, - &path - ); - - self.add_interface( - &path, - interfaces::Connection::new(self.actions.clone(), uuid), - ) - .await?; - - self.add_interface(&path, interfaces::Ip::new(self.actions.clone(), uuid)) - .await?; - - self.add_interface(&path, interfaces::Match::new(self.actions.clone(), uuid)) - .await?; - - if let ConnectionConfig::Bond(_) = conn.config { - self.add_interface(&path, interfaces::Bond::new(self.actions.clone(), uuid)) - .await?; - } - - if let ConnectionConfig::Wireless(_) = conn.config { - self.add_interface(&path, interfaces::Wireless::new(self.actions.clone(), uuid)) - .await?; - } - - Ok(path) - } - - /// Removes a connection from the tree - /// - /// * `uuid`: connection UUID. - pub async fn remove_connection(&mut self, uuid: Uuid) -> Result<(), ServiceError> { - let Some(path) = self.objects.connection_path(uuid) else { - return Ok(()); - }; - self.remove_connection_on(path.as_str()).await?; - self.objects.deregister_connection(uuid).unwrap(); - Ok(()) - } - - /// Returns all devices paths. - pub fn devices_paths(&self) -> Vec { - self.objects.devices_paths() - } - - pub fn device_path(&self, name: &str) -> Option { - self.objects.device_path(name).map(|o| o.into()) - } - - /// Returns all connection paths. - pub fn connections_paths(&self) -> Vec { - self.objects.connections_paths() - } - - pub fn connection_path(&self, uuid: Uuid) -> Option { - self.objects.connection_path(uuid).map(|o| o.into()) - } - - /// Adds connections to the D-Bus tree. - /// - /// * `connections`: list of connections. - async fn add_connections( - &mut self, - connections: &mut [Connection], - ) -> Result<(), ServiceError> { - for conn in connections.iter_mut() { - self.add_connection(conn).await?; - } - - self.add_interface( - CONNECTIONS_PATH, - interfaces::Connections::new(self.actions.clone()), - ) - .await?; - - Ok(()) - } - - /// Clears all the connections from the tree. - async fn remove_connections(&mut self) -> Result<(), ServiceError> { - for path in self.objects.connections.values() { - self.remove_connection_on(path.as_str()).await?; - } - self.objects.connections.clear(); - Ok(()) - } - - /// Clears all the devices from the tree. - async fn remove_devices(&mut self) -> Result<(), ServiceError> { - let object_server = self.connection.object_server(); - for path in self.objects.devices.values() { - object_server - .remove::(path.as_str()) - .await?; - } - self.objects.devices.clear(); - Ok(()) - } - - /// Removes a connection object on the given path - /// - /// * `path`: connection D-Bus path. - async fn remove_connection_on(&self, path: &str) -> Result<(), ServiceError> { - let object_server = self.connection.object_server(); - _ = object_server.remove::(path).await; - _ = object_server.remove::(path).await; - object_server.remove::(path).await?; - object_server.remove::(path).await?; - object_server - .remove::(path) - .await?; - Ok(()) - } - - async fn add_interface(&mut self, path: &str, iface: T) -> Result - where - T: zbus::Interface, - { - let object_server = self.connection.object_server(); - Ok(object_server.at(path, iface).await?) - } -} - -/// Objects paths for known devices and connections -/// -/// Connections are indexed by its Id, which is expected to be unique. -#[derive(Debug, Default)] -struct ObjectsRegistry { - /// device_name (eth0) -> object_path - devices: HashMap, - /// id -> object_path - connections: HashMap, -} - -impl ObjectsRegistry { - /// Registers a network device. - /// - /// * `id`: device name. - /// * `path`: object path. - pub fn register_device(&mut self, id: &str, path: ObjectPath) { - self.devices.insert(id.to_string(), path.into()); - } - - /// Registers a network connection and returns its D-Bus path. - /// - /// It returns the connection Id and the D-Bus path. Bear in mind that the Id can be different - /// in case the original one already existed. - /// - /// * `uuid`: network connection's UUID. - pub fn register_connection(&mut self, uuid: Uuid) -> ObjectPath { - let path = format!("{}/{}", CONNECTIONS_PATH, self.connections.len()); - let path = ObjectPath::try_from(path).unwrap(); - self.connections.insert(uuid, path.clone().into()); - path - } - - /// Returns the path for a device. - /// - /// * `name`: device name. - pub fn device_path(&self, name: &str) -> Option { - self.devices.get(name).map(|p| p.as_ref()) - } - /// Returns the path for a connection. - /// - /// * `uuid`: connection ID. - pub fn connection_path(&self, uuid: Uuid) -> Option { - self.connections.get(&uuid).map(|p| p.as_ref()) - } - - /// Deregisters a network connection. - /// - /// * `id`: connection ID. - pub fn deregister_connection(&mut self, uuid: Uuid) -> Option { - self.connections.remove(&uuid) - } - - /// Returns all devices paths. - pub fn devices_paths(&self) -> Vec { - self.devices.values().cloned().collect() - } - - /// Returns all connection paths. - pub fn connections_paths(&self) -> Vec { - self.connections.values().cloned().collect() - } -} diff --git a/rust/agama-server/src/network/system.rs b/rust/agama-server/src/network/system.rs index 45af45279a..1d83934b06 100644 --- a/rust/agama-server/src/network/system.rs +++ b/rust/agama-server/src/network/system.rs @@ -4,20 +4,17 @@ use super::{ NetworkAdapterError, }; use crate::network::{ - dbus::Tree, model::{Connection, GeneralState}, Action, Adapter, NetworkState, }; use agama_lib::{error::ServiceError, network::types::DeviceType}; -use std::{error::Error, sync::Arc}; +use std::error::Error; use tokio::sync::{ broadcast::{self, Receiver}, mpsc::{self, error::SendError, UnboundedReceiver, UnboundedSender}, oneshot::{self, error::RecvError}, - Mutex, }; use uuid::Uuid; -use zbus::zvariant::OwnedObjectPath; #[derive(thiserror::Error, Debug)] pub enum NetworkSystemError { @@ -47,10 +44,7 @@ pub enum NetworkSystemError { /// let adapter = NetworkManagerAdapter::from_system() /// .await /// .expect("Could not connect to NetworkManager."); -/// let dbus = connection() -/// .await -/// .expect("Could not connect to Agama's D-Bus server."); -/// let network = NetworkSystem::new(dbus, adapter); +/// let network = NetworkSystem::new(adapter); /// /// // Start the networking service and get the client for communication. /// let client = network.start() @@ -63,7 +57,6 @@ pub enum NetworkSystemError { /// # }); /// ``` pub struct NetworkSystem { - connection: zbus::Connection, adapter: T, } @@ -73,13 +66,9 @@ impl NetworkSystem { /// This function does not start the system. To get it running, you must call /// the [start](Self::start) method. /// - /// * `connection`: D-Bus connection to publish the network tree. /// * `adapter`: networking configuration adapter. - pub fn new(connection: zbus::Connection, adapter: T) -> Self { - Self { - connection, - adapter, - } + pub fn new(adapter: T) -> Self { + Self { adapter } } /// Starts the network configuration service and returns a client for communication purposes. @@ -87,7 +76,7 @@ impl NetworkSystem { /// This function starts the server (using [NetworkSystemServer]) on a separate /// task. All the communication is performed through the returned [NetworkSystemClient]. pub async fn start(self) -> Result { - let mut state = self.adapter.read(StateConfig::default()).await?; + let state = self.adapter.read(StateConfig::default()).await?; let (actions_tx, actions_rx) = mpsc::unbounded_channel(); let (updates_tx, _updates_rx) = broadcast::channel(1024); @@ -98,10 +87,6 @@ impl NetworkSystem { }); } - let mut tree = Tree::new(self.connection, actions_tx.clone()); - tree.set_connections(&mut state.connections).await?; - tree.set_devices(&state.devices).await?; - let updates_tx_clone = updates_tx.clone(); tokio::spawn(async move { let mut server = NetworkSystemServer { @@ -109,7 +94,6 @@ impl NetworkSystem { input: actions_rx, output: updates_tx_clone, adapter: self.adapter, - tree: Arc::new(Mutex::new(tree)), }; server.listen().await; @@ -238,7 +222,6 @@ struct NetworkSystemServer { input: UnboundedReceiver, output: broadcast::Sender, adapter: T, - tree: Arc>, } impl NetworkSystemServer { @@ -310,15 +293,7 @@ impl NetworkSystemServer { tx.send(connections).unwrap(); } - Action::GetConnectionPath(uuid, tx) => { - let tree = self.tree.lock().await; - let path = tree.connection_path(uuid); - tx.send(path).unwrap(); - } - Action::GetConnectionPathById(id, tx) => { - let path = self.get_connection_path_by_id_action(&id).await; - tx.send(path).unwrap(); - } + Action::GetController(uuid, tx) => { let result = self.get_controller_action(uuid); tx.send(result).unwrap() @@ -339,22 +314,9 @@ impl NetworkSystemServer { self.state.remove_device(&name)?; return Ok(Some(NetworkChange::DeviceRemoved(name))); } - Action::GetDevicePath(name, tx) => { - let tree = self.tree.lock().await; - let path = tree.device_path(name.as_str()); - tx.send(path).unwrap(); - } Action::GetDevices(tx) => { tx.send(self.state.devices.clone()).unwrap(); } - Action::GetDevicesPaths(tx) => { - let tree = self.tree.lock().await; - tx.send(tree.devices_paths()).unwrap(); - } - Action::GetConnectionsPaths(tx) => { - let tree = self.tree.lock().await; - tx.send(tree.connections_paths()).unwrap(); - } Action::SetPorts(uuid, ports, rx) => { let result = self.set_ports_action(uuid, *ports); rx.send(result).unwrap(); @@ -373,25 +335,7 @@ impl NetworkSystemServer { } Action::Apply(tx) => { let result = self.write().await; - let failed = result.is_err(); tx.send(result).unwrap(); - if failed { - return Ok(None); - } - - // TODO: re-creating the tree is kind of brute-force and it sends signals about - // adding/removing interfaces. We should add/update/delete objects as needed. - // NOTE updating the tree at the same time than dispatching actions can cause a - // deadlock. We might consider using message passing too but at this point - // is enough to use a separate task. - let mut connections = self.state.connections.clone(); - let tree = Arc::clone(&self.tree); - tokio::spawn(async move { - let mut tree = tree.lock().await; - if let Err(e) = tree.set_connections(&mut connections).await { - log::error!("Could not update the D-Bus tree: {}", e); - } - }); } } @@ -402,16 +346,11 @@ impl NetworkSystemServer { &mut self, name: String, ty: DeviceType, - ) -> Result { + ) -> Result<(), NetworkStateError> { let conn = Connection::new(name, ty); // TODO: handle tree handling problems self.state.add_connection(conn.clone())?; - let mut tree = self.tree.lock().await; - let path = tree - .add_connection(&conn) - .await - .expect("Could not update the D-Bus tree"); - Ok(path) + Ok(()) } fn set_ports_action( @@ -446,12 +385,6 @@ impl NetworkSystemServer { Ok((conn, controlled)) } - async fn get_connection_path_by_id_action(&mut self, id: &str) -> Option { - let conn = self.state.get_connection(id)?; - let tree = self.tree.lock().await; - tree.connection_path(conn.uuid) - } - /// Writes the network configuration. pub async fn write(&mut self) -> Result<(), NetworkAdapterError> { self.adapter.write(&self.state).await?; diff --git a/rust/agama-server/src/network/web.rs b/rust/agama-server/src/network/web.rs index a580225ba6..8e7c2e6e37 100644 --- a/rust/agama-server/src/network/web.rs +++ b/rust/agama-server/src/network/web.rs @@ -60,14 +60,13 @@ struct NetworkServiceState { } /// Sets up and returns the axum service for the network module. -/// -/// * `dbus`: zbus Connection. +/// * `adapter`: networking configuration adapter. +/// * `events`: sending-half of the broadcast channel. pub async fn network_service( - dbus: zbus::Connection, adapter: T, events: EventsSender, ) -> Result { - let network = NetworkSystem::new(dbus.clone(), adapter); + let network = NetworkSystem::new(adapter); // FIXME: we are somehow abusing ServiceError. The HTTP/JSON API should have its own // error type. let client = network diff --git a/rust/agama-server/src/web.rs b/rust/agama-server/src/web.rs index 5b03f4b4f7..725139bc1d 100644 --- a/rust/agama-server/src/web.rs +++ b/rust/agama-server/src/web.rs @@ -60,10 +60,7 @@ where .add_service("/manager", manager_service(dbus.clone()).await?) .add_service("/software", software_service(dbus.clone()).await?) .add_service("/storage", storage_service(dbus.clone()).await?) - .add_service( - "/network", - network_service(dbus.clone(), network_adapter, events).await?, - ) + .add_service("/network", network_service(network_adapter, events).await?) .add_service("/questions", questions_service(dbus.clone()).await?) .add_service("/users", users_service(dbus.clone()).await?) .with_config(config) diff --git a/rust/agama-server/tests/network_service.rs b/rust/agama-server/tests/network_service.rs index 0fac4c237f..26860de626 100644 --- a/rust/agama-server/tests/network_service.rs +++ b/rust/agama-server/tests/network_service.rs @@ -1,6 +1,5 @@ pub mod common; -use crate::common::DBusServer; use agama_lib::error::ServiceError; use agama_lib::network::settings::{BondSettings, NetworkConnection}; use agama_lib::network::types::{DeviceType, SSID}; @@ -12,7 +11,6 @@ use agama_server::network::{ }; use async_trait::async_trait; -use axum::body; use axum::http::header; use axum::{ body::Body, @@ -38,11 +36,9 @@ async fn build_state() -> NetworkState { } async fn build_service(state: NetworkState) -> Result { - let dbus = DBusServer::new().start().await?.connection(); - let adapter = NetworkTestAdapter(state); let (tx, _rx) = broadcast::channel(16); - Ok(network_service(dbus, adapter, tx).await?) + Ok(network_service(adapter, tx).await?) } #[derive(Default)]