Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package yast2-update for openSUSE:Factory checked in at 2021-12-01 20:46:14 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/yast2-update (Old) and /work/SRC/openSUSE:Factory/.yast2-update.new.31177 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "yast2-update" Wed Dec 1 20:46:14 2021 rev:145 rq:934607 version:4.4.5 Changes: -------- --- /work/SRC/openSUSE:Factory/yast2-update/yast2-update.changes 2021-11-20 02:38:44.804858050 +0100 +++ /work/SRC/openSUSE:Factory/.yast2-update.new.31177/yast2-update.changes 2021-12-02 02:29:13.075786074 +0100 @@ -1,0 +2,8 @@ +Fri Nov 26 15:02:03 UTC 2021 - David Diaz <dgonza...@suse.com> + +- Remove obsolete code for treating /var differently when mounting + partitions, avoiding calling old storage code and crashing + (related to bsc#1186268). +- 4.4.5 + +------------------------------------------------------------------- Old: ---- yast2-update-4.4.4.tar.bz2 New: ---- yast2-update-4.4.5.tar.bz2 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ yast2-update.spec ++++++ --- /var/tmp/diff_new_pack.gDZYgR/_old 2021-12-02 02:29:13.483784667 +0100 +++ /var/tmp/diff_new_pack.gDZYgR/_new 2021-12-02 02:29:13.483784667 +0100 @@ -17,7 +17,7 @@ Name: yast2-update -Version: 4.4.4 +Version: 4.4.5 Release: 0 Summary: YaST2 - Update License: GPL-2.0-only ++++++ yast2-update-4.4.4.tar.bz2 -> yast2-update-4.4.5.tar.bz2 ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-update-4.4.4/package/yast2-update.changes new/yast2-update-4.4.5/package/yast2-update.changes --- old/yast2-update-4.4.4/package/yast2-update.changes 2021-11-15 14:26:48.000000000 +0100 +++ new/yast2-update-4.4.5/package/yast2-update.changes 2021-11-29 17:42:40.000000000 +0100 @@ -1,4 +1,12 @@ ------------------------------------------------------------------- +Fri Nov 26 15:02:03 UTC 2021 - David Diaz <dgonza...@suse.com> + +- Remove obsolete code for treating /var differently when mounting + partitions, avoiding calling old storage code and crashing + (related to bsc#1186268). +- 4.4.5 + +------------------------------------------------------------------- Mon Nov 15 13:10:22 UTC 2021 - Imobach Gonzalez Sosa <igonzalezs...@suse.com> - Adapt to the ProductSpec API (bsc#1192626). diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-update-4.4.4/package/yast2-update.spec new/yast2-update-4.4.5/package/yast2-update.spec --- old/yast2-update-4.4.4/package/yast2-update.spec 2021-11-15 14:26:48.000000000 +0100 +++ new/yast2-update-4.4.5/package/yast2-update.spec 2021-11-29 17:42:40.000000000 +0100 @@ -17,7 +17,7 @@ Name: yast2-update -Version: 4.4.4 +Version: 4.4.5 Release: 0 Summary: YaST2 - Update Group: System/YaST diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-update-4.4.4/src/modules/RootPart.rb new/yast2-update-4.4.5/src/modules/RootPart.rb --- old/yast2-update-4.4.4/src/modules/RootPart.rb 2021-11-15 14:26:48.000000000 +0100 +++ new/yast2-update-4.4.5/src/modules/RootPart.rb 2021-11-29 17:42:40.000000000 +0100 @@ -100,10 +100,6 @@ # `mntpt The mount point, only for `type = "mount". Does not # include Installation::destdir. @activated = [] - - # translation from new to old device names - # such as /dev/sdc4 -> /dev/hdb4 - @backward_translation = {} end # Returns currently activated partitions. @@ -644,18 +640,6 @@ nil end - def FstabHasSeparateVar(fstab) - var_device_fstab = ( - fstab_ref = arg_ref(fstab.value) - _FindPartitionInFstab_result = FindPartitionInFstab(fstab_ref, "/var") - fstab.value = fstab_ref.value - _FindPartitionInFstab_result - ) - Builtins.y2milestone("/var partition is %1", var_device_fstab) - - !var_device_fstab.nil? - end - def FstabUsesKernelDeviceNameForHarddisks(fstab) fstab = deep_copy(fstab) # We just want to check the use of kernel device names for hard @@ -681,7 +665,6 @@ # @param list <map> ('pointer' to) crtab # @param string root device def read_fstab_and_cryptotab(fstab, crtab, _root_device_current) - @backward_translation = {} # /etc/cryptotab was deprecated in favor of /etc/crypttab # # crypttab file is processed by storage-ng, see {#MountPartitions}. @@ -825,146 +808,70 @@ success = true - Builtins.foreach(fstab) do |mounts| - vfstype = Ops.get_string(mounts, "vfstype", "") - mntops = Ops.get_string(mounts, "mntops", "") - spec = Ops.get_string(mounts, "spec", "") - fspath = Ops.get_string(mounts, "file", "") + return success if Mode.test - if mount_regular_fstab_entry?(mounts) - Builtins.y2milestone("mounting %1 to %2", spec, fspath) - - if !Mode.test - mount_type = "" - mount_type = vfstype if vfstype == "proc" - - mount_err = "" - until mount_err.nil? - # An encryption device might be probed with a name that does not match with the name - # indicated in the fstab file. For example, when the fstab entry is: - # - # /dev/mapper/cr_home /home ext4 defaults 0 0 - # - # and that encryption device was probed as /dev/mapper/cr-auto-1. - # - # In that case, to mount /dev/mapper/cr_home would fail because there is not a device - # in the inst-sys with such name. To avoid possible failures when mounting the fstab - # device, the safest device name is used instead, that is, UUID= format or its uuid - # udev name, see {#safest_device_name}. - mount_err = FsckAndMount(fspath, safest_device_name(spec), mount_type, mntops) - next if mount_err.nil? - - Builtins.y2error( - "mounting %1 (type %2) on %3 failed", - spec, - mount_type, - Ops.add(Installation.destdir, fspath) - ) - UI.OpenDialog( - VBox( - Label( - Builtins.sformat( - # label in a popup, %1 is device (eg. /dev/hda1), - # %2 is output of the 'mount' command - _( - "The partition %1 could not be mounted.\n" \ - "\n" \ - "%2\n" \ - "\n" \ - "If you are sure that the partition is not necessary for the\n" \ - "update (not a system partition), click Continue.\n" \ - "To check or fix the mount options, click Specify Mount Options.\n" \ - "To abort the update, click Cancel.\n" - ), - spec, - mount_err - ) - ), - VSpacing(1), - HBox( - PushButton(Id(:cont), Label.ContinueButton), - # push button - PushButton(Id(:cmd), _("&Specify Mount Options")), - PushButton(Id(:cancel), Label.CancelButton) - ) - ) - ) - act = Convert.to_symbol(UI.UserInput) - UI.CloseDialog - if act == :cancel - mount_err = nil - success = false - elsif act == :cont - mount_err = nil - elsif act == :cmd - UI.OpenDialog( - VBox( - # popup heading - Heading(_("Mount Options")), - VSpacing(0.6), - # text entry label - TextEntry(Id(:mp), _("&Mount Point"), fspath), - VSpacing(0.4), - # tex entry label - TextEntry(Id(:device), _("&Device"), spec), - VSpacing(0.4), - # text entry label - TextEntry( - Id(:fs), - _("&File System\n(empty for autodetection)"), - mount_type - ), - VSpacing(1), - HBox( - PushButton(Id(:ok), Label.OKButton), - PushButton(Id(:cancel), Label.CancelButton) - ) - ) - ) - act = Convert.to_symbol(UI.UserInput) - if act == :ok - fspath = Convert.to_string(UI.QueryWidget(Id(:mp), :Value)) - spec = Convert.to_string( - UI.QueryWidget(Id(:device), :Value) - ) - mount_type = Convert.to_string( - UI.QueryWidget(Id(:fs), :Value) - ) - end - UI.CloseDialog - end - end + fstab.each do |mounts| + vfstype = mounts.fetch("vfstype", "") + mntops = mounts.fetch("mntops", "") + spec = mounts.fetch("spec", "") + fspath = mounts.fetch("file", "") - if fspath == "/boot" || fspath == "/boot/" - checkspec = spec + if mount_regular_fstab_entry?(mounts) + log.info("mounting #{spec} to #{fspath}") - # translates new device name to the old one because - # storage still returns them in the old way - if Ops.get(@backward_translation, spec) - checkspec = Ops.get(@backward_translation, spec, spec) - end + mount_type = "" + mount_type = vfstype if vfstype == "proc" - success = false if !CheckBootSize(checkspec) + loop do + # An encryption device might be probed with a name that does not match with the name + # indicated in the fstab file. For example, when the fstab entry is: + # + # /dev/mapper/cr_home /home ext4 defaults 0 0 + # + # and that encryption device was probed as /dev/mapper/cr-auto-1. + # + # In that case, to mount /dev/mapper/cr_home would fail because there is not a device + # in the inst-sys with such name. To avoid possible failures when mounting the fstab + # device, the safest device name is used instead, that is, UUID= format or its uuid + # udev name, see {#safest_device_name}. + mount_error = FsckAndMount(fspath, safest_device_name(spec), mount_type, mntops) + break if mount_error.nil? + + mount_path = "#{Installation.destdir}/#{fspath}" + log.error("mounting #{spec} (type #{mount_type}) on #{mount_path} failed") + + action = mount_failed_action(spec, mount_error) + + case action + when :cont + break + when :cancel + success = false + break + when :cmd + fspath, spec, mount_type = user_mount_options(fspath, spec, mount_type) end end + + if fspath == "/boot" || fspath == "/boot/" + success = false unless CheckBootSize(spec) + end elsif vfstype == "swap" && fspath == "swap" - Builtins.y2milestone("mounting %1 to %2", spec, fspath) + log.info("mounting #{spec} to #{fspath}") - if !Mode.test - command = "/sbin/swapon " - if spec != "" - # swap-partition - command = Ops.add(command, spec) - - # run /sbin/swapon - ret_from_shell = Convert.to_integer( - SCR.Execute(path(".target.bash"), command) - ) - if ret_from_shell != 0 - Builtins.y2error("swapon failed: %1", command) - else - AddMountedPartition(type: "swap", device: spec) - end + command = "/sbin/swapon " + if spec != "" + # swap-partition + command = Ops.add(command, spec) + + # run /sbin/swapon + ret_from_shell = Convert.to_integer( + SCR.Execute(path(".target.bash"), command) + ) + if ret_from_shell != 0 + log.error("swapon failed: #{command}") + else + AddMountedPartition(type: "swap", device: spec) end end end @@ -973,222 +880,99 @@ success end - # Mount /var partition + # Displays a warning dialog to the suer when mount failed # - # @param device [String] name of the device holding /var - # @return [String, nil] nil on success, error description on fail - def MountVarPartition(device) - mount_err = FsckAndMount("/var", device, "") - - return nil unless mount_err - - log.error("failed to mount /var") - - # TRANSLATORS: error message when /var partition cannot be mounted. %{device} - # is replaced by a device name (e.g., /dev/sda2) and %{error} is replaced by - # error details. - format( - _("The /var partition %{device} could not be mounted.\n\n%{error}"), - device: device, - error: mount_err - ) - end - - # <-- BNC #448577, Cannot find /var partition automatically - # returns if successful - def MountUserDefinedVarPartition - # function return value - manual_mount_successful = false - - list_of_devices = [] - # $[ "/dev/sda3" : "Label: My_Partition" ] - device_info = {} - - # Creating the list of known partitions - Builtins.foreach(Storage.GetOndiskTarget) do |_device, description| - Builtins.foreach(Ops.get_list(description, "partitions", [])) do |partition| - # Some partitions logically can't be used for /var - next if Ops.get_symbol(partition, "detected_fs", :unknown) == :swap - next if Ops.get_symbol(partition, "type", :unknown) == :extended - next if !Builtins.haskey(partition, "device") - - list_of_devices = Builtins.add( - list_of_devices, - Ops.get_string(partition, "device", "") - ) - Ops.set( - device_info, - Ops.get_string(partition, "device", ""), + # Apart from informing, it lets on the user the next actions: to ignore the error and continue, + # to check and/or specify the mount options, or to abort the update. + # + # FIXME: this dialog should live in its own class. However, extracting it to a method + # looks like a good compromise in the context of the PBI it has been addressed. So please, + # feel free to make it a first-class citizen in future changes. + # + # @param spec [String] + # @param error [String] the error returned by {#FsckAndMount} + # @return [Symbol] the action chosen by the user, namely + # :cont if decides to continue because the partition is not necessary for the update + # :cmd when wants to check or specify the mount options + # :cancel whether goes for aborting the update process + def mount_failed_action(spec, error) + UI.OpenDialog( + VBox( + Label( Builtins.sformat( - # Informational text about selected partition, %x are replaced with values later + # label in a popup, %1 is device (eg. /dev/hda1), + # %2 is output of the 'mount' command _( - "<b>File system:</b> %1, <b>Type:</b> %2,<br>\n" \ - "<b>Label:</b> %3, <b>Size:</b> %4,<br>\n" \ - "<b>udev IDs:</b> %5,<br>\n" \ - "<b>udev path:</b> %6" - ), - # starts with >`< - Builtins.substring( - Builtins.tostring( - Ops.get_symbol(partition, "detected_fs", :unknown) - ), - 1 - ), - Ops.get_locale(partition, "fstype", _("Unknown")), - Ops.get_locale(partition, "label", _("None")), - String.FormatSize( - Ops.multiply(Ops.get_integer(partition, "size_k", 0), 1024) + "The partition %1 could not be mounted.\n" \ + "\n" \ + "%2\n" \ + "\n" \ + "If you are sure that the partition is not necessary for the\n" \ + "update (not a system partition), click Continue.\n" \ + "To check or fix the mount options, click Specify Mount Options.\n" \ + "To abort the update, click Cancel.\n" ), - Builtins.mergestring(Ops.get_list(partition, "udev_id", []), ", "), - Ops.get_locale(partition, "udev_path", _("Unknown")) - ) - ) - end - end - - list_of_devices = Builtins.sort(list_of_devices) - Builtins.y2milestone("Known devices: %1", list_of_devices) - - loop do - UI.OpenDialog( - VBox( - MarginBox( - 1, - 0, - VBox( - # a popup caption - Left( - Heading(_("Unable to find the /var partition automatically")) - ), - # a popup message - Left( - Label( - _( - "Your system uses a separate /var partition which is " \ - "required for the upgrade\n" \ - "process to detect the disk-naming changes. " \ - "Select the /var partition manually\n" \ - "to continue the upgrade process." - ) - ) - ), - VSpacing(1), - Left( - ComboBox( - Id("var_device"), - Opt(:notify), - # a combo-box label - _("&Select /var Partition Device"), - list_of_devices - ) - ), - VSpacing(0.5), - # an informational rich-text widget label - Left(Label(_("Device Info"))), - MinHeight(3, RichText(Id("device_info"), "")), - VSpacing(1) - ) - ), - MarginBox( - 1, - 0, - ButtonBox( - PushButton(Id(:ok), Opt(:okButton), Label.OKButton), - PushButton(Id(:cancel), Opt(:cancelButton), Label.CancelButton) - ) + spec, + error ) + ), + VSpacing(1), + HBox( + PushButton(Id(:cont), Label.ContinueButton), + PushButton(Id(:cmd), _("&Specify Mount Options")), + PushButton(Id(:cancel), Label.CancelButton) ) ) + ) - ret = nil - - # initial device - var_device = Convert.to_string(UI.QueryWidget(Id("var_device"), :Value)) - UI.ChangeWidget( - Id("device_info"), - :Value, - Ops.get(device_info, var_device, "") - ) - - # to handle switching the combo-box or [OK]/[Cancel] - loop do - ret = UI.UserInput - var_device = Convert.to_string( - UI.QueryWidget(Id("var_device"), :Value) - ) - - break if ret != "var_device" - - UI.ChangeWidget( - Id("device_info"), - :Value, - Ops.get(device_info, var_device, "") - ) - end - - UI.CloseDialog + action = UI.UserInput.to_sym - # Trying user-selection - if ret == :ok - Builtins.y2milestone("Trying to mount %1 as /var", var_device) - mount_error = MountVarPartition(var_device) - - if !mount_error.nil? - Report.Error(mount_error) - next - else - Builtins.y2milestone("Manual mount (/var) successful") - manual_mount_successful = true - break - end - # `cancel - else - Builtins.y2warning( - "User doesn't want to enter the /var partition device" - ) - break - end - end + UI.CloseDialog - manual_mount_successful + action end - def MountVarIfRequired(fstab, manual_var_mount) - fstab = deep_copy(fstab) - var_device_fstab = ( - fstab_ref = arg_ref(fstab) - FindPartitionInFstab(fstab_ref, "/var") + # Displays the Mount Options dialog to the user + # + # FIXME: this dialog should live in its own class. However, extracting it to a method + # looks like a good compromise in the context of the PBI it has been addressed. So please, + # feel free to make it a first-class citizen in future changes. + # + # @param fspath [String] the filesytem path + # @param spec [String] + # @param mount_type [String] + # + # @return [Array<(String, String, String)>] an array holding the current (if the user + # cancels) or the new (when user accepts) values for fspath, spec, and mount_type + def user_mount_options(fspath, spec, mount_type) + UI.OpenDialog( + VBox( + Heading(_("Mount Options")), + VSpacing(0.6), + TextEntry(Id(:mp), _("&Mount Point"), fspath), + VSpacing(0.4), + TextEntry(Id(:device), _("&Device"), spec), + VSpacing(0.4), + TextEntry(Id(:fs), _("&File System\n(empty for autodetection)"), mount_type), + VSpacing(1), + HBox( + PushButton(Id(:ok), Label.OKButton), + PushButton(Id(:cancel), Label.CancelButton) + ) + ) ) - # At this point, var_device_fstab contains the spec column of fstab - # for the /var mount point. E.g. "/dev/sda1", "/dev/system/var" or "UUID=00x00x00x" + action = UI.UserInput.to_sym - # No need to mount "/var", it's not separate == already mounted with "/" - if var_device_fstab.nil? - Builtins.y2milestone("Not a separate /var...") - return nil + if action == :ok + fspath = UI.QueryWidget(Id(:mp), :Value).to_s + spec = UI.QueryWidget(Id(:device), :Value).to_s + mount_type = UI.QueryWidget(Id(:fs), :Value).to_s end - filesystem = find_filesystem_by_fstab_spec(var_device_fstab) - - # Try to mount /var if any filesystem matches the fstab specification - return MountVarPartition(var_device_fstab) if filesystem - - # BNC #448577: cannot find /var partition automatically, so ask the user - return nil if manual_var_mount && MountUserDefinedVarPartition() - - # Everything else failed, return error message - log.error "Unable to mount /var partition" - - _("Unable to mount /var partition with this disk configuration.\n") - end + UI.CloseDialog - # Finds a filesystem that matches the given fstab spec - # - # @param spec [String] - # @return [Y2Storage::Filesystem, nil] - def find_filesystem_by_fstab_spec(spec) - probed.blk_filesystems.find { |f| f.match_fstab_spec?(spec) } + [fspath, spec, mount_type] end def has_pam_mount @@ -1303,64 +1087,57 @@ message = _("No fstab found.") success = false else - tmp_msg = MountVarIfRequired(fstab, true) - if !tmp_msg.nil? - Builtins.y2error("failed to mount /var!") - message = tmp_msg - success = false - else - tmp = "" + tmp = "" - if !( - tmp_ref = arg_ref(tmp) - check_root_device_result = check_root_device( - root_device_current, - fstab, - tmp_ref - ) - tmp = tmp_ref.value - check_root_device_result + if !( + tmp_ref = arg_ref(tmp) + check_root_device_result = check_root_device( + root_device_current, + fstab, + tmp_ref ) - Builtins.y2error("fstab has wrong root device!") + tmp = tmp_ref.value + check_root_device_result + ) + Builtins.y2error("fstab has wrong root device!") - # TRANSLATORS: Error message, where %{root} and %{tmp} are replaced by - # device names (e.g., /dev/sda1 and /dev/sda2). - message = format( - _("The root partition in /etc/fstab has an invalid root device.\n" \ - "It is currently mounted as %{root} but listed as %{tmp}."), - root: root_device_current, - tmp: tmp - ) + # TRANSLATORS: Error message, where %{root} and %{tmp} are replaced by + # device names (e.g., /dev/sda1 and /dev/sda2). + message = format( + _("The root partition in /etc/fstab has an invalid root device.\n" \ + "It is currently mounted as %{root} but listed as %{tmp}."), + root: root_device_current, + tmp: tmp + ) - success = false - else - Builtins.y2milestone("fstab %1", fstab) + success = false + else + Builtins.y2milestone("fstab %1", fstab) - legacy_filesystems = - Y2Storage::Filesystems::Type.legacy_home_filesystems.map(&:to_s) + legacy_filesystems = + Y2Storage::Filesystems::Type.legacy_home_filesystems.map(&:to_s) - legacy_entries = fstab.select { |e| legacy_filesystems.include?(e["vfstype"]) } + legacy_entries = fstab.select { |e| legacy_filesystems.include?(e["vfstype"]) } - # Removed ReiserFS support for system upgrade (fate#323394). - if !legacy_entries.empty? - message = - Builtins.sformat( - _("The mount points listed below are using legacy filesystems " \ - "that are not supported anymore:\n\n%1\n\n" \ - "Before upgrade you should migrate all " \ - "your data to another filesystem.\n"), - legacy_entries.map { |e| "#{e["file"]} (#{e["vfstype"]})" }.join("\n") - ) - - success = false - elsif !( - message_ref = arg_ref(message) - _MountFSTab_result = MountFSTab(fstab, message_ref) - message = message_ref.value - _MountFSTab_result + # Removed ReiserFS support for system upgrade (fate#323394). + if !legacy_entries.empty? + message = + Builtins.sformat( + _("The mount points listed below are using legacy filesystems " \ + "that are not supported anymore:\n\n%1\n\n" \ + "Before upgrade you should migrate all " \ + "your data to another filesystem.\n"), + legacy_entries.map { |e| "#{e["file"]} (#{e["vfstype"]})" }.join("\n") ) - success = false - end + + success = false + elsif !( + message_ref = arg_ref(message) + _MountFSTab_result = MountFSTab(fstab, message_ref) + message = message_ref.value + _MountFSTab_result + ) + success = false end end end @@ -2006,10 +1783,7 @@ return false unless ALLOWED_FS.include?(vfstype) return false if mntops.include?("noauto") - # The conditions above are enough for any mount point except /var. - # In the /var case, it should have been already processed by - # #MountVarIfRequired... except when /var is a subvolume - path != "/var" || mntops.include?("subvol=") + true end # Creates a pre-update snapshot and stores its number diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-update-4.4.4/test/root_part_test.rb new/yast2-update-4.4.5/test/root_part_test.rb --- old/yast2-update-4.4.4/test/root_part_test.rb 2021-11-15 14:26:48.000000000 +0100 +++ new/yast2-update-4.4.5/test/root_part_test.rb 2021-11-29 17:42:40.000000000 +0100 @@ -5,14 +5,21 @@ Yast.import "RootPart" describe Yast::RootPart do - describe "#MountVarIfRequired" do + describe "#MountFSTab" do before do stub_storage(scenario) + allow(subject).to receive(:FsckAndMount) + allow(Yast::UI).to receive(:OpenDialog) + allow(Yast::UI).to receive(:UserInput).twice.and_return(user_input, :ok) # Mock the system lookup executed as last resort when the devicegraph # doesn't contain the searched information allow(Y2Storage::BlkDevice).to receive(:find_by_any_name) end + let(:user_input) { :cancel } + + let(:message) { Yast.arg_ref("") } + let(:scenario) { "two-disks-two-btrfs.xml" } let(:fstab_sda1) do @@ -61,142 +68,155 @@ ] end - RSpec.shared_examples "mounting result" do - context "and mounting /var fails with an error message" do - before do - allow(subject).to receive(:FsckAndMount).with("/var", any_args) - .and_return "an error" - end + context "mounting /var" do + let(:fsck_and_mount_result) { nil } - it "returns a string including the device and the error " do - result = subject.MountVarIfRequired(fstab, false) - expect(result).to be_a(String) - expect(result).to include("an error") - expect(result).to include(var_spec) - end + before do + allow(subject).to receive(:FsckAndMount).with("/var", any_args) + .and_return(fsck_and_mount_result) end - context "and mounting /var succeeds" do - before do - allow(subject).to receive(:FsckAndMount).with("/var", any_args).and_return nil - end + RSpec.shared_examples "mounting /var fails" do + context "fails with an error message" do + let(:fsck_and_mount_result) { "an error while mounting" } - it "returns nil" do - expect(subject.MountVarIfRequired(fstab, false)).to be_nil - end - end - end + it "displays a dialog informing the user about it" do + expect(Yast::UI).to receive(:OpenDialog) do |content| + label = content.nested_find { |e| e.is_a?(Yast::Term) && e.value == :Label } + text = label.params.first - context "if there is no separate partition" do - context "and no @/var subvolume" do - let(:fstab) { fstab_sda2 } - let(:root_spec) { "UUID=d6e5c710-3067-48de-8363-433e54a9d0b5" } + expect(text).to include(var_spec) + expect(text).to include("could not be mounted") + expect(text).to include(fsck_and_mount_result) + end - it "does not try to mount /var" do - expect(subject).to_not receive(:FsckAndMount) - subject.MountVarIfRequired(fstab, false) - end + subject.MountFSTab(fstab, message) + end - it "returns nil" do - expect(subject.MountVarIfRequired(fstab, false)).to be_nil - end - end + context "but the user decides to continue anyway" do + let(:user_input) { :cont } - context "and there is a @/var subvolume" do - let(:fstab) { fstab_sda1 } - let(:root_spec) { "UUID=0a0ebfa7-e1a8-45f2-ad53-495e192fcc8d" } + it "returns true" do + result = subject.MountFSTab(fstab, message) + expect(result).to eq(true) + end + end - # The old code did not support Btrfs properly, so it mounted the /var - # subvolume as a partition, which produced big breakage. - it "does not try to mount /var" do - expect(subject).to_not receive(:FsckAndMount) - subject.MountVarIfRequired(fstab, false) - end + context "and the user decides to cancel" do + let(:user_input) { :cancel } - it "returns nil" do - expect(subject.MountVarIfRequired(fstab, false)).to be_nil - end - end - end + it "returns false" do + result = subject.MountFSTab(fstab, message) + expect(result).to eq(false) + end + end - context "if /var is a separate partition" do - let(:fstab) do - fstab_sda2 + [ - { - "file" => "/var", "mntops" => "defaults", "vfstype" => "xfs", - "spec" => var_spec - } - ] - end + context "and the user decides to check or fix the mount options" do + let(:user_input) { :cmd } - context "and the device is found in the system" do - let(:root_spec) { "UUID=d6e5c710-3067-48de-8363-433e54a9d0b5" } + it "displays the mount options dialog" do + expect(Yast::UI).to receive(:OpenDialog) # Let's skip the first dialog + expect(Yast::UI).to receive(:OpenDialog) do |content| + heading = content.nested_find { |e| e.is_a?(Yast::Term) && e.value == :Heading } + text = heading.params.first - let(:var_spec) { "UUID=c9510dc7-fb50-4f7b-bd84-886965c821f6" } + expect(text).to include("Mount Options") + end - it "tries to mount /var" do - expect(subject).to receive(:FsckAndMount).with("/var", var_spec, "") - subject.MountVarIfRequired(fstab, false) + subject.MountFSTab(fstab, message) + end + end end - - include_examples "mounting result" end - context "and the device is not found in the system" do - let(:root_spec) { "/dev/sda2" } + RSpec.shared_examples "mounting /var succeeds" do + context "and mounting /var succeeds" do + let(:fsck_and_mount_result) { nil } - let(:var_spec) { "/dev/sdc1" } + it "returns true" do + result = subject.MountFSTab(fstab, message) + expect(result).to eq(true) + end + end + end + RSpec.shared_examples "mounting /var does not happen" do it "does not try to mount /var" do - expect(subject).to_not receive(:FsckAndMount) - subject.MountVarIfRequired(fstab, false) - end + expect(subject).to_not receive(:FsckAndMount).with("/var", any_args) - it "returns an error" do - expect(subject.MountVarIfRequired(fstab, false)) - .to match(/Unable to mount/) + subject.MountFSTab(fstab, message) end end - end - context "if /var is a separate LVM logical volume" do - let(:scenario) { "trivial-lvm.yml" } + context "if there is no separate partition" do + context "and no @/var subvolume" do + let(:fstab) { fstab_sda2 } + let(:root_spec) { "UUID=d6e5c710-3067-48de-8363-433e54a9d0b5" } + + include_examples "mounting /var does not happen" + end + + context "and there is a @/var subvolume" do + let(:fstab) { fstab_sda1 } + let(:root_spec) { "UUID=0a0ebfa7-e1a8-45f2-ad53-495e192fcc8d" } - let(:fstab) do - fstab_sda2 + [ - { - "file" => "/var", "mntops" => "defaults", "vfstype" => "xfs", - "spec" => var_spec - } - ] + include_examples "mounting /var succeeds" + end end - context "and the LVM logical volume is found in the system" do - let(:root_spec) { "/dev/vg0/root" } + context "if /var is a separate partition" do + let(:fstab) do + fstab_sda2 + [ + { + "file" => "/var", "mntops" => "defaults", "vfstype" => "xfs", + "spec" => var_spec + } + ] + end + + context "and the device is found in the system" do + let(:root_spec) { "UUID=d6e5c710-3067-48de-8363-433e54a9d0b5" } - let(:var_spec) { "/dev/disk/by-uuid/4b85-3de0" } + let(:var_spec) { "UUID=c9510dc7-fb50-4f7b-bd84-886965c821f6" } - it "tries to mount /var" do - expect(subject).to receive(:FsckAndMount).with("/var", var_spec, "") - subject.MountVarIfRequired(fstab, false) + include_examples "mounting /var succeeds" end - include_examples "mounting result" + context "and the device is not found in the system" do + let(:root_spec) { "/dev/sda2" } + + let(:var_spec) { "/dev/sdc1" } + + include_examples "mounting /var fails" + end end - context "and the LVM logical volume is not found in the system" do - let(:root_spec) { "/dev/vg0/root" } + context "if /var is a separate LVM logical volume" do + let(:scenario) { "trivial-lvm.yml" } - let(:var_spec) { "/dev/disk/by-uuid/not-found" } + let(:fstab) do + fstab_sda2 + [ + { + "file" => "/var", "mntops" => "defaults", "vfstype" => "xfs", + "spec" => var_spec + } + ] + end - it "does not try to mount /var" do - expect(subject).to_not receive(:FsckAndMount) - subject.MountVarIfRequired(fstab, false) + context "and the LVM logical volume is found in the system" do + let(:root_spec) { "/dev/vg0/root" } + + let(:var_spec) { "/dev/disk/by-uuid/4b85-3de0" } + + include_examples "mounting /var succeeds" end - it "returns an error" do - expect(subject.MountVarIfRequired(fstab, false)) - .to match(/Unable to mount/) + context "and the LVM logical volume is not found in the system" do + let(:root_spec) { "/dev/vg0/root" } + + let(:var_spec) { "/dev/disk/by-uuid/not-found" } + + include_examples "mounting /var fails" end end end