Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
ccdd718
storage: add vgs and lvs to model schema
joseivanlopez Feb 27, 2025
8b545a1
storage: add conversion to model for LVM
joseivanlopez Feb 28, 2025
851d33d
feat(storage): make vg name mandatory
joseivanlopez Mar 3, 2025
f2bdb8c
fix(storage): drive model includes the searching name
joseivanlopez Mar 5, 2025
e99fb73
fix(storage): only exclude skipped devices from model
joseivanlopez Mar 5, 2025
6970c14
fix(storage): model always generates a min size
joseivanlopez Mar 5, 2025
4be9c6a
storage: add checker for model support
joseivanlopez Mar 3, 2025
e70204a
storage: use model support checker
joseivanlopez Mar 5, 2025
5983925
web: Extract repeated code to a new DeviceMenu component
ancorgs Mar 1, 2025
4016485
web: First real implementation of hasPV
ancorgs Mar 3, 2025
451637c
web: Refresh types/config-model.ts
ancorgs Mar 3, 2025
eb08eb0
web: First version of VolumeGroupEditor
ancorgs Mar 3, 2025
c0764ff
web: Add list of logical volumes
ancorgs Mar 3, 2025
552352d
web: add initial storage model hook
joseivanlopez Mar 6, 2025
8555ca7
web: use model hook
joseivanlopez Mar 6, 2025
4c46f93
web: add basic test for config editor
joseivanlopez Mar 6, 2025
e6cf582
storage: make global encryption to work with LVM
joseivanlopez Mar 7, 2025
8668a57
service: changelog
joseivanlopez Mar 7, 2025
0dd659f
rust: changelog
joseivanlopez Mar 7, 2025
7d64c00
web: changelog
joseivanlopez Mar 7, 2025
2dfb8d2
web: rename utils file
joseivanlopez Mar 10, 2025
44a7bb6
web: extract components
joseivanlopez Mar 10, 2025
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
28 changes: 28 additions & 0 deletions rust/agama-lib/share/examples/storage/model.json
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,34 @@
}
}
]
},
{
"name": "/dev/vdc",
"alias": "lvm",
"spacePolicy": "delete"
}
],
"volumeGroups": [
{
"name": "vg0",
"extentSize": 1024,
"targetDevices": ["lvm"],
"logicalVolumes": [
{
"name": "lv0",
"mountPath": "/data",
"filesystem": {
"default": false,
"type": "ext4"
},
"size": {
"default": true,
"min": 1111
},
"stripes": 8,
"stripeSize": 1204
}
]
}
]
}
33 changes: 33 additions & 0 deletions rust/agama-lib/share/storage.model.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
"drives": {
"type": "array",
"items": { "$ref": "#/$defs/drive" }
},
"volumeGroups": {
"type": "array",
"items": { "$ref": "#/$defs/volumeGroup" }
}
},
"$defs": {
Expand Down Expand Up @@ -79,6 +83,35 @@
"resizeIfNeeded": { "type": "boolean" }
}
},
"volumeGroup": {
"type": "object",
"additionalProperties": false,
"required": ["name"],
"properties": {
"name": { "type": "string" },
"extentSize": { "type": "integer" },
"targetDevices": {
"type": "array",
"items": { "$ref": "#/$defs/alias" }
},
"logicalVolumes": {
"type": "array",
"items": { "$ref": "#/$defs/logicalVolume" }
}
}
},
"logicalVolume": {
"type": "object",
"additionalProperties": false,
"properties": {
"name": { "type": "string" },
"mountPath": { "type": "string" },
"filesystem": { "$ref": "#/$defs/filesystem" },
"size": { "$ref": "#/$defs/size" },
"stripes": { "type": "integer" },
"stripeSize": { "type": "integer" }
}
},
"alias": {
"description": "Alias used to reference a device.",
"type": "string"
Expand Down
1 change: 1 addition & 0 deletions rust/agama-lib/share/storage.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@
"description": "LVM volume group.",
"type": "object",
"additionalProperties": false,
"required": ["name"],
"properties": {
"name": {
"description": "Volume group name.",
Expand Down
5 changes: 5 additions & 0 deletions rust/package/agama.changes
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
-------------------------------------------------------------------
Fri Mar 7 11:40:56 UTC 2025 - José Iván López González <jlopez@suse.com>

- Extend storage model schema with LVM (gh#agama-project/agama#2089).

-------------------------------------------------------------------
Thu Mar 6 12:51:42 UTC 2025 - Imobach Gonzalez Sosa <igonzalezsosa@suse.com>

Expand Down
16 changes: 13 additions & 3 deletions service/lib/agama/storage/config_checkers/volume_group.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# frozen_string_literal: true

# Copyright (c) [2024] SUSE LLC
# Copyright (c) [2024-2025] SUSE LLC
#
# All Rights Reserved.
#
Expand Down Expand Up @@ -41,23 +41,33 @@ def initialize(config, storage_config, product_config)
@config = config
end

# Volume group config issues.
# Issues from a volume group config.
#
# @return [Array<Issue>]
def issues
[
name_issue,
logical_volumes_issues,
physical_volumes_issues,
physical_volumes_devices_issues,
physical_volumes_encryption_issues
].flatten
].compact.flatten
end

private

# @return [Configs::VolumeGroup]
attr_reader :config

# Issue if the volume group name is missing.
#
# @return [Issue, nil]
def name_issue
return if config.name && !config.name.empty?

error(_("There is a volume group without name"))
end

# Issues from logical volumes.
#
# @return [Array<Issue>]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,11 @@
require "agama/storage/config_conversions/to_model_conversions/drive"
require "agama/storage/config_conversions/to_model_conversions/encryption"
require "agama/storage/config_conversions/to_model_conversions/filesystem"
require "agama/storage/config_conversions/to_model_conversions/logical_volume"
require "agama/storage/config_conversions/to_model_conversions/partition"
require "agama/storage/config_conversions/to_model_conversions/size"
require "agama/storage/config_conversions/to_model_conversions/space_policy"
require "agama/storage/config_conversions/to_model_conversions/volume_group"

module Agama
module Storage
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
require "agama/storage/config_conversions/to_model_conversions/boot"
require "agama/storage/config_conversions/to_model_conversions/encryption"
require "agama/storage/config_conversions/to_model_conversions/drive"
require "agama/storage/config_conversions/to_model_conversions/volume_group"

module Agama
module Storage
Expand All @@ -41,9 +42,10 @@ def initialize(config)
# @see Base#conversions
def conversions
{
boot: convert_boot,
encryption: convert_encryption,
drives: convert_drives
boot: convert_boot,
encryption: convert_encryption,
drives: convert_drives,
volumeGroups: convert_volume_groups
}
end

Expand All @@ -65,9 +67,14 @@ def convert_drives
valid_drives.map { |d| ToModelConversions::Drive.new(d).convert }
end

# @return [Array<Hash>]
def convert_volume_groups
config.volume_groups.map { |v| ToModelConversions::VolumeGroup.new(v).convert }
end

# @return [Array<Configs::Drive>]
def valid_drives
config.drives.select(&:found_device)
config.drives.reject { |d| d.search&.skip_device? }
end

# TODO: proper support for a base encryption.
Expand All @@ -81,19 +88,37 @@ def base_encryption
root_encryption || first_encryption
end

# Encryption from root partition.
# Encryption for root.
#
# @return [Configs::Encryption, nil] nil if there is no encryption for root partition.
# @note If root is a logical volume, then the encryption of the automatically generated
# physical volumes is considered. Encryption from logical volumes is ignored.
#
# @return [Configs::Encryption, nil] nil if there is no encryption for root.
def root_encryption
root_partition = config.partitions.find { |p| p.filesystem&.root? }
root_partition&.encryption
root_partition&.encryption || root_volume_group&.physical_volumes_encryption
end

# Encryption from the first encrypted partition.
# Partition config for root.
#
# @return [Configs::Encryption, nil] nil if there is no encrypted partition.
# @return [Configs::Partition, nil]
def root_partition
config.partitions.find(&:root?)
end

# Volume group config containing a logical volume for root.
#
# @return [Configs::LogicalVolume, nil]
def root_volume_group
config.volume_groups.find { |v| v.logical_volumes.any?(&:root?) }
end

# Encryption from the first encrypted partition or from the first volume group with
# automatically generated and encrypted physical volumes.
#
# @return [Configs::Encryption, nil]
def first_encryption
config.partitions.find(&:encryption)&.encryption
config.partitions.find(&:encryption)&.encryption ||
config.volume_groups.find(&:physical_volumes_encryption)&.physical_volumes_encryption
end
end
end
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# frozen_string_literal: true

# Copyright (c) [2024] SUSE LLC
# Copyright (c) [2024-2025] SUSE LLC
#
# All Rights Reserved.
#
Expand Down Expand Up @@ -45,7 +45,7 @@ def initialize(config)
# @see Base#conversions
def conversions
{
name: config.found_device&.name,
name: convert_name,
alias: config.alias,
mountPath: config.filesystem&.path,
filesystem: convert_filesystem,
Expand All @@ -54,6 +54,11 @@ def conversions
partitions: convert_partitions
}
end

# @return [String, nil]
def convert_name
config.found_device&.name || config.search&.name
end
end
end
end
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# frozen_string_literal: true

# Copyright (c) [2025] 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 "agama/storage/config_conversions/to_model_conversions/base"
require "agama/storage/config_conversions/to_model_conversions/with_filesystem"
require "agama/storage/config_conversions/to_model_conversions/with_size"

module Agama
module Storage
module ConfigConversions
module ToModelConversions
# LVM logical volume conversion to model according to the JSON schema.
class LogicalVolume < Base
include WithFilesystem
include WithSize

# @param config [Configs::LogicalVolume]
def initialize(config)
super()
@config = config
end

private

# @see Base#conversions
def conversions
{
name: config.name,
alias: config.alias,
mountPath: config.filesystem&.path,
filesystem: convert_filesystem,
size: convert_size,
stripes: config.stripes,
stripeSize: config.stripe_size&.to_i
}
end
end
end
end
end
end
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# frozen_string_literal: true

# Copyright (c) [2024] SUSE LLC
# Copyright (c) [2024-2025] SUSE LLC
#
# All Rights Reserved.
#
Expand Down Expand Up @@ -39,11 +39,16 @@ def initialize(config)
def conversions
{
default: config.default?,
min: config.min&.to_i,
min: convert_min_size,
max: convert_max_size
}
end

# @return [Integer]
def convert_min_size
config.min&.to_i || 0
end

# @return [Integer, nil]
def convert_max_size
max = config.max
Expand Down
Loading