diff --git a/package/yast2-registration.changes b/package/yast2-registration.changes index c906f7d7a..bfcbab1a2 100644 --- a/package/yast2-registration.changes +++ b/package/yast2-registration.changes @@ -1,3 +1,9 @@ +------------------------------------------------------------------- +Thu Sep 10 15:37:08 UTC 2015 - lslezak@suse.cz + +- set the $releasever URL variable to the new base product + during online migration (bsc#941563) + ------------------------------------------------------------------- Wed Sep 9 12:34:35 UTC 2015 - lslezak@suse.cz diff --git a/src/lib/registration/releasever.rb b/src/lib/registration/releasever.rb new file mode 100644 index 000000000..aadea208a --- /dev/null +++ b/src/lib/registration/releasever.rb @@ -0,0 +1,96 @@ +# ------------------------------------------------------------------------------ +# Copyright (c) 2015 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 about this file by physical or electronic mail, you may find +# current contact information at www.suse.com. +# ------------------------------------------------------------------------------ + +require "yast" + +module Registration + # this class handles activating the new releasever value in the package management + class Releasever + include Yast::Logger + + # the environment variable which overrides the system default in libzpp + RELEASEVER_ENV = "ZYPP_REPO_RELEASEVER" + + Yast.import "Pkg" + + # the new $releasever value + attr_reader :version + + # constructor + # @param [String] version the new release version value + def initialize(version) + @version = version + end + + # activate the new releasever + def activate + log.info "Setting $releasever to: #{version}" + # export the settings + ENV[RELEASEVER_ENV] = version + + repos = repos_to_refresh + return if repos.empty? + + # refresh the repositories and reload the packages + Yast::Pkg.SourceFinishAll + Yast::Pkg.SourceRestore + refresh(repos) + Yast::Pkg.SourceLoad + end + + private + + # get the repositories which contain "$releasever" directory in the URL + # @return [Array] the repository list + def repos_to_refresh + repos = Yast::Pkg.SourceGetCurrent(true) + repos.select! do |repo| + # check the raw URL (without expanded variables) + raw_url = Yast::Pkg.SourceGeneralData(repo)["raw_url"] + + next false unless raw_url + + # The URL variables can be encoded is several ways, like $releasever or + # ${releasever}, there are also $releasever_major and $releasever_minor + # variables which contain just parts of the $releasever. + # + # More over there can be complicated expressions like + # SLE_${releasever_major}${releasever_minor:+_SP$releasever_minor} + # which is expanded to "SLE_12" in SLES12 and to "SLE_12_SP1" in SLES12-SP1. + # + # Therefore do a simple check for "$" character here, in the worst case + # we do an unnecessary refresh which is better than a missing refresh and + # using the old packages. + raw_url.include?("$") + end + + log.info "Found repositories to refresh: #{repos}" + repos + end + + # refresh the requested repositories + # @param [Array] repos the repositories to refresh + def refresh(repos) + repos.each do |repo| + log.info "Refreshing repository #{repo}" + Yast::Pkg.SourceForceRefreshNow(repo) + end + end + end +end diff --git a/src/lib/registration/ui/migration_repos_workflow.rb b/src/lib/registration/ui/migration_repos_workflow.rb index 5d00f26a4..7e6ad62cd 100644 --- a/src/lib/registration/ui/migration_repos_workflow.rb +++ b/src/lib/registration/ui/migration_repos_workflow.rb @@ -17,6 +17,7 @@ require "registration/registration" require "registration/registration_ui" require "registration/migration_repositories" +require "registration/releasever" require "registration/sw_mgmt" require "registration/ui/migration_selection_dialog" require "registration/ui/migration_repos_selection_dialog" @@ -111,6 +112,9 @@ def run "select_migration_products" => { abort: :abort, cancel: :abort, + next: "update_releasever" + }, + "update_releasever" => { next: "register_migration_products" }, "register_migration_products" => { @@ -141,6 +145,7 @@ def run_sequence "find_products" => [->() { find_products }, true], "load_migration_products" => [->() { load_migration_products }, true], "select_migration_products" => ->() { select_migration_products }, + "update_releasever" => ->() { update_releasever }, "register_migration_products" => [->() { register_migration_products }, true], "activate_migration_repos" => [->() { activate_migration_repos }, true], "select_migration_repos" => ->() { select_migration_repos }, @@ -312,6 +317,21 @@ def store_repos_state RepoStateStorage.instance.write :next end + + # update the $releasever + def update_releasever + new_base = selected_migration.find(&:base) + + if new_base + log.info "Activating new $releasever for base product: #{new_base}" + releasever = Releasever.new(new_base.version) + releasever.activate + else + log.info "The base system is not updated, skipping $releasever update" + end + + :next + end end end end diff --git a/test/releasever_spec.rb b/test/releasever_spec.rb new file mode 100644 index 000000000..05f45c95e --- /dev/null +++ b/test/releasever_spec.rb @@ -0,0 +1,60 @@ +#! /usr/bin/env rspec + +require_relative "spec_helper" +require "yaml" + +describe Registration::Releasever do + let(:version) { "42" } + let(:repo) { 7 } + subject { Registration::Releasever.new(version) } + + describe "#activate" do + before do + allow(Yast::Pkg).to receive(:SourceFinishAll) + allow(Yast::Pkg).to receive(:SourceRestore) + allow(Yast::Pkg).to receive(:SourceLoad) + allow(Yast::Pkg).to receive(:SourceGetCurrent).and_return([repo]) + allow(ENV).to receive(:[]=).with("ZYPP_REPO_RELEASEVER", version) + end + + it "exports the new $releasever value in the environment" do + allow(Yast::Pkg).to receive(:SourceGeneralData).with(repo) + .and_return("raw_url" => "https://example.com/SLES") + expect(ENV).to receive(:[]=).with("ZYPP_REPO_RELEASEVER", version) + subject.activate + end + + it "refreshes the repositories containing $releasever in the URL" do + allow(Yast::Pkg).to receive(:SourceGeneralData).with(repo) + .and_return("raw_url" => "https://example.com/SLES/$releasever") + expect(Yast::Pkg).to receive(:SourceForceRefreshNow).with(repo) + subject.activate + end + + it "refreshes the repositories containing a complex $releasever in the URL" do + allow(Yast::Pkg).to receive(:SourceGeneralData).with(repo) + .and_return("raw_url" => "https://example.com/SLE_${releasever}") + expect(Yast::Pkg).to receive(:SourceForceRefreshNow).with(repo) + subject.activate + end + + # some complex test case (see bsc#944505#c0): + # SLE_${releasever_major}${releasever_minor:+_SP$releasever_minor} + it "refreshes the repositories containing an expression in the URL" do + allow(Yast::Pkg).to receive(:SourceGeneralData).with(repo).and_return("raw_url" => + "https://example.com/SLE_${releasever_major}${releasever_minor:+_SP$releasever_minor}") + expect(Yast::Pkg).to receive(:SourceForceRefreshNow).with(repo) + subject.activate + end + + it "skips repository reload if $releasever is not used in any repository" do + expect(Yast::Pkg).to_not receive(:SourceFinishAll) + expect(Yast::Pkg).to_not receive(:SourceRestore) + expect(Yast::Pkg).to_not receive(:SourceLoad) + allow(Yast::Pkg).to receive(:SourceGeneralData).with(repo) + .and_return("raw_url" => "https://example.com/") + expect(Yast::Pkg).to_not receive(:SourceForceRefreshNow) + subject.activate + end + end +end