Skip to content

Commit

Permalink
restore (enable) the Updates repositories (bsc#943960)
Browse files Browse the repository at this point in the history
...at the end of the migration workflow

Conflicts:
	src/lib/registration/ui/media_addon_workflow.rb
	test/media_addon_workflow_spec.rb
	test/registration_ui_test.rb
	test/sw_mgmt_spec.rb
  • Loading branch information
lslezak committed Sep 7, 2015
1 parent 8346792 commit 18fb514
Show file tree
Hide file tree
Showing 14 changed files with 504 additions and 29 deletions.
2 changes: 2 additions & 0 deletions package/yast2-registration.changes
Expand Up @@ -2,6 +2,8 @@
Tue Sep 2 10:27:28 UTC 2015 - lslezak@suse.cz

- disable "Back" at the initial dialog
- restore (enable) the Updates repositories at the end of the
migration workflow (bsc#943960)

-------------------------------------------------------------------
Wed Sep 2 08:11:42 UTC 2015 - lslezak@suse.cz
Expand Down
38 changes: 38 additions & 0 deletions src/clients/migration_finish.rb
@@ -0,0 +1,38 @@
# ------------------------------------------------------------------------------
# Copyright (c) 2015 SUSE LLC
#
# 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.
#
# ------------------------------------------------------------------------------
#

require "yast"
require "registration/ui/migration_finish_workflow"

module Yast
class MigrationFinishClient < Client
Yast.import "Wizard"

def main
textdomain "registration"

# create the Wizard dialog if needed
wizard_present = Wizard.IsWizardDialog
Wizard.CreateDialog unless wizard_present

begin
::Registration::UI::MigrationFinishWorkflow.run
ensure
Wizard.CloseDialog unless wizard_present
end
end
end unless defined?(YaST::MigrationFinishClient)
end

Yast::MigrationFinishClient.new.main
2 changes: 1 addition & 1 deletion src/clients/migration_repos.rb
Expand Up @@ -27,7 +27,7 @@ def main
Wizard.CreateDialog unless wizard_present

begin
::Registration::UI::MigrationReposWorkflow.run(*Yast::WFM.Args)
::Registration::UI::MigrationReposWorkflow.run
ensure
Wizard.CloseDialog unless wizard_present
end
Expand Down
16 changes: 1 addition & 15 deletions src/lib/registration/finish_dialog.rb
Expand Up @@ -43,7 +43,7 @@ def run(*args)
return nil unless Registration.is_registered?

# enable back the update repositories in the installed system
revert_repository_changes
RepoStateStorage.instance.restore_all

Yast.import "Installation"

Expand All @@ -63,19 +63,5 @@ def run(*args)
raise "Uknown action #{func} passed as first parameter"
end
end

private

# revert back the original repository states from the registration server
def revert_repository_changes
changed_repos = RepoStateStorage.instance.repositories
return if changed_repos.empty?

# activate the original repository states
changed_repos.each(&:restore)

# save all repositories
Yast::Pkg.SourceSaveAll
end
end
end
86 changes: 86 additions & 0 deletions src/lib/registration/repo_state.rb
Expand Up @@ -22,6 +22,7 @@
#

require "singleton"
require "yaml"

require "yast"

Expand All @@ -30,14 +31,94 @@ module Registration

# storage for changed repositories
class RepoStateStorage
include Yast::Logger
include Singleton

# array of RepoState objects
attr_accessor :repositories

# location of the persistent storage (to store the data when restarting YaST)
REPO_STATE_FILE = "/var/lib/YaST2/migration_repo_state.yml"

def initialize
@repositories = []
end

# @param [String] repo_id repository ID
# @param [Boolean] enabled the repository state to set
# (true = enable the repository, false = disable)
def add(repo_id, enabled)
repositories << RepoState.new(repo_id, enabled)
end

# restore all saved states
def restore_all
return if repositories.empty?

# activate the original repository states
repositories.each(&:restore)

# save all repositories
Yast::Pkg.SourceSaveAll
end

# write the current state to the persistent storage (to survive YaST restart)
def write
data = {}

# repo_id => alias mapping
repo_mapping = repository_mapping

repositories.each do |repository|
data[repo_mapping[repository.repo_id]] = repository.enabled
end

log.info "Exporting repository state: #{data.inspect}"
File.write(REPO_STATE_FILE, data.to_yaml)
end

# read the stored state from the persistent storage
def read
# reset the previous list
self.repositories = []

return unless File.exist?(REPO_STATE_FILE)

# inverse alias => repo_id mapping
repo_mapping = repository_mapping.invert

data = YAML.load_file(REPO_STATE_FILE)
log.info "Importing repository state: #{data}"

data.each do |repo_alias, enabled|
if repo_mapping[repo_alias]
add(repo_mapping[repo_alias], enabled)
else
log.warn "Repository #{repo_alias.inspect} is missing"
end
end
end

# clean the persistent storage
def clean
File.unlink(REPO_STATE_FILE) if File.exist?(REPO_STATE_FILE)
end

private

# create repository mapping repo_id => alias
# @return [Hash<Fixnum>,String>] the current repository mapping
def repository_mapping
ret = {}

Yast::Pkg.SourceGetCurrent(false).each do |repo|
ret[repo] = Yast::Pkg.SourceGeneralData(repo)["alias"]
end

log.info "Current repository setup: #{ret.inspect}"

ret
end
end

# store repository ID and it's original state (enabled/disabled)
Expand All @@ -46,11 +127,16 @@ class RepoState

attr_reader :repo_id, :enabled

# create repository state status
# @param [Fixnum] repo_id repository ID
# @param [Boolean] enabled the repository state to set
# (true = enable the repository, false = disable)
def initialize(repo_id, enabled)
@repo_id = repo_id
@enabled = enabled
end

# set the saved repository state
def restore
log.info "Restoring the original repository state: id: #{repo_id}, enabled: #{enabled}"
Yast::Pkg.SourceSetEnabled(repo_id, enabled)
Expand Down
8 changes: 5 additions & 3 deletions src/lib/registration/sw_mgmt.rb
Expand Up @@ -56,7 +56,9 @@ class SwMgmt

OEM_DIR = "/var/lib/suseRegister/OEM"

def self.init
# initialize the package management
# @param [Boolean] load_packages load also the available packages from the repositories
def self.init(load_packages = false)
# false = do not allow continuing without the libzypp lock
lock = PackageLock.Connect(false)
return false unless lock["connected"]
Expand All @@ -66,6 +68,7 @@ def self.init
Pkg.TargetInitialize(Installation.destdir)
Pkg.TargetLoad
Pkg.SourceRestore
load_packages ? Pkg.SourceLoad : true
end

# during installation /etc/zypp directory is not writable (mounted on
Expand Down Expand Up @@ -294,8 +297,7 @@ def self.set_repos_state(repos, enabled)
next if repo["enabled"] == enabled

# remember the original state
repo_state = RepoState.new(repo["SrcId"], repo["enabled"])
RepoStateStorage.instance.repositories << repo_state
RepoStateStorage.instance.add(repo["SrcId"], repo["enabled"])

log.info "Changing repository state: #{repo["name"]} enabled: #{enabled}"
Pkg.SourceSetEnabled(repo["SrcId"], enabled)
Expand Down
91 changes: 91 additions & 0 deletions src/lib/registration/ui/migration_finish_workflow.rb
@@ -0,0 +1,91 @@
# ------------------------------------------------------------------------------
# Copyright (c) 2015 SUSE LLC
#
# 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.
#
# ------------------------------------------------------------------------------
#

require "yast"

require "registration/repo_state"

module Registration
module UI
# This class handles the workflow for finishing the online migration
class MigrationFinishWorkflow
include Yast::Logger
include Yast::I18n
include Yast::UIShortcuts

Yast.import "Report"
Yast.import "Sequencer"

# run workflow for adding the migration services
# @return [Symbol] the UI symbol
def self.run
workflow = MigrationFinishWorkflow.new
workflow.run
end

# the constructor
def initialize
textdomain "registration"
end

# The migration finish workflow is:
# - restore the saved repository states (i.e. enable the Updates
# repositories when they were disabled during migration)
def run
ret = nil
begin
ret = run_sequence
rescue => e
log.error "Caught error: #{e.class}: #{e.message.inspect}, #{e.backtrace}"
# TRANSLATORS: error message, %s are details
Yast::Report.Error(_("Internal error: %s") % e.message)
ret = :abort
end

ret
end

private

WORKFLOW_SEQUENCE = {
"ws_start" => "restore_repos",
"restore_repos" => {
abort: :abort,
next: :next
}
}

# run the workflow
# @return [Symbol] the UI symbol
def run_sequence
aliases = {
"restore_repos" => ->() { restore_repos }
}

ui = Yast::Sequencer.Run(aliases, WORKFLOW_SEQUENCE)
log.info "User input: #{ui}"
ui
end

# restore all saved repository states
def restore_repos
log.info "Restoring the original repository setup..."
repo_state = RepoStateStorage.instance
repo_state.read
repo_state.restore_all
:next
end
end
end
end
24 changes: 15 additions & 9 deletions src/lib/registration/ui/migration_repos_workflow.rb
Expand Up @@ -122,12 +122,15 @@ def run
abort: :abort,
cancel: :abort,
repo_selection: "select_migration_repos",
next: :next
next: "store_repos_state"
},
"select_migration_repos" => {
abort: :abort,
cancel: :abort,
next: :next
next: "store_repos_state"
},
"store_repos_state" => {
next: :next
}
}

