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

feat(storage): config support to delete partitions #1572

Merged
merged 4 commits into from
Sep 4, 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
46 changes: 34 additions & 12 deletions rust/agama-lib/share/examples/storage.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@
"search": "/dev/vda",
"ptableType": "gpt",
"partitions": [
{
"search": {
"ifNotFound": "skip"
},
"delete": true
},
{
"id": "linux",
"size": "10 GiB",
Expand All @@ -30,12 +36,6 @@
}
},
{
"search": {
"condition": {
"name": "/dev/vda2"
},
"ifNotFound": "skip"
},
"encryption": {
"luks2": {
"password": "notsecret",
Expand All @@ -48,21 +48,43 @@
}
},
{
"search": {},
"encryption": "random_swap",
"filesystem": {
"type": "swap",
"path": "swap"
}
},
"size": "2 GiB"
}
]
},
{
"search": {
"condition": {
"name": "/dev/vda"
"search": "/dev/vdb",
"partitions": [
{
"search": {
"condition": { "name": "/dev/vdb1" },
"ifNotFound": "skip"
},
"deleteIfNeeded": true
},
{
"search": {
"ifNotFound": "skip"
},
"delete": true
},
"ifNotFound": "error"
{
"filesystem": {
"type": "xfs",
"path": "/data"
},
"size": { "min": "50 GiB" }
}
]
},
{
"search": {
"ifNotFound": "skip"
},
"filesystem": {
"type": "ext4",
Expand Down
83 changes: 62 additions & 21 deletions rust/agama-lib/share/profile.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -909,32 +909,73 @@
},
"partitions": {
"title": "Partitions",
"description": "Partitions to create, reuse or delete.",
"type": "array",
"items": {
"title": "Partition options",
"type": "object",
"additionalProperties": false,
"properties": {
"search": {
"description": "The search is limited to the partitions of the selected device scope.",
"$ref": "#/$defs/search"
},
"id": {
"title": "Partition ID",
"enum": ["linux", "swap", "lvm", "raid", "esp", "prep", "bios_boot"]
},
"size": {
"title": "Partition size",
"$ref": "#/$defs/sizeValue"
"anyOf": [
{
"title": "Partition to create or reuse",
"type": "object",
"additionalProperties": false,
"properties": {
"search": {
"description": "The search is limited to the partitions of the selected device scope.",
"$ref": "#/$defs/search"
},
"id": {
"title": "Partition ID",
"enum": ["linux", "swap", "lvm", "raid", "esp", "prep", "bios_boot"]
},
"size": {
"title": "Partition size",
"$ref": "#/$defs/size"
},
"encryption": {
"$ref": "#/$defs/encryption"
},
"filesystem": {
"$ref": "#/$defs/filesystem"
}
}
},
"encryption": {
"$ref": "#/$defs/encryption"
{
"title": "Partition to delete if needed",
"type": "object",
"additionalProperties": false,
"required": ["deleteIfNeeded", "search"],
"properties": {
"deleteIfNeeded": {
"title": "Delete if needed",
"description": "Delete the partition if needed to make space.",
"const": true
},
"search": {
"description": "The search is limited to the partitions of the selected device scope.",
"$ref": "#/$defs/search"
},
"size": {
"title": "Partition size",
"$ref": "#/$defs/size"
}
}
},
"filesystem": {
"$ref": "#/$defs/filesystem"
{
"title": "Partition to delete",
"type": "object",
"additionalProperties": false,
"required": ["delete", "search"],
"properties": {
"delete": {
"title": "Delete",
"description": "Delete the partition.",
"const": true
},
"search": {
"description": "The search is limited to the partitions of the selected device scope.",
"$ref": "#/$defs/search"
}
}
}
}
]
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,14 @@ def convert(default = nil)

convert_block_device(default_config).tap do |config|
search = convert_search(config.search)
delete = partition_json[:delete]
delete_if_needed = partition_json[:deleteIfNeeded]
id = convert_id
size = convert_size(config.size)

config.search = search if search
config.delete = delete unless delete.nil?
config.delete_if_needed = delete_if_needed unless delete_if_needed.nil?
config.id = id if id
config.size = size if size
end
Expand Down
10 changes: 10 additions & 0 deletions service/lib/agama/storage/configs/partition.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,14 @@ class Partition
# @return [Search, nil]
attr_accessor :search

# @return [Boolean]
attr_accessor :delete
alias_method :delete?, :delete

# @return [Boolean]
attr_accessor :delete_if_needed
alias_method :delete_if_needed?, :delete_if_needed

# @return [Y2Storage::PartitionId, nil]
attr_accessor :id

Expand All @@ -43,6 +51,8 @@ class Partition

def initialize
@size = Size.new
@delete = false
@delete_if_needed = false
end

# Assigned device according to the search.
Expand Down
5 changes: 3 additions & 2 deletions service/lib/y2storage/agama_proposal.rb
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ def initialize(initial_settings, devicegraph: nil, disk_analyzer: nil, issues_li

private

# @return [Proposal::SpaceMaker]
# @return [Proposal::AgamaSpaceMaker]
attr_reader :space_maker

# Whether the list of issues generated so far already includes any serious error
Expand Down Expand Up @@ -140,7 +140,7 @@ def propose_devicegraph
return if fatal_error?

configure_ptable_types(devicegraph)
clean_graph(devicegraph)
devicegraph = clean_graph(devicegraph)
complete_planned(devicegraph)
return if fatal_error?

Expand All @@ -162,6 +162,7 @@ def calculate_initial_planned(devicegraph)
def clean_graph(devicegraph)
remove_empty_partition_tables(devicegraph)
protect_sids
# {Proposal::SpaceMaker#prepare_devicegraph} returns a copy of the given devicegraph.
space_maker.prepare_devicegraph(devicegraph, partitions_for_clean)
end

Expand Down
24 changes: 14 additions & 10 deletions service/lib/y2storage/proposal/agama_device_planner.rb
Original file line number Diff line number Diff line change
Expand Up @@ -188,21 +188,25 @@ def configure_size(planned, settings)
end

# @param planned [Planned::Disk]
# @param settings [Agama::Storage::Configs::Drive]
def configure_partitions(planned, settings)
planned.partitions = settings.partitions.map do |partition_settings|
planned_partition(partition_settings).tap { |p| p.disk = settings.found_device.name }
# @param config [Agama::Storage::Configs::Drive]
def configure_partitions(planned, config)
partition_configs = 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 }
end
end

# @param settings [Agama::Storage::Configs::Partition]
# @param config [Agama::Storage::Configs::Partition]
# @return [Planned::Partition]
def planned_partition(settings)
def planned_partition(config)
Planned::Partition.new(nil, nil).tap do |planned|
planned.partition_id = settings.id
configure_reuse(planned, settings)
configure_device(planned, settings)
configure_size(planned, settings.size)
planned.partition_id = config.id
configure_reuse(planned, config)
configure_device(planned, config)
configure_size(planned, config.size)
end
end
end
Expand Down
69 changes: 63 additions & 6 deletions service/lib/y2storage/proposal/agama_space_maker.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,28 +26,85 @@ module Y2Storage
module Proposal
# Space maker for Agama.
class AgamaSpaceMaker < SpaceMaker
# Constructor
def initialize(disk_analyzer, settings)
super(disk_analyzer, guided_settings(settings))
# @param disk_analyzer [DiskAnalyzer]
# @param config [Agama::Storage::Config]
def initialize(disk_analyzer, config)
super(disk_analyzer, guided_settings(config))
end

private

# Method used by the constructor to somehow simulate a typical Guided Proposal
def guided_settings(settings)
#
# @param config [Agama::Storage::Config]
def guided_settings(config)
# Despite the "current_product" part in the name of the constructor, it only applies
# generic default values that are independent of the product (there is no YaST
# ProductFeatures mechanism in place).
Y2Storage::ProposalSettings.new_for_current_product.tap do |target|
target.space_settings.strategy = :bigger_resize
target.space_settings.actions = {}
target.space_settings.actions = space_actions(config)

boot_device = settings.boot_device
boot_device = config.boot_device

target.root_device = boot_device
target.candidate_devices = [boot_device].compact
end
end

# Space actions from the given config.
#
# @param config [Agama::Storage::Config]
# @return [Hash]
def space_actions(config)
force_delete_actions = force_delete_actions(config)
delete_actions = delete_actions(config)

force_delete_actions.merge(delete_actions)
end

# Space actions for devices that must be deleted.
#
# @param config [Agama::Storage::Config]
# @return [Hash]
def force_delete_actions(config)
partition_configs = partitions(config).select(&:delete?)
partition_names = device_names(partition_configs)

partition_names.each_with_object({}) { |p, a| a[p] = :force_delete }
end

# Space actions for devices that might be deleted.
#
# @note #delete? takes precedence over #delete_if_needed?.
#
# @param config [Agama::Storage::Config]
# @return [Hash]
def delete_actions(config)
partition_configs = partitions(config).select(&:delete_if_needed?).reject(&:delete?)
partition_names = device_names(partition_configs)

partition_names.each_with_object({}) { |p, a| a[p] = :delete }
end

# All partition configs from the given config.
#
# @param config [Agama::Storage::Config]
# @return [Array<Agama::Storage::Configs::Partition>]
def partitions(config)
config.drives.flat_map(&:partitions)
end

# Device names from the given configs.
#
# @param configs [Array<#found_device>]
# @return [Array<String>]
def device_names(configs)
configs
.map(&:found_device)
.compact
.map(&:name)
end
end
end
end
6 changes: 6 additions & 0 deletions service/package/rubygem-agama-yast.changes
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
-------------------------------------------------------------------
Wed Sep 4 08:55:29 UTC 2024 - José Iván López González <jlopez@suse.com>

- Storage: add support for deleting partitions in the storage
config (gh#openSUSE/agama#1572).

-------------------------------------------------------------------
Tue Sep 3 08:14:23 UTC 2024 - José Iván López González <jlopez@suse.com>

Expand Down
Loading
Loading