Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
joseivanlopez committed Sep 25, 2024
1 parent 0a2922d commit 90a22bc
Show file tree
Hide file tree
Showing 2 changed files with 592 additions and 17 deletions.
197 changes: 180 additions & 17 deletions service/lib/agama/storage/config_json_solver.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,28 +19,57 @@
# To contact SUSE LLC about this file by physical or electronic mail, you may
# find current contact information at www.suse.com.

require "agama/config"
require "agama/storage/volume_templates_builder"

module Agama
module Storage
# Class for solving a storage config.
# Class for solving a storage JSON config.
#
# A storage JSON config can contain keywords like "default" or "mandatory" for automatically
# generating partitions or logical volumes according to the product definition. That keywords
# are solved by replacing them by the corresponding configs. The solver takes into account other
# paths already present in the rest of the config.
#
# @example
# config_json = {
# drives: [
# "default",
# {
# filesystem: { path: "swap" }
# }
# ]
# }
#
# It assigns proper devices and size values according to the product and the system.
# ConfigJSONSolver.new(product_config).solve(config_json)
# config_json # => {
# # drives: [
# # {
# # filesystem: { path: "/" }
# # },
# # {
# # filesystem: { path: "/home" }
# # },
# # {
# # filesystem: { path: "swap" }
# # }
# # ]
# # }
class ConfigJSONSolver
# @param devicegraph [Y2Storage::Devicegraph]
# @param product_config [Agama::Config]
def initialize(product_config)
@product_config = product_config
def initialize(product_config = nil)
@product_config = product_config || Agama::Config.new
end

# Solves all the search and size configs within a given config.
# Solves all the keywords within a given config.
#
# @note The config object is modified.
# @note The config_json object is modified.
#
# @param config [Config]
# @param config_json [Hash]
def solve(config_json)
@config_json = config_json

solve_partitions
solve_logical_volumes
solve_keywords
end

private
Expand All @@ -51,33 +80,161 @@ def solve(config_json)
# @return [Agama::Config]
attr_reader :product_config

def solve_partitions
configs_with_partitions_keyword.each { |c| solve_partitions_keyword(c) }
def solve_keywords
drives_with_keyword.each { |c| solve_partitions_keyword(c) }
volume_groups_with_keyword.each { |c| solve_logical_volumes_keyword(c) }
end

# @param config [Hash]
def solve_partitions_keyword(config)
partitions = config[:partitions]
return unless partitions

solve_keyword(partitions)
end

# @param config [Hash]
def solve_logical_volumes_keyword(config)
logical_volumes = config[:logicalVolumes]
return unless logical_volumes

solve_keyword(logical_volumes)
end

# @param configs [Array<Hash>]
def solve_keyword(configs)
if with_default_keyword?(configs)
solve_default_keyword(configs)
elsif with_mandatory_keyword?(configs)
solve_mandatory_keyword(configs)
end
end

# @param configs [Array<Hash>]
def solve_default_keyword(configs)
configs.delete("default")
configs.delete("mandatory")
configs.concat(missing_default_configs)
end

# @param configs [Array<Hash>]
def solve_mandatory_keyword(configs)
configs.delete("mandatory")
configs.concat(missing_mandatory_configs)
end

def solve_logical_volumes
configs_with_logical_volumes_keyword.each { |c| solve_logical_volumes_keyword(c) }
# @return [Array<Hash>]
def missing_default_configs
missing_default_paths.map { |p| volume_config(p) }
end

def configs_with_partitions_keyword
configs = drive_configs
# @return [Array<String>]
def missing_default_paths
default_paths - current_paths
end

def explicit_paths
# @return [Array<String>]
def default_paths
product_config.data.dig("storage", "volumes") || []
end

# @return [Array<String>]
def current_paths
configs_with_filesystem
.select { |c| c.is_a?(Hash) }
.map { |c| c.dig(:filesystem, :path) }
.compact
end

# @return [Array<Hash>]
def missing_mandatory_configs
missing_mandatory_paths.map { |p| volume_config(p) }
end

# @return [Array<String>]
def missing_mandatory_paths
mandatory_paths - current_paths
end

# @return [Array<String>]
def mandatory_paths
default_paths.select { |p| mandatory_path?(p) }
end

# @param path [String]
# @return [Volume]
def mandatory_path?(path)
volume_builder.for(path).outline.required?
end

# @param path [String]
# @return [Hash]
def volume_config(path)
{ filesystem: { path: path } }
end

# @return [Array<Hash>]
def drives_with_keyword
drive_configs.select { |c| with_partitions_keyword?(c) }
end

# @return [Array<Hash>]
def volume_groups_with_keyword
volume_group_configs.select { |c| with_logical_volumes_keyword?(c) }
end

# @param config [Hash]
# @return [Boolean]
def with_partitions_keyword?(config)
partitions = config[:partitions]
return false unless partitions

with_keyword?(partitions)
end

# @param config [Hash]
# @return [Boolean]
def with_logical_volumes_keyword?(config)
logical_volumes = config[:logicalVolumes]
return false unless logical_volumes

with_keyword?(logical_volumes)
end

# @param configs [Array<Hash>]
# @return [Boolean]
def with_keyword?(configs)
with_default_keyword?(configs) || with_mandatory_keyword?(configs)
end

# @param configs [Array<Hash>]
# @return [Boolean]
def with_default_keyword?(configs)
configs.include?("default")
end

# @param configs [Array<Hash>]
# @return [Boolean]
def with_mandatory_keyword?(configs)
configs.include?("mandatory")
end

# @return [Array<Hash>]
def configs_with_filesystem
drive_configs + partition_configs + logical_volume_configs
end

# @return [Array<Hash>]
def drive_configs
config_json[:drives] || []
end

# @return [Array<Hash>]
def volume_group_configs
config_json[:volumeGroups] || []
end

# @return [Array<Hash>]
def partition_configs
drive_configs = config_json[:drives]
return [] unless drive_configs
Expand All @@ -87,6 +244,7 @@ def partition_configs
.compact
end

# @return [Array<Hash>]
def logical_volume_configs
volume_group_configs = config_json[:volumeGroups]
return [] unless volume_group_configs
Expand All @@ -95,6 +253,11 @@ def logical_volume_configs
.flat_map { |c| c[:logicalVolumes] }
.compact
end

# @return [VolumeTemplatesBuilder]
def volume_builder
@volume_builder ||= VolumeTemplatesBuilder.new_from_config(product_config)
end
end
end
end
Loading

0 comments on commit 90a22bc

Please sign in to comment.