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

Changes to allow automatic generation of LVM PVs at the AgamaProposal #1392

Merged
merged 6 commits into from
Oct 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
7 changes: 7 additions & 0 deletions package/yast2-storage-ng.changes
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
-------------------------------------------------------------------
Tue Oct 8 12:21:38 UTC 2024 - Ancor Gonzalez Sosa <ancor@suse.com>

- SpaceMaker: make it possible to generate physical volumes for
several volume groups (needed by gh#agama-project/agama#1655).
- 5.0.20

-------------------------------------------------------------------
Mon Sep 23 11:27:55 UTC 2024 - Stefan Hundhammer <shundhammer@suse.com>

Expand Down
2 changes: 1 addition & 1 deletion package/yast2-storage-ng.spec
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
#

Name: yast2-storage-ng
Version: 5.0.19
Version: 5.0.20
Release: 0
Summary: YaST2 - Storage Configuration
License: GPL-2.0-only OR GPL-3.0-only
Expand Down
18 changes: 13 additions & 5 deletions src/lib/y2storage/planned/can_be_encrypted.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,14 @@ module Planned
module CanBeEncrypted
include SecretAttributes

# This value matches Storage::Luks.metadata_size, which is not exposed in
# This value matches Storage::Luks.v1_metadata_size, which is not exposed in
# the libstorage API
ENCRYPTION_OVERHEAD = DiskSize.MiB(2)
private_constant :ENCRYPTION_OVERHEAD
LUKS1_OVERHEAD = DiskSize.MiB(2)
private_constant :LUKS1_OVERHEAD

# This value matches Storage::Luks.v2_metadata_size, see above
LUKS2_OVERHEAD = DiskSize.MiB(16)
private_constant :LUKS2_OVERHEAD

# @!attribute encryption_method
# @return [EncryptionMethod::Base, nil] method used to encrypt the device. If is nil,
Expand Down Expand Up @@ -152,9 +156,13 @@ module ClassMethods
# I.e. how much smaller will be an encrypted device compared to the plain
# one.
#
# @param type [EncryptionType]
# @return [DiskSize]
def encryption_overhead
ENCRYPTION_OVERHEAD
def encryption_overhead(type = EncryptionType::LUKS1)
return LUKS1_OVERHEAD if type&.is?(:luks1)
return LUKS2_OVERHEAD if type&.is?(:luks2)

DiskSize.zero
end
end
end
Expand Down
27 changes: 21 additions & 6 deletions src/lib/y2storage/planned/lvm_vg.rb
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,11 @@ class LvmVg < Device
# @return [Symbol]
attr_accessor :size_strategy

# Disks where the proposal can create extra physical volumes to honor {#size_strategy}
#
# @return [Array<String>] names of partitionable devices
attr_accessor :pvs_candidate_devices

# Builds a new instance based on a real VG
#
# The new instance represents the intention to reuse the real VG, so the
Expand Down Expand Up @@ -111,6 +116,7 @@ def initialize(volume_group_name: nil, lvs: [], pvs: [])
@pvs = pvs
@pvs_encryption_password = nil
@make_space_policy = :needed
@pvs_candidate_devices = []
end

# Initializes the object taking the values from a real volume group
Expand Down Expand Up @@ -150,10 +156,12 @@ def minimal_pv_partition
#
# This method is useful to generate a volume group with just one new PV.
#
# @param target [DiskSize, nil] aim for the provided size, instead of
# trying to provide the exact size needed by the volume group
# @return [Planned::Partition]
def single_pv_partition
def single_pv_partition(target: nil)
pv = minimal_pv_partition
pv.min_size = real_pv_size(missing_space)
pv.min_size = real_pv_size(target || missing_space)
pv.max_size = real_pv_size(max_size)
pv.weight = lvs_weight
pv
Expand Down Expand Up @@ -258,13 +266,15 @@ def self.to_string_attrs
end

# Device name of the disk-like device in which the volume group has to be
# physically located. If nil, the volume group can spread freely over any
# set of disks.
# physically located. If nil, the volume group can spread over a set of
# several disks (maybe even unlimited).
#
# @return [String, nil]
def forced_disk_name
forced_lv = lvs.find(&:disk)
forced_lv ? forced_lv.disk : nil
return forced_lv.disk if forced_lv

pvs_candidate_devices.size == 1 ? pvs_candidate_devices.first : nil
end

protected
Expand Down Expand Up @@ -313,7 +323,7 @@ def lvs_weight
#
# @return [DiskSize]
def useless_pv_space
pvs_encrypt? ? USELESS_PV_SPACE + Planned::Partition.encryption_overhead : USELESS_PV_SPACE
pvs_encrypt? ? USELESS_PV_SPACE + encryption_overhead : USELESS_PV_SPACE
end

def substract_reused_vg_size(size)
Expand All @@ -323,6 +333,11 @@ def substract_reused_vg_size(size)
DiskSize.zero
end
end

# @return [DiskSize]
def encryption_overhead
Planned::Partition.encryption_overhead(pvs_encryption_method&.encryption_type)
end
end
end
end
15 changes: 12 additions & 3 deletions src/lib/y2storage/proposal/autoinst_partitioner.rb
Original file line number Diff line number Diff line change
Expand Up @@ -155,12 +155,21 @@ def reuse_partitions_in_devicegraph(reused_parts, graph)
def best_distribution(planned_partitions, devices)
spaces = devices.map(&:free_spaces).flatten

calculator = Proposal::PartitionsDistributionCalculator.new
dist = calculator.best_distribution(planned_partitions, spaces)
dist = distribute_partitions(planned_partitions, spaces)
return dist if dist

# Second try with more flexible planned partitions
calculator.best_distribution(flexible_partitions(planned_partitions), spaces)
distribute_partitions(flexible_partitions(planned_partitions), spaces)
end

# @see #best_distribution
#
# @param partitions [Array<Planned::Partition>] list of planned partitions to create
# @param spaces [Array<FreeDiskSpace>] spaces to distribute the partitions
# @return [Planned::PartitionsDistribution, nil]
def distribute_partitions(partitions, spaces)
calculator = Proposal::PartitionsDistributionCalculator.new(partitions)
calculator.best_distribution(spaces)
end

# Checks whether (re)formatting the given device is acceptable
Expand Down
40 changes: 32 additions & 8 deletions src/lib/y2storage/proposal/devicegraph_generator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class DevicegraphGenerator

def initialize(settings, disk_analyzer)
@settings = settings
@space_maker = Proposal::SpaceMaker.new(disk_analyzer, settings)
@space_maker = Proposal::SpaceMaker.new(disk_analyzer, settings.space_settings)
end

# Devicegraph including all the specified volumes
Expand Down Expand Up @@ -84,8 +84,9 @@ def devicegraph(planned_devices, initial_graph)
# @return [Devicegraph]
def prepared(planned_devices, initial_graph)
protect_sids(planned_devices)
partitions = partitions_for(planned_devices)
space_maker.prepare_devicegraph(initial_graph, partitions)
disks = settings.candidate_devices + [settings.root_device] + forced_disks(planned_devices)
disks = disks.compact.sort.uniq
space_maker.prepare_devicegraph(initial_graph, disks)
end

protected
Expand All @@ -103,6 +104,21 @@ def partitions_for(planned_devices)
planned_devices.select { |d| plan_partition?(d) }.map { |d| planned_partition_for(d) }
end

# Disks that must be used by some of the given planned devices
#
# @param planned_devices [Array<Planned::Device>] list of planned devices
# @return [Array<String>]
def forced_disks(planned_devices)
partitions_for(planned_devices).map(&:disk).uniq.compact
end

# List of default disks for the SpaceMaker
#
# @return [Array<String>]
def default_disks
settings.candidate_devices
end

# Whether the given planned device must result in the creation of a partition
#
# @param device [Planned::Device]
Expand Down Expand Up @@ -167,14 +183,16 @@ def provide_space(planned_partitions, devicegraph, lvm_helper)
if settings.use_lvm
provide_space_lvm(planned_partitions, devicegraph, lvm_helper)
else
provide_space_no_lvm(planned_partitions, devicegraph, lvm_helper)
provide_space_no_lvm(planned_partitions, devicegraph)
end
end

# Variant of #provide_space when LVM is not involved
# @see #provide_space
def provide_space_no_lvm(planned_partitions, devicegraph, lvm_helper)
result = space_maker.provide_space(devicegraph, planned_partitions, lvm_helper)
def provide_space_no_lvm(planned_partitions, devicegraph)
result = space_maker.provide_space(
devicegraph, default_disks: default_disks, partitions: planned_partitions
)
log.info "Found enough space"
result
end
Expand All @@ -194,7 +212,10 @@ def provide_space_lvm(planned_partitions, devicegraph, lvm_helper)
original_sids = space_maker.protected_sids
space_maker.protected_sids += lvm_sids

result = space_maker.provide_space(devicegraph, planned_partitions, lvm_helper)
result = space_maker.provide_space(
devicegraph, default_disks: default_disks,
partitions: planned_partitions, volume_groups: [lvm_helper.volume_group]
)
log.info "Found enough space including LVM, reusing #{vg}"
return result
rescue Error
Expand All @@ -204,7 +225,10 @@ def provide_space_lvm(planned_partitions, devicegraph, lvm_helper)
end

lvm_helper.reused_volume_group = nil
result = space_maker.provide_space(devicegraph, planned_partitions, lvm_helper)
result = space_maker.provide_space(
devicegraph, default_disks: default_disks,
partitions: planned_partitions, volume_groups: [lvm_helper.volume_group]
)
log.info "Found enough space including LVM"

result
Expand Down
10 changes: 0 additions & 10 deletions src/lib/y2storage/proposal/lvm_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -111,16 +111,6 @@ def reused_volume_group=(vg)
@reused_volume_group.pvs_encryption_pbkdf = settings.encryption_pbkdf
end

# Checks whether the passed device is the volume group to be reused
#
# @param device [Device]
# @return [Boolean]
def vg_to_reuse?(device)
return false unless @reused_volume_group

device.is?(:lvm_vg) && @reused_volume_group.volume_group_name == device.vg_name
end

# Returns the planned volume group
#
# If no volume group is set (see {#reused_volume_group=}), it will create
Expand Down
Loading
Loading