Skip to content

Commit

Permalink
[WIP] Fetch profile from update installer (#424)
Browse files Browse the repository at this point in the history
* Fetch profile from update installer directly.

* Try to not block AutoYast while fetching the profile.

* Splited fetch profile in smallest methods and added documentation.

* Avoid the block of AutoYast by ProfileLocation.
  • Loading branch information
teclator authored and lslezak committed Aug 25, 2016
1 parent 9477683 commit be8168e
Show file tree
Hide file tree
Showing 3 changed files with 156 additions and 7 deletions.
132 changes: 125 additions & 7 deletions src/lib/installation/clients/inst_update_installer.rb
Expand Up @@ -24,6 +24,7 @@ class InstUpdateInstaller

UPDATED_FLAG_FILENAME = "installer_updated".freeze
REMOTE_SCHEMES = ["http", "https", "ftp", "tftp", "sftp", "nfs", "nfs4", "cifs", "smb"].freeze
PROFILE_FORBIDDEN_SCHEMES = ["label"].freeze
REGISTRATION_DATA_PATH = "/var/lib/YaST2/inst_update_installer.yaml".freeze

Yast.import "Pkg"
Expand All @@ -42,6 +43,9 @@ class InstUpdateInstaller
Yast.import "NetworkService"
Yast.import "Mode"
Yast.import "Profile"
Yast.import "ProfileLocation"
Yast.import "AutoinstConfig"
Yast.import "AutoinstGeneral"

def main
textdomain "installation"
Expand All @@ -58,6 +62,11 @@ def main

initialize_progress

if Mode.auto
process_profile
Yast::Progress.NextStage
end

# initialize packager, we need to load the base product name
# to properly obtain the update URL from the registration server
return :abort unless initialize_packager
Expand Down Expand Up @@ -526,6 +535,16 @@ def finish_packager

# Show global self update progress
def initialize_progress
stages = [
# TRANSLATORS: progress label
_("Add Update Repository"),
_("Download the Packages"),
_("Apply the Packages"),
_("Restart")
]

stages.unshift(_("Fetching AutoYast Profile")) if Mode.auto

# open a new wizard dialog with title on the top
# (the default dialog with title on the left looks ugly with the
# Progress dialog)
Expand All @@ -540,13 +559,7 @@ def initialize_progress
# max is 100%
100,
# stages
[
# TRANSLATORS: progress label
_("Add Update Repository"),
_("Download the Packages"),
_("Apply the Packages"),
_("Restart")
],
stages,
# steps
[],
# help text
Expand All @@ -564,5 +577,110 @@ def finish_progress
Yast::Progress.Finish
Yast::Wizard.CloseDialog
end

private

#
# TODO: Most of the code responsable of process the profile has been
# obtained from which inst_autoinit client in yast2-autoinstallation.
# We should try to move it to a independent class or to Yast::Profile.
#

# @return [Boolean] true if the scheme is not forbidden
def profile_valid_scheme?
!PROFILE_FORBIDDEN_SCHEMES.include? AutoinstConfig.scheme
end

# Obtains the current profile
#
# @return [Hash, nil] current profile if not empty; nil otherwise
#
# @see Yast::Profile.current
def current_profile
return nil if Yast::Profile.current == {}

Profile.current
end

# Fetchs the profile from the given URI
#
# @return [Hash, nil] current profile if fetched or exists; nil otherwise
#
# @see Yast::Profile.current
def fetch_profile
return current_profile if current_profile

if !profile_valid_scheme?
Report.Warning("The scheme used (#{AutoinstConfig.scheme}), " \
"is not supported in self update.")
return nil
end

Report.LogMessages(true)
Report.LogErrors(true)
Report.LogWarnings(true)

process_location

if !current_profile
secure_uri = Yast::URL.HidePassword(AutoinstConfig.OriginalURI)
log.info("Unable to load the profile from: #{secure_uri}")

return nil
end

if !Profile.ReadXML(AutoinstConfig.xml_tmpfile)
Report.Warning(_("Error while parsing the control file.\n\n"))
return nil
end

current_profile
end

# Imports Report settings from the current profile
def profile_prepare_reports
report = Profile.current["report"]

if report && !report.key?("yesno_messages")
report = Report.Export
report["yesno_messages"] = report.fetch("errors", {})
end

Report.Import(report)
end

# Imports general settings from the profile and set signature callbacks
def profile_prepare_signatures
AutoinstGeneral.Import(Profile.current.fetch("general", {}))
AutoinstGeneral.SetSignatureHandling
end

# Fetch profile and prepare reports and signature callbas in case of
# obtained a valid one.
def process_profile
log.info("Fetching the profile")
return false if !fetch_profile

profile_prepare_reports
profile_prepare_signatures
end

# It retrieves the profile and the user rules from the given location not
# blocking AutoYast
#
# @see ProfileLocation.Process
def process_location
# ProfileLocation reports an error in case that the profile was not
# available in the given URL. We change the timeout error to not block
# AutoYast during update_installer, just to this method.
report_settings = Report.Export

Report.Import(report_settings.merge("errors" => { "timeout" => 10 }))

log.info("Processing profile location...")
ProfileLocation.Process

Report.Import(report_settings)
end
end
end
11 changes: 11 additions & 0 deletions test/inst_update_installer_test.rb
Expand Up @@ -35,6 +35,7 @@ def import(_args); end
let(:restarting) { false }
let(:profile) { {} }
let(:ay_profile) { double("Yast::Profile", current: profile) }
let(:ay_profile_location) { double("Yast::ProfileLocation") }

before do
allow(Yast::GetInstArgs).to receive(:going_back).and_return(false)
Expand All @@ -52,6 +53,8 @@ def import(_args); end
# skip the libzypp initialization globally, enable in the specific tests
allow(subject).to receive(:initialize_packager).and_return(true)
allow(subject).to receive(:finish_packager)
allow(subject).to receive(:fetch_profile).and_return(ay_profile)
allow(subject).to receive(:process_profile)

# stub the Profile module to avoid dependency on autoyast2-installation
stub_const("Yast::Profile", ay_profile)
Expand Down Expand Up @@ -406,6 +409,14 @@ def import(_args); end
allow(::FileUtils).to receive(:touch)
end

it "tries to process the profile from the given URL" do
expect(subject).to receive(:process_profile)
expect(manager).to receive(:add_repository).with(URI(profile_url))
.and_return(true)

subject.main
end

context "the profile defines the update URL" do
it "gets the URL from AutoYaST profile" do
expect(manager).to receive(:add_repository).with(URI(profile_url))
Expand Down
20 changes: 20 additions & 0 deletions test/test_helper.rb
Expand Up @@ -25,14 +25,34 @@ def cio_ignore
def second_stage
end
end

AutoinstConfig = AutoinstConfigClass.new

class AutoinstGeneralClass
# we need at least one non-default methods, otherwise ruby-bindings thinks
# it is just namespace
def SetSignatureHandling
end

def Import(profile)
end
end

AutoinstGeneral = AutoinstGeneralClass.new

# Faked Profile module
class ProfileClass
def current
end
end
Profile = ProfileClass.new

class ProfileLocationClass
def Process
end
end

ProfileLocation = ProfileLocationClass.new
end

if ENV["COVERAGE"]
Expand Down

0 comments on commit be8168e

Please sign in to comment.