Skip to content

Commit

Permalink
Adapt iSCSI handling to the new architecture (#1187)
Browse files Browse the repository at this point in the history
This PR implements an HTTP/JSON API for managing iSCSI devices. It works
as a proxy over the real API which is implemented in D-Bus.

The API is composed of these parts:

* A bunch of HTTP/JSON endpoints to manage the iSCSI configuration.
* A stream of iSCSI nodes changes (adding, changing or removing nodes).
* A stream of initiator changes (not implemented yet).

NOTE: this PR should be merged after #1175.

## To do

- [x] Adapt the client
- [x] Populate the cache of ISCSI nodes in the stream
- [x] Allow changing the initiator name
- [x] Allow changing the startup
- [x] Emit initiator changes
- [x] OpenAPI documentation
- [x] Remove calls to `unwrap()` in the initiator changes stream

## References

* Trello: https://trello.com/c/TEQvbxAU/
  • Loading branch information
imobachgs authored May 13, 2024
2 parents 471dd9e + ba35ce8 commit 7aa44bb
Show file tree
Hide file tree
Showing 29 changed files with 1,511 additions and 233 deletions.
46 changes: 46 additions & 0 deletions doc/dbus/bus/org.opensuse.Agama.Storage1.ISCSI.Node.bus.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node name="/org/opensuse/Agama/Storage1/iscsi_nodes/1">
<interface name="org.freedesktop.DBus.Properties">
<method name="Get">
<arg name="interface_name" direction="in" type="s"/>
<arg name="property_name" direction="in" type="s"/>
<arg name="value" direction="out" type="v"/>
</method>
<method name="Set">
<arg name="interface_name" direction="in" type="s"/>
<arg name="property_name" direction="in" type="s"/>
<arg name="val" direction="in" type="v"/>
</method>
<method name="GetAll">
<arg name="interface_name" direction="in" type="s"/>
<arg name="value" direction="out" type="a{sv}"/>
</method>
<signal name="PropertiesChanged">
<arg name="interface" type="s"/>
<arg name="changed_properties" type="a{sv}"/>
<arg name="invalidated_properties" type="as"/>
</signal>
</interface>
<interface name="org.freedesktop.DBus.Introspectable">
<method name="Introspect">
<arg name="xml_data" direction="out" type="s"/>
</method>
</interface>
<interface name="org.opensuse.Agama.Storage1.ISCSI.Node">
<method name="Login">
<arg name="options" direction="in" type="a{sv}"/>
<arg name="result" direction="out" type="u"/>
</method>
<method name="Logout">
<arg name="result" direction="out" type="u"/>
</method>
<property type="s" name="Target" access="read"/>
<property type="s" name="Address" access="read"/>
<property type="u" name="Port" access="read"/>
<property type="s" name="Interface" access="read"/>
<property type="b" name="IBFT" access="read"/>
<property type="b" name="Connected" access="read"/>
<property type="s" name="Startup" access="readwrite"/>
</interface>
</node>
1 change: 1 addition & 0 deletions doc/dbus/bus/org.opensuse.Agama.Storage1.bus.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<node name="/org/opensuse/Agama/Storage1">
<node name="iscsi_nodes" />
<node name="zfcp_controllers" />
<node name="zfcp_disks" />
<interface name="org.freedesktop.DBus.Introspectable">
Expand Down
21 changes: 21 additions & 0 deletions doc/dbus/org.opensuse.Agama.Storage1.ISCSI.Initiator.doc.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node name="/org/opensuse/Agama/Storage1">
<node name="iscsi_nodes" />
<node name="zfcp_controllers" />
<node name="zfcp_disks" />
<interface name="org.opensuse.Agama.Storage1.ISCSI.Initiator">
<method name="Discover">
<arg name="address" direction="in" type="s"/>
<arg name="port" direction="in" type="u"/>
<arg name="options" direction="in" type="a{sv}"/>
<arg name="result" direction="out" type="u"/>
</method>
<method name="Delete">
<arg name="node" direction="in" type="o"/>
<arg name="result" direction="out" type="u"/>
</method>
<property type="s" name="InitiatorName" access="readwrite"/>
<property type="b" name="IBFT" access="read"/>
</interface>
</node>
20 changes: 20 additions & 0 deletions doc/dbus/org.opensuse.Agama.Storage1.ISCSI.Node.doc.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node name="/org/opensuse/Agama/Storage1/iscsi_nodes/1">
<interface name="org.opensuse.Agama.Storage1.ISCSI.Node">
<method name="Login">
<arg name="options" direction="in" type="a{sv}"/>
<arg name="result" direction="out" type="u"/>
</method>
<method name="Logout">
<arg name="result" direction="out" type="u"/>
</method>
<property type="s" name="Target" access="read"/>
<property type="s" name="Address" access="read"/>
<property type="u" name="Port" access="read"/>
<property type="s" name="Interface" access="read"/>
<property type="b" name="IBFT" access="read"/>
<property type="b" name="Connected" access="read"/>
<property type="s" name="Startup" access="readwrite"/>
</interface>
</node>
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node name="/org/opensuse/Agama/Storage1">
<node name="iscsi_nodes" />
<node name="zfcp_controllers" />
<node name="zfcp_disks" />
<!--
Expand Down
1 change: 1 addition & 0 deletions doc/dbus/org.opensuse.Agama.Storage1.doc.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node name="/org/opensuse/Agama/Storage1">
<node name="iscsi_nodes" />
<node name="zfcp_controllers" />
<node name="zfcp_disks" />
<interface name="org.opensuse.Agama.Storage1">
Expand Down
80 changes: 79 additions & 1 deletion rust/agama-lib/src/dbus.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use std::collections::HashMap;
use zbus::zvariant::{self, OwnedValue, Value};
use zbus::zvariant::{self, OwnedObjectPath, OwnedValue, Value};

/// Nested hash to send to D-Bus.
pub type NestedHash<'a> = HashMap<&'a str, HashMap<&'a str, zvariant::Value<'a>>>;
Expand Down Expand Up @@ -43,3 +43,81 @@ where
Ok(None)
}
}

