Skip to content

Commit

Permalink
feat(storage): use proper space policy
Browse files Browse the repository at this point in the history
If the space policy is not provided by the model:
  - Use 'keep' for a drive added for booting.
  - Use the default space policy defined by the product in other cases.
  • Loading branch information
joseivanlopez committed Dec 20, 2024
1 parent cbf0d39 commit a108175
Show file tree
Hide file tree
Showing 6 changed files with 282 additions and 204 deletions.
9 changes: 7 additions & 2 deletions service/lib/agama/storage/config_conversions/from_model.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,22 +28,27 @@ module ConfigConversions
# Config conversion from model according to the JSON schema.
class FromModel
# @param model_json [Hash]
def initialize(model_json)
# @param product_config [Agama::Config, nil]
def initialize(model_json, product_config: nil)
@model_json = model_json
@product_config = product_config || Agama::Config.new
end

# Performs the conversion from model according to the JSON schema.
#
# @return [Storage::Config]
def convert
# TODO: Raise error if model_json does not match the JSON schema.
FromModelConversions::Config.new(model_json).convert
FromModelConversions::Config.new(model_json, product_config).convert
end

private

# @return [Hash]
attr_reader :model_json

# @return [Agama::Config]
attr_reader :product_config
end
end
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,18 @@ module ConfigConversions
module FromModelConversions
# Config conversion from model according to the JSON schema.
class Config < Base
# @param model_json [Hash]
# @param product_config [Agama::Config]
def initialize(model_json, product_config)
super(model_json)
@product_config = product_config
end

private

# @return [Agama::Config]
attr_reader :product_config

# @see Base
# @return [Storage::Config]
def default_config
Expand Down Expand Up @@ -79,7 +89,7 @@ def convert_drives
# @param drive_model [Hash]
# @return [Configs::Drive]
def convert_drive(drive_model)
FromModelConversions::Drive.new(drive_model).convert
FromModelConversions::Drive.new(drive_model, product_config).convert
end

# Conversion for the boot device alias.
Expand Down Expand Up @@ -118,6 +128,7 @@ def drive_models
@drive_models = calculate_drive_models
end

# @see #drive_models
# @return [Array<Hash>, nil]
def calculate_drive_models
@calculated_drive_models = true
Expand All @@ -126,7 +137,10 @@ def calculate_drive_models
return if models.nil? && !missing_boot_drive?

models ||= []
models << { name: boot_device_name } if missing_boot_drive?
# The main use case for using a specific device for booting is to share the boot
# partition with other installed systems. So let's ensure the partitions are not deleted
# by setting the "keep" space policy.
models << { name: boot_device_name, spacePolicy: "keep" } if missing_boot_drive?
models
end

Expand All @@ -140,6 +154,7 @@ def missing_boot_drive?
@missing_boot_drive ||= calculate_missing_boot_drive
end

# @see #missing_boot_drive?
# @return [Boolean]
def calculate_missing_boot_drive
@calculated_missing_boot_drive = true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,23 @@ module ConfigConversions
module FromModelConversions
# Drive conversion from model according to the JSON schema.
class Drive < Base
private

include WithFilesystem
include WithPtableType
include WithPartitions
include WithSearch

# @param model_json [Hash]
# @param product_config [Agama::Config]
def initialize(model_json, product_config)
super(model_json)
@product_config = product_config
end

private

# @return [Agama::Config]
attr_reader :product_config

alias_method :drive_model, :model_json

# @see Base
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ module FromModelConversions
module WithPartitions
# @return [Array<Configs::Partition>]
def convert_partitions
space_policy = model_json[:spacePolicy]
# If the model does not indicate a space policy, then the space policy defined by the
# product is applied.
space_policy = model_json[:spacePolicy] || product_config.space_policy

case space_policy
when "keep"
Expand All @@ -55,6 +57,8 @@ def partition_configs
partitions.map { |p| convert_partition(p) }
end

# Partitions with any usage (format, mount, etc).
#
# @return [Array<Configs::Partition>]
def used_partition_configs
used_partitions.map { |p| convert_partition(p) }
Expand All @@ -67,35 +71,37 @@ def partitions

# @return [Array<Hash>]
def used_partitions
partitions.select { |p| used_partition?(p) }
partitions.reject { |p| space_policy_partition?(p) }
end

# Whether the partition only represents a space policy action.
#
# @param partition_model [Hash]
# @return [Boolean]
def used_partition?(partition_model)
new_partition?(partition_model) || reused_partition?(partition_model)
def space_policy_partition?(partition_model)
partition_model[:delete] ||
partition_model[:deleteIfNeeded] ||
resize_action_partition?(partition_model)
end

# @param partition_model [Hash]
# @return [Boolean]
def new_partition?(partition_model)
partition_model[:name].nil? &&
!partition_model[:delete] &&
!partition_model[:deleteIfNeeded]
def resize_action_partition?(partition_model)
return false if partition_model[:name].nil? || any_usage?(partition_model)

return true if partition_model[:resizeIfNeeded]

partition_model[:size] && !partition_model.dig(:size, :default)
end

# TODO: improve check by ensuring the alias is referenced by other device.
#
# @param partition_model [Hash]
# @return [Boolean]
def reused_partition?(partition_model)
# TODO: improve check by ensuring the alias is referenced by other device.
any_usage = partition_model[:mountPath] ||
def any_usage?(partition_model)
partition_model[:mountPath] ||
partition_model[:filesystem] ||
partition_model[:alias]

any_usage &&
partition_model[:name] &&
!partition_model[:delete] &&
!partition_model[:deleteIfNeeded]
end

# @return [Configs::Partition]
Expand Down
5 changes: 4 additions & 1 deletion service/lib/agama/storage/proposal.rb
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,10 @@ def calculate_from_json(source_json)
# @param model_json [Hash] Source config model according to the JSON schema.
# @return [Boolean] Whether the proposal successes.
def calculate_from_model(model_json)
config = ConfigConversions::FromModel.new(model_json).convert
config = ConfigConversions::FromModel
.new(model_json, product_config: product_config)
.convert

calculate_agama(config)
end

Expand Down
Loading

0 comments on commit a108175

Please sign in to comment.