Skip to content

Commit

Permalink
feat(storage): configure boot (#1808)
Browse files Browse the repository at this point in the history
* Add support in the config model for configuring boot. 
* The *Configure boot* option in the *More options* menu goes to the
page for configuring boot.
* Adapt the page for configuring boot to use the new config model hooks.

![localhost_8080_
(20)](https://github.com/user-attachments/assets/9cc18108-cbf2-4359-8115-2a744b936a57)
  • Loading branch information
joseivanlopez authored Dec 20, 2024
2 parents 31f5052 + ce3e1e9 commit e6d8bf4
Show file tree
Hide file tree
Showing 78 changed files with 3,659 additions and 1,572 deletions.
3 changes: 2 additions & 1 deletion rust/agama-lib/share/examples/storage/drives.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@
"storage": {
"boot": {
"configure": true,
"device": "/dev/vda"
"device": "vda"
},
"drives": [
{
"search": "/dev/vda",
"alias": "vda",
"ptableType": "gpt",
"partitions": [
{
Expand Down
7 changes: 7 additions & 0 deletions rust/agama-lib/share/examples/storage/model.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
{
"boot": {
"configure": true,
"device": {
"default": false,
"name": "/dev/vda"
}
},
"drives": [
{
"name": "/dev/vda",
Expand Down
27 changes: 25 additions & 2 deletions rust/agama-lib/share/storage.model.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,38 @@
"type": "object",
"additionalProperties": false,
"properties": {
"boot": { "$ref": "#/$defs/boot" },
"drives": {
"type": "array",
"items": { "$ref": "#/$defs/drive" }
}
},
"$defs": {
"boot": {
"type": "object",
"additionalProperties": false,
"required": ["configure"],
"properties": {
"configure": { "type": "boolean" },
"device": { "$ref": "#/$defs/bootDevice" }
}
},
"bootDevice": {
"type": "object",
"additionalProperties": false,
"required": ["default"],
"properties": {
"default": { "type": "boolean" },
"name": { "type": "string" }
}
},
"drive": {
"type": "object",
"additionalProperties": false,
"required": ["name"],
"properties": {
"name": { "type": "string" },
"alias": { "type": "string" },
"alias": { "$ref": "#/$defs/alias" },
"mountPath": { "type": "string" },
"filesystem": { "$ref": "#/$defs/filesystem" },
"spacePolicy": { "$ref": "#/$defs/spacePolicy" },
Expand All @@ -32,7 +51,7 @@
"additionalProperties": false,
"properties": {
"name": { "type": "string" },
"alias": { "type": "string" },
"alias": { "$ref": "#/$defs/alias" },
"id": { "$ref": "#/$defs/partitionId" },
"mountPath": { "type": "string" },
"filesystem": { "$ref": "#/$defs/filesystem" },
Expand All @@ -43,6 +62,10 @@
"resizeIfNeeded": { "type": "boolean" }
}
},
"alias": {
"description": "Alias used to reference a device.",
"type": "string"
},
"spacePolicy": {
"enum": ["delete", "resize", "keep", "custom"]
},
Expand Down
6 changes: 1 addition & 5 deletions rust/agama-lib/share/storage.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,7 @@
"description": "Whether to configure partitions for booting.",
"type": "boolean"
},
"device": {
"description": "The target installation device is used by default.",
"type": "string",
"examples": ["/dev/vda"]
}
"device": { "$ref": "#/$defs/alias" }
}
},
"driveElement": {
Expand Down
43 changes: 43 additions & 0 deletions service/lib/agama/storage/boot_settings.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# 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.

module Agama
module Storage
# Boot settings.
class BootSettings
# Whether to configure partitions for booting.
#
# @return [Boolean]
attr_accessor :configure
alias_method :configure?, :configure

# Boot device name.
#
# @return [String]
attr_accessor :device

# Constructor
def initialize
@configure = true
end
end
end
end
74 changes: 8 additions & 66 deletions service/lib/agama/storage/config.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@

require "agama/copyable"
require "agama/storage/configs/boot"
require "agama/storage/config_conversions/from_json"

module Agama
module Storage
Expand Down Expand Up @@ -61,11 +60,16 @@ def initialize
@nfs_mounts = []
end

# Name of the device that will presumably be used to boot the target system
# Name of the device that will be used to boot the target system, if any.
#
# @return [String, nil] nil if there is no enough information to infer a possible boot disk
# @note The config has to be solved.
#
# @return [String, nil]
def boot_device
explicit_boot_device || implicit_boot_device
return unless boot.configure? && boot.device.device_alias

boot_drive = drives.find { |d| d.alias?(boot.device.device_alias) }
boot_drive&.found_device&.name
end

# return [Array<Configs::Partition>]
Expand All @@ -77,68 +81,6 @@ def partitions
def logical_volumes
volume_groups.flat_map(&:logical_volumes)
end

private

# Device used for booting the target system
#
# @return [String, nil] nil if no disk is explicitly chosen
def explicit_boot_device
return nil unless boot.configure?

boot.device
end

# Device that seems to be expected to be used for booting, according to the drive definitions
#
# @return [String, nil] nil if the information cannot be inferred from the config
def implicit_boot_device
implicit_drive_boot_device || implicit_lvm_boot_device
end

# @see #implicit_boot_device
#
# @return [String, nil] nil if the information cannot be inferred from the list of drives
def implicit_drive_boot_device
root_drive = drives.find do |drive|
drive.partitions.any? { |p| p.filesystem&.root? }
end

root_drive&.found_device&.name
end

# @see #implicit_boot_device
#
# @return [String, nil] nil if the information cannot be inferred from the list of LVM VGs
def implicit_lvm_boot_device
root_vg = root_volume_group
return nil unless root_vg

root_drives = drives.select { |d| drive_for_vg?(d, root_vg) }
names = root_drives.map { |d| d.found_device&.name }.compact
# Return the first name in alphabetical order
names.min
end

# @see #implicit_lvm_boot_device
#
# @return [Configs::VolumeGroup, nil]
def root_volume_group
volume_groups.find do |vg|
vg.logical_volumes.any? { |lv| lv.filesystem&.root? }
end
end

# @see #implicit_lvm_boot_device
#
# @return [Boolean]
def drive_for_vg?(drive, volume_group)
return true if volume_group.physical_volumes_devices.any? { |d| drive.alias?(d) }

volume_group.physical_volumes.any? do |pv|
drive.partitions.any? { |p| p.alias?(pv) }
end
end
end
end
end
Loading

0 comments on commit e6d8bf4

Please sign in to comment.