diff --git a/package/yast2-storage-ng.changes b/package/yast2-storage-ng.changes index d039edc63..c63c1a9db 100644 --- a/package/yast2-storage-ng.changes +++ b/package/yast2-storage-ng.changes @@ -1,3 +1,10 @@ +------------------------------------------------------------------- +Wed Apr 17 15:56:25 UTC 2024 - Ladislav Slezák + +- Optionally add the encryption status in the device description + (gh#openSUSE/agama#1155) +- 5.0.12 + ------------------------------------------------------------------- Wed Apr 3 09:52:32 UTC 2024 - Ancor Gonzalez Sosa diff --git a/package/yast2-storage-ng.spec b/package/yast2-storage-ng.spec index 91cfb9479..14bcb8502 100644 --- a/package/yast2-storage-ng.spec +++ b/package/yast2-storage-ng.spec @@ -16,7 +16,7 @@ # Name: yast2-storage-ng -Version: 5.0.11 +Version: 5.0.12 Release: 0 Summary: YaST2 - Storage Configuration License: GPL-2.0-only OR GPL-3.0-only diff --git a/src/lib/y2storage/device_description.rb b/src/lib/y2storage/device_description.rb index 1a0957a5f..4af9e012f 100644 --- a/src/lib/y2storage/device_description.rb +++ b/src/lib/y2storage/device_description.rb @@ -31,10 +31,12 @@ class DeviceDescription # # @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) + # @param include_encryption [Boolean] Whether to include the encryption status in the label or not + def initialize(device, system_graph: nil, include_encryption: false) textdomain "storage" @device = device @system_graph = system_graph || StorageManager.instance.probed + @include_encryption = include_encryption end # Text representation of the description @@ -52,6 +54,9 @@ def to_s # @return [Y2Storage::Devicegraph] attr_reader :system_graph + # @return [Boolean] + attr_reader :include_encryption + # Default labels based on the device type # # @see #default_label @@ -86,13 +91,27 @@ def to_s # @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 filesystem_label(device) if device.is?(:filesystem) + return default_label(device, false) 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 + # Filesystem name + # + # @param filesystem [Y2Storage::Filesystems::Base] + # @return [String] + def filesystem_label(filesystem) + label = filesystem.type.to_human_string + if filesystem.encrypted? && include_encryption + # TRANSLATORS: %s is a type of filesystem + format(_("Encrypted %s")) + else + label + end + end + # Label for the device in the given fstab entry # # @param fstab_entry [Y2Storage::SimpleEtcFstabEntry] @@ -113,16 +132,26 @@ def formatted_device_type_label(device) return nil unless fs if device.journal? - journal_type_label(fs) + journal_type_label(fs, device.encrypted?) elsif show_multidevice_type_label?(fs) - multidevice_type_label(fs) + multidevice_type_label(fs, device.encrypted?) + elsif device.encrypted? && include_encryption + # TRANSLATORS: Encrypted device + # %{fs_type} is the filesystem type. I.e., FAT, Ext4, etc + # %{device_label} is the device label. I.e., Partition, Disk, etc + format( + _("Encrypted %{fs_type} %{device_label}"), + fs_type: fs_type(device, fs), + # false to avoid adding "Encrypted" twice + device_label: default_label(device, false) + ) 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) + device_label: default_label(device, false) ) end end @@ -143,27 +172,42 @@ def fs_type(device, filesystem) # @return [String] def unformatted_device_type_label(device) if device.lvm_pv - lvm_pv_type_label(device.lvm_pv) + lvm_pv_type_label(device.lvm_pv, device.encrypted?) elsif device.md - part_of_label(device.md) + part_of_label(device.md, device.encrypted?) elsif device.bcache - bcache_backing_label(device.bcache) + bcache_backing_label(device.bcache, device.encrypted?) elsif device.in_bcache_cset bcache_cset_label else - default_unformatted_label(device) + default_unformatted_label(device, device.encrypted?) end end # Label when the device is a LVM physical volume # # @param lvm_pv [Y2Storage::LvmPv] + # @param encrypted [Boolean] # @return [String] - def lvm_pv_type_label(lvm_pv) + def lvm_pv_type_label(lvm_pv, encrypted) vg = lvm_pv.lvm_vg - return _("Unused LVM PV") if vg.nil? - return _("PV of LVM") if vg.basename.empty? + if vg.nil? + return _("Unused encrypted LVM PV") if encrypted && include_encryption + + return _("Unused LVM PV") + end + + if vg.basename.empty? + return _("Encrypted PV of LVM") if encrypted && include_encryption + + return _("PV of LVM") + end + + if encrypted && include_encryption + # TRANSLATORS: %s is the volume group name. E.g., "vg0" + format(_("Encrypted PV of %s"), vg.basename) + end # TRANSLATORS: %s is the volume group name. E.g., "vg0" format(_("PV of %s"), vg.basename) @@ -176,11 +220,21 @@ def lvm_pv_type_label(lvm_pv) 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}") + if lvm_snapshot.encrypted? && include_encryption + # TRANSLATORS: %{origin} is replaced by an LVM logical volume name + # (e.g., /dev/vg0/user-data) + _("Encrypted Thin Snapshot of %{origin}") + else + # TRANSLATORS: %{origin} is replaced by an LVM logical volume name + # (e.g., /dev/vg0/user-data) + _("Thin Snapshot of %{origin}") + end + elsif lvm_snapshot.encrypted? && include_encryption + _("Encrypted Snapshot of %{origin}") + # TRANSLATORS: %{origin} is replaced by an LVM logical volume name + # (e.g., /dev/vg0/user-data) else - # TRANSLATORS: %{origin} is replaced by an LVM logical volumme name + # TRANSLATORS: %{origin} is replaced by an LVM logical volume name # (e.g., /dev/vg0/user-data) _("Snapshot of %{origin}") end @@ -191,39 +245,68 @@ def snapshot_type_label(lvm_snapshot) # Label when the device holds a journal # # @param filesystem [Y2Storage::BlkFilesystem] + # @param encrypted [Boolean] # @return [String] - def journal_type_label(filesystem) + def journal_type_label(filesystem, encrypted) 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 - ) + if encrypted && include_encryption + # TRANSLATORS: Encrypted journal device + # %{fs_type} is the filesystem type. E.g., Btrfs, Ext4, etc. + # %{data_device_name} is the data device name. E.g., sda1 + format( + _("Encrypted %{fs_type} Journal (%{data_device_name})"), + fs_type: filesystem.type.to_human_string, + data_device_name: data_device.basename + ) + else + # 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 end # Label when the device belongs to a multi-device filesystem # # @param filesystem [Y2Storage::BlkFilesystem] + # @param encrypted [Boolean] # @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 - ) + def multidevice_type_label(filesystem, encrypted) + if encrypted && include_encryption + # 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 encrypted %{fs_name} %{blk_device_name}"), + fs_name: filesystem.type, + blk_device_name: filesystem.blk_device_basename + ) + else + # 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 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) + # @param encrypted [Boolean] + def bcache_backing_label(device, encrypted) + if encrypted && include_encryption + # TRANSLATORS: %{bcache} is replaced by a device name (e.g., bcache0). + format(_("Encrypted backing of %{bcache}"), bcache: device.basename) + else + # TRANSLATORS: %{bcache} is replaced by a device name (e.g., bcache0). + format(_("Backing of %{bcache}"), bcache: device.basename) + end end # Label when the device is used as caching device in a Bcache @@ -237,15 +320,21 @@ def bcache_cset_label # Label when the device is part of another one, like Bcache or RAID # # @param ancestor_device [Y2Storage::BlkDevice] + # @param encrypted [Boolean] # @return [String] - def part_of_label(ancestor_device) - format(_("Part of %s"), ancestor_device.basename) + def part_of_label(ancestor_device, encrypted) + if encrypted && include_encryption + format(_("Encrypted part of %s"), ancestor_device.basename) + else + format(_("Part of %s"), ancestor_device.basename) + end end # Default label when device is unformatted # + # @param encrypted [Boolean] # @return [String] - def default_unformatted_label(device) + def default_unformatted_label(device, encrypted) # 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 || "" @@ -253,7 +342,7 @@ def default_unformatted_label(device) return model unless model.empty? return device.id.to_human_string if device.respond_to?(:id) - default_label(device) + default_label(device, encrypted) end # Default label for the device @@ -261,13 +350,21 @@ def default_unformatted_label(device) # @see DEVICE_LABELS # # @param device [Y2Storage::Device] + # @param encrypted [Boolean] # @return [String] - def default_label(device) + def default_label(device, encrypted) type = DEVICE_LABELS.keys.find { |k| device.is?(k) } return "" if type.nil? - _(DEVICE_LABELS[type]) + label = _(DEVICE_LABELS[type]) + + if encrypted && include_encryption + # TRANSLATORS: %s is a type of the device, e.g. disk, partition, RAID, LVM,... + label = format(_("Encrypted %s"), label) + end + + label end # Whether the "Part of *fs.type*" label should be displayed diff --git a/test/y2storage/device_description_test.rb b/test/y2storage/device_description_test.rb index 41d01a1ad..1e706d8f6 100755 --- a/test/y2storage/device_description_test.rb +++ b/test/y2storage/device_description_test.rb @@ -22,8 +22,23 @@ require_relative "spec_helper" require "y2storage/device_description" +RSpec.shared_examples "Encrypted device" do + context "when the device is encrypted and the encryption status is required" do + it "displays the encryption status" do + # ignore case + expect(description_with_encryption.downcase).to include("encrypted") + end + end +end + describe Y2Storage::DeviceDescription do subject { described_class.new(device) } + let(:subject_with_encryption) do + dev = fake_devicegraph.find_by_name(device_name) + # enable encryption + dev.encrypt + described_class.new(dev, include_encryption: true) + end describe "#to_s" do let(:scenario) { "lvm-types1.xml" } @@ -33,6 +48,7 @@ let(:device) { blk_device } let(:blk_filesystem) { blk_device.blk_filesystem } let(:description) { subject.to_s } + let(:description_with_encryption) { subject_with_encryption.to_s } before do fake_scenario(scenario) @@ -43,6 +59,8 @@ let(:device_name) { "/dev/sdd1" } let(:device) { blk_filesystem } + include_examples "Encrypted device" + it "returns its human readable type" do expect(description).to include("Btrfs") end @@ -53,6 +71,8 @@ let(:filesystem) { devicegraph.find_by_name("/dev/sda2").filesystem } let(:device) { filesystem.btrfs_subvolumes.first } + include_examples "Encrypted device" + it "returns 'Btrfs Subvolume'" do expect(description).to eq("Btrfs Subvolume") end @@ -69,6 +89,8 @@ context "when the device is an LVM non-thin snapshot" do let(:device_name) { "/dev/vg0/snap_normal1" } + include_examples "Encrypted device" + it "includes the 'Snapshot of'" do expect(description).to include("Snapshot of") end @@ -81,6 +103,8 @@ context "when the device is an LVM thin snapshot" do let(:device_name) { "/dev/vg0/snap_thinvol1" } + include_examples "Encrypted device" + it "includes the 'Thin Snapshot of'" do expect(description).to include("Thin Snapshot of") end @@ -93,6 +117,8 @@ context "when the device is formatted" do let(:device_name) { "/dev/vg0/cached1" } + include_examples "Encrypted device" + it "includes the human readable filesystem type" do expect(description).to include("XFS") end @@ -105,6 +131,8 @@ let(:scenario) { "bug_1145841.xml" } let(:device_name) { "/dev/sdd1" } + include_examples "Encrypted device" + it "includes the human readable filesystem type" do expect(description).to include("Ext4") end @@ -122,6 +150,8 @@ let(:scenario) { "btrfs2-devicegraph.xml" } let(:device_name) { "/dev/sdb1" } + include_examples "Encrypted device" + it "includes 'Part of'" do expect(description).to include("Part of") end @@ -166,6 +196,8 @@ let(:scenario) { "unused_lvm_pvs.xml" } let(:device_name) { "/dev/sda2" } + include_examples "Encrypted device" + it "returns 'Unused LVM PV'" do expect(description).to eq("Unused LVM PV") end @@ -175,6 +207,8 @@ let(:scenario) { "md_raid" } let(:device_name) { "/dev/sda2" } + include_examples "Encrypted device" + it "includes 'Part of'" do expect(description).to include("Part of") end @@ -188,6 +222,8 @@ let(:scenario) { "bcache1.xml" } let(:device_name) { "/dev/vdc" } + include_examples "Encrypted device" + it "includes 'Backing of'" do expect(description).to include("Backing of") end