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

Storage reprobing #484

Merged
merged 9 commits into from
Mar 24, 2023
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
6 changes: 6 additions & 0 deletions doc/dbus_api.md
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,12 @@ Install()
Finish()
~~~

##### Properties

~~~
DeprecatedSystem readable b
~~~

#### `org.opensuse.DInstaller.Storage1.Proposal.Calculator` Interface

Allows creating a storage proposal.
Expand Down
35 changes: 34 additions & 1 deletion service/lib/dinstaller/dbus/storage/manager.rb
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ def initialize(backend, logger)
register_progress_callbacks
register_service_status_callbacks
register_iscsi_callbacks
register_software_callbacks
return unless Yast::Arch.s390

singleton_class.include DBus::Interfaces::Dasd
Expand All @@ -71,7 +72,10 @@ def initialize(backend, logger)
private_constant :STORAGE_INTERFACE

def probe
busy_while { backend.probe }
busy_while do
backend.probe
storage_properties_changed
end
end

def install
Expand All @@ -82,10 +86,18 @@ def finish
busy_while { backend.finish }
end

# Whether the system is in a deprecated status
#
# @return [Boolean]
def deprecated_system
backend.deprecated_system
end

dbus_interface STORAGE_INTERFACE do
dbus_method(:Probe) { probe }
dbus_method(:Install) { install }
dbus_method(:Finish) { finish }
dbus_reader(:deprecated_system, "b")
end

PROPOSAL_CALCULATOR_INTERFACE = "org.opensuse.DInstaller.Storage1.Proposal.Calculator"
Expand Down Expand Up @@ -246,6 +258,27 @@ def register_iscsi_callbacks
backend.iscsi.on_probe do
refresh_iscsi_nodes
end

backend.iscsi.on_sessions_change do
deprecate_system
end
end

def register_software_callbacks
backend.software.on_product_selected do |_product|
backend.proposal.reset
end
end

def deprecate_system
backend.deprecated_system = true
storage_properties_changed
update_validation
end

def storage_properties_changed
properties = interfaces_and_properties[STORAGE_INTERFACE]
dbus_properties_changed(STORAGE_INTERFACE, properties, [])
end

def proposal_properties_changed
Expand Down
23 changes: 21 additions & 2 deletions service/lib/dinstaller/storage/iscsi/manager.rb
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ def initialize(logger: nil)

@on_activate_callbacks = []
@on_probe_callbacks = []
@on_sessions_change_callbacks = []
end

# Performs actions for activating iSCSI
Expand Down Expand Up @@ -116,11 +117,14 @@ def login(node, authentication, startup: nil)

ensure_activated

probe_after do
result = probe_after do
Yast::IscsiClientLib.currentRecord = record_from(node)
Yast::IscsiClientLib.login_into_current(authentication, silent: true) &&
Yast::IscsiClientLib.setStartupStatus(startup)
end

run_on_sessions_change_callbacks
result
end

# Closes an iSCSI session
Expand All @@ -132,11 +136,14 @@ def login(node, authentication, startup: nil)
def logout(node)
ensure_activated

probe_after do
result = probe_after do
Yast::IscsiClientLib.currentRecord = record_from(node)
# Yes, this is the correct method name for logging out
Yast::IscsiClientLib.deleteRecord
end

run_on_sessions_change_callbacks
result
end

# Deletes an iSCSI node from the database
Expand Down Expand Up @@ -181,6 +188,13 @@ def on_probe(&block)
@on_probe_callbacks << block
end

# Registers a callback to be called when a session changes
#
# @param block [Proc]
def on_sessions_change(&block)
@on_sessions_change_callbacks << block
end

private

# @return [Logger]
Expand Down Expand Up @@ -248,6 +262,11 @@ def find_session_for(record)
def probe_after(&block)
block.call.tap { probe }
end

# Runs callbacks when a session changes
def run_on_sessions_change_callbacks
@on_sessions_change_callbacks.each(&:call)
end
end
end
end
Expand Down
53 changes: 40 additions & 13 deletions service/lib/dinstaller/storage/manager.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
require "dinstaller/storage/finisher"
require "dinstaller/with_progress"
require "dinstaller/security"
require "dinstaller/validation_error"
require "dinstaller/dbus/clients/questions"
require "dinstaller/dbus/clients/software"

Expand All @@ -40,13 +41,23 @@ module Storage
class Manager
include WithProgress

# Whether the system is in a deprecated status
#
# The system is usually set as deprecated as effect of managing some kind of devices, for
# example, when iSCSI sessions are created.
#
# A deprecated system means that the probed system could not match with the current system.
attr_accessor :deprecated_system

def initialize(config, logger)
@config = config
@logger = logger
@deprecated_system = false
end

# Probes storage devices and performs an initial proposal
def probe
@deprecated_system = false
start_progress(4)
config.pick_product(software.selected_product)
progress.step("Activating storage devices") { activate_devices }
Expand Down Expand Up @@ -97,7 +108,15 @@ def iscsi
#
# @return [Array<ValidationError>] List of validation errors
def validate
proposal.validate
errors = [deprecated_system_error] + proposal.validate
errors.compact
end