Expand All @@ -140,7 +143,8 @@ def run_sequence
"select_migration_products" => ->() { select_migration_products },
"register_migration_products" => [->() { register_migration_products }, true],
"activate_migration_repos" => [->() { activate_migration_repos }, true],
"select_migration_repos" => ->() { select_migration_repos }
"select_migration_repos" => ->() { select_migration_repos },
"store_repos_state" => ->() { store_repos_state }
}

ui = Yast::Sequencer.Run(aliases, WORKFLOW_SEQUENCE)
Expand All @@ -153,14 +157,11 @@ def run_sequence
def find_products
log.info "Loading installed products"

if !SwMgmt.init
if !SwMgmt.init(true)
Yast::Report.Error(Yast::Pkg.LastError)
return :abort
end

# load the resolvables from the repositories
Yast::Pkg.SourceLoad

self.products = ::Registration::SwMgmt.installed_products.map do |product|
::Registration::SwMgmt.remote_product(product)
end
Expand Down Expand Up @@ -256,8 +257,8 @@ def register_migration_products
# synchronize the changes done by modifying the services,
# reinitialize the repositories and reload the available packages
Yast::Pkg.SourceFinishAll
Yast::Pkg.SourceRestore
Yast::Pkg.SourceLoad
Yast::Pkg.TargetFinish
SwMgmt.init(true)

log.info "Registered services: #{registered_services}"
:next
Expand Down Expand Up @@ -309,6 +310,11 @@ def activate_migration_repos
def select_migration_repos
UI::MigrationReposSelectionDialog.run
end

def store_repos_state
RepoStateStorage.instance.write
:next
end
end
end
end

0 comments on commit 18fb514

Please sign in to comment.