Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expose the networking API over HTTP #1064

Merged
merged 8 commits into from
Mar 22, 2024
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
19 changes: 16 additions & 3 deletions rust/agama-lib/src/network/types.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
use cidr::errors::NetworkParseError;
use serde::{Deserialize, Serialize};
use std::{fmt, str};
use std::{
fmt,
str::{self, FromStr},
};
use thiserror::Error;
use zbus;

/// Network device
#[derive(Debug, Clone)]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "type")]
pub struct Device {
pub name: String,
pub type_: DeviceType,
Expand All @@ -25,13 +30,21 @@ impl fmt::Display for SSID {
}
}

impl FromStr for SSID {
type Err = NetworkParseError;

fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(SSID(s.as_bytes().into()))
}
}

impl From<SSID> for Vec<u8> {
fn from(value: SSID) -> Self {
value.0
}
}

#[derive(Debug, PartialEq, Copy, Clone, Serialize, Deserialize)]
#[derive(Debug, PartialEq, Copy, Clone, Serialize, Deserialize, utoipa::ToSchema)]
pub enum DeviceType {
Loopback = 0,
Ethernet = 1,
Expand Down
2 changes: 1 addition & 1 deletion rust/agama-server/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ tokio-stream = "0.1.14"
gettext-rs = { version = "0.7.0", features = ["gettext-system"] }
regex = "1.10.2"
once_cell = "1.18.0"
macaddr = "1.0"
macaddr = { version = "1.0", features = ["serde_std"] }
async-trait = "0.1.75"
axum = { version = "0.7.4", features = ["ws"] }
serde_json = "1.0.113"
Expand Down
1 change: 1 addition & 0 deletions rust/agama-server/src/network.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ pub mod error;
pub mod model;
mod nm;
pub mod system;
pub mod web;

pub use action::Action;
pub use adapter::{Adapter, NetworkAdapterError};
Expand Down
32 changes: 26 additions & 6 deletions rust/agama-server/src/network/action.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use crate::network::model::Connection;
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, NetworkAdapterError};
use super::{error::NetworkStateError, model::GeneralState, NetworkAdapterError};

pub type Responder<T> = oneshot::Sender<T>;
pub type ControllerConnection = (Connection, Vec<String>);
Expand All @@ -21,11 +21,18 @@ pub enum Action {
DeviceType,
Responder<Result<OwnedObjectPath, NetworkStateError>>,
),
/// Gets a connection
/// Add a new connection
NewConnection(
Connection,
Copy link
Member

Choose a reason for hiding this comment

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

To be consistent, it should be named AddConnection. I know it collides with the AddConnection action for the D-Bus part, but perhaps it is time to start dropping them. But we can handle that in a separate PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I planned to add this new method, but at the end used the AddConnection + UpdateConnection, but as you commented maybe it is the time to remove them and any DBUS specific action.

Responder<Result<OwnedObjectPath, NetworkStateError>>,
),
/// Gets a connection by its Uuid
GetConnection(Uuid, Responder<Option<Connection>>),
/// Gets a connection
GetConnections(Responder<Vec<Connection>>),
/// Gets a connection path
GetConnectionPath(Uuid, Responder<Option<OwnedObjectPath>>),
/// Gets a connection
/// Gets a connection path by id
GetConnectionPathById(String, Responder<Option<OwnedObjectPath>>),
Copy link
Member

Choose a reason for hiding this comment

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

Another candidate to drop :-)

/// Get connections paths
GetConnectionsPaths(Responder<Vec<OwnedObjectPath>>),
Expand All @@ -34,19 +41,32 @@ pub enum Action {
Uuid,
Responder<Result<ControllerConnection, NetworkStateError>>,
),
/// Gets all scanned access points
GetAccessPoints(Responder<Vec<AccessPoint>>),
/// Gets a device by its name
GetDevice(String, Responder<Option<Device>>),
/// Gets all the existent devices
GetDevices(Responder<Vec<Device>>),
/// Gets a device path
GetDevicePath(String, Responder<Option<OwnedObjectPath>>),
/// Get devices paths
GetDevicesPaths(Responder<Vec<OwnedObjectPath>>),
GetGeneralState(Responder<GeneralState>),
/// Sets a controller's ports. It uses the Uuid of the controller and the IDs or interface names
/// of the ports.
SetPorts(
Uuid,
Box<Vec<String>>,
Responder<Result<(), NetworkStateError>>,
),
/// Update a connection (replacing the old one).
/// Updates a connection (replacing the old one).
UpdateConnection(Box<Connection>),
/// Updates the general network configuration
UpdateGeneralState(GeneralState),
/// Forces a wireless networks scan refresh
RefreshScan(Responder<Result<(), NetworkAdapterError>>),
/// Remove the connection with the given Uuid.
RemoveConnection(Uuid),
RemoveConnection(Uuid, Responder<Result<(), NetworkStateError>>),
/// Apply the current configuration.
Apply(Responder<Result<(), NetworkAdapterError>>),
}
3 changes: 2 additions & 1 deletion rust/agama-server/src/network/adapter.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::network::model::StateConfig;
use crate::network::NetworkState;
use agama_lib::error::ServiceError;
use async_trait::async_trait;
Expand All @@ -16,7 +17,7 @@ pub enum NetworkAdapterError {
/// A trait for the ability to read/write from/to a network service
#[async_trait]
pub trait Adapter {
async fn read(&self) -> Result<NetworkState, NetworkAdapterError>;
async fn read(&self, config: StateConfig) -> Result<NetworkState, NetworkAdapterError>;
async fn write(&self, network: &NetworkState) -> Result<(), NetworkAdapterError>;
}

Expand Down
7 changes: 5 additions & 2 deletions rust/agama-server/src/network/dbus/interfaces/connections.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ pub struct Connections {
impl Connections {
/// Creates a Connections interface object.
///
/// * `objects`: Objects paths registry.
/// * `actions`: sending-half of a channel to send actions.
pub fn new(actions: UnboundedSender<Action>) -> Self {
Self {
actions: Arc::new(Mutex::new(actions)),
Expand Down Expand Up @@ -101,7 +101,10 @@ impl Connections {
.parse()
.map_err(|_| NetworkStateError::InvalidUuid(uuid.to_string()))?;
let actions = self.actions.lock().await;
actions.send(Action::RemoveConnection(uuid)).unwrap();
let (tx, rx) = oneshot::channel();
actions.send(Action::RemoveConnection(uuid, tx)).unwrap();

rx.await.unwrap()?;
Ok(())
}

Expand Down
10 changes: 10 additions & 0 deletions rust/agama-server/src/network/dbus/tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,10 @@ impl Tree {
self.objects.devices_paths()
}

pub fn device_path(&self, name: &str) -> Option<OwnedObjectPath> {
Copy link
Member

Choose a reason for hiding this comment

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

I do not think we want to evolve the D-Bus interface even more. We should be dropping most of it (and just keeping the signals).

self.objects.device_path(name).map(|o| o.into())
}

/// Returns all connection paths.
pub fn connections_paths(&self) -> Vec<OwnedObjectPath> {
self.objects.connections_paths()
Expand Down Expand Up @@ -237,6 +241,12 @@ impl ObjectsRegistry {
path
}

/// Returns the path for a device.
///
/// * `name`: device name.
pub fn device_path(&self, name: &str) -> Option<ObjectPath> {
self.devices.get(name).map(|p| p.as_ref())
}
/// Returns the path for a connection.
///
/// * `uuid`: connection ID.
Expand Down