# Returns the client to ask the software service
#
# @return [DInstaller::DBus::Clients::Software]
def software
@software ||= DBus::Clients::Software.new
end

private
Expand Down Expand Up @@ -126,12 +145,18 @@ def probe_devices
Y2Storage::StorageManager.instance.probe(Y2Storage::Callbacks::UserProbe.new)
end

# Calculates the default proposal
# Calculates the proposal
#
# It reuses the settings from the previous proposal, if any.
def calculate_proposal
settings = ProposalSettings.new
# FIXME: by now, the UI only allows to select one disk
device = proposal.available_devices.first&.name
settings.candidate_devices << device if device
settings = proposal.settings

if !settings
settings = ProposalSettings.new
# FIXME: by now, the UI only allows to select one disk
device = proposal.available_devices.first&.name
settings.candidate_devices << device if device
end

proposal.calculate(settings)
end
Expand All @@ -146,6 +171,15 @@ def add_packages
Yast::PackagesProposal.SetResolvables(PROPOSAL_ID, :package, packages)
end

# Returns an error if the system is deprecated
#
# @return [ValidationError, nil]
def deprecated_system_error
return unless deprecated_system

ValidationError.new("The system devices have changed")
end

# Security manager
#
# @return [Security]
Expand All @@ -159,13 +193,6 @@ def security
def questions_client
@questions_client ||= DInstaller::DBus::Clients::Questions.new(logger: logger)
end

# Returns the client to ask the software service
#
# @return [DInstaller::DBus::Clients::Software]
def software
@software ||= DBus::Clients::Software.new
end
end
end
end
52 changes: 35 additions & 17 deletions service/lib/dinstaller/storage/proposal.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ module Storage
# proposal.calculate(settings) #=> true
# proposal.calculated_volumes #=> [Volume, Volume]
class Proposal
# Settings used for calculating the proposal
#
# @return [ProposalSettings, nil]
attr_reader :settings

# Constructor
#
# @param logger [Logger]
Expand All @@ -51,6 +56,10 @@ def initialize(logger, config)
@on_calculate_callbacks = []
end

def reset
@settings = nil
end

# Stores callbacks to be call after calculating a proposal
def on_calculate(&block)
@on_calculate_callbacks << block
Expand Down Expand Up @@ -114,14 +123,14 @@ def calculated_settings

# Calculates a new proposal
#
# @param settings [ProposalSettings] settings to calculate the proposal
# @param settings [ProposalSettings, nil] settings to calculate the proposal
# @return [Boolean] whether the proposal was correctly calculated
def calculate(settings = nil)
settings ||= ProposalSettings.new
settings.freeze
proposal_settings = to_y2storage_settings(settings)
@settings = settings || ProposalSettings.new
@settings.freeze
y2storage_settings = to_y2storage_settings(@settings)

@proposal = new_proposal(proposal_settings)
@proposal = new_proposal(y2storage_settings)
storage_manager.proposal = proposal

@on_calculate_callbacks.each(&:call)
Expand All @@ -145,9 +154,10 @@ def validate
return [] if proposal.nil?

[
validate_proposal,
validate_available_devices,
validate_candidate_devices
empty_available_devices_error,
empty_candidate_devices_error,
missing_candidate_devices_error,
proposal_error
].compact
end

Expand Down Expand Up @@ -248,24 +258,32 @@ def storage_manager
Y2Storage::StorageManager.instance
end

def validate_proposal
return if candidate_devices.empty? || !proposal.failed?

ValidationError.new("Cannot accommodate the required file systems for installation")
end

def validate_available_devices
def empty_available_devices_error
return if available_devices.any?

ValidationError.new("There is no suitable device for installation")
end

def validate_candidate_devices
return if available_devices.empty? || candidate_devices.any?
def empty_candidate_devices_error
return if candidate_devices.any?

ValidationError.new("No devices are selected for installation")
end

def missing_candidate_devices_error
available_names = available_devices.map(&:name)
missing = candidate_devices - available_names
return if missing.none?

ValidationError.new("Some selected devices are not found in the system")
end

def proposal_error
return unless proposal.failed?

ValidationError.new("Cannot accommodate the required file systems for installation")
end

# Adjusts the encryption-related settings of the given Y2Storage::ProposalSettings object
#
# @param settings [Y2Storage::ProposalSettings]
Expand Down
7 changes: 7 additions & 0 deletions service/package/rubygem-d-installer.changes
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
-------------------------------------------------------------------
Thu Mar 23 17:04:54 UTC 2023 - José Iván López González <[email protected]>

- Set system as deprecated after changing iSCSI sessions.
- Reuse settings from previous proposal.
- gh#yast/d-installer#484

-------------------------------------------------------------------
Wed Mar 22 16:05:14 UTC 2023 - Knut Anderssen <[email protected]>

Expand Down
Loading