Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
joseivanlopez committed Sep 16, 2024
1 parent 979615d commit aee4484
Show file tree
Hide file tree
Showing 6 changed files with 405 additions and 51 deletions.
38 changes: 28 additions & 10 deletions service/lib/y2storage/proposal/agama_device_planner.rb
Original file line number Diff line number Diff line change
Expand Up @@ -200,27 +200,45 @@ def configure_size(planned, config)
end

# @param planned [Planned::Disk]
# @param config [Agama::Storage::Configs::Drive]
def configure_partitions(planned, config)
partition_configs = config.partitions
# @param device_config [Agama::Storage::Configs::Drive]
# @param config [Agama::Storage::Config]
def configure_partitions(planned, device_config, config)
partition_configs = device_config.partitions
.reject(&:delete?)
.reject(&:delete_if_needed?)

planned.partitions = partition_configs.map do |partition_config|
planned_partition(partition_config).tap { |p| p.disk = config.found_device.name }
planned_partition(partition_config, device_config, config)
end
end

# @param config [Agama::Storage::Configs::Partition]
# @param partition_config [Agama::Storage::Configs::Partition]
# @param device_config [Agama::Storage::Configs::Drive]
# @param config [Agama::Storage::Config]
#
# @return [Planned::Partition]
def planned_partition(config)
def planned_partition(partition_config, device_config, config)
Planned::Partition.new(nil, nil).tap do |planned|
planned.partition_id = config.id
configure_reuse(planned, config)
configure_block_device(planned, config)
configure_size(planned, config.size)
planned.disk = device_config.found_device.name
planned.partition_id = partition_config.id
configure_reuse(planned, partition_config)
configure_block_device(planned, partition_config)
configure_size(planned, partition_config.size)
configure_pv(planned, partition_config, config)
end
end

# @param planned [Planned::Disk, Planned::Partition]
# @param device_config [Agama::Storage::Configs::Drive, Agama::Storage::Configs::Partition]
# @param config [Agama::Storage::Config]
def configure_pv(planned, device_config, config)
return unless planned.respond_to?(:lvm_volume_group_name) && device_config.alias

vg = config.volume_groups.find { |v| v.physical_volumes.include?(device_config.alias) }
return unless vg

planned.lvm_volume_group_name = vg.name
end
end
end
end
63 changes: 53 additions & 10 deletions service/lib/y2storage/proposal/agama_devices_creator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,10 @@
# To contact SUSE LLC about this file by physical or electronic mail, you may
# find current contact information at www.suse.com.

require "y2storage/proposal/agama_lvm_helper"
require "y2storage/exceptions"
require "y2storage/proposal/agama_lvm_helper"
require "y2storage/proposal/lvm_creator"
require "y2storage/proposal/partition_creator"

module Y2Storage
module Proposal
Expand Down Expand Up @@ -110,6 +112,13 @@ def reset
# planned devices have been allocated
def process_devices
process_existing_partitionables
process_volume_groups

# This may be unexpected if the storage configuration provided by the user includes
# carefully crafted mount options but may be needed in weird situations for more automated
# proposals. Let's re-evaluate over time.
devicegraph.mount_points.each(&:adjust_mount_options)

creator_result
end

Expand All @@ -136,17 +145,43 @@ def process_existing_partitionables
# But I'm not so sure if growing is so fine (we may need to make some space first).
# I don't think we have the growing case covered by SpaceMaker, the distribution
# calculator, etc.
#
planned_devices.each do |planned|
next unless planned.reuse?
planned_devices
.select(&:reuse?)
.map { |d| d.reuse!(devicegraph) }
end

planned.reuse!(devicegraph)
end
# @see #process_devices
def process_volume_groups
# TODO: Reuse volume groups.
planned_devices.vgs.map { |v| create_volume_group(v) }
end

# This may be unexpected if the storage configuration provided by the user includes
# carefully crafted mount options but may be needed in weird situations for more automated
# proposals. Let's re-evaluate over time.
devicegraph.mount_points.each(&:adjust_mount_options)
# Creates a volume group for the the given planned device.
#
# @param planned [Planned::LvmVg]
def create_volume_group(planned)
pv_names = physical_volumes_for(planned.volume_group_name)
# TODO: Generate issue if there are no physical volumes.
return if pv_names.empty?

creator = Proposal::LvmCreator.new(creator_result.devicegraph)
new_result = creator.create_volumes(planned, pv_names)
self.creator_result = creator_result.merge(new_result)
end

