Skip to content

Commit

Permalink
Add methods needed by AgamaProposal to grow partitions
Browse files Browse the repository at this point in the history
  • Loading branch information
ancorgs committed Sep 19, 2024
1 parent 86b0940 commit 1410fee
Show file tree
Hide file tree
Showing 7 changed files with 162 additions and 0 deletions.
19 changes: 19 additions & 0 deletions src/lib/y2storage/partition.rb
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,25 @@ def windows_suitable?
!disk.nil? && type.is?(:primary) && id.is?(:windows_system)
end

# Whether the given disk space is located right after this partition
#
# @param disk_space [FreeDiskSpace]
# @return [Boolean]
def subsequent_slot?(disk_space)
return false if disk_space.disk != partition_table.partitionable
return false unless disk_space.region.start > region.end

# The simplest case can be easily evaluated
return true if disk_space.region.start == (region.end + 1)

# But if the end of the partition is not properly aligned, we may need to look closer
# FIXME: this can likely be both simpler and more efficient. But since it's used
# only for missaligned partitions is not a priority
slots = partition_table.partitions + partition_table.unused_partition_slots
break_points = slots.flat_map { |s| [s.region.start, s.region.end] }
break_points.none? { |p| p > region.end && p < disk_space.region.start }
end

protected

# Values for volume specification matching
Expand Down
9 changes: 9 additions & 0 deletions src/lib/y2storage/planned/assigned_space.rb
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,15 @@ def total_missing_size
end
end

# Space that can be sustracted from the start of the region without invalidating this
# valid assignation
#
# @return [DiskSize]
def disposable_size
# FIXME: This is more based on trial and error than on a real rationale
usable_extra_size - align_grain
end

# Space consumed by the EBR of one logical partition in a given disk
# See https://en.wikipedia.org/wiki/Extended_boot_record
#
Expand Down
9 changes: 9 additions & 0 deletions src/lib/y2storage/planned/can_be_resized.rb
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,15 @@ def shrink?(devicegraph)
max_size <= device_to_reuse(devicegraph).size
end

# Limit the max size to ensure the device does not grow more than a give margin
#
# @param max_grow [DiskSize] max margin to grow the device
# @param devicegraph [Devicegraph]
def limit_grow(max_grow, devicegraph)
limit = device_to_reuse(devicegraph).size + max_grow
self.max_size = [max_size, limit].min
end

protected

# Implements reuse_device! hook
Expand Down
13 changes: 13 additions & 0 deletions src/lib/y2storage/planned/partition.rb
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,19 @@ def initialize(mount_point, filesystem_type = nil)
@primary = false
end

# Whether this corresponds to a reused partition that is located right before the given
# assigned space
#
# @param assigned_space [AssignedSpace]
# @return [Boolean]
def subsequent_slot?(assigned_space)
devicegraph = assigned_space.disk_space.disk.devicegraph
dev = device_to_reuse(devicegraph)
return false unless dev

dev.subsequent_slot?(assigned_space.disk_space)
end

def self.to_string_attrs
[
:mount_point, :reuse_name, :reuse_sid, :min_size, :max_size,
Expand Down
49 changes: 49 additions & 0 deletions test/y2storage/partition_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -446,6 +446,55 @@
end
end

describe "#subsequent_slot?" do
let(:disk) { fake_devicegraph.find_by_name(disk_name) }
let(:region) { disk.partition_table.unused_partition_slots[slot].region }
let(:slot) { 0 }
let(:space) { Y2Storage::FreeDiskSpace.new(disk, region) }
subject(:partition) { fake_devicegraph.find_by_name(part_name) }

context "when the space starts at the sector right after the partition" do
let(:scenario) { "spaces_5_5_10" }
let(:part_name) { "/dev/sda1" }
let(:disk_name) { "/dev/sda" }

it "returns true" do
expect(partition.subsequent_slot?(space)).to eq true
end
end

context "when the space is right after a partition with missaligned end" do
let(:scenario) { "alignment" }
let(:part_name) { "/dev/sdb1" }
let(:disk_name) { "/dev/sdb" }

it "returns true" do
expect(partition.subsequent_slot?(space)).to eq true
end
end

context "when the space is not adyacent to the partition" do
let(:scenario) { "spaces_5_5_10" }
let(:part_name) { "/dev/sda1" }
let(:disk_name) { "/dev/sda" }
let(:slot) { 1 }

it "returns false" do
expect(partition.subsequent_slot?(space)).to eq false
end
end

context "when the space starts at an appropriate sector but is in another disk" do
let(:scenario) { "alignment" }
let(:part_name) { "/dev/sdb1" }
let(:disk_name) { "/dev/sdc" }

it "returns false" do
expect(partition.subsequent_slot?(space)).to eq false
end
end
end

# Only basic cases are tested here. More exhaustive tests can be found in tests
# for Y2Storage::MatchVolumeSpec
describe "#match_volume?" do
Expand Down
14 changes: 14 additions & 0 deletions test/y2storage/planned/can_be_resized_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -172,4 +172,18 @@ class ResizableDevice < Y2Storage::Planned::Device
end
end
end

describe "#limit_grow" do
before { planned.max_size = 70.GiB }

it "limits the max size if the sum of the new limit and the original size is smaller" do
planned.limit_grow(5.GiB, devicegraph)
expect(planned.max_size).to eq 55.GiB
end

it "leaves the max size untouched if the sum of original size and limit is bigger" do
planned.limit_grow(50.GiB, devicegraph)
expect(planned.max_size).to eq 70.GiB
end
end
end
49 changes: 49 additions & 0 deletions test/y2storage/planned/partition_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -111,4 +111,53 @@
end
end
end

describe "#subsequent_slot?" do
let(:assigned_space) { Y2Storage::Planned::AssignedSpace.new(space, []) }
let(:space) do
instance_double(
"Y2Storage::FreeDiskSpace",
disk: disk,
disk_size: 500.GiB,
align_grain: 1.MiB,
require_end_alignment?: false
)
end

let(:disk) { instance_double("Y2Storage::Disk", devicegraph: devicegraph) }
let(:devicegraph) { instance_double("Y2Storage::Devicegraph") }

context "when the plan is to create a new partition" do
it "returns false" do
expect(partition.subsequent_slot?(assigned_space)).to eq false
end
end

context "when the plan is to reuse an existing partition" do
let(:real_partition) { instance_double("Y2Storage::Partition", sid: 123) }

before do
partition.assign_reuse(real_partition)

allow(devicegraph).to receive(:find_device).and_return real_partition
allow(real_partition).to receive(:subsequent_slot?).with(space).and_return subsequent
end

context "if the reused partition is next to the region of the assigned space" do
let(:subsequent) { true }

it "returns true" do
expect(partition.subsequent_slot?(assigned_space)).to eq true
end
end

context "if the reused partition is not adjacent to the region of the assigned space" do
let(:subsequent) { false }

it "returns false" do
expect(partition.subsequent_slot?(assigned_space)).to eq false
end
end
end
end
end

0 comments on commit 1410fee

Please sign in to comment.