Hello community, here is the log from the commit of package yast2-installation for openSUSE:Factory checked in at 2016-08-31 00:03:00 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/yast2-installation (Old) and /work/SRC/openSUSE:Factory/.yast2-installation.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "yast2-installation" Changes: -------- --- /work/SRC/openSUSE:Factory/yast2-installation/yast2-installation.changes 2016-08-22 10:48:15.000000000 +0200 +++ /work/SRC/openSUSE:Factory/.yast2-installation.new/yast2-installation.changes 2016-08-31 00:03:02.000000000 +0200 @@ -1,0 +2,26 @@ +Thu Aug 25 14:23:20 UTC 2016 - lsle...@suse.cz + +- Move the installer self update step earlier in the workflow + so the user entered values are not lost after restart and avoid + repeating some steps again (bsc#985055) +- This also fixes losing some values due to restaring YaST (bsc#993690), + (bsc#992608) +- Improved the self update URL handling - the boot parameter has + the highest priority, always ask user when a SLP service is found, + in AutoYaST mode SLP needs to be enabled in the profile +- Display progress when downloading and applying the updates +- 3.1.213 + +------------------------------------------------------------------- +Wed Aug 25 12:51:45 UTC 2016 - c...@suse.com + +- Replace unicode bullet char by asterisk for ncurses (bsc#995082) +- 3.1.212 + +------------------------------------------------------------------- +Thu Aug 25 07:33:10 UTC 2016 - jreidin...@suse.com + +- fix writing proposals (bnc#994127) +- 3.1.211 + +------------------------------------------------------------------- Old: ---- yast2-installation-3.1.210.tar.bz2 New: ---- yast2-installation-3.1.213.tar.bz2 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ yast2-installation.spec ++++++ --- /var/tmp/diff_new_pack.y1Ti69/_old 2016-08-31 00:03:03.000000000 +0200 +++ /var/tmp/diff_new_pack.y1Ti69/_new 2016-08-31 00:03:03.000000000 +0200 @@ -17,7 +17,7 @@ Name: yast2-installation -Version: 3.1.210 +Version: 3.1.213 Release: 0 BuildRoot: %{_tmppath}/%{name}-%{version}-build @@ -66,8 +66,8 @@ # Lazy loading in ProductLicense Requires: yast2-packager >= 3.1.113 -# Yast::Storage.multipath_off? -Requires: yast2-storage >= 3.1.97 +# Storage::GetDetectedDiskPaths +Requires: yast2-storage >= 2.24.1 # use in startup scripts Requires: initviocons ++++++ yast2-installation-3.1.210.tar.bz2 -> yast2-installation-3.1.213.tar.bz2 ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-installation-3.1.210/doc/SELF_UPDATE.md new/yast2-installation-3.1.213/doc/SELF_UPDATE.md --- old/yast2-installation-3.1.210/doc/SELF_UPDATE.md 2016-08-19 16:32:01.000000000 +0200 +++ new/yast2-installation-3.1.213/doc/SELF_UPDATE.md 2016-08-30 14:17:36.000000000 +0200 @@ -21,6 +21,18 @@ 3. The update will be applied to the installation system. 4. YaST will be restarted and the installation will be resumed. +### Language Selection + +The self-update step is executed before selecting the language +(`inst_complex_welcome` client). That means the self-update progress and +the errors which happens during the self-update process are by default displayed +in English. + +To use another language also for the self-update press `F2` in the DVD boot menu +and select the language from the list. Or use the `language` boot option, e.g. +`language=de_DE`. + + ## Update Format YaST will use RPM packages stored in a rpm-md repository, although they are @@ -46,11 +58,15 @@ ``` 3. Registration server (SCC/SMT), not available in openSUSE. The URL of the registration server which should be used is determined via: - 1. AutoYaST profile ([reg_server element](https://www.suse.com/documentation/sles-12/singlehtml/book_autoyast/book_autoyast.html#CreateProfile.Register)). - 2. The `regurl` boot parameter + 1. The `regurl` boot parameter + 2. AutoYaST profile ([reg_server element](https://www.suse.com/documentation/sles-12/singlehtml/book_autoyast/book_autoyast.html#CreateProfile.Register)). 3. SLP lookup (this behavior applies to regular and AutoYaST installations): - * If one server is found, it will be used automatically. - * If more than one server is found, it will ask the user to choose one. + * If at least one server is found it will ask the user to choose one. + * In AutoYaST mode SLP is skipped unless enabled in the profile in the + registration section (see [documentation](https://www.suse.com/documentation/sles-12/singlehtml/book_autoyast/book_autoyast.html#idm140139881100304)). + AutoYaST expects that only one server is reported by SLP, if more + servers are found it is considered as an error and user interaction is + required just like in manual installation. 4. Default SUSE Customer Center API (`https://scc.suse.com/`). 4. Hard-coded in the `control.xml` file on the installation medium (thus it depends on the base product): @@ -63,7 +79,7 @@ The first suitable URL will be used. There are two exceptions: -* Of course, if no update URL is found then the self update is skipped. +* Of course, if no update URL is found then the self-update is skipped. * If SCC/SMT provides multiple URLs, they will be all used. The URL can contain a variable `$arch` that will be replaced by the system's @@ -93,6 +109,14 @@ correct (or is missing), the user will be asked whether she/he wants to apply the update (although it's a security risk). +When using AutoYaST, this behavior can be modified including the +[/general/signature-handling](https://www.suse.com/documentation/sles-12/singlehtml/book_autoyast/book_autoyast.html#idm140139881381840) +section in the profile. + +On the other hand, if SLP discovery is enabled, a popup is displayed to choose the +server to use. SLP by default does not use any authentication, everybody on the +local network can announce a registration server. + ## Self-update and User Updates Changes introduced by the user via Driver Updates (`dud` boot option) will take @@ -103,14 +127,19 @@ ## Resume installation -Any client called before the self update step is responsible to remember its state (if +Any client called before the self-update step is responsible to remember its state (if needed) and automatically going to the next dialog after the YaST restart. -Once the self update step is reached again it will remove the restarting flag. +Once the self-update step is reached again it will remove the restarting flag. + +The self-update step is called very early in the workflow, for the self-update +step only configured network is needed. That is configured either by `linuxrc` +or by the `setup_dhcp` YaST client which does not need to remember any state. + +## Supported URL Schemes -Currently there is no API available for remembering the client states. The easiest -way is to store the configuration into an YAML file and load it when restarting the -installer. See the [example](https://github.com/yast/yast-installation/pull/367/files#diff-4c91d6424e08c9bef9237f7d959fc0c2R48) -in the `inst_complex_welcome` client. +Currently only HTTP/HTTPS and FTP URL schemes are supported for downloading +the updates. Some additional schemes might work but are not tested and therefore +not supported. ## Error handling diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-installation-3.1.210/package/yast2-installation.changes new/yast2-installation-3.1.213/package/yast2-installation.changes --- old/yast2-installation-3.1.210/package/yast2-installation.changes 2016-08-19 16:32:01.000000000 +0200 +++ new/yast2-installation-3.1.213/package/yast2-installation.changes 2016-08-30 14:17:36.000000000 +0200 @@ -1,4 +1,30 @@ ------------------------------------------------------------------- +Thu Aug 25 14:23:20 UTC 2016 - lsle...@suse.cz + +- Move the installer self update step earlier in the workflow + so the user entered values are not lost after restart and avoid + repeating some steps again (bsc#985055) +- This also fixes losing some values due to restaring YaST (bsc#993690), + (bsc#992608) +- Improved the self update URL handling - the boot parameter has + the highest priority, always ask user when a SLP service is found, + in AutoYaST mode SLP needs to be enabled in the profile +- Display progress when downloading and applying the updates +- 3.1.213 + +------------------------------------------------------------------- +Wed Aug 25 12:51:45 UTC 2016 - c...@suse.com + +- Replace unicode bullet char by asterisk for ncurses (bsc#995082) +- 3.1.212 + +------------------------------------------------------------------- +Thu Aug 25 07:33:10 UTC 2016 - jreidin...@suse.com + +- fix writing proposals (bnc#994127) +- 3.1.211 + +------------------------------------------------------------------- Wed Aug 17 15:02:02 UTC 2016 - jreidin...@suse.com - filter out same repositories from extraurls if they differ only diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-installation-3.1.210/package/yast2-installation.spec new/yast2-installation-3.1.213/package/yast2-installation.spec --- old/yast2-installation-3.1.210/package/yast2-installation.spec 2016-08-19 16:32:01.000000000 +0200 +++ new/yast2-installation-3.1.213/package/yast2-installation.spec 2016-08-30 14:17:36.000000000 +0200 @@ -17,7 +17,7 @@ Name: yast2-installation -Version: 3.1.210 +Version: 3.1.213 Release: 0 BuildRoot: %{_tmppath}/%{name}-%{version}-build @@ -63,8 +63,8 @@ # Lazy loading in ProductLicense Requires: yast2-packager >= 3.1.113 -# Yast::Storage.multipath_off? -Requires: yast2-storage >= 3.1.97 +# Storage::GetDetectedDiskPaths +Requires: yast2-storage >= 2.24.1 # use in startup scripts Requires: initviocons diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-installation-3.1.210/src/lib/installation/clients/inst_complex_welcome.rb new/yast2-installation-3.1.213/src/lib/installation/clients/inst_complex_welcome.rb --- old/yast2-installation-3.1.210/src/lib/installation/clients/inst_complex_welcome.rb 2016-08-19 16:32:01.000000000 +0200 +++ new/yast2-installation-3.1.213/src/lib/installation/clients/inst_complex_welcome.rb 2016-08-30 14:17:36.000000000 +0200 @@ -45,10 +45,6 @@ @license_id = Ops.get(Pkg.SourceGetCurrent(true), 0, 0) # ------------------------------------- main part of the client ----------- - if Installation.restarting? && data_stored? - apply_data - return :next - end @argmap = GetInstArgs.argmap @@ -127,8 +123,6 @@ setup_final_choice - store_data - return :next when :show_fulscreen_license UI.OpenDialog(all_licenses_dialog) @@ -383,35 +377,6 @@ log.info "Language: '#{@language}', system encoding '#{WFM.GetEncoding}'" end - DATA_PATH = "/var/lib/YaST2/complex_welcome_store.yaml".freeze - - def data_stored? - ::File.exist?(DATA_PATH) - end - - def store_data - data = { - "language" => @language, - "keyboard" => @keyboard, - "license_accepted" => InstData.product_license_accepted - } - - File.write(DATA_PATH, data.to_yaml) - end - - def apply_data - data = YAML.load(File.read(DATA_PATH)) - @language = data["language"] - @keyboard = data["keyboard"] - InstData.product_license_accepted = data["license_accepted"] - ProductLicense.info_seen!(@license_id) - - change_language - setup_final_choice - - ::FileUtils.rm_rf(DATA_PATH) - end - def text_mode? return @text_mode unless @text_mode.nil? diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-installation-3.1.210/src/lib/installation/clients/inst_disks_activate.rb new/yast2-installation-3.1.213/src/lib/installation/clients/inst_disks_activate.rb --- old/yast2-installation-3.1.210/src/lib/installation/clients/inst_disks_activate.rb 2016-08-19 16:32:01.000000000 +0200 +++ new/yast2-installation-3.1.213/src/lib/installation/clients/inst_disks_activate.rb 2016-08-30 14:17:36.000000000 +0200 @@ -58,8 +58,6 @@ @have_zfcp = false @want_fcoe = false - return :next if Installation.restarting? - if Arch.s390 # popup label UI.OpenDialog(Label(_("Detecting Available Controllers"))) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-installation-3.1.210/src/lib/installation/clients/inst_system_analysis.rb new/yast2-installation-3.1.213/src/lib/installation/clients/inst_system_analysis.rb --- old/yast2-installation-3.1.210/src/lib/installation/clients/inst_system_analysis.rb 2016-08-19 16:32:01.000000000 +0200 +++ new/yast2-installation-3.1.213/src/lib/installation/clients/inst_system_analysis.rb 2016-08-30 14:17:36.000000000 +0200 @@ -26,19 +26,15 @@ # Lukas Ocilka <loci...@suse.cz> require "yast" -require "fileutils" module Yast class InstSystemAnalysisClient < Client - include Yast::Logger - def main Yast.import "UI" textdomain "installation" Yast.import "Arch" - Yast.import "Directory" Yast.import "GetInstArgs" Yast.import "Hotplug" Yast.import "InstData" @@ -60,8 +56,6 @@ Yast.include self, "packager/storage_include.rb" Yast.include self, "packager/load_release_notes.rb" - @multipath_off_file = File.join(Directory.vardir, "multipath_off") - if Mode.autoupgrade Report.Import( @@ -150,9 +144,6 @@ _("YaST is probing computer hardware and installed systems now.") ) - # bug#989770 - Storage.SetMultipathStartup(false) if persisted_multipath_off? - actions_functions.each do |run_function| Progress.NextStage # Bugzilla #298049 @@ -174,12 +165,6 @@ end Installation.probing_done = true - # bug#989770 - if Storage.multipath_off? - log.info "The user decided to not activate multipath" - persist_multipath_off - end - # the last step is hidden return :abort if ProductProfile.CheckCompliance(nil) == false @@ -370,22 +355,5 @@ true end - - protected - - # Sets a mark for the installer (in case it's executed again due to - # self-update) to disable multipath without asking the user - def persist_multipath_off - log.info "Multipath activation pop-up will be skipped if installer restarts" - ::FileUtils.touch(@multipath_off_file) - end - - # Checks if #persist_multipath_off was called in the previous execution of - # the installer. @see #persist_multipath_off - # - # @return [Boolean] - def persisted_multipath_off? - ::File.exist?(@multipath_off_file) - end end end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-installation-3.1.210/src/lib/installation/clients/inst_update_installer.rb new/yast2-installation-3.1.213/src/lib/installation/clients/inst_update_installer.rb --- old/yast2-installation-3.1.210/src/lib/installation/clients/inst_update_installer.rb 2016-08-19 16:32:01.000000000 +0200 +++ new/yast2-installation-3.1.213/src/lib/installation/clients/inst_update_installer.rb 2016-08-30 14:17:36.000000000 +0200 @@ -24,9 +24,14 @@ 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" + Yast.import "Packages" + Yast.import "PackageCallbacks" + Yast.import "InstURL" + Yast.import "Language" Yast.import "GetInstArgs" Yast.import "Directory" Yast.import "Installation" @@ -38,6 +43,9 @@ Yast.import "NetworkService" Yast.import "Mode" Yast.import "Profile" + Yast.import "ProfileLocation" + Yast.import "AutoinstConfig" + Yast.import "AutoinstGeneral" def main textdomain "installation" @@ -49,16 +57,38 @@ Installation.finish_restarting! end + # shortcut - already updated or disabled via boot option + if installer_updated? || disabled_in_linuxrc? + log.info "Self update not needed, skipping" + return :next + end + + initialize_progress + + if Mode.auto + process_profile + Yast::Progress.NextStage + end + + initialize_packager + + # self update disabled or not possible return :next unless try_to_update? log.info("Trying installer update") + installer_updated = update_installer - if update_installer - ::FileUtils.touch(update_flag_file) # Indicates that the installer was updated. + if installer_updated + # Indicates that the installer was updated. + ::FileUtils.touch(update_flag_file) + Yast::Progress.NextStage Installation.restart! else :next end + ensure + finish_packager + finish_progress end # Tries to update the installer @@ -80,6 +110,7 @@ if updated log.info("Applying installer updates") + Yast::Progress.NextStage updates_manager.apply_all end updated @@ -103,7 +134,7 @@ # # @return [Boolean] True if it's enabled; false otherwise. def self_update_enabled? - if Linuxrc.InstallInf("SelfUpdate") == "0" # disabled via Linuxrc + if disabled_in_linuxrc? log.info("self-update was disabled through Linuxrc") false else @@ -111,6 +142,13 @@ end end + # disabled via Linuxrc ? + # @return [Boolean] true if self update has been disabled by "self_update=0" + # boot option + def disabled_in_linuxrc? + Linuxrc.InstallInf("SelfUpdate") == "0" + end + # Return the self-update URLs # # @return [Array<URI>] self-update URLs @@ -132,6 +170,9 @@ # @return [Array<URI>] self-update URLs def default_self_update_urls return @default_self_update_urls if @default_self_update_urls + # load the base product from the installation medium, + # the registration server needs it for evaluating the self update URL + add_installation_repo @default_self_update_urls = self_update_url_from_connect return @default_self_update_urls unless @default_self_update_urls.empty? @default_self_update_urls = Array(self_update_url_from_control) @@ -176,27 +217,42 @@ # # Determined in the following order: # - # * via AutoYaST profile - # * regurl boot parameter + # * "regurl" boot parameter + # * From AutoYaST profile # * SLP look up - # * If there's only 1 SMT server, it will be chosen automatically. - # * If there's more than 1 SMT server, it will ask the user to choose one + # * In AutoYaST mode the SLP needs to be explicitly enabled in the profile, + # if the scan finds *exactly* one SLP service then it is used. If more + # than one service is found then an interactive popup is displayed. + # (This breaks the AY unattended concept but basically more services + # is treated as an error, AytoYaST cannot know which one to use.) + # * In non-AutoYaST mode it will ask the user to choose the found SLP + # servise or the SCC default. + # * Fallbacks to SCC if no SLP service is found. # # @return [URI,:scc,:cancel] Registration URL; :scc if SCC server was selected; # :cancel if dialog was dismissed. # - # @see #registration_server_from_user + # @see #registration_service_from_user def registration_url - url = registration_url_from_profile || ::Registration::UrlHelpers.boot_reg_url + url = ::Registration::UrlHelpers.boot_reg_url || registration_url_from_profile return URI(url) if url + + # do the SLP scan in AutoYast mode only when allowed in the profile + return :scc if Mode.auto && registration_profile["slp_discovery"] != true + services = ::Registration::UrlHelpers.slp_discovery + log.info "SLP discovery result: #{services.inspect}" return :scc if services.empty? + service = - if services.size > 1 - registration_service_from_user(services) - else + if Mode.auto && services.size == 1 services.first + else + registration_service_from_user(services) end + + log.info "Selected SLP service: #{service.inspect}" + return service unless service.respond_to?(:slp_url) URI(::Registration::UrlHelpers.service_url(service.slp_url)) end @@ -208,9 +264,15 @@ def registration_url_from_profile return nil unless Mode.auto + get_url_from(registration_profile["reg_server"]) + end + + # return the registration settings from the loaded AutoYaST profile + # @return [Hash] the current settings, returns empty Hash if the + # registration section is missing in the profile + def registration_profile profile = Yast::Profile.current - profile_url = profile.fetch("suse_register", {})["reg_server"] - get_url_from(profile_url) + profile.fetch("suse_register", {}) end # Ask the user to chose a registration server @@ -434,5 +496,188 @@ Yast::Profile.current.fetch("suse_register", {}) ) end + + # Initialize the package management so we can download the updates from + # the update repository. + def initialize_packager + return if @packager_initialized + log.info "Initializing the package management..." + + # Add the initial installation repository. + # Unfortunately the Packages.InitializeCatalogs call cannot be used here + # as is does too much (adds y2update.tgz, selects the product, selects + # the default patterns, looks for the addon product files...). + + # initialize package callbacks to show a progress while downloading the files + PackageCallbacks.InitPackageCallbacks + + # set the language for the package manager (mainly error messages) + Pkg.SetTextLocale(Language.language) + + # set the target to inst-sys otherwise libzypp complains in the GPG check + Pkg.TargetInitialize("/") + + # load the GPG keys (*.gpg files) from inst-sys + Packages.ImportGPGKeys + + @packager_initialized = true + end + + def add_installation_repo + base_url = InstURL.installInf2Url("") + initial_repository = Pkg.SourceCreateBase(base_url, "") + + until initial_repository + log.error "Adding the installation repository failed" + # ask user to retry + base_url = Packages.UpdateSourceURL(base_url) + + # aborted by user + return false if base_url == "" + + initial_repository = Pkg.SourceCreateBase(base_url, "") + end + end + + # delete all added installation repositories + # to make sure there is no leftover which could affect the installation later + def finish_packager + return unless @packager_initialized + # false = all repositories, even the disabled ones + Pkg.SourceGetCurrent(false).each { |r| Pkg.SourceDelete(r) } + Pkg.SourceSaveAll + Pkg.SourceFinishAll + Pkg.TargetFinish + end + + # 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) + Yast::Wizard.CreateDialog + @wizard_open = true + + Yast::Progress.New( + # TRANSLATORS: dialog title + _("Updating the Installer..."), + # TRANSLATORS: progress title + _("Updating the Installer..."), + # max is 100% + 100, + # stages + stages, + # steps + [], + # help text + "" + ) + + # mark the first stage active + Yast::Progress.NextStage + end + + # Finish the self update progress + def finish_progress + return unless @wizard_open + + 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 Profile.current == {} + + Profile.current + end + + # Fetch 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 + + 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"] + 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 + # + # @see ProfileLocation.Process + def process_location + log.info("Processing profile location...") + ProfileLocation.Process + end end end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-installation-3.1.210/src/lib/installation/proposal_runner.rb new/yast2-installation-3.1.213/src/lib/installation/proposal_runner.rb --- old/yast2-installation-3.1.210/src/lib/installation/proposal_runner.rb 2016-08-19 16:32:01.000000000 +0200 +++ new/yast2-installation-3.1.213/src/lib/installation/proposal_runner.rb 2016-08-30 14:17:36.000000000 +0200 @@ -261,7 +261,9 @@ def pre_continue_handling @skip = if Yast::UI.WidgetExists(Id(:skip)) - Yast::UI.QueryWidget(Id(:skip), :Value) + val = Yast::UI.QueryWidget(Id(:skip), :Value) + log.info "there is :skip widget with value #{val.inspect}." + val else true end @@ -510,7 +512,9 @@ def write_settings success = true - @store.proposal_names do |submod| + log.info "Writting settings for proposal" + + @store.proposal_names.each do |submod| submod_success = submod_write_settings(submod) submod_success = true if submod_success.nil? log.error "Write() failed for submodule #{submod}" unless submod_success diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-installation-3.1.210/src/lib/installation/proposal_store.rb new/yast2-installation-3.1.213/src/lib/installation/proposal_store.rb --- old/yast2-installation-3.1.210/src/lib/installation/proposal_store.rb 2016-08-19 16:32:01.000000000 +0200 +++ new/yast2-installation-3.1.213/src/lib/installation/proposal_store.rb 2016-08-30 14:17:36.000000000 +0200 @@ -100,11 +100,14 @@ return @can_skip unless @can_skip.nil? @can_skip = if properties.key?("enable_skip") + log.info "properties skip available #{properties["enable_skip"].inspect}." properties["enable_skip"] == "yes" else !["initial", "uml"].include?(@proposal_mode) end + log.info "can skip set to #{@can_skip.inspect}." + @can_skip end @@ -390,11 +393,17 @@ end def properties - @proposal_properties ||= Yast::ProductControl.getProposalProperties( + return @proposal_properties unless @proposal_properties.nil? + + @proposal_properties = Yast::ProductControl.getProposalProperties( Yast::Stage.stage, Yast::Mode.mode, @proposal_mode ) + + log.info "Properties #{@proposal_properties.inspect}" + + @proposal_properties end def make_proposal(client, force_reset: false, language_changed: false, callback: proc {}) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-installation-3.1.210/src/lib/installation/select_system_role.rb new/yast2-installation-3.1.213/src/lib/installation/select_system_role.rb --- old/yast2-installation-3.1.210/src/lib/installation/select_system_role.rb 2016-08-19 16:32:01.000000000 +0200 +++ new/yast2-installation-3.1.213/src/lib/installation/select_system_role.rb 2016-08-30 14:17:36.000000000 +0200 @@ -1,3 +1,4 @@ +# coding: utf-8 # Copyright (c) 2016 SUSE LLC. # All Rights Reserved. @@ -94,10 +95,12 @@ def role_buttons ui_roles = role_attributes.each_with_object(VBox()) do |r, vbox| + # bsc#995082: System role descriptions use a character that is missing in console font + description = Yast::UI.TextMode ? r[:description].tr("•", "*") : r[:description] vbox << Left(RadioButton(Id(r[:id]), r[:label])) vbox << HBox( HSpacing(Yast::UI.TextMode ? 4 : 2), - Left(Label(r[:description])) + Left(Label(description)) ) vbox << VSpacing(2) end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-installation-3.1.210/src/lib/installation/update_repository.rb new/yast2-installation-3.1.213/src/lib/installation/update_repository.rb --- old/yast2-installation-3.1.210/src/lib/installation/update_repository.rb 2016-08-19 16:32:01.000000000 +0200 +++ new/yast2-installation-3.1.213/src/lib/installation/update_repository.rb 2016-08-30 14:17:36.000000000 +0200 @@ -39,6 +39,7 @@ # end class UpdateRepository include Yast::Logger + include Yast::I18n # @return [URI] URI of the repository attr_reader :uri @@ -96,6 +97,9 @@ # @param instsys_parts_path [Pathname] Path to instsys.parts registry def initialize(uri, instsys_parts_path = Pathname("/etc/instsys.parts")) Yast.import "Pkg" + Yast.import "Progress" + + textdomain "installation" @uri = uri @repo_id = add_repo @@ -129,6 +133,9 @@ # If a known error occurs, it will be converted to a CouldNotFetchUpdate # exception. # + # A progress is displayed when the packages are downloaded. + # The progress can be disabled by calling `Yast::Progress.set(false)`. + # # @param path [Pathname] Directory to store the updates # @return [Pathname] Paths to the updates # @@ -138,7 +145,10 @@ # # @raise CouldNotFetchUpdate def fetch(path = Pathname("/download")) - packages.each_with_object(update_files) do |package, files| + init_progress + + packages.each_with_object(update_files).with_index do |(package, files), index| + update_progress(100 * index / packages.size) files << fetch_package(package, path) end rescue PackageNotFound, CouldNotExtractPackage, CouldNotSquashPackage => e @@ -166,6 +176,15 @@ # * Mount the squashfs filesystem # * Add files/directories to inst-sys using the /etc/adddir script # + # @note The current implementation creates one squashfs image per package + # and mounting a squashfs image consumes one loop device (/dev/loop*). + # Inst-sys has by default 64 loop devices, but some of them already used, + # in an extreme case we might run out of loop devices. + # + # On the other hand downloading and unpacking all packages at once might + # require a lot of memory, the installer could crash on a system with + # small memory. + # # @param mount_path [Pathname] Directory to mount the update # # @raise UpdatesNotFetched @@ -186,7 +205,10 @@ # # Release the repository def cleanup + Yast::Pkg.SourceReleaseAll Yast::Pkg.SourceDelete(repo_id) + # make sure it's also removed from disk + Yast::Pkg.SourceSaveAll end # Determine whether the repository is empty or not @@ -231,15 +253,15 @@ # Extract a RPM contents to a given directory # - # @param package_path [Pathname] RPM local path + # @param package_file [File] RPM package (local file name) # @param dir [Pathname] Directory to extract the RPM contents # # @raise CouldNotExtractPackage - def extract(package_path, dir) + def extract(package_file, dir) Dir.chdir(dir) do - cmd = format(EXTRACT_CMD, source: package_path.path) + cmd = format(EXTRACT_CMD, source: package_file.path) out = Yast::SCR.Execute(Yast::Path.new(".target.bash_output"), cmd) - log.info("Extracting package #{package_path}: #{out}") + log.info("Extracting package #{package_file.inspect}: #{out}") raise CouldNotExtractPackage unless out["exit"].zero? end end @@ -367,5 +389,17 @@ f.puts "#{path.relative_path_from(Pathname("/"))} #{mountpoint}" end end + + # Initialize the progress + def init_progress + # mark the next stage active + Yast::Progress.NextStage + end + + # Display the current Progress + # @param [Fixnum] percent the current progress in range 0..100 + def update_progress(percent) + Yast::Progress.Step(percent) + end end end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-installation-3.1.210/test/inst_complex_welcome_test.rb new/yast2-installation-3.1.213/test/inst_complex_welcome_test.rb --- old/yast2-installation-3.1.210/test/inst_complex_welcome_test.rb 2016-08-19 16:32:01.000000000 +0200 +++ new/yast2-installation-3.1.213/test/inst_complex_welcome_test.rb 2016-08-30 14:17:37.000000000 +0200 @@ -22,6 +22,7 @@ # null object returned above as parameter and it raise exception from # component system stub_const("Yast::UI", double.as_null_object) + allow(Yast::Pkg).to receive(:SourceGetCurrent).and_return([]) end after do @@ -44,105 +45,78 @@ allow(Yast::Installation).to receive(:restarting?) { restarting } end - context "and installer is restarting" do - let(:restarting) { true } - it "applies data if exists and returns next" do - allow(subject).to receive(:data_stored?) { true } - expect(subject).to receive(:apply_data) + it "initializes dialog" do + allow(subject).to receive(:event_loop) + expect(subject).to receive(:initialize_dialog) - expect(subject.main).to eql(:next) - end + subject.main + end - it "does not apply data if not exists and continues as not restarting" do - allow(subject).to receive(:data_stored?) { false } - expect(subject).not_to receive(:apply_data) - allow(subject).to receive(:event_loop) - expect(subject).to receive(:initialize_dialog) + it "starts input loop" do + expect(subject).to receive(:initialize_dialog) + expect(subject).to receive(:event_loop) - subject.main - end + subject.main end - context "and installer is not restarting" do - before do - allow(subject).to receive(:data_stored?) { false } - end + context "when back is selected" do - it "initializes dialog" do - allow(subject).to receive(:event_loop) + it "returns back" do expect(subject).to receive(:initialize_dialog) + expect(Yast::UI).to receive(:UserInput).and_return(:back) - subject.main + expect(subject.main).to eql(:back) end + end - it "starts input loop" do - expect(subject).to receive(:initialize_dialog) - expect(subject).to receive(:event_loop) + context "when next is selected" do + before do + allow(Yast::Mode).to receive(:config).and_return(false) + allow(Yast::Stage).to receive(:initial).and_return(true) - subject.main - end + allow(Yast::Language).to receive(:CheckIncompleteTranslation).and_return(true) + allow(Yast::Language).to receive(:CheckLanguagesSupport) - context "when back is selected" do + allow(Yast::ProductLicense).to receive(:AcceptanceNeeded).and_return(license_needed) + allow(Yast::ProductLicense).to receive(:cache_license_acceptance_needed).and_return(nil) + allow(subject).to receive(:license_accepted?).and_return(license_accepted) + end - it "returns back" do - expect(subject).to receive(:initialize_dialog) - expect(Yast::UI).to receive(:UserInput).and_return(:back) + context "when license is required and not accepted" do + let(:license_needed) { true } + let(:license_accepted) { false } + it "not returns" do + expect(Yast::UI).to receive(:UserInput).and_return(:next, :back) + expect(Yast::Report).to receive(:Message) + .with(_("You must accept the license to install this product")) expect(subject.main).to eql(:back) end end - context "when next is selected" do - before do - allow(Yast::Mode).to receive(:config).and_return(false) - allow(Yast::Stage).to receive(:initial).and_return(true) - - allow(Yast::Language).to receive(:CheckIncompleteTranslation).and_return(true) - allow(Yast::Language).to receive(:CheckLanguagesSupport) - - allow(Yast::ProductLicense).to receive(:AcceptanceNeeded).and_return(license_needed) - allow(Yast::ProductLicense).to receive(:cache_license_acceptance_needed).and_return(nil) - allow(subject).to receive(:license_accepted?).and_return(license_accepted) - end - - context "when license is required and not accepted" do - let(:license_needed) { true } - let(:license_accepted) { false } - - it "not returns" do - expect(Yast::UI).to receive(:UserInput).and_return(:next, :back) - expect(Yast::Report).to receive(:Message) - .with(_("You must accept the license to install this product")) - expect(subject.main).to eql(:back) - end - end - - context "when license is not required" do - let(:license_needed) { false } - let(:license_accepted) { false } - - it "stores selected data and returns next" do - expect(Yast::UI).to receive(:UserInput).and_return(:next) - expect(subject).to receive(:setup_final_choice) - expect(subject).to receive(:store_data) - expect(Yast::Report).to_not receive(:Message) + context "when license is not required" do + let(:license_needed) { false } + let(:license_accepted) { false } + + it "stores selected data and returns next" do + expect(Yast::UI).to receive(:UserInput).and_return(:next) + expect(subject).to receive(:setup_final_choice) + expect(Yast::Report).to_not receive(:Message) - expect(subject.main).to eql(:next) - end + expect(subject.main).to eql(:next) end + end - context "when license is required and accepted" do - let(:license_needed) { true } - let(:license_accepted) { true } - - it "stores selected data and returns next" do - expect(Yast::UI).to receive(:UserInput).and_return(:next) - expect(subject).to receive(:setup_final_choice) - expect(subject).to receive(:store_data) - expect(Yast::Report).to_not receive(:Message) + context "when license is required and accepted" do + let(:license_needed) { true } + let(:license_accepted) { true } + + it "stores selected data and returns next" do + expect(Yast::UI).to receive(:UserInput).and_return(:next) + expect(subject).to receive(:setup_final_choice) + expect(Yast::Report).to_not receive(:Message) - expect(subject.main).to eql(:next) - end + expect(subject.main).to eql(:next) end end end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-installation-3.1.210/test/inst_disks_activate_test.rb new/yast2-installation-3.1.213/test/inst_disks_activate_test.rb --- old/yast2-installation-3.1.210/test/inst_disks_activate_test.rb 2016-08-19 16:32:01.000000000 +0200 +++ new/yast2-installation-3.1.213/test/inst_disks_activate_test.rb 2016-08-30 14:17:37.000000000 +0200 @@ -14,7 +14,6 @@ describe "#main" do let(:probed_disks) { [] } let(:s390) { false } - let(:restarting) { false } before do allow(Yast::Linuxrc).to receive(:InstallInf).with("WithFCoE").and_return("0") @@ -23,19 +22,9 @@ allow(Yast::Popup).to receive(:ConfirmAbort).with(:painless).and_return(true) allow(Yast::Arch).to receive(:s390).and_return(s390) allow(Yast::GetInstArgs).to receive(:going_back) { going_back } - allow(Yast::Installation).to receive(:restarting?) { restarting } stub_const("Yast::Storage", double("Yast::Storage", ReReadTargetMap: true)) end - context "when installation is restarting" do - let(:restarting) { true } - it "returns next" do - expect(Yast::Arch).to_not receive(:s390) - - expect(subject.main).to eql(:next) - end - end - context "when architecture is s390" do let(:s390) { true } before do diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-installation-3.1.210/test/inst_finish_test.rb new/yast2-installation-3.1.213/test/inst_finish_test.rb --- old/yast2-installation-3.1.210/test/inst_finish_test.rb 2016-08-19 16:32:01.000000000 +0200 +++ new/yast2-installation-3.1.213/test/inst_finish_test.rb 2016-08-30 14:17:37.000000000 +0200 @@ -24,6 +24,10 @@ allow(Yast::PackageCallbacks).to receive(:RegisterEmptyProgressCallbacks) allow(Yast::PackageCallbacks).to receive(:RestorePreviousProgressCallbacks) + allow(Yast::Pkg).to receive(:TargetInitialize) + allow(Yast::Pkg).to receive(:TargetLoad) + allow(Yast::Pkg).to receive(:PkgInstalled).and_return(false) + allow(Yast::Hooks).to receive(:run) end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-installation-3.1.210/test/inst_update_installer_test.rb new/yast2-installation-3.1.213/test/inst_update_installer_test.rb --- old/yast2-installation-3.1.210/test/inst_update_installer_test.rb 2016-08-19 16:32:01.000000000 +0200 +++ new/yast2-installation-3.1.213/test/inst_update_installer_test.rb 2016-08-30 14:17:37.000000000 +0200 @@ -35,8 +35,10 @@ 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) allow(Yast::Pkg).to receive(:GetArchitecture).and_return(arch) allow(Yast::Mode).to receive(:auto).and_return(false) allow(Yast::NetworkService).to receive(:isNetworkRunning).and_return(network_running) @@ -48,6 +50,12 @@ allow(::FileUtils).to receive(:touch) stub_const("Registration::Storage::InstallationOptions", FakeInstallationOptions) stub_const("Registration::Storage::Config", FakeRegConfig) + # 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(:add_installation_repo) + 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) @@ -64,7 +72,44 @@ end end - context "when update is enabled" do + it "cleans up the package management at the end" do + # override the global stub + expect(subject).to receive(:finish_packager).and_call_original + # pretend the package management has been initialized + # TODO: test the uninitialized case as well + subject.instance_variable_set(:@packager_initialized, true) + + expect(Yast::Pkg).to receive(:SourceGetCurrent).and_return([0]) + expect(Yast::Pkg).to receive(:SourceDelete).with(0) + expect(Yast::Pkg).to receive(:SourceSaveAll) + expect(Yast::Pkg).to receive(:SourceFinishAll) + expect(Yast::Pkg).to receive(:TargetFinish) + + # just a shortcut to avoid mocking the whole update + allow(subject).to receive(:disabled_in_linuxrc?).and_return(true) + subject.main + end + + it "displays a progress" do + expect(Yast::Wizard).to receive(:CreateDialog) + expect(Yast::Progress).to receive(:New) + expect(Yast::Progress).to receive(:NextStage) + + # just a shortcut to avoid mocking the whole update + allow(subject).to receive(:self_update_enabled?).and_return(false) + subject.main + end + + it "finishes the progress at the end" do + expect(Yast::Progress).to receive(:Finish) + expect(Yast::Wizard).to receive(:CloseDialog) + + # just a shortcut to avoid mocking the whole update + allow(subject).to receive(:self_update_enabled?).and_return(false) + subject.main + end + + context "when update URL is configured in control.xml" do before do allow(Yast::ProductFeatures).to receive(:GetStringFeature).and_return(url) end @@ -246,6 +291,23 @@ allow(File).to receive(:write) end + it "initializes the package management" do + # override the global stubs + expect(subject).to receive(:initialize_packager).and_call_original + expect(subject).to receive(:add_installation_repo).and_call_original + + url = "cd:///" + expect(Yast::Pkg).to receive(:SetTextLocale) + expect(Yast::Pkg).to receive(:TargetInitialize).with("/") + expect(Yast::Packages).to receive(:ImportGPGKeys) + expect(Yast::InstURL).to receive(:installInf2Url).and_return(url) + expect(Yast::Pkg).to receive(:SourceCreateBase).with(url, "").and_return(0) + + # just a shortcut to avoid mocking the whole update + allow(subject).to receive(:update_installer).and_return(false) + subject.main + end + it "tries to update the installer using the given URL" do expect(manager).to receive(:add_repository).with(URI(update0.url)) .and_return(true) @@ -324,27 +386,6 @@ end end - context "when only one SMT server exist" do - before do - allow(url_helpers).to receive(:slp_discovery).and_return([smt0]) - end - - it "is selected automatically" do - expect(regservice_selection).to_not receive(:run) - expect(registration_class).to receive(:new).with(smt0.slp_url) - .and_return(registration) - subject.main - end - - it "saves the registration URL to be used later" do - allow(manager).to receive(:add_repository) - expect(FakeInstallationOptions.instance).to receive(:custom_url=).with(smt0.slp_url) - expect(File).to receive(:write).with(/\/inst_update_installer.yaml\z/, - { "custom_url" => smt0.slp_url }.to_yaml) - subject.main - end - end - context "when a registration configuration is specified via AutoYaST profile" do let(:reg_server_url) { "http://ay.test.example.com/update" } let(:profile) { { "suse_register" => { "reg_server" => reg_server_url } } } @@ -376,6 +417,14 @@ 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)) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-installation-3.1.210/test/test_helper.rb new/yast2-installation-3.1.213/test/test_helper.rb --- old/yast2-installation-3.1.210/test/test_helper.rb 2016-08-19 16:32:01.000000000 +0200 +++ new/yast2-installation-3.1.213/test/test_helper.rb 2016-08-30 14:17:37.000000000 +0200 @@ -25,14 +25,34 @@ 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"] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-installation-3.1.210/test/update_repository_test.rb new/yast2-installation-3.1.213/test/update_repository_test.rb --- old/yast2-installation-3.1.210/test/update_repository_test.rb 2016-08-19 16:32:01.000000000 +0200 +++ new/yast2-installation-3.1.213/test/update_repository_test.rb 2016-08-30 14:17:37.000000000 +0200 @@ -243,8 +243,11 @@ end describe "#cleanup" do - it "deletes the repository" do + it "deletes and releases the repository" do expect(Yast::Pkg).to receive(:SourceDelete).with(repo_id) + expect(Yast::Pkg).to receive(:SourceReleaseAll) + expect(Yast::Pkg).to receive(:SourceSaveAll) + subject.cleanup end end