Skip to content

Commit

Permalink
feature: Device and boot selection (#1127)
Browse files Browse the repository at this point in the history
Merging feature branch which includes:

* #1068
* #1106
  • Loading branch information
joseivanlopez authored Apr 4, 2024
2 parents e63f418 + 2adc9bb commit 6291da5
Show file tree
Hide file tree
Showing 76 changed files with 5,111 additions and 2,141 deletions.
9 changes: 1 addition & 8 deletions doc/dbus/bus/org.opensuse.Agama.Storage1.Proposal.bus.xml
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,7 @@
</signal>
</interface>
<interface name="org.opensuse.Agama.Storage1.Proposal">
<property type="s" name="BootDevice" access="read"/>
<property type="b" name="LVM" access="read"/>
<property type="as" name="SystemVGDevices" access="read"/>
<property type="s" name="EncryptionPassword" access="read"/>
<property type="s" name="EncryptionMethod" access="read"/>
<property type="s" name="EncryptionPBKDFunction" access="read"/>
<property type="s" name="SpacePolicy" access="read"/>
<property type="aa{sv}" name="Volumes" access="read"/>
<property type="a{sv}" name="Settings" access="read"/>
<property type="aa{sv}" name="Actions" access="read"/>
</interface>
</node>
54 changes: 38 additions & 16 deletions doc/dbus/org.opensuse.Agama.Storage1.Proposal.Calculator.doc.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,14 @@
<!--
MountPath s
MountOptions as
Target s
TargetDevice s (only makes sense if Target is not default)
Target s (options: "default", "new_partition", "new_vg", "device", "filesystem")
TargetDevice s (only makes sense if Target is not "default")
FsType s
MinSize t (bytes)
MaxSize t (bytes. Optional, max size is considered as unlimited if omitted)
AutoSize b
Snapshots b
Snapshots b (makes sense only for btrfs)
Transactional b (makes sense only for btrfs)
Outline a{sv}
Required b
FsTypes as
Expand All @@ -39,20 +40,41 @@
Calculates a new proposal.
-->
<method name="Calculate">
<!--
BootDevice s
LVM b
SystemVGDevices as
EncryptionPassword s
EncryptionMethod s
EncryptionPBKDFunction s
SpacePolicy s
SpaceActions a{ss}
Volumes aa{sv}
List of volumes to create. The values for each volume are the same as the values returned
by DefaultVolume method. The Outline (if given) would be ignored.
-->
<!--
Target s (options: "disk", "newLvmVg", "reusedLvmVg")
TargeDevice s (optional: does not make sense if Target is "newLvmVg")
TargetPVDevices as (optional: only makes sense if Target is "newLvmVg")
ConfigureBoot b
BootDevice s
EncryptionPassword s
EncryptionMethod s
EncryptionPBKDFunction s
SpacePolicy s
SpaceActions aa{sv}
Volumes aa{sv}
Each space action has the following properties:
Device s
Action s (options: "force_delete", "resize")
Each volume has the following properties:
MountPath s
MountOptions as
Target s (options: "default", "new_partition", "new_vg", "device", "filesystem")
TargetDevice s (only makes sense if Target is not "default")
FsType s
MinSize t (bytes)
MaxSize t (bytes. Optional, max size is considered as unlimited if omitted)
AutoSize b
Snapshots b (makes sense only for btrfs)
Transactional b (makes sense only for btrfs)
-->
<arg name="settings" direction="in" type="a{sv}"/>
<!--
Whether the proposal was correctly calculated:
0: success
1: failure
-->
<arg name="result" direction="out" type="u"/>
</method>
<property type="ao" name="AvailableDevices" access="read"/>
Expand Down
37 changes: 24 additions & 13 deletions doc/dbus/org.opensuse.Agama.Storage1.Proposal.doc.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,36 @@
Interfaces with the properties of the calculated proposal.
-->
<interface name="org.opensuse.Agama.Storage1.Proposal">
<property type="s" name="BootDevice" access="read"/>
<property type="b" name="LVM" access="read"/>
<property type="as" name="SystemVGDevices" access="read"/>
<property type="s" name="EncryptionPassword" access="read"/>
<property type="s" name="EncryptionMethod" access="read"/>
<property type="s" name="EncryptionPBKDFunction" access="read"/>
<property type="s" name="SpacePolicy" access="read"/>
<!--
List of volumes used for calculating the proposal.
Proposal settings:
Target s (options: "disk", "newLvmVg", "reusedLvmVg")
TargeDevice s (optional: does not make sense if Target is "newLvmVg")
TargetPVDevices as (optional: only makes sense if Target is "newLvmVg")
ConfigureBoot b
BootDevice s
DefaultBootDevice s
EncryptionPassword s
EncryptionMethod s
EncryptionPBKDFunction s
SpacePolicy s
SpaceActions aa{sv}
Volumes aa{sv}
Each space action has the following properties:
Device s
Action s (options: "force_delete", "resize")
Each volume has the following properties:
MountPath s
MountOptions as
Target s
TargetDevice s (only makes sense if Target is not default)
Target s (options: "default", "new_partition", "new_vg", "device", "filesystem")
TargetDevice s (only makes sense if Target is not "default")
FsType s
MinSize t (bytes)
MaxSize t (bytes. Optional, max size is considered as unlimited if omitted)
AutoSize b
Snapshots b ( makes sense only for btrfs )
Transactional b ( makes sense only for btrfs )
Snapshots b (makes sense only for btrfs)
Transactional b (makes sense only for btrfs)
Outline a{sv}
Required b
FsTypes as
Expand All @@ -32,10 +42,11 @@
SnapshotsAffectSizes b
SizeRelevantVolumes as
-->
<property type="aa{sv}" name="Volumes" access="read"/>
<property type="a{sv}" name="Settings" access="read"/>
<!--
Actions to perform in the system in order to create the volumes.
Each action has the following properties:
Device s
Text s
Subvol b
Delete b
Expand Down
8 changes: 5 additions & 3 deletions service/Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
PATH
remote: .
specs:
agama (7)
agama-yast (7.devel737)
cfa (~> 1.0.2)
cfa_grub2 (~> 2.0.0)
cheetah (~> 1.0.0)
Expand All @@ -26,7 +26,9 @@ GEM
docile (1.4.0)
eventmachine (1.2.7)
fast_gettext (2.3.0)
nokogiri (1.15.5-x86_64-linux)
mini_portile2 (2.8.5)
nokogiri (1.15.5)
mini_portile2 (~> 2.8.2)
racc (~> 1.4)
packaging_rake_tasks (1.5.4)
rake
Expand Down Expand Up @@ -63,7 +65,7 @@ PLATFORMS
x86_64-linux-gnu

DEPENDENCIES
agama!
agama-yast!
byebug
packaging_rake_tasks (~> 1.5.1)
rake (~> 13.0.6)
Expand Down
154 changes: 154 additions & 0 deletions service/lib/agama/dbus/hash_validator.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
# 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.

require "agama/dbus/types"

module Agama
module DBus
# Validates a Hash (dictionary) from D-Bus according to an scheme.
#
# This validation is useful to check the expected types of a D-Bus call when some parameter is
# a dictionary with variant types.
#
# @example
# # Let's say there is a D-Bus method with the following signature:
#
# dbus_method :Calculate, "in settings:a{sv}"
#
# # The settings parameter will be transformed to a ruby Hash and this class allows to
# # validate the types of the hash values.
#
# scheme = {
# "ID" => Integer,
# "Name" => String,
# "Children" => Agama::DBus::Types.Array.new(Integer)
# }
#
# value1 = { "ID" => 10, "Name" => "Foo", "Color" => "red" }
# validator = HashValidator.new(value1, scheme: scheme)
# validator.valid? #=> true
# validator.missing_keys #=> ["Children"]
# validator.extra_keys #=> ["Color"]
# validator.issues #=> ["Unknown D-Bus property Color"]
#
# value2 = { "ID" => 10, "Name" => 33 }
# validator = HashValidator.new(value2, scheme: scheme)
# validator.valid? #=> false
# validator.missing_keys #=> ["Children"]
# validator.wrong_type_keys #=> ["Name"]
# validator.issues.size #=> 1
class HashValidator
# @param value [Hash{String => Object}] Hash to validate.
# @param scheme [Hash{String => Class, Types::BOOL, Types::Array, Types::Hash}] Scheme
# for validating the hash.
def initialize(value, scheme:)
@value = value
@scheme = scheme
end

# Whether the hash is valid.
#
# The hash is consider as valid if there is no key with wrong type. Missing and extra keys are
# not validated.
#
# @return [Boolean]
def valid?
wrong_type_keys.none?
end

# Keys with correct type.
#
# Missing and extra keys are ignored.
#
# @return [Array<String>]
def valid_keys
value.keys.select { |k| valid_key?(k) }
end

# Keys with incorrect type.
#
# Missing and extra keys are ignored.
#
# @return [Array<String>]
def wrong_type_keys
value.keys.select { |k| !extra_key?(k) && wrong_type_key?(k) }
end

# Keys not included in the scheme.
#
# @return [Array<String>]
def extra_keys
value.keys.select { |k| extra_key?(k) }
end

# Keys included in the scheme but missing in the hash value.
#
# @return [Array<String>]
def missing_keys
scheme.keys - value.keys
end

# List of issues.
#
# There is an issue for each extra key and for each key with wrong type.
#
# @return [Array<String>]
def issues
issues = []

extra_keys.map do |key|
issues << "Unknown D-Bus property #{key}"
end

wrong_type_keys.map do |key|
type = scheme[key]
value = self.value[key]

issues << "D-Bus property #{key} must be #{type}: #{value} (#{value.class})"
end

issues
end

private

# @return [Hash{String => Object}]
attr_reader :value

# @return [Hash{String => Class, Types::BOOL, Types::Array, Types::Hash}]
attr_reader :scheme

def valid_key?(key)
!(extra_key?(key) || wrong_type_key?(key))
end

def extra_key?(key)
!scheme.keys.include?(key)
end

def wrong_type_key?(key)
type = scheme[key]
checker = Types::Checker.new(type)
!checker.match?(value[key])
end
end
end
end
15 changes: 13 additions & 2 deletions service/lib/agama/dbus/storage/interfaces/device/drive.rb
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,10 @@ def drive_model
#
# @return [String]
def drive_bus
storage_device.bus || ""
# FIXME: not sure whether checking for "none" is robust enough
return "" if storage_device.bus.nil? || storage_device.bus.casecmp?("none")

storage_device.bus
end

# Bus Id for DASD
Expand All @@ -110,7 +113,15 @@ def drive_driver
def drive_transport
return "" unless storage_device.respond_to?(:transport)

storage_device.transport.to_s
transport = storage_device.transport
return "" if transport.nil? || transport.is?(:unknown)

# FIXME: transport does not have proper i18n support at yast2-storage-ng, so we are
# just duplicating some logic from yast2-storage-ng here
return "USB" if transport.is?(:usb)
return "IEEE 1394" if transport.is?(:sbp)

transport.to_s
end

# More info about the device
Expand Down
4 changes: 3 additions & 1 deletion service/lib/agama/dbus/storage/manager.rb
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,9 @@ def default_volume(mount_path)
# @param dbus_settings [Hash]
# @return [Integer] 0 success; 1 error
def calculate_proposal(dbus_settings)
settings = ProposalSettingsConversion.from_dbus(dbus_settings, config: config)
settings = ProposalSettingsConversion.from_dbus(dbus_settings,
config: config, logger: logger)

logger.info(
"Calculating storage proposal from D-Bus.\n " \
"D-Bus settings: #{dbus_settings}\n" \
Expand Down
Loading

0 comments on commit 6291da5

Please sign in to comment.