# Physical volumes (new partitions and reused devices) for a new volume group.
#
# @param vg_name [String]
# @return [Array<String>]
def physical_volumes_for(vg_name)
pv_condition = proc { |d| d.respond_to?(:pv_for?) && d.pv_for?(vg_name) }

new_pvs = creator_result.created_names(&pv_condition)
reused_pvs = reused_planned_devices
.select(&pv_condition)
.map(&:reuse_name)

new_pvs + reused_pvs
end

# @see #process_existing_partitionables
Expand All @@ -163,6 +198,14 @@ def partitions_for_existing(planned_devices)
planned_devices.partitions.reject(&:reuse?)
end

# Planned devices configured to be reused.
#
# @return [Array<Planned::Device>]
def reused_planned_devices
planned_devices.disks.select(&:reuse?) +
planned_devices.disks.flat_map(&:partitions).select(&:reuse?)
end

# Formats and/or mounts the disk-like block devices
#
# XEN partitions (StrayBlkDevice) are intentionally left out for now
Expand Down
21 changes: 15 additions & 6 deletions service/lib/y2storage/proposal/agama_devices_planner.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@
# To contact SUSE LLC about this file by physical or electronic mail, you may
# find current contact information at www.suse.com.

require "y2storage/planned/devices_collection"
require "y2storage/proposal/agama_drive_planner"
require "y2storage/planned"
require "y2storage/proposal/agama_vg_planner"

module Y2Storage
module Proposal
Expand All @@ -38,8 +39,7 @@ def initialize(devicegraph, issues_list)
# List of devices that need to be created to satisfy the settings. Does not include
# devices needed for booting.
#
# For the time being, this implements only stuff coming from partitition elements within
# drive elements.
# For the time being, this only plans for drives, partitions, and new LVM volume groups.
#
# @param config [Agama::Storage::Config]
# @return [Planned::DevicesCollection]
Expand All @@ -49,7 +49,7 @@ def planned_devices(config)
# - For dedicated VGs it creates a Planned VG containing a Planned LV, but no PVs
# - For LVM volumes it create a Planned LV but associated to no planned VG
# - For partition volumes, it creates a planned partition, of course
planned = planned_for_drives(config)
planned = planned_drives(config) + planned_vgs(config)
Planned::DevicesCollection.new(planned)
end

Expand All @@ -63,10 +63,19 @@ def planned_devices(config)

# @param config [Agama::Storage::Config]
# @return [Array<Planned::Device>]
def planned_for_drives(config)
def planned_drives(config)
config.drives.flat_map do |drive|
planner = AgamaDrivePlanner.new(devicegraph, issues_list)
planner.planned_devices(drive)
planner.planned_devices(drive, config)
end
end

# @param config [Agama::Storage::Config]
# @return [Array<Planned::Device>]
def planned_vgs(config)
config.volume_groups.flat_map do |vg|
planner = AgamaVgPlanner.new(devicegraph, issues_list)
planner.planned_devices(vg)
end
end
end
Expand Down
39 changes: 24 additions & 15 deletions service/lib/y2storage/proposal/agama_drive_planner.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,40 +26,49 @@ module Y2Storage
module Proposal
# Drive planner for Agama.
class AgamaDrivePlanner < AgamaDevicePlanner
# @param settings [Agama::Storage::Configs::Drive]
# @param drive_config [Agama::Storage::Configs::Drive]
# @param config [Agama::Storage::Config]
#
# @return [Array<Planned::Device>]
def planned_devices(settings)
[planned_drive(settings)]
def planned_devices(drive_config, config)
[planned_drive(drive_config, config)]
end

private

# Support for StrayBlkDevice is intentionally left out. As far as we know, the plan
# for SLE/Leap 16 is to drop XEN support
#
# @param settings [Agama::Storage::Configs::Drive]
# @param drive_config [Agama::Storage::Configs::Drive]
# @param config [Agama::Storage::Config]
#
# @return [Planned::Disk]
def planned_drive(settings)
return planned_full_drive(settings) unless settings.partitions?
def planned_drive(drive_config, config)
return planned_full_drive(drive_config, config) unless drive_config.partitions?

planned_partitioned_drive(settings)
planned_partitioned_drive(drive_config, config)
end

# @param settings [Agama::Storage::Configs::Drive]
# @param drive_config [Agama::Storage::Configs::Drive]
# @param config [Agama::Storage::Config]
#
# @return [Planned::Disk]
def planned_full_drive(settings)
def planned_full_drive(drive_config, config)
Planned::Disk.new.tap do |planned|
configure_reuse(planned, settings)
configure_block_device(planned, settings)
configure_reuse(planned, drive_config)
configure_block_device(planned, drive_config)
configure_pv(planned, drive_config, config)
end
end