#[macro_export]
macro_rules! property_from_dbus {
($self:ident, $field:ident, $key:expr, $dbus:ident, $type:ty) => {
if let Some(v) = get_optional_property($dbus, $key)? {
$self.$field = v;
}
};
}

/// Converts a hash map containing zbus non-owned values to hash map with owned ones.
///
/// NOTE: we could follow a different approach like building our own type (e.g.
/// using the newtype idiom) and offering a better API.
///
/// * `source`: hash map containing non-onwed values ([zbus::zvariant::Value]).
pub fn to_owned_hash(source: &HashMap<&str, Value<'_>>) -> HashMap<String, OwnedValue> {
let mut owned = HashMap::new();
for (key, value) in source.iter() {
if let Ok(owned_value) = value.try_into() {
owned.insert(key.to_string(), owned_value);
}
}
owned
}

/// Extracts the object ID from the path.
///
/// TODO: should we merge this feature with the "DeviceSid"?
pub fn extract_id_from_path(path: &OwnedObjectPath) -> Result<u32, zvariant::Error> {
path.as_str()
.rsplit_once("/")
.and_then(|(_, id)| id.parse::<u32>().ok())
.ok_or_else(|| {
zvariant::Error::Message(format!("Could not extract the ID from {}", path.as_str()))
})
}

#[cfg(test)]
mod tests {
use std::collections::HashMap;

use zbus::zvariant::{self, OwnedValue, Str};

use crate::dbus::{get_optional_property, get_property};

#[test]
fn test_get_property() {
let data: HashMap<String, OwnedValue> = HashMap::from([
("Id".to_string(), (1 as u8).into()),
("Device".to_string(), Str::from_static("/dev/sda").into()),
]);
let id: u8 = get_property(&data, "Id").unwrap();
assert_eq!(id, 1);

let device: String = get_property(&data, "Device").unwrap();
assert_eq!(device, "/dev/sda".to_string());
}

#[test]
fn test_get_property_wrong_type() {
let data: HashMap<String, OwnedValue> =
HashMap::from([("Id".to_string(), (1 as u8).into())]);
let result: Result<u16, _> = get_property(&data, "Id");
assert_eq!(result, Err(zvariant::Error::IncorrectType));
}

#[test]
fn test_get_optional_property() {
let data: HashMap<String, OwnedValue> =
HashMap::from([("Id".to_string(), (1 as u8).into())]);
let id: Option<u8> = get_optional_property(&data, "Id").unwrap();
assert_eq!(id, Some(1));

let device: Option<String> = get_optional_property(&data, "Device").unwrap();
assert_eq!(device, None);
}
}
5 changes: 4 additions & 1 deletion rust/agama-lib/src/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ pub mod proxies;
mod settings;
mod store;

pub use client::StorageClient;
pub use client::{
iscsi::{ISCSIAuth, ISCSIClient, ISCSIInitiator, ISCSINode},
StorageClient,
};
pub use settings::StorageSettings;
pub use store::StorageStore;
1 change: 1 addition & 0 deletions rust/agama-lib/src/storage/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use zbus::fdo::ObjectManagerProxy;
use zbus::names::{InterfaceName, OwnedInterfaceName};
use zbus::zvariant::{OwnedObjectPath, OwnedValue};
use zbus::Connection;
pub mod iscsi;

type DBusObject = (
OwnedObjectPath,
Expand Down
Loading

0 comments on commit 7aa44bb

Please sign in to comment.