diff --git a/package/yast2-storage-ng.changes b/package/yast2-storage-ng.changes index a2de34f20..3aff342ff 100644 --- a/package/yast2-storage-ng.changes +++ b/package/yast2-storage-ng.changes @@ -1,3 +1,11 @@ +------------------------------------------------------------------- +Thu Mar 7 16:26:04 UTC 2024 - José Iván López González + +- Share the logic for generating the description of a device and + the label of a file system. +- Needed for (gh#openSUSE/agama#1079). +- 5.0.8 + ------------------------------------------------------------------- Mon Mar 4 14:36:58 UTC 2024 - Ancor Gonzalez Sosa diff --git a/package/yast2-storage-ng.spec b/package/yast2-storage-ng.spec index 43b52e70d..f01c1d17f 100644 --- a/package/yast2-storage-ng.spec +++ b/package/yast2-storage-ng.spec @@ -16,7 +16,7 @@ # Name: yast2-storage-ng -Version: 5.0.7 +Version: 5.0.8 Release: 0 Summary: YaST2 - Storage Configuration License: GPL-2.0-only OR GPL-3.0-only diff --git a/src/lib/y2partitioner/widgets/columns/filesystem_label.rb b/src/lib/y2partitioner/widgets/columns/filesystem_label.rb index 5dd57a4cb..cb50e5e8e 100644 --- a/src/lib/y2partitioner/widgets/columns/filesystem_label.rb +++ b/src/lib/y2partitioner/widgets/columns/filesystem_label.rb @@ -1,4 +1,4 @@ -# Copyright (c) [2020] SUSE LLC +# Copyright (c) [2020-2024] SUSE LLC # # All Rights Reserved. # @@ -19,6 +19,7 @@ require "yast" require "y2partitioner/widgets/columns/base" +require "y2storage/filesystem_label" module Y2Partitioner module Widgets @@ -39,45 +40,13 @@ def title # @see Columns::Base#value_for def value_for(device) - return fstab_filesystem_label(device) if fstab_entry?(device) - - filesystem_label(device) + Y2Storage::FilesystemLabel.new(device, system_graph: system_graph).to_s end # @see Columns::Base#id def id :label end - - private - - # Returns the label for the given device, when possible - # - # @param device [Y2Storage::Device, nil] - # @return [String] the label if possible; empty string otherwise - def filesystem_label(device) - return "" unless device - return "" if device.is?(:btrfs_subvolume) - - filesystem = filesystem_for(device) - - return "" unless filesystem - return "" if part_of_multidevice?(device, filesystem) - # fs may not support labels, like NFS - return "" unless filesystem.respond_to?(:label) - - filesystem.label - end - - # Returns the label for the given fstab entry, when possible - # - # @see #filesystem_label - # @param fstab_entry [Y2Storage::SimpleEtcFstabEntry] - def fstab_filesystem_label(fstab_entry) - device = fstab_entry.device(system_graph) - - filesystem_label(device) - end end end end diff --git a/src/lib/y2partitioner/widgets/columns/type.rb b/src/lib/y2partitioner/widgets/columns/type.rb index f23904a2f..38ec79123 100644 --- a/src/lib/y2partitioner/widgets/columns/type.rb +++ b/src/lib/y2partitioner/widgets/columns/type.rb @@ -1,4 +1,4 @@ -# Copyright (c) [2020] SUSE LLC +# Copyright (c) [2020-2024] SUSE LLC # # All Rights Reserved. # @@ -20,6 +20,7 @@ require "yast" require "y2partitioner/icons" require "y2partitioner/widgets/columns/base" +require "y2storage/device_description" module Y2Partitioner module Widgets @@ -45,34 +46,6 @@ class Type < Base } private_constant :DEVICE_ICONS - # Default labels based on the device type - # - # @see #default_label - DEVICE_LABELS = { - bcache: N_("Bcache"), - disk: N_("Disk"), - dasd: N_("Disk"), - multipath: N_("Multipath"), - nfs: N_("NFS"), - bios_raid: N_("BIOS RAID"), - software_raid: N_("RAID"), - lvm_pv: N_("PV"), - lvm_vg: N_("LVM"), - lvm_thin: N_("Thin LV"), - lvm_thin_pool: N_("Thin Pool"), - lvm_raid: N_("RAID LV"), - lvm_cache: N_("Cache LV"), - lvm_cache_pool: N_("Cache Pool"), - lvm_writecache: N_("Writecache LV"), - lvm_snapshot: N_("Snapshot LV"), - lvm_mirror: N_("Mirror LV"), - lvm_lv: N_("LV"), - stray: N_("Xen"), - partition: N_("Partition"), - btrfs_subvolume: N_("Btrfs Subvolume") - } - private_constant :DEVICE_LABELS - # Constructor def initialize super @@ -128,208 +101,12 @@ def fstab_device_icon(fstab_entry) # A text describing the given device # - # @see DEVICE_ICONS + # @see DeviceDescription # # @param device [Y2Storage::Device, Y2Storage::LvmPv, Y2Storage::SimpleEtcFstabEntry] # @return [String] def device_label(device) - return fstab_device_label(device) if fstab_entry?(device) - return device.type.to_human_string if device.is?(:filesystem) - return default_label(device) if device.is?(:lvm_vg, :btrfs_subvolume) - return snapshot_type_label(device) if device.is?(:lvm_snapshot) - - formatted_device_type_label(device) || unformatted_device_type_label(device) - end - - # Label for the device in the given fstab entry - # - # @param fstab_entry [Y2Storage::SimpleEtcFstabEntry] - # @return [String] the #device_label if device is found in the system; empty string otherwise - def fstab_device_label(fstab_entry) - device = fstab_entry.device(system_graph) - device ? device_label(device) : "" - end - - # Label for a formatted device (e.g., Ext4 LVM, XFS RAID, Swap Partition, etc) - # - # @return [String, nil] label if the device has a filesystem; nil otherwise - def formatted_device_type_label(device) - fs = filesystem_for(device) - - return nil unless fs - - if device.journal? - journal_type_label(fs) - elsif show_multidevice_type_label?(fs) - multidevice_type_label(fs) - else - # TRANSLATORS: %{fs_type} is the filesystem type. I.e., FAT, Ext4, etc - # %{device_label} is the device label. I.e., Partition, Disk, etc - format( - _("%{fs_type} %{device_label}"), - fs_type: fs_type(device, fs), - device_label: default_label(device) - ) - end - end - - # The filesystem type representation (FAT, Ext4, etc) - # - # @return [String] - def fs_type(device, filesystem) - if device.is?(:partition) && device.efi_system? - device.id.to_human_string - else - filesystem.type.to_human_string - end - end - - # Label for unformatted device (e.g., LVM, RAID, Partition, etc) - # - # @return [String] - def unformatted_device_type_label(device) - if device.lvm_pv - lvm_pv_type_label(device.lvm_pv) - elsif device.md - part_of_label(device.md) - elsif device.bcache - bcache_backing_label(device.bcache) - elsif device.in_bcache_cset - bcache_cset_label - else - default_unformatted_label(device) - end - end - - # Label when the device is a LVM physical volume - # - # @param lvm_pv [Y2Storage::LvmPv] - # @return [String] - def lvm_pv_type_label(lvm_pv) - vg = lvm_pv.lvm_vg - - return _("Unused LVM PV") if vg.nil? - return _("PV of LVM") if vg.basename.empty? - - # TRANSLATORS: %s is the volume group name. E.g., "vg0" - format(_("PV of %s"), vg.basename) - end - - # Label for an LVM snapshot device - # - # @param lvm_snapshot [Y2Storage::LvmLv] - # @return [String] - def snapshot_type_label(lvm_snapshot) - label = - if lvm_snapshot.is?(:lvm_thin_snapshot) - # TRANSLATORS: %{origin} is replaced by an LVM logical volumme name - # (e.g., /dev/vg0/user-data) - _("Thin Snapshot of %{origin}") - else - # TRANSLATORS: %{origin} is replaced by an LVM logical volumme name - # (e.g., /dev/vg0/user-data) - _("Snapshot of %{origin}") - end - - format(label, origin: lvm_snapshot.origin.lv_name) - end - - # Label when the device holds a journal - # - # @param filesystem [Y2Storage::BlkFilesystem] - # @return [String] - def journal_type_label(filesystem) - data_device = filesystem.blk_devices.find { |d| !d.journal? } - - # TRANSLATORS: %{fs_type} is the filesystem type. E.g., Btrfs, Ext4, etc. - # %{data_device_name} is the data device name. E.g., sda1 - format( - _("%{fs_type} Journal (%{data_device_name})"), - fs_type: filesystem.type.to_human_string, - data_device_name: data_device.basename - ) - end - - # Label when the device belongs to a multi-device filesystem - # - # @param filesystem [Y2Storage::BlkFilesystem] - # @return [String] - def multidevice_type_label(filesystem) - # TRANSLATORS: %{fs_name} is the filesystem name. E.g., Btrfs, Ext4, etc. - # %{blk_device_name} is a device base name. E.g., sda1... - format( - _("Part of %{fs_name} %{blk_device_name}"), - fs_name: filesystem.type, - blk_device_name: filesystem.blk_device_basename - ) - end - - # Label when the device is used as backing device of a Bcache - # - # @param [Y2Storage::Device] device - def bcache_backing_label(device) - # TRANSLATORS: %{bcache} is replaced by a device name (e.g., bcache0). - format(_("Backing of %{bcache}"), bcache: device.basename) - end - - # Label when the device is used as caching device in a Bcache - # - # @return [String] - def bcache_cset_label - # TRANSLATORS: an special type of device - _("Bcache caching") - end - - # Label when the device is part of another one, like Bcache or RAID - # - # @param ancestor_device [Y2Storage::BlkDevice] - # @return [String] - def part_of_label(ancestor_device) - format(_("Part of %s"), ancestor_device.basename) - end - - # Default label when device is unformatted - # - # @return [String] - def default_unformatted_label(device) - # The "model" field from hwinfo is a combination of vendor + device with quite some added - # heuristics to make the result nice looking. See comment#66 at bsc#1200975. - model = device.model || "" - - return model unless model.empty? - return device.id.to_human_string if device.respond_to?(:id) - - default_label(device) - end - - # Default label for the device - # - # @see DEVICE_LABELS - # - # @param device [Y2Storage::Device] - # @return [String] - def default_label(device) - type = DEVICE_LABELS.keys.find { |k| device.is?(k) } - - return "" if type.nil? - - _(DEVICE_LABELS[type]) - end - - # Whether the "Part of *fs.type*" label should be displayed - # - # The Ext3/4 filesystem could be detected as a multi-device filesystem - # when its journal is placed in an external device. However, we do not - # want to display "Part of ..." for them because we know that data - # partition is over a single device. - # - # @see #formatted_device_type_label - # @return [Boolean] true if the filesystem is multi-device BUT not an Ext3/4 one - def show_multidevice_type_label?(filesystem) - return false unless filesystem - return false if filesystem.type.is?(:ext3, :ext4) - - filesystem.multidevice? + Y2Storage::DeviceDescription.new(device, system_graph: system_graph).to_s end end end diff --git a/src/lib/y2storage/device_description.rb b/src/lib/y2storage/device_description.rb new file mode 100644 index 000000000..1a0957a5f --- /dev/null +++ b/src/lib/y2storage/device_description.rb @@ -0,0 +1,300 @@ +# Copyright (c) [2024] 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 LLC about this file by physical or electronic mail, you may +# find current contact information at www.suse.com. + +require "yast/i18n" +require "y2storage/storage_manager" +require "y2storage/simple_etc_fstab_entry" + +module Y2Storage + # Helper class to generate a description for a device + class DeviceDescription + extend Yast::I18n + include Yast::I18n + + # Constructor + # + # @param device [Y2Storage::Device, Y2Storage::LvmPv, Y2Storage::SimpleEtcFstabEntry] + # @param system_graph [Y2Storage::Devicegraph] Representation of the system in its initial state + def initialize(device, system_graph: nil) + textdomain "storage" + @device = device + @system_graph = system_graph || StorageManager.instance.probed + end + + # Text representation of the description + # + # @return [String] + def to_s + device_label(device) + end + + private + + # @return [Y2Storage::Device, Y2Storage::LvmPv, Y2Storage::SimpleEtcFstabEntry] + attr_reader :device + + # @return [Y2Storage::Devicegraph] + attr_reader :system_graph + + # Default labels based on the device type + # + # @see #default_label + DEVICE_LABELS = { + bcache: N_("Bcache"), + disk: N_("Disk"), + dasd: N_("Disk"), + multipath: N_("Multipath"), + nfs: N_("NFS"), + bios_raid: N_("BIOS RAID"), + software_raid: N_("RAID"), + lvm_pv: N_("PV"), + lvm_vg: N_("LVM"), + lvm_thin: N_("Thin LV"), + lvm_thin_pool: N_("Thin Pool"), + lvm_raid: N_("RAID LV"), + lvm_cache: N_("Cache LV"), + lvm_cache_pool: N_("Cache Pool"), + lvm_writecache: N_("Writecache LV"), + lvm_snapshot: N_("Snapshot LV"), + lvm_mirror: N_("Mirror LV"), + lvm_lv: N_("LV"), + stray: N_("Xen"), + partition: N_("Partition"), + btrfs_subvolume: N_("Btrfs Subvolume") + } + private_constant :DEVICE_LABELS + + # A text describing the device + # + # @param device [Y2Storage::Device, Y2Storage::LvmPv, Y2Storage::SimpleEtcFstabEntry] + # @return [String] + def device_label(device) + return fstab_device_label(device) if device.is_a?(SimpleEtcFstabEntry) + return device.type.to_human_string if device.is?(:filesystem) + return default_label(device) if device.is?(:lvm_vg, :btrfs_subvolume) + return snapshot_type_label(device) if device.is?(:lvm_snapshot) + + formatted_device_type_label(device) || unformatted_device_type_label(device) + end + + # Label for the device in the given fstab entry + # + # @param fstab_entry [Y2Storage::SimpleEtcFstabEntry] + # @return [String] the #device_label if device is found in the system; empty string otherwise + def fstab_device_label(fstab_entry) + device = fstab_entry.device(system_graph) + return "" unless device + + device_label(device) + end + + # Label for a formatted device (e.g., Ext4 LVM, XFS RAID, Swap Partition, etc) + # + # @return [String, nil] label if the device has a filesystem; nil otherwise + def formatted_device_type_label(device) + fs = filesystem_for(device) + + return nil unless fs + + if device.journal? + journal_type_label(fs) + elsif show_multidevice_type_label?(fs) + multidevice_type_label(fs) + else + # TRANSLATORS: %{fs_type} is the filesystem type. I.e., FAT, Ext4, etc + # %{device_label} is the device label. I.e., Partition, Disk, etc + format( + _("%{fs_type} %{device_label}"), + fs_type: fs_type(device, fs), + device_label: default_label(device) + ) + end + end + + # The filesystem type representation (FAT, Ext4, etc) + # + # @return [String] + def fs_type(device, filesystem) + if device.is?(:partition) && device.efi_system? + device.id.to_human_string + else + filesystem.type.to_human_string + end + end + + # Label for unformatted device (e.g., LVM, RAID, Partition, etc) + # + # @return [String] + def unformatted_device_type_label(device) + if device.lvm_pv + lvm_pv_type_label(device.lvm_pv) + elsif device.md + part_of_label(device.md) + elsif device.bcache + bcache_backing_label(device.bcache) + elsif device.in_bcache_cset + bcache_cset_label + else + default_unformatted_label(device) + end + end + + # Label when the device is a LVM physical volume + # + # @param lvm_pv [Y2Storage::LvmPv] + # @return [String] + def lvm_pv_type_label(lvm_pv) + vg = lvm_pv.lvm_vg + + return _("Unused LVM PV") if vg.nil? + return _("PV of LVM") if vg.basename.empty? + + # TRANSLATORS: %s is the volume group name. E.g., "vg0" + format(_("PV of %s"), vg.basename) + end + + # Label for an LVM snapshot device + # + # @param lvm_snapshot [Y2Storage::LvmLv] + # @return [String] + def snapshot_type_label(lvm_snapshot) + label = + if lvm_snapshot.is?(:lvm_thin_snapshot) + # TRANSLATORS: %{origin} is replaced by an LVM logical volumme name + # (e.g., /dev/vg0/user-data) + _("Thin Snapshot of %{origin}") + else + # TRANSLATORS: %{origin} is replaced by an LVM logical volumme name + # (e.g., /dev/vg0/user-data) + _("Snapshot of %{origin}") + end + + format(label, origin: lvm_snapshot.origin.lv_name) + end + + # Label when the device holds a journal + # + # @param filesystem [Y2Storage::BlkFilesystem] + # @return [String] + def journal_type_label(filesystem) + data_device = filesystem.blk_devices.find { |d| !d.journal? } + + # TRANSLATORS: %{fs_type} is the filesystem type. E.g., Btrfs, Ext4, etc. + # %{data_device_name} is the data device name. E.g., sda1 + format( + _("%{fs_type} Journal (%{data_device_name})"), + fs_type: filesystem.type.to_human_string, + data_device_name: data_device.basename + ) + end + + # Label when the device belongs to a multi-device filesystem + # + # @param filesystem [Y2Storage::BlkFilesystem] + # @return [String] + def multidevice_type_label(filesystem) + # TRANSLATORS: %{fs_name} is the filesystem name. E.g., Btrfs, Ext4, etc. + # %{blk_device_name} is a device base name. E.g., sda1... + format( + _("Part of %{fs_name} %{blk_device_name}"), + fs_name: filesystem.type, + blk_device_name: filesystem.blk_device_basename + ) + end + + # Label when the device is used as backing device of a Bcache + # + # @param [Y2Storage::Device] device + def bcache_backing_label(device) + # TRANSLATORS: %{bcache} is replaced by a device name (e.g., bcache0). + format(_("Backing of %{bcache}"), bcache: device.basename) + end + + # Label when the device is used as caching device in a Bcache + # + # @return [String] + def bcache_cset_label + # TRANSLATORS: an special type of device + _("Bcache caching") + end + + # Label when the device is part of another one, like Bcache or RAID + # + # @param ancestor_device [Y2Storage::BlkDevice] + # @return [String] + def part_of_label(ancestor_device) + format(_("Part of %s"), ancestor_device.basename) + end + + # Default label when device is unformatted + # + # @return [String] + def default_unformatted_label(device) + # The "model" field from hwinfo is a combination of vendor + device with quite some added + # heuristics to make the result nice looking. See comment#66 at bsc#1200975. + model = device.model || "" + + return model unless model.empty? + return device.id.to_human_string if device.respond_to?(:id) + + default_label(device) + end + + # Default label for the device + # + # @see DEVICE_LABELS + # + # @param device [Y2Storage::Device] + # @return [String] + def default_label(device) + type = DEVICE_LABELS.keys.find { |k| device.is?(k) } + + return "" if type.nil? + + _(DEVICE_LABELS[type]) + end + + # Whether the "Part of *fs.type*" label should be displayed + # + # The Ext3/4 filesystem could be detected as a multi-device filesystem + # when its journal is placed in an external device. However, we do not + # want to display "Part of ..." for them because we know that data + # partition is over a single device. + # + # @see #formatted_device_type_label + # @return [Boolean] true if the filesystem is multi-device BUT not an Ext3/4 one + def show_multidevice_type_label?(filesystem) + return false unless filesystem + return false if filesystem.type.is?(:ext3, :ext4) + + filesystem.multidevice? + end + + # Returns the filesystem for the given device, when possible + # + # @return [Y2Storage::Filesystems::Base, nil] + def filesystem_for(device) + if device.is?(:filesystem) + device + elsif device.respond_to?(:filesystem) + device.filesystem + end + end + end +end diff --git a/src/lib/y2storage/filesystem_label.rb b/src/lib/y2storage/filesystem_label.rb new file mode 100644 index 000000000..c9175cb84 --- /dev/null +++ b/src/lib/y2storage/filesystem_label.rb @@ -0,0 +1,101 @@ +# Copyright (c) [2024] 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 LLC about this file by physical or electronic mail, you may +# find current contact information at www.suse.com. + +require "y2storage/storage_manager" +require "y2storage/simple_etc_fstab_entry" + +module Y2Storage + # Helper class to generate the label of the filesystem + class FilesystemLabel + # Constructor + # + # @param device [Y2Storage::Device, Y2Storage::LvmPv, Y2Storage::SimpleEtcFstabEntry] + # @param system_graph [Y2Storage::Devicegraph] Representation of the system in its initial state + def initialize(device, system_graph: nil) + @device = device + @system_graph = system_graph || StorageManager.instance.probed + end + + # Text representation of the filesystem label + # + # @return [String] + def to_s + return fstab_filesystem_label(device) if device.is_a?(SimpleEtcFstabEntry) + + filesystem_label(device) + end + + private + + # @return [Y2Storage::Device, Y2Storage::LvmPv, Y2Storage::SimpleEtcFstabEntry] + attr_reader :device + + # @return [Y2Storage::Devicegraph] + attr_reader :system_graph + + # Returns the label for the given device, when possible + # + # @param device [Y2Storage::Device, nil] + # @return [String] the label if possible; empty string otherwise + def filesystem_label(device) + return "" unless device + return "" if device.is?(:btrfs_subvolume) + + filesystem = filesystem_for(device) + + return "" unless filesystem + return "" if part_of_multidevice?(device, filesystem) + # fs may not support labels, like NFS + return "" unless filesystem.respond_to?(:label) + + filesystem.label + end + + # Returns the label for the given fstab entry, when possible + # + # @see #filesystem_label + # @param fstab_entry [Y2Storage::SimpleEtcFstabEntry] + def fstab_filesystem_label(fstab_entry) + device = fstab_entry.device(system_graph) + + filesystem_label(device) + end + + # Returns the filesystem for the given device, when possible + # + # @return [Y2Storage::Filesystems::Base, nil] + def filesystem_for(device) + if device.is?(:filesystem) + device + elsif device.respond_to?(:filesystem) + device.filesystem + end + end + + # Whether the device belongs to a multi-device filesystem + # + # @param device [Device] + # @return [Boolean] + def part_of_multidevice?(device, filesystem) + return false unless device.is?(:blk_device) + + filesystem.multidevice? + end + end +end diff --git a/test/y2partitioner/widgets/columns/filesystem_label_test.rb b/test/y2partitioner/widgets/columns/filesystem_label_test.rb index 20851f559..935028026 100755 --- a/test/y2partitioner/widgets/columns/filesystem_label_test.rb +++ b/test/y2partitioner/widgets/columns/filesystem_label_test.rb @@ -1,6 +1,6 @@ #!/usr/bin/env rspec -# Copyright (c) [2020] SUSE LLC +# Copyright (c) [2020-2024] SUSE LLC # # All Rights Reserved. # @@ -33,78 +33,15 @@ let(:scenario) { "mixed_disks" } let(:devicegraph) { Y2Partitioner::DeviceGraphs.instance.current } let(:device) { Y2Storage::BlkDevice.find_by_name(devicegraph, device_name) } - let(:device_name) { "/dev/sda1" } + let(:device_name) { "/dev/sdb2" } before do devicegraph_stub(scenario) end - context "when a there is not a filesystem for given device" do - let(:scenario) { "btrfs2-devicegraph.xml" } - let(:device_name) { "/dev/sdb" } - - it "returns an empty string" do - expect(subject.value_for(device)).to eq("") - end - end - - context "when a fstab entry is given" do - let(:btrfs) { Y2Storage::Filesystems::Type::BTRFS } - let(:root_fstab_entry) { fstab_entry("/dev/sdb2", "/", btrfs, ["subvol=@/"], 0, 0) } - let(:unknown_fstab_entry) { fstab_entry("/dev/vdz", "/home", btrfs, [], 0, 0) } - - context "and the device is found in the system" do - let(:device) { root_fstab_entry } - - it "returns the filesystem label" do - expect(subject.value_for(device)).to eq("suse_root") - end - end - - context "but the device is not found in the system" do - let(:device) { unknown_fstab_entry } - - it "returns an empty string" do - expect(subject.value_for(device)).to eq("") - end - end - end - - context "when the device is part of a multi-device filesystem" do - let(:scenario) { "btrfs2-devicegraph.xml" } - let(:device_name) { "/dev/sdb1" } - - it "returns an empty string" do - expect(subject.value_for(device)).to eq("") - end - end - - context "when the device is a Btrfs subvolume" do - let(:scenario) { "mixed_disks_btrfs" } - let(:filesystem) { devicegraph.find_by_name("/dev/sda2").filesystem } - let(:device) { filesystem.btrfs_subvolumes.first } - - it "returns an empty string" do - expect(subject.value_for(device)).to eq("") - end - end - - context "when filesystem responds to #label" do - let(:device_name) { "/dev/sdb2" } - - it "returns the filesystem label" do + describe "#value_for" do + it "includes the filesystem label" do expect(subject.value_for(device)).to eq("suse_root") end end - - context "when filesystem does not respond to #label" do - let(:scenario) { "nfs1.xml" } - let(:device) do - Y2Storage::Filesystems::Nfs.find_by_server_and_path(devicegraph, "srv", "/home/a") - end - - it "returns an empty string" do - expect(subject.value_for(device)).to eq("") - end - end end diff --git a/test/y2partitioner/widgets/columns/type_test.rb b/test/y2partitioner/widgets/columns/type_test.rb index 10fab1fae..ad6478538 100755 --- a/test/y2partitioner/widgets/columns/type_test.rb +++ b/test/y2partitioner/widgets/columns/type_test.rb @@ -1,6 +1,6 @@ #!/usr/bin/env rspec -# Copyright (c) [2020] SUSE LLC +# Copyright (c) [2020-2024] SUSE LLC # # All Rights Reserved. # @@ -29,13 +29,10 @@ include_examples "Y2Partitioner::Widgets::Column" - describe "#values_for" do - let(:scenario) { "lvm-types1.xml" } + describe "#value_for" do + let(:scenario) { "md_raid.yml" } let(:devicegraph) { Y2Partitioner::DeviceGraphs.instance.current } - let(:blk_device) { devicegraph.find_by_name(device_name) } - let(:device_name) { "/dev/sda1" } - let(:device) { blk_device } - let(:blk_filesystem) { blk_device.blk_filesystem } + let(:device) { devicegraph.find_by_name("/dev/sda2") } let(:label) { subject.value_for(device).params.find { |param| !param.is_a?(Yast::Term) } } before do @@ -53,173 +50,8 @@ expect(icon).to_not be_nil end - context "when the device is a filesystem" do - let(:scenario) { "mixed_disks_btrfs" } - let(:device_name) { "/dev/sdd1" } - let(:device) { blk_filesystem } - - it "returns its human readable type" do - expect(subject.value_for(device)).to include("Btrfs") - end - end - - context "when the device is a Btrfs subvolume" do - let(:scenario) { "mixed_disks_btrfs" } - let(:filesystem) { devicegraph.find_by_name("/dev/sda2").filesystem } - let(:device) { filesystem.btrfs_subvolumes.first } - - it "returns 'Btrfs Subvolume'" do - expect(label).to eq("Btrfs Subvolume") - end - end - - context "when the device is an LVM volume group" do - let(:device_name) { "/dev/vg0" } - - it "returns 'LVM'" do - expect(label).to eq("LVM") - end - end - - context "when the device is an LVM non-thin snapshot" do - let(:device_name) { "/dev/vg0/snap_normal1" } - - it "includes the 'Snapshot of'" do - expect(label).to include("Snapshot of") - end - - it "includes the origin volume basename" do - expect(label).to include("normal1") - end - end - - context "when the device is an LVM thin snapshot" do - let(:device_name) { "/dev/vg0/snap_thinvol1" } - - it "includes the 'Thin Snapshot of'" do - expect(label).to include("Thin Snapshot of") - end - - it "includes the origin volume basename" do - expect(label).to include("thinvol1") - end - end - - context "when the device is formatted" do - let(:device_name) { "/dev/vg0/cached1" } - - it "includes the human readable filesystem type" do - expect(label).to include("XFS") - end - - it "includes default device label" do - expect(label).to include("Cache LV") - end - - context "but it is the external journal of an Ext3/4 filesystem" do - let(:scenario) { "bug_1145841.xml" } - let(:device_name) { "/dev/sdd1" } - - it "includes the human readable filesystem type" do - expect(label).to include("Ext4") - end - - it "includes 'Journal'" do - expect(label).to include("Journal") - end - - it "includes the data device base name" do - expect(label).to include("BACKUP_R6") - end - end - - context "but it is part of a multi-device filesystem" do - let(:scenario) { "btrfs2-devicegraph.xml" } - let(:device_name) { "/dev/sdb1" } - - it "includes 'Part of'" do - expect(label).to include("Part of") - end - - it "includes the filesystem name" do - expect(label).to include("btrfs") - end - - it "includes the block device basename" do - expect(label).to include("sdb1") - end - end - end - - context "when the device is not formatted" do - context "and it is an used LVM physical volume" do - let(:device_name) { "/dev/sdb1" } - let(:vg) { device.lvm_pv.lvm_vg } - - context "in a volume group with name" do - it "includes 'PV of'" do - expect(label).to include("PV of") - end - - it "includes the volume group name" do - expect(label).to include("vg0") - end - end - - context "in a volume group with an empty name" do - before do - vg.vg_name = "" - end - - it "returns 'PV of LVM'" do - expect(label).to eq("PV of LVM") - end - end - end - - context "and it is an unused LVM physical volume" do - let(:scenario) { "unused_lvm_pvs.xml" } - let(:device_name) { "/dev/sda2" } - - it "returns 'Unused LVM PV'" do - expect(label).to eq("Unused LVM PV") - end - end - - context "and it is part of an MD RAID" do - let(:scenario) { "md_raid.yml" } - let(:device_name) { "/dev/sda2" } - - it "includes 'Part of'" do - expect(label).to include("Part of") - end - - it "includes the MD RAID name" do - expect(label).to include("md0") - end - end - - context "and it is part of a bcache" do - let(:scenario) { "bcache1.xml" } - let(:device_name) { "/dev/vdc" } - - it "includes 'Backing of'" do - expect(label).to include("Backing of") - end - - it "includes the bcache name" do - expect(label).to include("bcache0") - end - end - - context "and it is used as caching device in a bcache" do - let(:scenario) { "bcache1.xml" } - let(:device_name) { "/dev/vdb" } - - it "returns 'Bcache cache'" do - expect(label).to include("Bcache caching") - end - end + it "includes the description of the device" do + expect(label).to include("Part of md0") end end end diff --git a/test/y2storage/device_description_test.rb b/test/y2storage/device_description_test.rb new file mode 100755 index 000000000..41d01a1ad --- /dev/null +++ b/test/y2storage/device_description_test.rb @@ -0,0 +1,210 @@ +#!/usr/bin/env rspec + +# Copyright (c) [2024] 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 LLC about this file by physical or electronic mail, you may +# find current contact information at www.suse.com. + +require_relative "spec_helper" +require "y2storage/device_description" + +describe Y2Storage::DeviceDescription do + subject { described_class.new(device) } + + describe "#to_s" do + let(:scenario) { "lvm-types1.xml" } + let(:devicegraph) { fake_devicegraph } + let(:blk_device) { fake_devicegraph.find_by_name(device_name) } + let(:device_name) { "/dev/sda1" } + let(:device) { blk_device } + let(:blk_filesystem) { blk_device.blk_filesystem } + let(:description) { subject.to_s } + + before do + fake_scenario(scenario) + end + + context "when the device is a filesystem" do + let(:scenario) { "mixed_disks_btrfs" } + let(:device_name) { "/dev/sdd1" } + let(:device) { blk_filesystem } + + it "returns its human readable type" do + expect(description).to include("Btrfs") + end + end + + context "when the device is a Btrfs subvolume" do + let(:scenario) { "mixed_disks_btrfs" } + let(:filesystem) { devicegraph.find_by_name("/dev/sda2").filesystem } + let(:device) { filesystem.btrfs_subvolumes.first } + + it "returns 'Btrfs Subvolume'" do + expect(description).to eq("Btrfs Subvolume") + end + end + + context "when the device is an LVM volume group" do + let(:device_name) { "/dev/vg0" } + + it "returns 'LVM'" do + expect(description).to eq("LVM") + end + end + + context "when the device is an LVM non-thin snapshot" do + let(:device_name) { "/dev/vg0/snap_normal1" } + + it "includes the 'Snapshot of'" do + expect(description).to include("Snapshot of") + end + + it "includes the origin volume basename" do + expect(description).to include("normal1") + end + end + + context "when the device is an LVM thin snapshot" do + let(:device_name) { "/dev/vg0/snap_thinvol1" } + + it "includes the 'Thin Snapshot of'" do + expect(description).to include("Thin Snapshot of") + end + + it "includes the origin volume basename" do + expect(description).to include("thinvol1") + end + end + + context "when the device is formatted" do + let(:device_name) { "/dev/vg0/cached1" } + + it "includes the human readable filesystem type" do + expect(description).to include("XFS") + end + + it "includes default device description" do + expect(description).to include("Cache LV") + end + + context "but it is the external journal of an Ext3/4 filesystem" do + let(:scenario) { "bug_1145841.xml" } + let(:device_name) { "/dev/sdd1" } + + it "includes the human readable filesystem type" do + expect(description).to include("Ext4") + end + + it "includes 'Journal'" do + expect(description).to include("Journal") + end + + it "includes the data device base name" do + expect(description).to include("BACKUP_R6") + end + end + + context "but it is part of a multi-device filesystem" do + let(:scenario) { "btrfs2-devicegraph.xml" } + let(:device_name) { "/dev/sdb1" } + + it "includes 'Part of'" do + expect(description).to include("Part of") + end + + it "includes the filesystem name" do + expect(description).to include("btrfs") + end + + it "includes the block device basename" do + expect(description).to include("sdb1") + end + end + end + + context "when the device is not formatted" do + context "and it is an used LVM physical volume" do + let(:device_name) { "/dev/sdb1" } + let(:vg) { device.lvm_pv.lvm_vg } + + context "in a volume group with name" do + it "includes 'PV of'" do + expect(description).to include("PV of") + end + + it "includes the volume group name" do + expect(description).to include("vg0") + end + end + + context "in a volume group with an empty name" do + before do + vg.vg_name = "" + end + + it "returns 'PV of LVM'" do + expect(description).to eq("PV of LVM") + end + end + end + + context "and it is an unused LVM physical volume" do + let(:scenario) { "unused_lvm_pvs.xml" } + let(:device_name) { "/dev/sda2" } + + it "returns 'Unused LVM PV'" do + expect(description).to eq("Unused LVM PV") + end + end + + context "and it is part of an MD RAID" do + let(:scenario) { "md_raid" } + let(:device_name) { "/dev/sda2" } + + it "includes 'Part of'" do + expect(description).to include("Part of") + end + + it "includes the MD RAID name" do + expect(description).to include("md0") + end + end + + context "and it is part of a bcache" do + let(:scenario) { "bcache1.xml" } + let(:device_name) { "/dev/vdc" } + + it "includes 'Backing of'" do + expect(description).to include("Backing of") + end + + it "includes the bcache name" do + expect(description).to include("bcache0") + end + end + + context "and it is used as caching device in a bcache" do + let(:scenario) { "bcache1.xml" } + let(:device_name) { "/dev/vdb" } + + it "returns 'Bcache caching'" do + expect(description).to include("Bcache caching") + end + end + end + end +end diff --git a/test/y2storage/filesystem_label_test.rb b/test/y2storage/filesystem_label_test.rb new file mode 100755 index 000000000..e836f9093 --- /dev/null +++ b/test/y2storage/filesystem_label_test.rb @@ -0,0 +1,108 @@ +#!/usr/bin/env rspec + +# Copyright (c) [2024] 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 LLC about this file by physical or electronic mail, you may +# find current contact information at www.suse.com. + +require_relative "spec_helper" +require "y2storage/filesystem_label" + +describe Y2Storage::FilesystemLabel do + subject { described_class.new(device) } + + describe "#to_s" do + let(:scenario) { "mixed_disks" } + let(:devicegraph) { fake_devicegraph } + let(:device) { fake_devicegraph.find_by_name(device_name) } + let(:device_name) { "/dev/sda1" } + + before do + fake_scenario(scenario) + end + + context "when a there is not a filesystem for given device" do + let(:scenario) { "btrfs2-devicegraph.xml" } + let(:device_name) { "/dev/sdb" } + + it "returns an empty string" do + expect(subject.to_s).to eq("") + end + end + + context "when a fstab entry is given" do + let(:btrfs) { Y2Storage::Filesystems::Type::BTRFS } + let(:root_fstab_entry) { fstab_entry("/dev/sdb2", "/", btrfs, ["subvol=@/"], 0, 0) } + let(:unknown_fstab_entry) { fstab_entry("/dev/vdz", "/home", btrfs, [], 0, 0) } + + context "and the device is found in the system" do + let(:device) { root_fstab_entry } + + it "returns the filesystem label" do + expect(subject.to_s).to eq("suse_root") + end + end + + context "but the device is not found in the system" do + let(:device) { unknown_fstab_entry } + + it "returns an empty string" do + expect(subject.to_s).to eq("") + end + end + end + + context "when the device is part of a multi-device filesystem" do + let(:scenario) { "btrfs2-devicegraph.xml" } + let(:device_name) { "/dev/sdb1" } + + it "returns an empty string" do + expect(subject.to_s).to eq("") + end + end + + context "when the device is a Btrfs subvolume" do + let(:scenario) { "mixed_disks_btrfs" } + let(:filesystem) { fake_devicegraph.find_by_name("/dev/sda2").filesystem } + let(:device) { filesystem.btrfs_subvolumes.first } + + it "returns an empty string" do + expect(subject.to_s).to eq("") + end + end + + context "when filesystem responds to #label" do + let(:device_name) { "/dev/sdb2" } + + it "returns the filesystem label" do + expect(subject.to_s).to eq("suse_root") + end + end + + context "when filesystem does not respond to #label" do + let(:scenario) { "nfs1.xml" } + let(:device) do + Y2Storage::Filesystems::Nfs.find_by_server_and_path(devicegraph, "srv", "/home/a") + end + + it "returns an empty string" do + expect(subject.to_s).to eq("") + end + end + + end +end