# @param settings [Agama::Storage::Configs::Drive]
# @param drive_config [Agama::Storage::Configs::Drive]
# @param config [Agama::Storage::Config]
#
# @return [Planned::Disk]
def planned_partitioned_drive(settings)
def planned_partitioned_drive(drive_config, config)
Planned::Disk.new.tap do |planned|
configure_reuse(planned, settings)
configure_partitions(planned, settings)
configure_reuse(planned, drive_config)
configure_partitions(planned, drive_config, config)
end
end
end
Expand Down
119 changes: 119 additions & 0 deletions service/lib/y2storage/proposal/agama_vg_planner.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
# frozen_string_literal: true

# Copyright (c) [2024] SUSE LLC
#
# All Rights Reserved.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of version 2 of the GNU General Public License as published
# by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
# more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, contact SUSE LLC.
#
# To contact SUSE LLC about this file by physical or electronic mail, you may
# find current contact information at www.suse.com.

require "y2storage/lv_type"
require "y2storage/proposal/agama_device_planner"

module Y2Storage
module Proposal
# Volume group planner for Agama.
class AgamaVgPlanner < AgamaDevicePlanner
# @param config [Agama::Storage::Configs::VolumeGroup]
# @return [Array<Planned::Device>]
def planned_devices(config)
[planned_vg(config)]
end

private

# @param config [Agama::Storage::Configs::VolumeGroup]
# @return [Planned::LvmVg]
def planned_vg(config)
# TODO: A volume group name is expected. Otherwise, the planned physical volumes cannot
# be associated to the planned volume group. Should the volume group name be
# automatically generated if missing?
#
# @see AgamaDevicePlanner#configure_pv

# TODO: Generate issue if the config has an unknown physical volume alias.
# TODO: Generate issue if a thin lv config has an unknown pool alias.
Y2Storage::Planned::LvmVg.new(volume_group_name: config.name).tap do |planned|
planned.extent_size = config.extent_size
planned.lvs = planned_lvs(config)
end
end

# @param config [Agama::Storage::Configs::VolumeGroup]
# @return [Array<Planned::LvmLv>]
def planned_lvs(config)
normal_lvs = planned_normal_lvs(config)
thin_pool_lvs = planned_thin_pool_lvs(config)

normal_lvs + thin_pool_lvs
end

# @param config [Agama::Storage::Configs::VolumeGroup]
# @return [Array<Planned::LvmLv>]
def planned_normal_lvs(config)
configs = config.logical_volumes.reject(&:pool?).reject(&:thin_volume?)
configs.map { |c| planned_lv(c, LvType::NORMAL) }
end

# @param config [Agama::Storage::Configs::VolumeGroup]
# @return [Array<Planned::LvmLv>]
def planned_thin_pool_lvs(config)
pool_configs = config.logical_volumes.select(&:pool?)
pool_configs.map { |c| planned_thin_pool_lv(c, config) }
end

# Plan a thin pool logical volume and its thin volumes.
#
# @param pool_config [Agama::Storage::Configs::LogicalVolume]
# @param config [Agama::Storage::Configs::VolumeGroup]
#
# @return [Planned::LvmLv]
def planned_thin_pool_lv(pool_config, config)
planned_thin_lvs = planned_thin_lvs(config, pool_config.alias)

planned_lv(pool_config, LvType::THIN_POOL).tap do |planned|
planned_thin_lvs.each { |v| planned.add_thin_lv(v) }
end
end

# @param config [Agama::Storage::Configs::VolumeGroup]
# @param pool_alias [String]
#
# @return [Array<Planned::LvmLv>]
def planned_thin_lvs(config, pool_alias)
thin_configs = config.logical_volumes
.select(&:thin_volume?)
.select { |c| c.used_pool == pool_alias }

thin_configs.map { |c| planned_lv(c, LvType::THIN) }
end

# @param config [Agama::Storage::Configs::LogicalVolume]
# @param type [LvType]
#
# @return [Planned::LvmLv]
def planned_lv(config, type)
Planned::LvmLv.new(nil, nil).tap do |planned|
planned.logical_volume_name = config.name
planned.lv_type = type
planned.stripes = config.stripes
planned.stripe_size = config.stripe_size
configure_block_device(planned, config)
configure_size(planned, config.size)
end
end
end
end
end
Loading

0 comments on commit aee4484

Please sign in to comment.