Skip to content

Commit

Permalink
rollback registration (FATE#315161)
Browse files Browse the repository at this point in the history
restore the original product registration when online migration is aborted
  • Loading branch information
lslezak committed Sep 22, 2015
1 parent 4d5f3cb commit e432f91
Show file tree
Hide file tree
Showing 12 changed files with 325 additions and 9 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ before_install:
# disable rvm, use system Ruby
- rvm reset
- wget https://raw.githubusercontent.com/yast/yast-devtools/master/travis-tools/travis_setup.sh
- sh ./travis_setup.sh -p "yast2-devtools yast2 yast2-slp yast2-add-on" -g bundler
- sh ./travis_setup.sh -p "yast2-devtools yast2 yast2-slp yast2-add-on yast2-update" -g bundler
script:
- rake check:pot
- rubocop
Expand Down
6 changes: 6 additions & 0 deletions package/yast2-registration.changes
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
-------------------------------------------------------------------
Mon Sep 21 13:53:12 UTC 2015 - lslezak@suse.cz

- restore the original product registration when online migration
is aborted (FATE#315161)

-------------------------------------------------------------------
Wed Sep 16 19:04:05 UTC 2015 - lslezak@suse.cz

Expand Down
6 changes: 4 additions & 2 deletions package/yast2-registration.spec
Original file line number Diff line number Diff line change
Expand Up @@ -32,19 +32,21 @@ Requires: yast2 >= 3.1.26
Requires: yast2-pkg-bindings >= 3.1.27
# N_() method
Requires: yast2-ruby-bindings >= 3.1.12
Requires: rubygem(suse-connect) >= 0.2.18
Requires: rubygem(suse-connect) >= 0.2.22
Requires: yast2-slp >= 3.1.2
Requires: yast2-add-on >= 3.1.8
Requires: yast2-packager >= 3.1.26
Requires: yast2-update >= 3.1.19

BuildRequires: yast2 >= 3.1.26
BuildRequires: update-desktop-files
BuildRequires: yast2-devtools >= 3.1.6
BuildRequires: rubygem(yast-rake) >= 0.1.8
BuildRequires: rubygem(rspec)
BuildRequires: rubygem(suse-connect) >= 0.2.18
BuildRequires: rubygem(suse-connect) >= 0.2.22
BuildRequires: yast2-slp >= 3.1.2
BuildRequires: yast2-packager >= 3.1.26
BuildRequires: yast2-update >= 3.1.19

BuildArch: noarch

Expand Down
38 changes: 38 additions & 0 deletions src/clients/registration_sync.rb
Original file line number Diff line number Diff line change
@@ -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/registration_sync_workflow"

module Yast
class RegistrationSyncClient < 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::RegistrationSyncWorkflow.run
ensure
Wizard.CloseDialog unless wizard_present
end
end
end unless defined?(YaST::RegistrationSyncClient)
end

Yast::RegistrationSyncClient.new.main
30 changes: 30 additions & 0 deletions src/lib/registration/registration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
# ------------------------------------------------------------------------------
#

require "ostruct"
require "yast"
require "suse/connect"

Expand Down Expand Up @@ -85,6 +86,35 @@ def upgrade_product(product)
end
end

# downgrade product registration
# used when restoring the original registration after aborted migration
# @param [Hash] product libzypp product to which the registration should be downgraded
def downgrade_product(product)
service_for_product(product) do |product_ident, params|
log.info "Downgrading product: #{product}"
service = SUSE::Connect::YaST.downgrade_product(product_ident, params)
log.info "Downgrade product result: #{service}"

service
end
end

# synchronize the registedred products on the server with the local installed products

This comment has been minimized.

Copy link
@imobachgs

imobachgs Sep 23, 2015

Contributor

typo registedred -> registered

# (removes all o registrered products)

This comment has been minimized.

Copy link
@imobachgs

imobachgs Sep 23, 2015

Contributor

typo? removes all o registered products

This comment has been minimized.

Copy link
@lslezak

lslezak Sep 23, 2015

Author Member

Ouch, too many typos, looks like we should enhance the rake check:spelling task to also check the code comments...

# @param [Array<Hash>] products list of installed libzypp products
def synchronize_products(products)
remote_products = products.map do |product|
OpenStruct.new(
arch: product["arch"],
identifier: product["name"],
version: product["version_version"],
release_type: product["release_type"]
)
end
log.info "Synchronizing products: #{remote_products}"
SUSE::Connect::YaST.synchronize(remote_products)
end

# @param [String] target_distro new target distribution
# @return [OpenStruct] SCC response
def update_system(target_distro = nil)
Expand Down
34 changes: 34 additions & 0 deletions src/lib/registration/registration_ui.rb
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,40 @@ def update_addons(addons, enable_updates: true)
failed_addons
end

# downgrade product registration
# @param [Hash] product libzypp product which registration will be downgraded
# @return [Array<Boolean, OpenStruct>] a pair with success flag and the
# registered remote service
def downgrade_product(product)
product_service = nil
success = ConnectHelpers.catch_registration_errors do
product_service = Yast::Popup.Feedback(
_(CONTACTING_MESSAGE),
# updating product registration, %s is a product name
_("Updating to %s ...") % SwMgmt.product_label(product)
) do
registration.downgrade_product(product)
end
end

[success, product_service]
end

# synchronize the local products with the registration server
# @param [Array<Hash>] products libzypp products to synchronize
# @return [Boolean] true on success
def synchronize_products(products)
ConnectHelpers.catch_registration_errors do
Yast::Popup.Feedback(
_(CONTACTING_MESSAGE),
# TRANSLATORS: progress label
_("Synchronizing Products...")
) do
registration.synchronize_products(products)
end
end
end

# load available addons from SCC server
# the result is cached to avoid reloading when going back and forth in the
# installation workflow
Expand Down
5 changes: 3 additions & 2 deletions src/lib/registration/sw_mgmt.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
require "tmpdir"
require "fileutils"
require "shellwords"
require "ostruct"

require "registration/exceptions"
require "registration/helpers"
Expand Down Expand Up @@ -135,7 +136,7 @@ def self.installed_products
# @param product [Hash] product Hash obtained from pkg-bindings
# @return [SUSE::Connect::Remote::Product] the remote product
def self.remote_product(product)
SUSE::Connect::Remote::Product.new(
OpenStruct.new(
arch: product["arch"],
identifier: product["name"],
version: product["version"],
Expand Down Expand Up @@ -477,6 +478,6 @@ def self.raise_pkg_exception
raise PkgError.new, Pkg.LastError
end

private_class_method :each_repo, :get_release_type
private_class_method :each_repo
end
end
1 change: 1 addition & 0 deletions src/lib/registration/ui/migration_repos_workflow.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
require "registration/migration_repositories"
require "registration/releasever"
require "registration/sw_mgmt"
require "registration/url_helpers"
require "registration/ui/migration_selection_dialog"
require "registration/ui/migration_repos_selection_dialog"

Expand Down
110 changes: 110 additions & 0 deletions src/lib/registration/ui/registration_sync_workflow.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
# ------------------------------------------------------------------------------
# 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/registration_ui"
require "registration/sw_mgmt"
require "registration/url_helpers"

module Registration
module UI
# This class handles synchronizing the repositories/services after abort
class RegistrationSyncWorkflow
include Yast::Logger
include Yast::I18n
include Yast::UIShortcuts

Yast.import "Report"
Yast.import "Pkg"
Yast.import "Update"
Yast.import "Installation"

# run the registration synchronization
# @return [Symbol] the UI symbol (:next on sucess, :abort on error)
def self.run
workflow = RegistrationSyncWorkflow.new
workflow.run
end

# the constructor
def initialize
textdomain "registration"

registration = Registration.new(UrlHelpers.registration_url)
self.registration_ui = RegistrationUI.new(registration)
end

# run the registration synchronization
# @return [Symbol] the UI symbol (:next on sucess, :abort on error)
def run
rollback
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)
return :abort
end

private

attr_accessor :registration_ui

# restore the registration status
# @return [Symbol] :next on sucess, :abort on error
def rollback
log.info "Restoring the original repository and registration status..."

restore_repos

# load the installed products
Yast::Pkg.TargetLoad
products = SwMgmt.installed_products

# downgrade all installed products
return :abort unless downgrade_products(products)

reload_repos

# synchronize all installed products (remove additional registrations at the server)
registration_ui.synchronize_products(products) ? :next : :abort
end

# restore the repositpories from the backup archive
def restore_repos
# finish the sources and the target to reload the repositories from the backup
Yast::Pkg.SourceFinishAll
Yast::Pkg.TargetFinish
Yast::Update.restore_backup
Yast::Pkg.TargetInitialize(Yast::Installation.destdir)
end

# reload the repositories to synchronize the changes
def reload_repos
Yast::Pkg.SourceFinishAll
Yast::Pkg.SourceRestore
end

# downgrade product registrations (restore the original status before upgrading)
# @return [Boolean] true on success
def downgrade_products(products)
products.all? do |product|
product["release_type"] = SwMgmt.get_release_type(product)
success, _service = registration_ui.downgrade_product(product)
success
end
end
end
end
end
37 changes: 33 additions & 4 deletions test/registration_spec.rb
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
#! /usr/bin/env rspec

require_relative "spec_helper"
require "yaml"

describe "Registration::Registration" do
let(:yast_wfm) { double("Yast::Wfm") }

describe Registration::Registration do
let(:installed_sles) { load_yaml_fixture("products_legacy_installation.yml")[1] }
before do
allow(Yast::WFM).to receive(:GetLanguage).and_return("en")
allow(Registration::Helpers).to receive(:insecure_registration).and_return(false)
Expand Down Expand Up @@ -180,4 +178,35 @@
expect(result).to eq(migration_products)
end
end

describe "#synchronize_products" do
it "synchronizes the local products with the server" do
expect(SUSE::Connect::YaST).to receive(:synchronize)
.with([
OpenStruct.new(
arch: "x86_64",
identifier: "SLES",
version: "12",
release_type: nil
)])

subject.synchronize_products([installed_sles])
end
end

describe "#downgrade_product" do
it "downgrades the product registration" do
expect(SUSE::Connect::YaST).to receive(:downgrade_product)
.with(
OpenStruct.new(
arch: "x86_64",
identifier: "SLES",
version: "12-0",
release_type: nil
),
anything)

expect(subject.downgrade_product(installed_sles))
end
end
end
Loading

0 comments on commit e432f91

Please sign in to comment.