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

feat(storage): allow selecting space policy #1791

Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
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
4 changes: 4 additions & 0 deletions doc/dbus/bus/org.opensuse.Agama.Storage1.bus.xml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@
<method name="GetConfig">
<arg name="serialized_config" direction="out" type="s"/>
</method>
<method name="SetConfigModel">
<arg name="serialized_model" direction="in" type="s"/>
<arg name="result" direction="out" type="u"/>
</method>
<method name="GetConfigModel">
<arg name="serialized_model" direction="out" type="s"/>
</method>
Expand Down
25 changes: 25 additions & 0 deletions doc/dbus/org.opensuse.Agama.Storage1.doc.xml
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,31 @@
-->
<arg name="serialized_config" direction="out" type="s"/>
</method>
<!--
Sets the storage config model.
-->
<method name="SetConfigModel">
<!--
E.g.,
{
"drives": [
{
"name": "/dev/vda",
"partitions": [
{ "mountPath": "/" }
]
}
]
}
-->
<arg name="serialized_model" direction="in" type="s"/>
<!--
Whether the proposal was correctly calculated with the given config model:
0: success
1: failure
-->
<arg name="result" direction="out" type="u"/>
</method>
<!--
Gets the storage config model.
-->
Expand Down
8 changes: 8 additions & 0 deletions rust/agama-lib/src/storage/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,14 @@ impl<'a> StorageClient<'a> {
Ok(settings)
}

/// Set the storage config according to the JSON schema
pub async fn set_config_model(&self, model: Box<RawValue>) -> Result<u32, ServiceError> {
Ok(self
.storage_proxy
.set_config_model(serde_json::to_string(&model).unwrap().as_str())
.await?)
}

/// Get the storage config model according to the JSON schema
pub async fn get_config_model(&self) -> Result<Box<RawValue>, ServiceError> {
let serialized_config_model = self.storage_proxy.get_config_model().await?;
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 @@ -62,6 +62,9 @@ pub trait Storage1 {
/// Get the current storage config according to the JSON schema
fn get_config(&self) -> zbus::Result<String>;

/// Set the storage config model according to the JSON schema
fn set_config_model(&self, model: &str) -> zbus::Result<u32>;

/// Get the storage config model according to the JSON schema
fn get_config_model(&self) -> zbus::Result<String>;

Expand Down
45 changes: 36 additions & 9 deletions rust/agama-server/src/storage/web.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ pub async fn storage_service(dbus: zbus::Connection) -> Result<Router, ServiceEr
let state = StorageState { client };
let router = Router::new()
.route("/config", put(set_config).get(get_config))
.route("/config_model", get(get_config_model))
.route("/config_model", put(set_config_model).get(get_config_model))
.route("/probe", post(probe))
.route("/devices/dirty", get(devices_dirty))
.route("/devices/system", get(system_devices))
Expand Down Expand Up @@ -157,6 +157,32 @@ async fn get_config(State(state): State<StorageState<'_>>) -> Result<Json<Storag
Ok(Json(settings))
}

/// Sets the storage configuration.
///
/// * `state`: service state.
/// * `config`: storage configuration.
#[utoipa::path(
put,
path = "/config",
context_path = "/api/storage",
operation_id = "set_storage_config",
responses(
(status = 200, description = "Set the storage configuration"),
(status = 400, description = "The D-Bus service could not perform the action")
)
)]
async fn set_config(
State(state): State<StorageState<'_>>,
Json(settings): Json<StorageSettings>,
) -> Result<Json<()>, Error> {
let _status: u32 = state
.client
.set_config(settings)
.await
.map_err(Error::Service)?;
Ok(Json(()))
}

/// Returns the storage config model.
///
/// * `state` : service state.
Expand All @@ -181,27 +207,28 @@ async fn get_config_model(
Ok(Json(config_model))
}

