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

Storage AutoYaST backward compatibility #1284

Merged
merged 15 commits into from
Jun 6, 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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion rust/agama-derive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ enum SettingKind {
Collection,
/// The value is another FooSettings, use `#[settings(nested)]`.
Nested,
Ignored,
}

/// Represents a setting and its configuration
Expand Down Expand Up @@ -176,7 +177,7 @@ fn expand_merge_fn(settings: &SettingFieldsList) -> TokenStream2 {
let arms = settings.all().iter().map(|s| {
let field_name = &s.ident;
match s.kind {
SettingKind::Scalar => quote! {
SettingKind::Scalar | SettingKind::Ignored => quote! {
Copy link
Contributor

Choose a reason for hiding this comment

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

Sadly, this code will go away in a matter of hours or days 😅 (we are dropping agama-derive and agama-settings).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ces't la vie.

if let Some(value) = &other.#field_name {
self.#field_name = Some(value.clone())
}
Expand Down Expand Up @@ -274,6 +275,10 @@ fn parse_setting_fields(fields: Vec<&syn::Field>) -> SettingFieldsList {
setting.kind = SettingKind::Nested;
}

if meta.path.is_ident("ignored") {
setting.kind = SettingKind::Ignored;
}

if meta.path.is_ident("flatten") {
setting.flatten = true;
}
Expand Down
2 changes: 1 addition & 1 deletion rust/agama-lib/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jsonschema = { version = "0.16.1", default-features = false }
log = "0.4"
reqwest = { version = "0.12.4", features = ["json", "cookies"] }
serde = { version = "1.0.152", features = ["derive"] }
serde_json = "1.0.94"
serde_json = { version = "1.0.94", features = ["raw_value"] }
serde_repr = "0.1.18"
tempfile = "3.4.0"
thiserror = "1.0.39"
Expand Down
17 changes: 14 additions & 3 deletions rust/agama-lib/src/install_settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use crate::{
};
use agama_settings::Settings;
use serde::{Deserialize, Serialize};
use serde_json::value::RawValue;
use std::default::Default;
use std::str::FromStr;

Expand All @@ -22,6 +23,8 @@ pub enum Scope {
Software,
/// Storage settings
Storage,
/// Storage AutoYaST settings (for backward compatibility with AutoYaST profiles)
StorageAutoyast,
/// Network settings
Network,
/// Product settings
Expand All @@ -34,13 +37,14 @@ impl Scope {
/// Returns known scopes
///
// TODO: we can rely on strum so we do not forget to add them
pub fn all() -> [Scope; 6] {
pub fn all() -> [Scope; 7] {
[
Scope::Localization,
Scope::Network,
Scope::Product,
Scope::Software,
Scope::Storage,
Scope::StorageAutoyast,
Scope::Users,
]
}
Expand All @@ -49,6 +53,9 @@ impl Scope {
impl FromStr for Scope {
type Err = &'static str;

// Do not generate the StorageAutoyast scope. Note that storage AutoYaST settings will only be
// temporary available for importing an AutoYaST profile. But CLI should not allow modifying the
// storate AutoYaST settings.
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"users" => Ok(Self::Users),
Expand Down Expand Up @@ -81,6 +88,9 @@ pub struct InstallSettings {
#[serde(default)]
#[settings(nested)]
pub storage: Option<StorageSettings>,
#[serde(default, rename = "legacyAutoyastStorage")]
#[settings(ignored)]
pub storage_autoyast: Option<Box<RawValue>>,
#[serde(default)]
#[settings(nested)]
pub network: Option<NetworkSettings>,
Expand All @@ -95,11 +105,12 @@ impl InstallSettings {
if self.user.is_some() {
scopes.push(Scope::Users);
}

if self.storage.is_some() {
scopes.push(Scope::Storage);
}

if self.storage_autoyast.is_some() {
scopes.push(Scope::StorageAutoyast);
}
if self.software.is_some() {
scopes.push(Scope::Software);
}
Expand Down
2 changes: 1 addition & 1 deletion rust/agama-lib/src/software/store.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//! Implements the store for the storage settings.
//! Implements the store for the software settings.

use std::collections::HashMap;

Expand Down
2 changes: 2 additions & 0 deletions rust/agama-lib/src/storage.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
//! Implements support for handling the storage settings

mod autoyast;
pub mod client;
pub mod model;
pub mod proxies;
mod settings;
mod store;

pub use autoyast::store::StorageAutoyastStore;
pub use client::{
iscsi::{ISCSIAuth, ISCSIClient, ISCSIInitiator, ISCSINode},
StorageClient,
Expand Down
2 changes: 2 additions & 0 deletions rust/agama-lib/src/storage/autoyast.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
//! Implements support for handling the storage AutoYaST settings
pub mod store;
26 changes: 26 additions & 0 deletions rust/agama-lib/src/storage/autoyast/store.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//! Implements the store for the storage AutoYaST settings.

use crate::error::ServiceError;
use crate::storage::StorageClient;
use zbus::Connection;

/// Stores the storage AutoYaST settings to the D-Bus service.
///
/// NOTE: The AutoYaST settings are not loaded from D-Bus because they cannot be modified. The only
/// way of using the storage AutoYaST settings is by loading a JSON config file.
pub struct StorageAutoyastStore<'a> {
storage_client: StorageClient<'a>,
}

impl<'a> StorageAutoyastStore<'a> {
pub async fn new(connection: Connection) -> Result<StorageAutoyastStore<'a>, ServiceError> {
Ok(Self {
storage_client: StorageClient::new(connection).await?,
})
}

pub async fn store(&self, settings: &str) -> Result<(), ServiceError> {
self.storage_client.calculate_autoyast(settings).await?;
Ok(())
}
}
4 changes: 4 additions & 0 deletions rust/agama-lib/src/storage/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,10 @@ impl<'a> StorageClient<'a> {
Ok(self.calculator_proxy.calculate(settings.into()).await?)
}

pub async fn calculate_autoyast(&self, settings: &str) -> Result<u32, ServiceError> {
Ok(self.calculator_proxy.calculate_autoyast(settings).await?)
}

/// Calculates a new proposal with the given settings.
pub async fn calculate(&self, settings: &StorageSettings) -> Result<u32, ServiceError> {
let mut dbus_settings: HashMap<&str, zbus::zvariant::Value<'_>> = HashMap::new();
Expand Down
11 changes: 7 additions & 4 deletions rust/agama-lib/src/storage/proxies.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,15 @@ trait Storage1 {
default_path = "/org/opensuse/Agama/Storage1"
)]
trait ProposalCalculator {
/// Calculate method
/// Calculate guided proposal
fn calculate(
&self,
settings: std::collections::HashMap<&str, zbus::zvariant::Value<'_>>,
) -> zbus::Result<u32>;

/// Calculate AutoYaST proposal
fn calculate_autoyast(&self, settings: &str) -> zbus::Result<u32>;

/// DefaultVolume method
fn default_volume(
&self,
Expand All @@ -53,9 +56,9 @@ trait ProposalCalculator {
#[dbus_proxy(property)]
fn product_mount_points(&self) -> zbus::Result<Vec<String>>;

/// Result property
#[dbus_proxy(property)]
fn result(&self) -> zbus::Result<zbus::zvariant::OwnedObjectPath>;
/// Proposal result
fn result(&self)
-> zbus::Result<std::collections::HashMap<String, zbus::zvariant::OwnedValue>>;
}

#[dbus_proxy(
Expand Down
20 changes: 17 additions & 3 deletions rust/agama-lib/src/store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ use crate::error::ServiceError;
use crate::install_settings::{InstallSettings, Scope};
use crate::{
localization::LocalizationStore, network::NetworkStore, product::ProductStore,
software::SoftwareStore, storage::StorageStore, users::UsersStore,
software::SoftwareStore, storage::StorageAutoyastStore, storage::StorageStore,
users::UsersStore,
};
use zbus::Connection;

Expand All @@ -21,6 +22,7 @@ pub struct Store<'a> {
product: ProductStore<'a>,
software: SoftwareStore<'a>,
storage: StorageStore<'a>,
storage_autoyast: StorageAutoyastStore<'a>,
localization: LocalizationStore<'a>,
}

Expand All @@ -35,11 +37,16 @@ impl<'a> Store<'a> {
network: NetworkStore::new(http_client).await?,
product: ProductStore::new(connection.clone()).await?,
software: SoftwareStore::new(connection.clone()).await?,
storage: StorageStore::new(connection).await?,
storage: StorageStore::new(connection.clone()).await?,
storage_autoyast: StorageAutoyastStore::new(connection).await?,
})
}

/// Loads the installation settings from the D-Bus service
/// Loads the installation settings from the D-Bus service.
///
/// NOTE: The storage AutoYaST settings cannot be loaded because they cannot be modified. The
/// ability of using the storage AutoYaST settings from a JSON config file is temporary and it
/// will be removed in the future.
pub async fn load(&self, only: Option<Vec<Scope>>) -> Result<InstallSettings, ServiceError> {
let scopes = match only {
Some(scopes) => scopes,
Expand All @@ -50,6 +57,7 @@ impl<'a> Store<'a> {
if scopes.contains(&Scope::Network) {
settings.network = Some(self.network.load().await?);
}

if scopes.contains(&Scope::Storage) {
settings.storage = Some(self.storage.load().await?);
}
Expand Down Expand Up @@ -97,6 +105,12 @@ impl<'a> Store<'a> {
if let Some(storage) = &settings.storage {
self.storage.store(storage).await?;
}
if let Some(storage_autoyast) = &settings.storage_autoyast {
// Storage scope has precedence.
if settings.storage.is_none() {
self.storage_autoyast.store(storage_autoyast.get()).await?;
}
}
Ok(())
}
}
6 changes: 6 additions & 0 deletions rust/package/agama.changes
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
-------------------------------------------------------------------
Wed Jun 5 13:53:59 UTC 2024 - José Iván López González <jlopez@suse.com>

- Process the legacyAutoyastStorage section of the profile
(gh#openSUSE/agama#1284).

-------------------------------------------------------------------
Mon Jun 3 07:49:16 UTC 2024 - Josef Reidinger <jreidinger@suse.com>

Expand Down
52 changes: 1 addition & 51 deletions service/lib/agama/dbus/clients/storage.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# frozen_string_literal: true

# Copyright (c) [2022-2023] SUSE LLC
# Copyright (c) [2022-2024] SUSE LLC
#
# All Rights Reserved.
#
Expand Down Expand Up @@ -36,12 +36,6 @@ class Storage < Base
STORAGE_IFACE = "org.opensuse.Agama.Storage1"
private_constant :STORAGE_IFACE

PROPOSAL_CALCULATOR_IFACE = "org.opensuse.Agama.Storage1.Proposal.Calculator"
private_constant :PROPOSAL_CALCULATOR_IFACE

PROPOSAL_IFACE = "org.opensuse.Agama.Storage1.Proposal"
private_constant :PROPOSAL_IFACE

def service_name
@service_name ||= "org.opensuse.Agama.Storage1"
end
Expand All @@ -66,56 +60,12 @@ def finish
dbus_object.Finish
end

# Devices available for the installation
#
# @return [Array<String>] name of the devices
def available_devices
dbus_object[PROPOSAL_CALCULATOR_IFACE]["AvailableDevices"]
.map(&:first)
end

# Devices selected for the installation
#
# @return [Array<String>] name of the devices
def candidate_devices
return [] unless dbus_proposal

dbus_proposal[PROPOSAL_IFACE]["CandidateDevices"]
end

# Actions to perform in the storage devices
#
# @return [Array<String>]
def actions
return [] unless dbus_proposal

dbus_proposal[PROPOSAL_IFACE]["Actions"].map do |a|
a["Text"]
end
end

# Calculates the storage proposal with the given devices
#
# @param candidate_devices [Array<String>] name of the new candidate devices
def calculate(candidate_devices)
calculator_iface = dbus_object[PROPOSAL_CALCULATOR_IFACE]
calculator_iface.Calculate({ "CandidateDevices" => candidate_devices })
end

private

# @return [::DBus::Object]
def dbus_object
@dbus_object ||= service["/org/opensuse/Agama/Storage1"].tap(&:introspect)
end

# @return [::DBus::Object, nil]
def dbus_proposal
path = dbus_object["org.opensuse.Agama.Storage1.Proposal.Calculator"]["Result"]
return nil if path == "/"

service.object(path).tap(&:introspect)
end
end
end
end
Expand Down
Loading
Loading