Skip to content

Commit

Permalink
wip API for getting a solved model
Browse files Browse the repository at this point in the history
  • Loading branch information
joseivanlopez committed Jan 31, 2025
1 parent 6cc7c1f commit 9930da4
Show file tree
Hide file tree
Showing 6 changed files with 78 additions and 2 deletions.
9 changes: 8 additions & 1 deletion rust/agama-lib/src/storage/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ impl<'a> StorageClient<'a> {
Ok(settings)
}

/// Set the storage config according to the JSON schema
/// Set the storage config model according to the JSON schema
pub async fn set_config_model(&self, model: Box<RawValue>) -> Result<u32, ServiceError> {
Ok(self
.storage_proxy
Expand All @@ -174,6 +174,13 @@ impl<'a> StorageClient<'a> {
Ok(config_model)
}

/// Solves the storage config model
pub async fn solve_config_model(&self, model: &str) -> Result<Box<RawValue>, ServiceError> {
let serialized_solved_model = self.storage_proxy.solve_config_model(model).await?;
let solved_model = serde_json::from_str(serialized_solved_model.as_str()).unwrap();
Ok(solved_model)
}

pub async fn calculate(&self, settings: ProposalSettingsPatch) -> Result<u32, ServiceError> {
let map: HashMap<&str, zbus::zvariant::Value> = settings.into();
let options: HashMap<&str, &zbus::zvariant::Value> =
Expand Down
3 changes: 3 additions & 0 deletions rust/agama-lib/src/storage/proxies/storage1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,9 @@ pub trait Storage1 {
/// Get the storage config model according to the JSON schema
fn get_config_model(&self) -> zbus::Result<String>;

/// Solve a storage config model
fn solve_config_model(&self, model: &str) -> zbus::Result<String>;

/// DeprecatedSystem property
#[zbus(property)]
fn deprecated_system(&self) -> zbus::Result<bool>;
Expand Down
2 changes: 1 addition & 1 deletion rust/agama-server/src/software/web.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use tokio_stream::{Stream, StreamExt};

use super::license::{License, LicenseContent};
use super::license::License;

#[derive(Clone)]
struct SoftwareState<'a> {
Expand Down
32 changes: 32 additions & 0 deletions rust/agama-server/src/storage/web.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ pub async fn storage_service(dbus: zbus::Connection) -> Result<Router, ServiceEr
let router = Router::new()
.route("/config", put(set_config).get(get_config))
.route("/config_model", put(set_config_model).get(get_config_model))
.route("/config_model/solve", get(solve_config_model))
.route("/probe", post(probe))
.route("/reprobe", post(reprobe))
.route("/devices/dirty", get(devices_dirty))
Expand Down Expand Up @@ -235,6 +236,37 @@ async fn set_config_model(
Ok(Json(()))
}

/// Solves a storage config model.
#[utoipa::path(
get,
path = "/config_model/solve",
context_path = "/api/storage",
params(SolveModelQuery),
operation_id = "solve_storage_config_model",
responses(
(status = 200, description = "Solve the storage config model", body = String),
(status = 400, description = "The D-Bus service could not perform the action")
)
)]
async fn solve_config_model(
State(state): State<StorageState<'_>>,
query: Query<SolveModelQuery>,
) -> Result<Json<Box<RawValue>>, Error> {
let solved_model = state
.client
.solve_config_model(query.model.as_str())
.await
.map_err(Error::Service)?;
Ok(Json(solved_model))
}

#[derive(Deserialize, utoipa::IntoParams)]
struct SolveModelQuery {
/// Serialized config model.
model: String,
}


/// Probes the storage devices.
#[utoipa::path(
post,
Expand Down
15 changes: 15 additions & 0 deletions service/lib/agama/dbus/storage/manager.rb
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,18 @@ def recover_model
JSON.pretty_generate(json)
end

# Solves the given serialized config model.
#
# @param serialized_model [String] Serialized storage config model.
# @return [String] Serialized solved model.
def solve_model(serialized_model)
logger.info("Solving storage config model from D-Bus: #{serialized_model}")

model_json = JSON.parse(serialized_model, symbolize_names: true)
solved_model_json = proposal.solve_model(model_json)
JSON.pretty_generate(solved_model_json)
end

def install
busy_while { backend.install }
end
Expand All @@ -173,6 +185,9 @@ def deprecated_system
busy_while { apply_config_model(serialized_model) }
end
dbus_method(:GetConfigModel, "out serialized_model:s") { recover_model }
dbus_method(:SolveConfigModel, "in sparse_model:s, out solved_model:s") do |sparse_model|
solve_model(sparse_model)
end
dbus_method(:Install) { install }
dbus_method(:Finish) { finish }
dbus_reader(:deprecated_system, "b")
Expand Down
19 changes: 19 additions & 0 deletions service/lib/agama/storage/proposal.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
require "agama/issue"
require "agama/storage/actions_generator"
require "agama/storage/config_conversions"
require "agama/storage/config_solver"
require "agama/storage/proposal_settings"
require "agama/storage/proposal_strategies"
require "json"
Expand Down Expand Up @@ -100,6 +101,24 @@ def model_json
ConfigConversions::ToModel.new(config).convert
end

# Solves a given model.
#
# @param model_json [Hash] Config model according to the JSON schema.
# @param [Hash, nil] Solved config model or nil if the model cannot be solved yet.
def solve_model(model_json)
return unless storage_manager.probed?

config = ConfigConversions::FromModel
.new(model_json, product_config: product_config)
.convert

ConfigSolver
.new(product_config, storage_manager.probed, disk_analyzer: disk_analyzer)
.solve(config)

ConfigConversions::ToModel.new(config).convert
end

# Calculates a new proposal using the given JSON.
#
# @raise If the JSON is not valid.
Expand Down

0 comments on commit 9930da4

Please sign in to comment.