/// Sets the storage configuration.
/// Sets the storage config model.
///
/// * `state`: service state.
/// * `config`: storage configuration.
/// * `config_model`: storage config model.
#[utoipa::path(
put,
path = "/config",
request_body = String,
path = "/config_model",
context_path = "/api/storage",
operation_id = "set_storage_config",
operation_id = "set_storage_config_model",
responses(
(status = 200, description = "Set the storage configuration"),
(status = 200, description = "Set the storage config model"),
(status = 400, description = "The D-Bus service could not perform the action")
)
)]
async fn set_config(
async fn set_config_model(
State(state): State<StorageState<'_>>,
Json(settings): Json<StorageSettings>,
Json(model): Json<Box<RawValue>>,
) -> Result<Json<()>, Error> {
let _status: u32 = state
.client
.set_config(settings)
.set_config_model(model)
.await
.map_err(Error::Service)?;
Ok(Json(()))
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 @@ -119,6 +119,18 @@ def recover_config
JSON.pretty_generate(json)
end

# Applies the given serialized config model according to the JSON schema.
#
# @param serialized_model [String] Serialized storage config model.
# @return [Integer] 0 success; 1 error
def apply_config_model(serialized_model)
logger.info("Setting storage config model from D-Bus: #{serialized_model}")

model_json = JSON.parse(serialized_model, symbolize_names: true)
proposal.calculate_from_model(model_json)
proposal.success? ? 0 : 1
end

# Gets and serializes the storage config model.
#
# @return [String]
Expand Down Expand Up @@ -148,6 +160,9 @@ def deprecated_system
busy_while { apply_config(serialized_config) }
end
dbus_method(:GetConfig, "out serialized_config:s") { recover_config }
dbus_method(:SetConfigModel, "in serialized_model:s, out result:u") do |serialized_model|
busy_while { apply_config_model(serialized_model) }
end
dbus_method(:GetConfigModel, "out serialized_model:s") { recover_model }
dbus_method(:Install) { install }
dbus_method(:Finish) { finish }
Expand Down
1 change: 1 addition & 0 deletions service/lib/agama/storage/config_conversions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
# find current contact information at www.suse.com.

require "agama/storage/config_conversions/from_json"
require "agama/storage/config_conversions/from_model"
require "agama/storage/config_conversions/to_json"
require "agama/storage/config_conversions/to_model"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,17 @@ module ConfigConversions
module FromJSONConversions
# Base class for conversions from JSON hash according to schema.
class Base
# @param config_json [Hash]
def initialize(config_json)
@config_json = config_json
end

# Performs the conversion from Hash according to the JSON schema.
#
# @param config [Object] A {Config} or any of its configs from {Storage::Configs}.
# @return [Object] A {Config} or any its configs from {Storage::Configs}.
def convert(config)
def convert
config = default_config

conversions.each do |property, value|
next if value.nil?

Expand All @@ -45,8 +47,16 @@ def convert(config)

private

# @return [Hash]
attr_reader :config_json

# Default config object (defined by derived classes).
#
# @return [Object]
def default_config
raise "Undefined default config"
end

# Values to apply to the config.
#
# @return [Hash] e.g., { name: "/dev/vda" }.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,16 @@ module ConfigConversions
module FromJSONConversions
# Boot conversion from JSON hash according to schema.
class Boot < Base
# @see Base#convert
# @return [Configs::Boot]
def convert
super(Configs::Boot.new)
end

private

alias_method :boot_json, :config_json

# @see Base
# @return [Configs::Boot]
def default_config
Configs::Boot.new
end

# @see Base#conversions
# @return [Hash]
def conversions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,16 @@ module ConfigConversions
module FromJSONConversions
# Btrfs conversion from JSON hash according to schema.
class Btrfs < Base
# @see Base#convert
# @return [Configs::Btrfs]
def convert
super(Configs::Btrfs.new)
end

private

alias_method :btrfs_json, :config_json

# @see Base
# @return [Configs::Btrfs]
def default_config
Configs::Btrfs.new
end

# @see Base#conversions
# @return [Hash]
def conversions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,14 @@ module ConfigConversions
module FromJSONConversions
# Config conversion from JSON hash according to schema.
class Config < Base
# @see Base#convert
private

# @see Base
# @return [Config]
def convert
super(Storage::Config.new)
def default_config
Storage::Config.new
end

private

# @see Base#conversions
# @return [Hash]
def conversions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,22 +33,22 @@ module ConfigConversions
module FromJSONConversions
# Drive conversion from JSON hash according to schema.
class Drive < Base
private

include WithSearch
include WithEncryption
include WithFilesystem
include WithPtableType
include WithPartitions

# @see Base#convert
alias_method :drive_json, :config_json

# @see Base
# @return [Configs::Drive]
def convert
super(Configs::Drive.new)
def default_config
Configs::Drive.new
end

private

alias_method :drive_json, :config_json

# @see Base#conversions
# @return [Hash]
def conversions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,16 +30,16 @@ module ConfigConversions
module FromJSONConversions
# Encryption conversion from JSON hash according to schema.
class Encryption < Base
# @see Base#convert
# @return [Configs::Encryption]
def convert
super(Configs::Encryption.new)
end

private

alias_method :encryption_json, :config_json

# @see Base
# @return [Configs::Encryption]
def default_config
Configs::Encryption.new
end

# @see Base#conversions
# @return [Hash]
def conversions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,16 +30,16 @@ module ConfigConversions
module FromJSONConversions
# Filesystem conversion from JSON hash according to schema.
class Filesystem < Base
# @see Base#convert
# @return [Configs::Filesystem]
def convert
super(Configs::Filesystem.new)
end

private

alias_method :filesystem_json, :config_json

# @see Base
# @return [Configs::Filesystem]
def default_config
Configs::Filesystem.new
end

# @see Base#conversions
# @return [Hash]
def conversions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,16 @@ module ConfigConversions
module FromJSONConversions
# Filesystem type conversion from JSON hash according to schema.
class FilesystemType < Base
# @see Base#convert
# @return [Configs::FilesystemType]
def convert
super(Configs::FilesystemType.new)
end

private

alias_method :filesystem_type_json, :config_json

# @see Base
# @return [Configs::FilesystemType]
def default_config
Configs::FilesystemType.new
end

# @see Base#conversions
# @return [Hash]
def conversions
Expand Down
Loading
Loading