From ce32dc603a78d0adda4bfa7fc5a6b1d776746063 Mon Sep 17 00:00:00 2001
From: Arvin Schnell
Date: Mon, 18 Feb 2019 14:55:34 +0100
Subject: [PATCH 01/25] handle device_order for MD RAIDs during installation
---
package/yast2-storage-ng.changes | 7 +++++
package/yast2-storage-ng.spec | 2 +-
src/lib/y2storage/planned/md.rb | 4 +--
.../y2storage/proposal/autoinst_md_planner.rb | 1 +
test/y2storage/autoinst_proposal_md_test.rb | 14 ++++++---
test/y2storage/planned/md_test.rb | 29 +++++++------------
6 files changed, 30 insertions(+), 27 deletions(-)
diff --git a/package/yast2-storage-ng.changes b/package/yast2-storage-ng.changes
index 384e0076ef..67e807e493 100644
--- a/package/yast2-storage-ng.changes
+++ b/package/yast2-storage-ng.changes
@@ -1,3 +1,10 @@
+-------------------------------------------------------------------
+Mon Feb 18 14:54:15 CET 2019 - aschnell@suse.com
+
+- AutoYaST: handle device_order for MD RAIDs during installation
+ (bsc#1083542)
+- 4.1.60
+
-------------------------------------------------------------------
Thu Feb 14 17:03:05 UTC 2019 - Stefan Hundhammer
diff --git a/package/yast2-storage-ng.spec b/package/yast2-storage-ng.spec
index 8c289bc7f0..0c856381a7 100644
--- a/package/yast2-storage-ng.spec
+++ b/package/yast2-storage-ng.spec
@@ -16,7 +16,7 @@
#
Name: yast2-storage-ng
-Version: 4.1.59
+Version: 4.1.60
Release: 0
BuildRoot: %{_tmppath}/%{name}-%{version}-build
diff --git a/src/lib/y2storage/planned/md.rb b/src/lib/y2storage/planned/md.rb
index 4dc5d57a77..a54a990d81 100644
--- a/src/lib/y2storage/planned/md.rb
+++ b/src/lib/y2storage/planned/md.rb
@@ -96,9 +96,7 @@ def add_devices(md_device, devices)
included + missing
end
- sorted.each do |device|
- md_device.add_device(device)
- end
+ md_device.sorted_devices = sorted
end
# Whether the given name matches the name of the planned MD
diff --git a/src/lib/y2storage/proposal/autoinst_md_planner.rb b/src/lib/y2storage/proposal/autoinst_md_planner.rb
index f142ea0ce8..8b5786d4a2 100644
--- a/src/lib/y2storage/proposal/autoinst_md_planner.rb
+++ b/src/lib/y2storage/proposal/autoinst_md_planner.rb
@@ -119,6 +119,7 @@ def add_raid_options(md, raid_options)
md.name = raid_options.raid_name if raid_options.raid_name
md.chunk_size = chunk_size_from_string(raid_options.chunk_size) if raid_options.chunk_size
md.md_parity = MdParity.find(raid_options.parity_algorithm) if raid_options.parity_algorithm
+ md.devices_order = raid_options.device_order if !raid_options.device_order.empty?
end
# Sets 'reusing' attributes for a MD RAID
diff --git a/test/y2storage/autoinst_proposal_md_test.rb b/test/y2storage/autoinst_proposal_md_test.rb
index a22858a4dc..acc2c90c8e 100644
--- a/test/y2storage/autoinst_proposal_md_test.rb
+++ b/test/y2storage/autoinst_proposal_md_test.rb
@@ -50,7 +50,10 @@
{
"create" => create, "filesystem" => :xfs, "format" => create, "mount" => "/home",
"mountby" => :uuid, "partition_nr" => partition_nr,
- "raid_options" => { "raid_type" => "raid1" }
+ "raid_options" => {
+ "raid_type" => "raid1",
+ "device_order" => ["/dev/vdb1", "/dev/vdc1"]
+ }
}
]
},
@@ -140,11 +143,14 @@
raid_sid = fake_devicegraph.raids.first.sid
proposal.propose
- raids = proposal.devices.raids
+ raids = proposal.devices.raids
expect(raids.size).to eq 1
- expect(raids.first.sid).to_not eq raid_sid
- expect(raids.first.devices.map(&:name)).to contain_exactly("/dev/vdb1", "/dev/vdc1")
+
+ raid = raids.first
+ expect(raid.sid).to_not eq raid_sid
+ expect(raid.md_level).to eq Y2Storage::MdLevel::RAID1
+ expect(raid.sorted_devices.map(&:name)).to eq ["/dev/vdb1", "/dev/vdc1"]
end
include_examples "format MD with no issues"
diff --git a/test/y2storage/planned/md_test.rb b/test/y2storage/planned/md_test.rb
index d2aeb7c83f..5b53c50012 100755
--- a/test/y2storage/planned/md_test.rb
+++ b/test/y2storage/planned/md_test.rb
@@ -36,16 +36,14 @@
let(:real_md) { double("Y2Storage::Md") }
it "calls Y2Storage::Md#add_device for all the devices" do
- expect(real_md).to receive(:add_device).exactly(4).times
+ expect(real_md).to receive(:sorted_devices=).once
+
planned_md.add_devices(real_md, devices)
end
context "if #devices_order is not set" do
it "adds the devices in name's alphabetical order" do
- expect(real_md).to receive(:add_device).with(sda1).ordered
- expect(real_md).to receive(:add_device).with(sda2).ordered
- expect(real_md).to receive(:add_device).with(sdb1).ordered
- expect(real_md).to receive(:add_device).with(sdb2).ordered
+ expect(real_md).to receive(:sorted_devices=).with([sda1, sda2, sdb1, sdb2]).once
planned_md.add_devices(real_md, devices)
end
@@ -57,10 +55,7 @@
end
it "adds the devices in the specified order" do
- expect(real_md).to receive(:add_device).with(sdb2).ordered
- expect(real_md).to receive(:add_device).with(sda1).ordered
- expect(real_md).to receive(:add_device).with(sda2).ordered
- expect(real_md).to receive(:add_device).with(sdb1).ordered
+ expect(real_md).to receive(:sorted_devices=).with([sdb2, sda1, sda2, sdb1]).once
planned_md.add_devices(real_md, devices)
end
@@ -71,16 +66,14 @@
end
it "adds the devices in the specified order" do
- expect(real_md).to receive(:add_device).with(sdb2).ordered
- expect(real_md).to receive(:add_device).with(sda1).ordered
- expect(real_md).to receive(:add_device).with(sda2).ordered
- expect(real_md).to receive(:add_device).with(sdb1).ordered
+ expect(real_md).to receive(:sorted_devices=).with([sdb2, sda1, sda2, sdb1]).once
planned_md.add_devices(real_md, devices)
end
it "does not try to add additional devices" do
- expect(real_md).to receive(:add_device).exactly(4).times
+ expect(real_md).to receive(:sorted_devices=).once
+
planned_md.add_devices(real_md, devices)
end
end
@@ -89,15 +82,13 @@
before { planned_md.devices_order = ["/dev/sdb2", "/dev/sda2"] }
it "adds all the devices" do
- expect(real_md).to receive(:add_device).exactly(4).times
+ expect(real_md).to receive(:sorted_devices=).once
+
planned_md.add_devices(real_md, devices)
end
it "adds first the sorted devices and then the rest (alphabetically)" do
- expect(real_md).to receive(:add_device).with(sdb2).ordered
- expect(real_md).to receive(:add_device).with(sda2).ordered
- expect(real_md).to receive(:add_device).with(sda1).ordered
- expect(real_md).to receive(:add_device).with(sdb1).ordered
+ expect(real_md).to receive(:sorted_devices=).with([sdb2, sda2, sda1, sdb1]).once
planned_md.add_devices(real_md, devices)
end
From a0da574cc593a4b369ba92be975e589be0977dcc Mon Sep 17 00:00:00 2001
From: Stefan Hundhammer
Date: Mon, 18 Feb 2019 17:37:22 +0100
Subject: [PATCH 02/25] Help texts for guided setup
---
.../dialogs/guided_setup/select_disks.rb | 20 ++++++++++
.../guided_setup/select_filesystem/base.rb | 12 ++++++
.../dialogs/guided_setup/select_root_disk.rb | 37 ++++++++++++++++++
.../dialogs/guided_setup/select_scheme.rb | 38 +++++++++++++++++++
4 files changed, 107 insertions(+)
diff --git a/src/lib/y2storage/dialogs/guided_setup/select_disks.rb b/src/lib/y2storage/dialogs/guided_setup/select_disks.rb
index 1b6d41e1e2..3f32864c66 100644
--- a/src/lib/y2storage/dialogs/guided_setup/select_disks.rb
+++ b/src/lib/y2storage/dialogs/guided_setup/select_disks.rb
@@ -75,6 +75,26 @@ def update_settings!
settings.candidate_devices = selected_disks.map(&:name)
end
+ def help_text
+ # TRANSLATORS: Help text for guided storage setup
+ _(
+ "" \
+ "Select the disks to install on." \
+ "
" \
+ "In later dialogs, you can select which of those disks " \
+ "will be used for the root filesystem and what to do with " \
+ "any existing Linux, Windows or other partitions (keep, " \
+ "remove, sometimes resize)." \
+ "
" \
+ "How many of the disks you select here will actually be used " \
+ "depends on the exact scenario you choose (LVM, with or " \
+ "without separate home partition etc.)." \
+ "
" \
+ "Disks that are not selected here remain completely untouched." \
+ "
"
+ )
+ end
+
private
def valid?
diff --git a/src/lib/y2storage/dialogs/guided_setup/select_filesystem/base.rb b/src/lib/y2storage/dialogs/guided_setup/select_filesystem/base.rb
index 0127767f2e..47d794a52b 100644
--- a/src/lib/y2storage/dialogs/guided_setup/select_filesystem/base.rb
+++ b/src/lib/y2storage/dialogs/guided_setup/select_filesystem/base.rb
@@ -38,6 +38,18 @@ def initialize(*params)
def dialog_title
_("Filesystem Options")
end
+
+ def help_text
+ settings.lvm ? help_text_for_volumes : help_text_for_partitions
+ end
+
+ def help_text_for_volumes
+ _("Select the filesystem type for each of the volumes.")
+ end
+
+ def help_text_for_partitions
+ _("Select the filesystem type for each of the partitions.")
+ end
end
end
end
diff --git a/src/lib/y2storage/dialogs/guided_setup/select_root_disk.rb b/src/lib/y2storage/dialogs/guided_setup/select_root_disk.rb
index f8e9a4b50f..4f8cc89526 100644
--- a/src/lib/y2storage/dialogs/guided_setup/select_root_disk.rb
+++ b/src/lib/y2storage/dialogs/guided_setup/select_root_disk.rb
@@ -161,6 +161,43 @@ def update_settings!
update_windows_settings if activate_windows_actions?
end
+ def help_text
+ # TRANSLATORS: Help text for root disk selection
+ msg = _(
+ "" \
+ "Select the disk where to create the root filesystem. " \
+ "
" \
+ "This is also the disk where any boot-related partitions " \
+ "will be created as necessary: /boot, ESP (EFI System " \
+ "Partition), BIOS-Grub. " \
+ "That means that this disk should be usable by the machine's " \
+ "BIOS / firmware." \
+ "
" \
+ "In this dialog you can also choose what to do with existing partitions:" \
+ "
" \
+ "
" \
+ "- Do not modify (keep them as they are)
" \
+ "- Remove if needed
" \
+ "- Remove even if not needed (always remove)
" \
+ "
"
+ )
+
+ # TRANSLATORS: Help text for root disk selection, continued
+ msg << _(
+ "" \
+ "- Resize if needed (Windows partitions only)
" \
+ "- Resize or remove if needed (Windows partitions only)
" \
+ "
" \
+ "" \
+ "That last option means to try to resize the Windows partition(s) to " \
+ "make enough disk space available for Linux, but if that is not " \
+ "enough, completely delete the Windows partition." \
+ "
"
+ ) if activate_windows_actions?
+
+ msg
+ end
+
private
def update_windows_settings
diff --git a/src/lib/y2storage/dialogs/guided_setup/select_scheme.rb b/src/lib/y2storage/dialogs/guided_setup/select_scheme.rb
index fa4d5a71a5..8bf00ba8e1 100644
--- a/src/lib/y2storage/dialogs/guided_setup/select_scheme.rb
+++ b/src/lib/y2storage/dialogs/guided_setup/select_scheme.rb
@@ -107,6 +107,44 @@ def update_settings!
settings.encryption_password = password
end
+ # rubocop:disable Metrics/MethodLength
+ def help_text
+ # TRANSLATORS: Help text for the partitioning scheme (LVM / encryption)
+ _(
+ "" \
+ "Select the parititioning scheme:" \
+ "
" \
+ "
" \
+ "- Plain partitions (no LVM), the simple traditional way
" \
+ "- LVM (Logical Volume Management): " \
+ "
" \
+ "This is a more flexible way of managing disk space. " \
+ "
" \
+ "You can spread single filesystems over multiple disks and add " \
+ "(or, to some extent, remove) disks later as necessary. " \
+ "
" \
+ "You define PVs (Physical Volumes) from partitions or whole disks " \
+ "and combine them into VGs (Volume Groups) that serve as storage " \
+ "pools. You can create LVs (logical volumes) to create filesystems " \
+ "(Btrfs, Ext2/3/4, XFS) on." \
+ "
" \
+ "In this Guided Setup, all this is done for you for the " \
+ "standard filesystem layout if you check Enable LVM." \
+ "
" \
+ "
" \
+ "
" \
+ "Enable Disk Encryption (with or without LVM) adds a LUKS " \
+ " disk encryption layer to the partitioning setup. " \
+ "Notice that you will have to enter the correct password each time " \
+ "you boot the system. " \
+ "
" \
+ "If you lose the password, there is no way to recover it, " \
+ "so make sure not to lose it!" \
+ "
"
+ )
+ # rubocop:enable Metrics/MethodLength
+ end
+
private
def valid?
From 77e25cfdd3a1dc4910c8a80039d143ddac83c103 Mon Sep 17 00:00:00 2001
From: Stefan Hundhammer
Date: Tue, 19 Feb 2019 14:40:28 +0100
Subject: [PATCH 03/25] Version bump and change log
---
package/yast2-storage-ng.changes | 6 ++++++
package/yast2-storage-ng.spec | 2 +-
2 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/package/yast2-storage-ng.changes b/package/yast2-storage-ng.changes
index 67e807e493..1e3a083fcc 100644
--- a/package/yast2-storage-ng.changes
+++ b/package/yast2-storage-ng.changes
@@ -1,3 +1,9 @@
+-------------------------------------------------------------------
+Tue Feb 19 13:39:49 UTC 2019 - Stefan Hundhammer
+
+- Added help texts for guided setup (bsc#1121801)
+- 4.1.61
+
-------------------------------------------------------------------
Mon Feb 18 14:54:15 CET 2019 - aschnell@suse.com
diff --git a/package/yast2-storage-ng.spec b/package/yast2-storage-ng.spec
index 0c856381a7..586822cb7b 100644
--- a/package/yast2-storage-ng.spec
+++ b/package/yast2-storage-ng.spec
@@ -16,7 +16,7 @@
#
Name: yast2-storage-ng
-Version: 4.1.60
+Version: 4.1.61
Release: 0
BuildRoot: %{_tmppath}/%{name}-%{version}-build
From a511878598ffc83d4a047be049974b7e34cea76c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jos=C3=A9=20Iv=C3=A1n=20L=C3=B3pez=20Gonz=C3=A1lez?=
Date: Fri, 15 Feb 2019 16:10:59 +0000
Subject: [PATCH 04/25] Adapt Bcache wrapper
---
src/lib/y2storage/bcache.rb | 6 ++++--
test/y2storage/bcache_test.rb | 40 ++++++++++++++++++++++++++++++-----
2 files changed, 39 insertions(+), 7 deletions(-)
diff --git a/src/lib/y2storage/bcache.rb b/src/lib/y2storage/bcache.rb
index 14f3c3c702..784f320ce3 100644
--- a/src/lib/y2storage/bcache.rb
+++ b/src/lib/y2storage/bcache.rb
@@ -53,7 +53,7 @@ class Bcache < Partitionable
# @return [BlkDevice, nil] nil for Flash-only Bcache
storage_forward :backing_device, as: "BlkDevice"
- # @!method attach_bcache_cset(set)
+ # @!method add_bcache_cset(set)
# This method does not make sense for Flash-only Bcache devices.
#
# @raise [storage::Exception] if attaching failed
@@ -61,7 +61,9 @@ class Bcache < Partitionable
# the Bcache device already has a caching set.
#
# @param set [BcacheCset] set to attach
- storage_forward :attach_bcache_cset
+ storage_forward :add_bcache_cset
+
+ storage_forward :remove_bcache_cset
# @!attribute cache_mode
# Mode in which cache operates.
diff --git a/test/y2storage/bcache_test.rb b/test/y2storage/bcache_test.rb
index b01d77b3a2..da72931ea1 100644
--- a/test/y2storage/bcache_test.rb
+++ b/test/y2storage/bcache_test.rb
@@ -119,7 +119,7 @@
end
end
- describe "#attach_bcache_cset" do
+ describe "#add_bcache_cset" do
before do
described_class.create(fake_devicegraph, bcache_name)
end
@@ -128,19 +128,49 @@
let(:cset) { fake_devicegraph.bcache_csets.first }
- it "attach a caching set to bcache device" do
+ it "adds a caching set to bcache device" do
expect(subject.bcache_cset).to be_nil
- subject.attach_bcache_cset(cset)
+ subject.add_bcache_cset(cset)
expect(subject.bcache_cset).to eq(cset)
end
context "when the bcache already has an associated caching set" do
+ let(:bcache_name) { "/dev/bcache0" }
+
+ it "raises an exception" do
+ expect { subject.add_bcache_cset(cset) }.to raise_error(Storage::LogicException)
+ end
+ end
+
+ context "when the bcache is flash-only" do
let(:bcache_name) { "/dev/bcache1" }
it "raises an exception" do
- expect { subject.attach_bcache_cset(cset) }.to raise_error(Storage::LogicException)
+ expect { subject.add_bcache_cset(cset) }.to raise_error(Storage::LogicException)
+ end
+ end
+ end
+
+ describe "#remove_bcache_cset" do
+ let(:bcache_name) { "/dev/bcache0" }
+
+ it "removes the caching set" do
+ expect(subject.bcache_cset).to_not be_nil
+
+ subject.remove_bcache_cset
+
+ expect(subject.bcache_cset).to be_nil
+ end
+
+ context "when the bcache has no caching set" do
+ before do
+ subject.remove_bcache_cset
+ end
+
+ it "raises an exception" do
+ expect { subject.remove_bcache_cset }.to raise_error(Storage::LogicException)
end
end
@@ -148,7 +178,7 @@
let(:bcache_name) { "/dev/bcache1" }
it "raises an exception" do
- expect { subject.attach_bcache_cset(cset) }.to raise_error(Storage::LogicException)
+ expect { subject.remove_bcache_cset }.to raise_error(Storage::LogicException)
end
end
end
From 0d45274ffd4fe6b1e019ba282e35132c6ddaa248 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jos=C3=A9=20Iv=C3=A1n=20L=C3=B3pez=20Gonz=C3=A1lez?=
Date: Fri, 15 Feb 2019 16:11:58 +0000
Subject: [PATCH 05/25] Add devicegraph method for removing caching set
---
src/lib/y2storage/devicegraph.rb | 11 ++++++++++-
test/data/devicegraphs/bcache2.xml | 4 ++--
test/y2storage/devicegraph_test.rb | 19 +++++++++++++++++++
3 files changed, 31 insertions(+), 3 deletions(-)
diff --git a/src/lib/y2storage/devicegraph.rb b/src/lib/y2storage/devicegraph.rb
index cab1ebb9a5..2fb341d6fe 100644
--- a/src/lib/y2storage/devicegraph.rb
+++ b/src/lib/y2storage/devicegraph.rb
@@ -1,6 +1,6 @@
# encoding: utf-8
-# Copyright (c) [2017] SUSE LLC
+# Copyright (c) [2017-2019] SUSE LLC
#
# All Rights Reserved.
#
@@ -381,6 +381,15 @@ def remove_bcache(bcache)
remove_with_dependants(bcache_cset) if bcache_cset && bcache_cset.bcaches.empty?
end
+ def remove_bcache_cset(bcache_cset)
+ if !(bcache_cset && bcache_cset.is?(:bcache_cset))
+ raise(ArgumentError, "Incorrect device #{bcache_cset.inspect}")
+ end
+
+ # Bcaches using this caching set are not removed
+ remove_device(bcache_cset)
+ end
+
# Removes a Md raid and all its descendants
#
# It also removes other devices that may have become useless, like the
diff --git a/test/data/devicegraphs/bcache2.xml b/test/data/devicegraphs/bcache2.xml
index 5a74eb2be9..4af3cd6de2 100644
--- a/test/data/devicegraphs/bcache2.xml
+++ b/test/data/devicegraphs/bcache2.xml
@@ -283,11 +283,11 @@
133128257536
192.168.56.1
- /home/ivan/projects
+ /home/user/projects
69
- /home/ivan/projects
+ /home/user/projects
device
nfs
true
diff --git a/test/y2storage/devicegraph_test.rb b/test/y2storage/devicegraph_test.rb
index 7b1a29b7d0..eac82388f9 100644
--- a/test/y2storage/devicegraph_test.rb
+++ b/test/y2storage/devicegraph_test.rb
@@ -728,6 +728,25 @@ def with_sda2_deleted(initial_graph)
end
end
+ describe "#remove_bcache_cset" do
+ subject(:devicegraph) { Y2Storage::StorageManager.instance.staging }
+
+ before do
+ fake_scenario("bcache1.xml")
+ end
+
+ it "removes the given caching set device" do
+ bcache_cset = Y2Storage::BcacheCset.all(devicegraph).first
+ expect(bcache_cset).to_not be_nil
+
+ sid = bcache_cset.sid
+
+ devicegraph.remove_bcache_cset(bcache_cset)
+
+ expect(devicegraph.find_device(sid)).to be_nil
+ end
+ end
+
describe "#remove_md" do
subject(:devicegraph) { Y2Storage::StorageManager.instance.staging }
From 30f4075aee65121c9dd2ce3f4c083eb6a05d032d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jos=C3=A9=20Iv=C3=A1n=20L=C3=B3pez=20Gonz=C3=A1lez?=
Date: Fri, 15 Feb 2019 16:17:11 +0000
Subject: [PATCH 06/25] Add controller for bcache actions
---
.../actions/controllers/bcache.rb | 303 ++++++++
.../actions/controllers/bcache_test.rb | 673 ++++++++++++++++++
2 files changed, 976 insertions(+)
create mode 100644 src/lib/y2partitioner/actions/controllers/bcache.rb
create mode 100644 test/y2partitioner/actions/controllers/bcache_test.rb
diff --git a/src/lib/y2partitioner/actions/controllers/bcache.rb b/src/lib/y2partitioner/actions/controllers/bcache.rb
new file mode 100644
index 0000000000..18d9b753b3
--- /dev/null
+++ b/src/lib/y2partitioner/actions/controllers/bcache.rb
@@ -0,0 +1,303 @@
+# encoding: utf-8
+
+# Copyright (c) [2019] 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"
+require "y2storage/bcache"
+require "y2partitioner/device_graphs"
+require "y2partitioner/ui_state"
+require "y2partitioner/blk_device_restorer"
+
+module Y2Partitioner
+ module Actions
+ module Controllers
+ # This class is used by different Bcache actions (see, {Actions::AddBcache},
+ # {Actions::EditBcache} and {Actions::DeleteBcache}).
+ class Bcache
+ # @return [Y2Storage::Bcache]
+ attr_reader :bcache
+
+ # Constructor
+ #
+ # @param bcache [Y2Storage::Bcache, nil] nil if a new bcache is being created.
+ def initialize(bcache = nil)
+ @bcache = bcache
+
+ UIState.instance.select_row(bcache) if bcache
+ end
+
+ # Suitable devices to be used as backing device
+ #
+ # When the bcache is being edited, only its own backing device is returned.
+ #
+ # @return [Array]
+ def suitable_backing_devices
+ return [bcache.backing_device] if bcache
+
+ usable_blk_devices
+ end
+
+ # Suitable devices to be used for caching
+ #
+ # @return [Array]
+ def suitable_caching_devices
+ bcache_csets + usable_blk_devices
+ end
+
+ # Creates a bcache device
+ #
+ # @param backing_device [Y2Storage::BlkDevice]
+ # @param caching_device [Y2Storage::BlkDevice, Y2Storage::BcacheCset, nil]
+ # @param options [Hash]
+ def create_bcache(backing_device, caching_device, options)
+ raise "A Bcache cannot be created without a Backing device." unless backing_device
+
+ BlkDeviceRestorer.new(backing_device).update_checkpoint
+
+ @bcache = backing_device.create_bcache(Y2Storage::Bcache.find_free_name(current_graph))
+
+ apply_options(options)
+ attach(caching_device) if caching_device
+ end
+
+ # Updates the bcache device
+ #
+ # @param caching_device [Y2Storage::BlkDevice, Y2Storage::BcacheCset, nil]
+ # @param options [Hash]
+ def update_bcache(caching_device, options)
+ apply_options(options)
+
+ return if caching_device == bcache.bcache_cset
+
+ detach if bcache.bcache_cset
+
+ attach(caching_device) if caching_device
+ end
+
+ # Deletes the bcache device
+ def delete_bcache
+ backing_device = bcache.backing_device
+ caching_device = nil
+
+ if bcache.bcache_cset && bcache.bcache_cset.bcaches.size == 1
+ caching_device = bcache.bcache_cset.blk_devices.first
+ end
+
+ current_graph.remove_bcache(bcache)
+
+ # Tries to restore the previous status of the caching and backing devices
+ # (e.g., its filesystem is restored back).
+ BlkDeviceRestorer.new(caching_device).restore_from_checkpoint if caching_device
+ BlkDeviceRestorer.new(backing_device).restore_from_checkpoint
+ end
+
+ # Whether the bcache already exists on disk
+ #
+ # @return [Boolean]
+ def committed_bcache?
+ !committed_bcache.nil?
+ end
+
+ # Whether the bcache on disk already had a caching set
+ #
+ # @return [Boolean]
+ def committed_bcache_cset?
+ !committed_bcache_cset.nil?
+ end
+
+ # Whether the bcache on disk already had a caching set, and this caching set was not
+ # used by another bcache.
+ #
+ # @return [Boolean]
+ def single_committed_bcache_cset?
+ return false unless committed_bcache_cset?
+
+ committed_bcache_cset.bcaches.size == 1
+ end
+
+ private
+
+ # Block devices that can be used as backing or caching device
+ #
+ # @return [Array]
+ def usable_blk_devices
+ current_graph.blk_devices.select { |d| usable_blk_device?(d) }
+ end
+
+ # Whether the device can be used as backing or caching device
+ #
+ # @param device [Y2Storage::BlkDevice]
+ # @return [Boolean]
+ def usable_blk_device?(device)
+ !device_used?(device) &&
+ !device_formatted_and_mounted?(device) &&
+ !device_has_partitions?(device) &&
+ !device_extended_partition?(device) &&
+ !device_belong_to_bcache?(device)
+ end
+
+ # Whether the device is already in use (e.g., as LVM PV or raid disk)
+ #
+ # @param device [Y2Storage::BlkDevice]
+ # @return [Boolean]
+ def device_used?(device)
+ device.component_of.any?
+ end
+
+ # Whether the device is formatted and mounted
+ #
+ # @param device [Y2Storage::BlkDevice]
+ # @return [Boolean]
+ def device_formatted_and_mounted?(device)
+ device.filesystem && device.filesystem.mount_point
+ end
+
+ # Whether the device has partitions
+ #
+ # @param device [Y2Storage::BlkDevice]
+ # @return [Boolean]
+ def device_has_partitions?(device)
+ device.respond_to?(:partitions) && device.partitions.any?
+ end
+
+ # Whether the device is an extended partition
+ #
+ # @param device [Y2Storage::BlkDevice]
+ # @return [Boolean]
+ def device_extended_partition?(device)
+ device.is?(:partition) && device.type.is?(:extended)
+ end
+
+ # Whether the device is part of a bcache device
+ #
+ # @param device [Y2Storage::BlkDevice]
+ # @return [Boolean]
+ def device_belong_to_bcache?(device)
+ # do not allow nested bcaches, see doc/bcache.md
+ ([device] + device.ancestors).any? { |a| a.is?(:bcache, :bcache_cset) }
+ end
+
+ # Currently existing caching sets
+ #
+ # @return [Array]
+ def bcache_csets
+ current_graph.bcache_csets
+ end
+
+ # Applies options to the bcache device
+ #
+ # Right now, only the cache mode can be permanently modified.
+ #
+ # @param options [Hash]
+ def apply_options(options)
+ options.each_pair do |key, value|
+ bcache.public_send(:"#{key}=", value)
+ end
+ end
+
+ # Attaches the selected caching to the bcache
+ #
+ # @param caching_device [Y2Storage::BcacheCset, Y2Storage::BlkDevice]
+ def attach(caching_device)
+ bcache_cset = create_bcache_cset(caching_device)
+
+ bcache.add_bcache_cset(bcache_cset)
+ end
+
+ # Detaches the caching set from the bcache device
+ def detach
+ bcache_cset = bcache.bcache_cset
+
+ bcache.remove_bcache_cset
+
+ remove_bcache_cset(bcache_cset) if remove_bcache_cset?(bcache_cset)
+ end
+
+ # Creates a new caching set if the given caching device is not a caching set yet
+ #
+ # @param caching_device [Y2Storage::BlkDevice, Y2Storage::BcacheCset]
+ def create_bcache_cset(caching_device)
+ return caching_device if caching_device.is?(:bcache_cset)
+
+ # The descendants of the caching device should be restored in case that
+ # this caching set is finally removed and not used at all.
+ BlkDeviceRestorer.new(caching_device).update_checkpoint
+
+ caching_device.remove_descendants
+ caching_device.create_bcache_cset
+ end
+
+ # Whether the caching set can be removed
+ #
+ # @param bcache_cset [Y2Storage::BcacheCset]
+ def remove_bcache_cset?(bcache_cset)
+ bcache_cset.bcaches.none?
+ end
+
+ # Removes the caching set
+ #
+ # Previous state of the caching device is retored.
+ #
+ # @param bcache_cset [Y2Storage::BcacheCset]
+ def remove_bcache_cset(bcache_cset)
+ caching_device = bcache_cset.blk_devices.first
+
+ current_graph.remove_bcache_cset(bcache_cset)
+
+ BlkDeviceRestorer.new(caching_device).restore_from_checkpoint
+ end
+
+ # Bcache existing on disk
+ #
+ # @return [Y2Storage::Bcache, nil] nil if the bcache is being created or
+ # does not exist on the disk yet.
+ def committed_bcache
+ return nil unless bcache
+
+ system_graph.find_device(bcache.sid)
+ end
+
+ # Caching set of the bcache existing on disk
+ #
+ # @return [Y2Storage::BcacheCset, nil] nil if the bcache does not exist
+ # on disk or it has no caching set.
+ def committed_bcache_cset
+ return nil unless committed_bcache
+
+ committed_bcache.bcache_cset
+ end
+
+ # Current devicegraph in which the action operates on
+ #
+ # @return [Y2Storage::Devicegraph]
+ def current_graph
+ DeviceGraphs.instance.current
+ end
+
+ # Devicegraph representing the system status
+ #
+ # @return [Y2Storage::Devicegraph]
+ def system_graph
+ DeviceGraphs.instance.system
+ end
+ end
+ end
+ end
+end
diff --git a/test/y2partitioner/actions/controllers/bcache_test.rb b/test/y2partitioner/actions/controllers/bcache_test.rb
new file mode 100644
index 0000000000..0d10e94e0f
--- /dev/null
+++ b/test/y2partitioner/actions/controllers/bcache_test.rb
@@ -0,0 +1,673 @@
+#!/usr/bin/env rspec
+# encoding: utf-8
+
+# Copyright (c) [2019] 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 "../../test_helper"
+
+require "y2partitioner/device_graphs"
+require "y2partitioner/actions/controllers/bcache"
+
+describe Y2Partitioner::Actions::Controllers::Bcache do
+ before do
+ devicegraph_stub(scenario)
+ end
+
+ subject(:controller) { described_class.new(device) }
+
+ let(:device) { nil }
+
+ let(:current_graph) { Y2Partitioner::DeviceGraphs.instance.current }
+
+ def dev(name)
+ result = Y2Storage::BlkDevice.find_by_name(current_graph, name)
+ result ||= Y2Storage::LvmVg.all(current_graph).find { |i| i.name == name }
+ result
+ end
+
+ shared_examples "usable devices" do
+ def name_of_devices
+ devices = controller.send(testing_method)
+ devices = devices.select { |d| d.respond_to?(:name) }
+
+ devices.map(&:name)
+ end
+
+ let(:scenario) { "complex-lvm-encrypt.yml" }
+
+ it "returns an array of block devices" do
+ expect(controller.send(testing_method)).to be_an(Array)
+ expect(controller.send(testing_method)).to all be_a(Y2Storage::BlkDevice)
+ end
+
+ it "includes partitions with an unmounted filesystem" do
+ expect(name_of_devices).to include("/dev/sda2", "/dev/sde3")
+ end
+
+ it "excludes partitions with a mount point" do
+ expect(name_of_devices).to include("/dev/sda2", "/dev/sde3")
+
+ sda2 = dev("/dev/sda2")
+ sda2.filesystem.mount_path = "/var"
+ sde3 = dev("/dev/sde3")
+ sde3.filesystem.mount_path = "swap"
+
+ expect(name_of_devices).to_not include("/dev/sda2", "/dev/sde3")
+ end
+
+ it "excludes partitions that are part of an LVM" do
+ expect(name_of_devices).to_not include("/dev/sde1", "/dev/sde2")
+ sda3 = dev("/dev/sda3")
+ expect(controller.send(testing_method)).to include sda3
+
+ vg0 = dev("/dev/vg0")
+ vg0.add_lvm_pv(sda3)
+ expect(controller.send(testing_method)).to_not include sda3
+ end
+
+ it "excludes partitions that are part of a MD Raid" do
+ sda3 = dev("/dev/sda3")
+ expect(controller.send(testing_method)).to include sda3
+
+ new_md = Y2Storage::Md.create(current_graph, "/dev/md0")
+ new_md.add_device(sda3)
+ expect(controller.send(testing_method)).to_not include sda3
+ end
+
+ it "includes disks with no partition tables" do
+ expect(name_of_devices).to include "/dev/sdb"
+ end
+
+ it "includes disks with empty partition tables" do
+ sdb = dev("/dev/sdb")
+ sdb.create_partition_table(Y2Storage::PartitionTables::Type::GPT)
+
+ expect(name_of_devices).to include "/dev/sdb"
+ end
+
+ it "excludes disks with partitions" do
+ expect(name_of_devices).to_not include "/dev/sdf"
+ end
+
+ it "excludes disks with a mount point" do
+ expect(name_of_devices).to include "/dev/sdb"
+
+ sdb = dev("/dev/sdb")
+ sdb.create_filesystem(Y2Storage::Filesystems::Type::EXT3)
+ sdb.filesystem.mount_path = "/var"
+
+ expect(name_of_devices).to_not include "/dev/sdb"
+ end
+
+ it "excludes disks that are part of an LVM" do
+ expect(name_of_devices).to_not include "/dev/sdg"
+ end
+
+ it "excludes disks that are part of a MD Raid" do
+ sdb = dev("/dev/sdb")
+ expect(controller.send(testing_method)).to include sdb
+
+ new_md = Y2Storage::Md.create(current_graph, "/dev/md0")
+ new_md.add_device(sdb)
+ expect(controller.send(testing_method)).to_not include sdb
+ end
+
+ context "when there are extended partitions" do
+ let(:scenario) { "lvm-two-vgs.yml" }
+
+ it "excludes extended partitions" do
+ expect(name_of_devices).to_not include("/dev/sda3")
+ end
+ end
+
+ context "when there are DM RAIDs" do
+ let(:scenario) { "empty-dm_raids.xml" }
+
+ it "excludes disks that are part of a DM RAID" do
+ expect(name_of_devices).to_not include("/dev/sdb", "/dev/sdc")
+ end
+ end
+
+ context "when there are bcaches" do
+ let(:scenario) { "bcache2.xml" }
+
+ it "excludes Bcaches" do
+ expect(name_of_devices).to_not include("/dev/bcache0", "/dev/bcache1", "/dev/bcache2")
+ end
+
+ it "excludes partitions from a Bcache" do
+ expect(name_of_devices).to_not include("/dev/bcache1p1", "/dev/bcache1p2")
+ end
+
+ it "excludes devices used as backing device" do
+ expect(name_of_devices).to_not include("/dev/sdb2")
+ end
+
+ it "excludes devices used as caching device" do
+ expect(name_of_devices).to_not include("/dev/sdb1")
+ end
+ end
+ end
+
+ describe "#suitable_backing_devices" do
+ context "when the bcache device is being created" do
+ let(:device) { nil }
+
+ let(:testing_method) { :suitable_backing_devices }
+
+ include_examples "usable devices"
+
+ context "when there are caching sets" do
+ let(:scenario) { "bcache2.xml" }
+
+ it "excludes all caching set devices" do
+ bcache_csets = Y2Storage::BcacheCset.all(current_graph)
+
+ expect(controller.suitable_backing_devices).to_not include(bcache_csets)
+ end
+ end
+ end
+
+ context "when the bcache device is being edited" do
+ let(:scenario) { "bcache2.xml" }
+
+ let(:device) { current_graph.find_by_name("/dev/bcache0") }
+
+ it "returns an array of block devices" do
+ expect(controller.suitable_backing_devices).to be_an(Array)
+ expect(controller.suitable_backing_devices).to all be_a(Y2Storage::BlkDevice)
+ end
+
+ it "only includes its backing device" do
+ expect(controller.suitable_backing_devices.map(&:name)).to contain_exactly("/dev/sdb2")
+ end
+ end
+ end
+
+ describe "#suitable_caching_devices" do
+ let(:testing_method) { :suitable_caching_devices }
+
+ include_examples "usable devices"
+
+ context "when there are caching sets" do
+ let(:scenario) { "bcache1.xml" }
+
+ before do
+ vda1 = current_graph.find_by_name("/dev/vda1")
+ vda1.create_bcache_cset
+ end
+
+ it "includes all caching set devices" do
+ bcache_csets = Y2Storage::BcacheCset.all(current_graph)
+
+ expect(bcache_csets.size).to eq(2)
+
+ expect(controller.suitable_caching_devices).to include(*bcache_csets)
+ end
+ end
+ end
+
+ describe "#create_bcache" do
+ let(:scenario) { "bcache2.xml" }
+
+ let(:backing_device) { current_graph.find_by_name("/dev/sda1") }
+
+ let(:caching_device) { nil }
+
+ let(:options) { { cache_mode: Y2Storage::CacheMode::WRITEBACK } }
+
+ it "creates a new bcache over the given backing device" do
+ expect(current_graph.find_by_name("/dev/bcache3")).to be_nil
+
+ subject.create_bcache(backing_device, caching_device, options)
+
+ bcache = current_graph.find_by_name("/dev/bcache3")
+
+ expect(bcache).to_not be_nil
+ expect(bcache.backing_device).to eq(backing_device)
+ end
+
+ it "creates a new bcache with the given cache mode" do
+ expect(current_graph.find_by_name("/dev/bcache3")).to be_nil
+
+ subject.create_bcache(backing_device, caching_device, options)
+
+ bcache = current_graph.find_by_name("/dev/bcache3")
+
+ expect(bcache).to_not be_nil
+ expect(bcache.cache_mode).to eq(options[:cache_mode])
+ end
+
+ context "when non caching device is given" do
+ let(:caching_device) { nil }
+
+ it "creates a new bcache without an associated caching set" do
+ expect(current_graph.find_by_name("/dev/bcache3")).to be_nil
+
+ subject.create_bcache(backing_device, caching_device, options)
+
+ bcache = current_graph.find_by_name("/dev/bcache3")
+
+ expect(bcache).to_not be_nil
+ expect(bcache.bcache_cset).to be_nil
+ end
+ end
+
+ context "when a blk device is given for caching" do
+ let(:caching_device) { current_graph.find_by_name("/dev/sda2") }
+
+ it "creates a new bcache with the given device for caching" do
+ expect(current_graph.find_by_name("/dev/bcache3")).to be_nil
+
+ subject.create_bcache(backing_device, caching_device, options)
+
+ bcache = current_graph.find_by_name("/dev/bcache3")
+
+ expect(bcache).to_not be_nil
+ expect(bcache.bcache_cset.blk_devices.first).to eq(caching_device)
+ end
+ end
+
+ context "when a existing caching set is given for caching" do
+ let(:caching_device) { current_graph.bcache_csets.first }
+
+ it "creates a new bcache with the given caching set for caching" do
+ expect(current_graph.find_by_name("/dev/bcache3")).to be_nil
+
+ subject.create_bcache(backing_device, caching_device, options)
+
+ bcache = current_graph.find_by_name("/dev/bcache3")
+
+ expect(bcache).to_not be_nil
+ expect(bcache.bcache_cset).to eq(caching_device)
+ end
+ end
+ end
+
+ shared_examples "update previous caching" do
+ def call_testing_method
+ subject.send(*testing_method)
+ end
+
+ context "and the previous caching set was being used only by this bcache" do
+ let(:previous_caching_device) { current_graph.find_by_name("/dev/sda1") }
+
+ it "removes the previous caching set" do
+ expect(previous_caching_device.in_bcache_cset).to_not be_nil
+
+ call_testing_method
+
+ expect(previous_caching_device.in_bcache_cset).to be_nil
+ end
+
+ it "restores the previous status of the caching device" do
+ expect(previous_caching_device.filesystem).to be_nil
+
+ call_testing_method
+
+ expect(previous_caching_device.filesystem).to_not be_nil
+ end
+ end
+
+ context "and the previous caching set was being used by several bcache devices" do
+ let(:previous_caching_device) { Y2Storage::BcacheCset.all(current_graph).first }
+
+ it "does not remove the previous caching set" do
+ call_testing_method
+
+ expect(previous_caching_device).to_not be_nil
+ end
+ end
+ end
+
+ describe "#update_bcache" do
+ let(:scenario) { "bcache2.xml" }
+
+ before do
+ sda2 = current_graph.find_by_name("/dev/sda2")
+ described_class.new.create_bcache(sda2, previous_caching_device, {})
+ end
+
+ let(:device) { current_graph.find_by_name("/dev/bcache3") }
+
+ let(:previous_caching_device) { nil }
+
+ let(:caching_device) { nil }
+
+ let(:options) { { cache_mode: Y2Storage::CacheMode::WRITEBACK } }
+
+ shared_examples "detach actions" do
+ it "detaches its previous caching set" do
+ previous_sid = device.bcache_cset.sid
+
+ subject.update_bcache(caching_device, options)
+
+ detached = device.bcache_cset.nil? || device.bcache_cset.sid != previous_sid
+
+ expect(detached).to eq(true)
+ end
+
+ let(:testing_method) { [:update_bcache, caching_device, options] }
+
+ include_examples "update previous caching"
+ end
+
+ it "sets the given cache mode" do
+ expect(device.cache_mode).to_not eq(options[:cache_mode])
+
+ subject.update_bcache(caching_device, options)
+
+ expect(device.cache_mode).to eq(options[:cache_mode])
+ end
+
+ context "when a caching device is given" do
+ let(:caching_device) { Y2Storage::BcacheCset.all(current_graph).first }
+
+ context "and the bcache has no previous caching set" do
+ let(:previous_caching_device) { nil }
+
+ it "attaches the given caching device" do
+ expect(device.bcache_cset).to be_nil
+
+ subject.update_bcache(caching_device, options)
+
+ expect(device.bcache_cset).to eq(caching_device)
+ end
+ end
+
+ context "and the bcache is already associated to the given caching set" do
+ let(:previous_caching_device) { caching_device }
+
+ it "does not change the caching set" do
+ expect(device.bcache_cset).to eq(previous_caching_device)
+
+ subject.update_bcache(caching_device, options)
+
+ expect(device.bcache_cset).to eq(previous_caching_device)
+ end
+ end
+
+ context "and the bcache is already associated to another caching set" do
+ let(:previous_caching_device) { current_graph.find_by_name("/dev/sda1") }
+
+ it "attaches the given caching device" do
+ expect(device.bcache_cset).to eq(previous_caching_device.in_bcache_cset)
+
+ subject.update_bcache(caching_device, options)
+
+ expect(device.bcache_cset).to eq(caching_device)
+ end
+
+ include_examples "detach actions"
+ end
+ end
+
+ context "when a caching device is not given" do
+ let(:caching_device) { nil }
+
+ context "and the bcache has already a previous caching set" do
+ let(:previous_caching_device) { Y2Storage::BcacheCset.all(current_graph).first }
+
+ include_examples "detach actions"
+ end
+ end
+ end
+
+ describe "#delete_bcache" do
+ let(:scenario) { "bcache2.xml" }
+
+ before do
+ described_class.new.create_bcache(backing_device, previous_caching_device, {})
+ end
+
+ let(:device) { current_graph.find_by_name("/dev/bcache3") }
+
+ let(:backing_device) { current_graph.find_by_name("/dev/sda3") }
+
+ let(:previous_caching_device) { nil }
+
+ it "deletes the bcache device" do
+ expect(current_graph.find_by_name("/dev/bcache3")).to_not be_nil
+
+ subject.delete_bcache
+
+ expect(current_graph.find_by_name("/dev/bcache3")).to be_nil
+ end
+
+ it "restores the previous status of the backing device" do
+ backing_device = device.backing_device
+
+ expect(backing_device.filesystem).to be_nil
+
+ subject.delete_bcache
+
+ expect(backing_device.filesystem).to_not be_nil
+ end
+
+ context "when the bcache has an associated caching set" do
+ let(:testing_method) { [:delete_bcache] }
+
+ include_examples "update previous caching"
+ end
+ end
+
+ describe "#committed_bcache?" do
+ let(:scenario) { "bcache2.xml" }
+
+ context "when the bcache exists on disk" do
+ let(:device) { current_graph.find_by_name("/dev/bcache0") }
+
+ it "returns true" do
+ expect(subject.committed_bcache?).to eq(true)
+ end
+ end
+
+ context "when the bcache does not exist on disk" do
+ before do
+ sdb1 = current_graph.find_by_name("/dev/sdb1")
+ sdb1.create_bcache("/dev/bcache99")
+ end
+
+ let(:device) { current_graph.find_by_name("/dev/bcache99") }
+
+ it "returns false" do
+ expect(subject.committed_bcache?).to eq(false)
+ end
+ end
+ end
+
+ describe "#committed_bcache_cset?" do
+ let(:scenario) { "bcache1.xml" }
+
+ let(:system_graph) { Y2Partitioner::DeviceGraphs.instance.system }
+
+ let(:system_device) { system_graph.find_by_name(device.name) }
+
+ context "when the bcache exists on disk" do
+ let(:device) { current_graph.find_by_name("/dev/bcache0") }
+
+ context "and currently it has a caching set" do
+ before do
+ expect(device.bcache_cset).to_not be_nil
+ end
+
+ context "but it does not have a caching set on disk" do
+ before do
+ system_device.remove_bcache_cset
+ end
+
+ it "returns false" do
+ expect(subject.committed_bcache_cset?).to eq(false)
+ end
+ end
+
+ context "and it has a caching set on disk" do
+ before do
+ expect(system_device.bcache_cset).to_not be_nil
+ end
+
+ it "returns true" do
+ expect(subject.committed_bcache_cset?).to eq(true)
+ end
+ end
+ end
+
+ context "and currently it does not have a caching set" do
+ before do
+ device.remove_bcache_cset
+ end
+
+ context "and it does not have a caching set on disk" do
+ before do
+ system_device.remove_bcache_cset
+ end
+
+ it "returns false" do
+ expect(subject.committed_bcache_cset?).to eq(false)
+ end
+ end
+
+ context "but it has a caching set on disk" do
+ before do
+ expect(system_device.bcache_cset).to_not be_nil
+ end
+
+ it "returns true" do
+ expect(subject.committed_bcache_cset?).to eq(true)
+ end
+ end
+ end
+ end
+
+ context "when the bcache does not exist on disk" do
+ before do
+ sdb1 = current_graph.find_by_name("/dev/vda1")
+ sdb1.create_bcache("/dev/bcache99")
+ end
+
+ let(:device) { current_graph.find_by_name("/dev/bcache99") }
+
+ it "returns false" do
+ expect(subject.committed_bcache_cset?).to eq(false)
+ end
+ end
+ end
+
+ describe "#single_committed_bcache_cset" do
+ let(:scenario) { "bcache1.xml" }
+
+ let(:system_graph) { Y2Partitioner::DeviceGraphs.instance.system }
+
+ let(:system_device) { system_graph.find_by_name(device.name) }
+
+ def bcache_cset_only_for(bcache)
+ bcache.bcache_cset.bcaches.each do |dev|
+ dev.remove_bcache_cset if dev != bcache
+ end
+ end
+
+ shared_examples "caching set usage" do
+ context "and its caching set is used only by this bcache on disk" do
+ before do
+ bcache_cset_only_for(system_device)
+ end
+
+ it "returns true" do
+ expect(subject.single_committed_bcache_cset?).to eq(true)
+ end
+ end
+
+ context "and its caching set is used by several bcaches on disk" do
+ before do
+ expect(system_device.bcache_cset.bcaches.size).to be > 1
+ end
+
+ it "returns false" do
+ expect(subject.single_committed_bcache_cset?).to eq(false)
+ end
+ end
+ end
+
+ context "when the bcache exists on disk" do
+ let(:device) { current_graph.find_by_name("/dev/bcache0") }
+
+ context "and currently it has a caching set" do
+ before do
+ expect(device.bcache_cset).to_not be_nil
+ end
+
+ context "but it does not have a caching set on disk" do
+ before do
+ system_device.remove_bcache_cset
+ end
+
+ it "returns false" do
+ expect(subject.single_committed_bcache_cset?).to eq(false)
+ end
+ end
+
+ context "and it has a caching set on disk" do
+ before do
+ expect(system_device.bcache_cset).to_not be_nil
+ end
+
+ include_examples "caching set usage"
+ end
+ end
+
+ context "and currently it does not have a caching set" do
+ before do
+ device.remove_bcache_cset
+ end
+
+ context "and it does not have a caching set on disk" do
+ before do
+ system_device.remove_bcache_cset
+ end
+
+ it "returns false" do
+ expect(subject.single_committed_bcache_cset?).to eq(false)
+ end
+ end
+
+ context "but it has a caching set on disk" do
+ before do
+ expect(system_device.bcache_cset).to_not be_nil
+ end
+
+ include_examples "caching set usage"
+ end
+ end
+ end
+
+ context "when the bcache does not exist on disk" do
+ before do
+ sdb1 = current_graph.find_by_name("/dev/vda1")
+ sdb1.create_bcache("/dev/bcache99")
+ end
+
+ let(:device) { current_graph.find_by_name("/dev/bcache99") }
+
+ it "returns false" do
+ expect(subject.single_committed_bcache_cset?).to eq(false)
+ end
+ end
+ end
+end
From 40e01f82408ad02c2712842ee92be571a96fa2d2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jos=C3=A9=20Iv=C3=A1n=20L=C3=B3pez=20Gonz=C3=A1lez?=
Date: Fri, 15 Feb 2019 16:17:36 +0000
Subject: [PATCH 07/25] Add base class for partitioner actions
---
src/lib/y2partitioner/actions/base.rb | 89 +++++++++++++++++++++++++++
1 file changed, 89 insertions(+)
create mode 100644 src/lib/y2partitioner/actions/base.rb
diff --git a/src/lib/y2partitioner/actions/base.rb b/src/lib/y2partitioner/actions/base.rb
new file mode 100644
index 0000000000..4b2d339c63
--- /dev/null
+++ b/src/lib/y2partitioner/actions/base.rb
@@ -0,0 +1,89 @@
+# encoding: utf-8
+
+# Copyright (c) [2019] 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"
+require "yast/i18n"
+require "yast2/popup"
+
+require "abstract_method"
+
+module Y2Partitioner
+ module Actions
+ # Base class for actions that can be performed by the Expert Partitioner
+ #
+ # This base class is mainly intended to one-step actions. For more complex actions,
+ # see {TransactionWizard}.
+ class Base
+ include Yast::I18n
+
+ def initialize
+ textdomain "storage"
+ end
+
+ # Runs a dialog for adding a bcache and also modifies the device graph if the user
+ # confirms the dialog.
+ #
+ # @return [Symbol] :back, :finish
+ def run
+ return :back unless run?
+
+ perform_action
+
+ :finish
+ end
+
+ private
+
+ # Performs the action, see {#run}
+ #
+ # This method should be defined by derived classes.
+ abstract_method :perform_action
+
+ # Checks whether the action can be performed
+ #
+ # @return [Boolean]
+ def run?
+ validate
+ end
+
+ # Validations before performing the action
+ #
+ # @note The action can be performed if there are no errors (see #errors).
+ # Only the first error is shown.
+ #
+ # @return [Boolean]
+ def validate
+ current_errors = errors
+ return true if current_errors.empty?
+
+ Yast2::Popup.show(current_errors.first, headline: :error)
+ false
+ end
+
+ # List of errors that avoid to perform the action
+ #
+ # @return [Array] translated error messages
+ def errors
+ []
+ end
+ end
+ end
+end
From 514e2430aa475400e9492dca263abe64330d46e7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jos=C3=A9=20Iv=C3=A1n=20L=C3=B3pez=20Gonz=C3=A1lez?=
Date: Fri, 15 Feb 2019 16:19:49 +0000
Subject: [PATCH 08/25] Adapt action for adding a bcache
---
src/lib/y2partitioner/actions/add_bcache.rb | 136 ++++--------------
src/lib/y2partitioner/dialogs/bcache.rb | 22 +--
test/y2partitioner/actions/add_bcache_test.rb | 2 +
test/y2partitioner/dialogs/bcache_test.rb | 19 ++-
4 files changed, 56 insertions(+), 123 deletions(-)
diff --git a/src/lib/y2partitioner/actions/add_bcache.rb b/src/lib/y2partitioner/actions/add_bcache.rb
index e4cbb9d6ec..3a37c750d4 100644
--- a/src/lib/y2partitioner/actions/add_bcache.rb
+++ b/src/lib/y2partitioner/actions/add_bcache.rb
@@ -20,150 +20,64 @@
# find current contact information at www.suse.com.
require "yast"
-require "yast/i18n"
-require "yast2/popup"
-require "y2storage/bcache"
+require "y2partitioner/actions/base"
+require "y2partitioner/actions/controllers/bcache"
require "y2partitioner/dialogs/bcache"
-require "y2partitioner/device_graphs"
module Y2Partitioner
module Actions
- # Action for adding a bcache device
- class AddBcache
- include Yast::I18n
-
+ # Action for adding a bcache device, see {Actions::Base}
+ class AddBcache < Base
def initialize
- textdomain "storage"
- end
-
- # Runs a dialog for adding a bcache and also modifies the device graph if the user
- # confirms the dialog.
- #
- # @return [Symbol] :back, :finish
- def run
- return :back unless validate
+ super
- dialog = Dialogs::Bcache.new(suitable_backing_devices, suitable_caching_devices)
-
- create_device(dialog) if dialog.run == :next
+ textdomain "storage"
- :finish
+ @controller = Controllers::Bcache.new
end
private
- # Validations before performing the action
- #
- # @note The action can be performed is there are no errors (see #errors).
- # Only the first error is shown.
- #
- # @return [Boolean]
- def validate
- current_errors = errors
- return true if current_errors.empty?
-
- Yast2::Popup.show(current_errors.first, headline: :error)
- false
- end
+ # @return [Controllers::Bcache]
+ attr_reader :controller
# List of errors that avoid to create a Bcache
#
+ # @see Actions::Base#errors
+ #
# @return [Array]
def errors
- [no_backing_devices_error].compact
+ (super + [no_backing_devices_error]).compact
end
# Error when there is no suitable backing devices for creating a Bcache
#
- # @return [String, nil] nil if there are devices.
+ # @return [String, nil] nil if there are suitable backing devices.
def no_backing_devices_error
- return nil if suitable_backing_devices.any?
+ return nil if suitable_backing_devices?
# TRANSLATORS: Error message.
_("There are not enough suitable unused devices to create a Bcache.")
end
- # Creates a bcache device according to the user input
- #
- # @param dialog [Dialogs::Bcache]
- def create_device(dialog)
- backing = dialog.backing_device
-
- raise "Invalid result #{dialog.inspect}. Backing not found." unless backing
-
- bcache = backing.create_bcache(Y2Storage::Bcache.find_free_name(device_graph))
-
- apply_options(bcache, dialog.options)
-
- attach(bcache, dialog.caching_device) if dialog.caching_device
- end
-
- # Applies options to the bcache device
- #
- # Right now, the dialog only allows to indicate the cache mode.
- #
- # @param bcache [Y2Storage::Bcache]
- # @param options [Hash]
- def apply_options(bcache, options)
- options.each_pair do |key, value|
- bcache.public_send(:"#{key}=", value)
- end
- end
-
- # Attaches the selected caching to the bcache
- #
- # @param bcache [Y2Storage::Bcache]
- # @param caching [Y2Storage::BcacheCset, Y2Storage::BlkDevice, nil]
- def attach(bcache, caching)
- return if caching.nil?
-
- if !caching.is?(:bcache_cset)
- caching.remove_descendants
- caching = caching.create_bcache_cset
- end
-
- bcache.attach_bcache_cset(caching)
- end
-
- # Device graph in which the action operates on
+ # Opens a dialog to create a Bcache
#
- # @return [Y2Storage::Devicegraph]
- def device_graph
- DeviceGraphs.instance.current
- end
-
- # Suitable devices to be used as backing device
+ # The Bcache is created only if the dialog is accepted.
#
- # @return [Array]
- def suitable_backing_devices
- usable_blk_devices
- end
+ # @see Actions::Base#perform_action
+ def perform_action
+ dialog = Dialogs::Bcache.new(controller)
- # Suitable devices to be used for caching
- #
- # @return [Array]
- def suitable_caching_devices
- existing_caches + usable_blk_devices
- end
+ return unless dialog.run == :next
- # Block devices that can be used as backing or caching device
- #
- # @return [Array]
- def usable_blk_devices
- device_graph.blk_devices.select do |dev|
- dev.component_of.empty? &&
- (dev.filesystem.nil? || dev.filesystem.mount_point.nil?) &&
- (!dev.respond_to?(:partitions) || dev.partitions.empty?) &&
- # do not allow nested bcaches, see doc/bcache.md
- ([dev] + dev.ancestors).none? { |a| a.is?(:bcache, :bcache_cset) }
- end
+ controller.create_bcache(dialog.backing_device, dialog.caching_device, dialog.options)
end
- # Currently existing caching sets
+ # Whether there is suitable backing devices
#
- # @return [Array]
- def existing_caches
- device_graph.bcache_csets
+ # @return [Boolean]
+ def suitable_backing_devices?
+ controller.suitable_backing_devices.any?
end
end
end
diff --git a/src/lib/y2partitioner/dialogs/bcache.rb b/src/lib/y2partitioner/dialogs/bcache.rb
index d2cdb9b0c1..f953891d00 100644
--- a/src/lib/y2partitioner/dialogs/bcache.rb
+++ b/src/lib/y2partitioner/dialogs/bcache.rb
@@ -34,16 +34,14 @@ module Dialogs
class Bcache < Base
# Constructor
#
- # @param suitable_backing [Array] devices that can be used for backing.
- # @param suitable_caching [Array]
- # devices that can be used for caching.
- # @param device [Y2Storage::Bcache] existing bcache device or nil if it is a new one.
- def initialize(suitable_backing, suitable_caching, device = nil)
+ # @param controller [Actions::Controllers::Bcache]
+ def initialize(controller)
textdomain "storage"
- @caching = CachingDeviceSelector.new(device, suitable_caching)
- @backing = BackingDeviceSelector.new(device, suitable_backing, @caching)
- @cache_mode = CacheModeSelector.new(device)
+ @caching = CachingDeviceSelector.new(controller.bcache, controller.suitable_caching_devices)
+ @backing = BackingDeviceSelector.new(controller.bcache,
+ controller.suitable_backing_devices, @caching)
+ @cache_mode = CacheModeSelector.new(controller.bcache)
end
# @macro seeDialog
@@ -189,6 +187,12 @@ def initialize(bcache, devices, caching)
@caching = caching
end
+ def init
+ super
+
+ disable if bcache
+ end
+
# @macro seeAbstractWidget
def label
_("Backing Device")
@@ -290,7 +294,7 @@ def item_for_non_device
# When the bcache exists, its caching set should be the default device.
# Otherwise, the first available device is the default one.
def default_device
- return bcache.bcache_cset if bcache && bcache.bcache_cset
+ return bcache.bcache_cset if bcache
super
end
diff --git a/test/y2partitioner/actions/add_bcache_test.rb b/test/y2partitioner/actions/add_bcache_test.rb
index 5c97841063..be709aae8b 100644
--- a/test/y2partitioner/actions/add_bcache_test.rb
+++ b/test/y2partitioner/actions/add_bcache_test.rb
@@ -165,6 +165,8 @@
end
context "when the dialog is discarded" do
+ let(:dialog_result) { :back }
+
it "does not create a new bcache" do
subject.run
diff --git a/test/y2partitioner/dialogs/bcache_test.rb b/test/y2partitioner/dialogs/bcache_test.rb
index 08dc348149..583fdd28d0 100644
--- a/test/y2partitioner/dialogs/bcache_test.rb
+++ b/test/y2partitioner/dialogs/bcache_test.rb
@@ -1,7 +1,7 @@
#!/usr/bin/env rspec
# encoding: utf-8
-# Copyright (c) [2018] SUSE LLC
+# Copyright (c) [2018-2019] SUSE LLC
#
# All Rights Reserved.
#
@@ -26,15 +26,28 @@
require "cwm/rspec"
require "y2storage"
require "y2partitioner/dialogs/bcache"
+require "y2partitioner/actions/controllers/bcache"
describe Y2Partitioner::Dialogs::Bcache do
- before { devicegraph_stub("bcache1.xml") }
+ before do
+ devicegraph_stub("bcache1.xml")
+
+ allow(Y2Partitioner::Actions::Controllers::Bcache).to receive(:new).and_return(controller)
+
+ allow(controller).to receive(:bcache).and_return(bcache)
+ allow(controller).to receive(:suitable_caching_devices).and_return(suitable_caching)
+ allow(controller).to receive(:suitable_backing_devices).and_return(suitable_backing)
+ end
let(:architecture) { :x86_64 } # bcache is only supported on x86_64
+
+ let(:controller) { instance_double(Y2Partitioner::Actions::Controllers::Bcache) }
+
+ let(:bcache) { nil }
let(:suitable_backing) { fake_devicegraph.blk_devices }
let(:suitable_caching) { fake_devicegraph.blk_devices + fake_devicegraph.bcache_csets }
- subject { described_class.new(suitable_backing, suitable_caching) }
+ subject { described_class.new(controller) }
include_examples "CWM::Dialog"
From 2a3dca2b117d3e1cc93a5fd4d02707fa30cb86ad Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jos=C3=A9=20Iv=C3=A1n=20L=C3=B3pez=20Gonz=C3=A1lez?=
Date: Fri, 15 Feb 2019 16:21:52 +0000
Subject: [PATCH 09/25] Adapt action for deleting a bcache
---
.../y2partitioner/actions/delete_bcache.rb | 84 +++++---
.../y2partitioner/actions/delete_device.rb | 66 +++----
.../actions/delete_bcache_test.rb | 182 ++++++++++++------
3 files changed, 205 insertions(+), 127 deletions(-)
diff --git a/src/lib/y2partitioner/actions/delete_bcache.rb b/src/lib/y2partitioner/actions/delete_bcache.rb
index a7e46ab4a5..6d3c42a272 100644
--- a/src/lib/y2partitioner/actions/delete_bcache.rb
+++ b/src/lib/y2partitioner/actions/delete_bcache.rb
@@ -1,6 +1,6 @@
# encoding: utf-8
-# Copyright (c) [2018] SUSE LLC
+# Copyright (c) [2018-2019] SUSE LLC
#
# All Rights Reserved.
#
@@ -21,48 +21,66 @@
require "yast"
require "y2partitioner/actions/delete_device"
-require "y2partitioner/device_graphs"
+require "y2partitioner/actions/controllers/bcache"
module Y2Partitioner
module Actions
- # Action for deleting a Bcache
- #
- # @see DeleteDevice
+ # Action for deleting a Bcache, see {Actions::DeleteBcache}
class DeleteBcache < DeleteDevice
- def initialize(*args)
+ # Constructor
+ #
+ # @param bcache [Y2Storage::Bcache]
+ def initialize(bcache)
super
+
textdomain "storage"
+
+ @bcache_controller = Controllers::Bcache.new(bcache)
end
private
- # @see DeleteDevice#errors
+ # @return [Controllers::Bcache]
+ attr_reader :bcache_controller
+
+ # @see Actions::Base#errors
def errors
- errors = super + [shared_cset]
+ (super + [flash_only_error, unsafe_detach_error]).compact
+ end
+
+ # Error when the bcache is Flash-only
+ #
+ # @return [String, nil] nil if the bcache is not Flash-only.
+ def flash_only_error
+ return nil unless flash_only_bcache?
- errors.compact
+ # TRANSLATORS: error message, %{name} is replaced by a bcache name (e.g., /dev/bcache0)
+ format(
+ _("The device %{name} is a Flash-only Bcache. Deleting this kind of devices\n" \
+ "is not supported yet."),
+ name: bcache_controller.bcache.name
+ )
end
- # Error when the bcache shares cset with any other bcache.
+ # Error when the caching set cannot be detached safely
#
# @see doc/bcache.md
- # @return [String, nil] nil if there is no error
- def shared_cset
- return nil unless device.bcache_cset
- system = Y2Partitioner::DeviceGraphs.instance.system
- return nil if single_bcache_cset? || !device.exists_in_devicegraph?(system)
+ #
+ # @return [String, nil] nil if detach is safe
+ def unsafe_detach_error
+ return nil if safe_detach_bcache?
- # TRANSLATORS: Error when trying to modify an existing bcache that shares caches.
+ # TRANSLATORS: Error message when detach is not a safe action
_(
- "The bcache shares its cache set with other devices.\nThis can result in unreachable space " \
- "if done without detaching.\nDetaching can take a very long time in some situations."
+ "The bcache cannot be deleted because it shares its cache set with other devices.\n" \
+ "Detaching is required to avoid possible unreachable space, but detaching action\n" \
+ "could take a very long time in some situations."
)
end
- # Deletes the indicated Bcache (see {DeleteDevice#device})
+ # Deletes the indicated Bcache (see {Actions::DeleteDevice#device})
def delete
- log.info "deleting bcache #{device}"
- device_graph.remove_bcache(device)
+ bcache_controller.delete_bcache
end
# @see DeleteDevice
@@ -75,13 +93,12 @@ def recursive_confirm_text_below
bcache_cset_note + super
end
- # Note explaining that also bcache cset will be deleted
+ # Note explaining that the caching set will be deleted
#
- # @return [String] empty string if the bcache cset is not going
- # to be deleted
+ # @return [String] empty string if the caching set is not going to be deleted.
def bcache_cset_note
# no note if there is no bcache cset associated or if cset is shared by more devices
- return "" unless single_bcache_cset?
+ return "" unless bcache_controller.single_committed_bcache_cset?
_(
"The selected Bcache is the only one using its caching set.\n" \
@@ -89,9 +106,20 @@ def bcache_cset_note
)
end
- # Checks if there is only single bcache cset used by this bcache, so it will be deleted
- def single_bcache_cset?
- device.bcache_cset && device.bcache_cset.bcaches.size == 1
+ # Whether the bcache is Flash-only
+ #
+ # @return [Boolean]
+ def flash_only_bcache?
+ bcache_controller.bcache.flash_only?
+ end
+
+ # Whether the caching set can be safely detached
+ #
+ # @return [Boolean]
+ def safe_detach_bcache?
+ !bcache_controller.committed_bcache? ||
+ !bcache_controller.committed_bcache_cset? ||
+ bcache_controller.single_committed_bcache_cset?
end
end
end
diff --git a/src/lib/y2partitioner/actions/delete_device.rb b/src/lib/y2partitioner/actions/delete_device.rb
index fbc51c70ed..5c906ad950 100644
--- a/src/lib/y2partitioner/actions/delete_device.rb
+++ b/src/lib/y2partitioner/actions/delete_device.rb
@@ -1,6 +1,6 @@
# encoding: utf-8
-# Copyright (c) [2017] SUSE LLC
+# Copyright (c) [2017-2019] SUSE LLC
#
# All Rights Reserved.
#
@@ -20,11 +20,11 @@
# find current contact information at www.suse.com.
require "yast"
-require "yast/i18n"
require "yast2/popup"
require "y2partitioner/device_graphs"
require "y2partitioner/confirm_recursive_delete"
require "y2partitioner/immediate_unmount"
+require "y2partitioner/actions/base"
require "y2partitioner/actions/controllers/blk_device"
require "y2storage/filesystems/btrfs"
require "abstract_method"
@@ -32,76 +32,56 @@
module Y2Partitioner
module Actions
# Base class for the action to delete a device
- class DeleteDevice
+ class DeleteDevice < Base
include Yast::Logger
- include Yast::I18n
include Yast::UIShortcuts
include ConfirmRecursiveDelete
include ImmediateUnmount
# Constructor
+ #
# @param device [Y2Storage::Device]
def initialize(device)
+ super()
+
textdomain "storage"
@device = device
end
- # Checks whether delete action can be performed and if so, a confirmation popup is shown.
- # It only asks for unmounting the device it is currently mounted in the system.
- #
- # @note Delete action and refresh for shadowing of BtrFS subvolumes
- # are only performed when user confirms.
- #
- # @see Y2Storage::Filesystems::Btrfs.refresh_subvolumes_shadowing
- #
- # @return [Symbol, nil]
- def run
- return :back unless validate && try_unmount && confirm
- delete
- Y2Storage::Filesystems::Btrfs.refresh_subvolumes_shadowing(device_graph)
-
- :finish
- end
-
private
# @return [Y2Storage::Device] device to delete
attr_reader :device
- # Current devicegraph
- #
- # @return [Y2Storage::Devicegraph]
- def device_graph
- DeviceGraphs.instance.current
- end
-
# Deletes the indicated device
#
- # @note Derived classes should implement this method.
+ # Derived classes should implement this method.
abstract_method :delete
- # Validations before performing the delete action
+ # Checks whether delete action can be performed and if so, a confirmation popup is shown.
+ # It only asks for unmounting the device it is currently mounted in the system.
#
- # @note The action can be performed is there are no errors (see #errors).
- # Only the first error is shown.
+ # @see Actions::Base#run?
#
# @return [Boolean]
- def validate
- current_errors = errors
- return true if current_errors.empty?
-
- Yast2::Popup.show(current_errors.first, headline: :error)
- false
+ def run?
+ super && try_unmount && confirm
end
- # List of errors that avoid to delete the device
+ # Deletes the device and refreshes the shadowing BtrFS subvolumes
#
- # @note Derived classes should overload this method.
+ # @see Y2Storage::Filesystems::Btrfs.refresh_subvolumes_shadowing
+ def perform_action
+ delete
+ Y2Storage::Filesystems::Btrfs.refresh_subvolumes_shadowing(device_graph)
+ end
+
+ # Current devicegraph
#
- # @return [Array]
- def errors
- []
+ # @return [Y2Storage::Devicegraph]
+ def device_graph
+ DeviceGraphs.instance.current
end
# Confirmation before performing the delete action
diff --git a/test/y2partitioner/actions/delete_bcache_test.rb b/test/y2partitioner/actions/delete_bcache_test.rb
index 57a991b15e..fd6436c098 100644
--- a/test/y2partitioner/actions/delete_bcache_test.rb
+++ b/test/y2partitioner/actions/delete_bcache_test.rb
@@ -1,7 +1,7 @@
#!/usr/bin/env rspec
# encoding: utf-8
-# Copyright (c) [2018] SUSE LLC
+# Copyright (c) [2018-2019] SUSE LLC
#
# All Rights Reserved.
#
@@ -26,6 +26,12 @@
require "y2partitioner/actions/delete_bcache"
describe Y2Partitioner::Actions::DeleteBcache do
+ def bcache_cset_only_for(bcache)
+ bcache.bcache_cset.bcaches.each do |dev|
+ dev.remove_bcache_cset if dev != bcache
+ end
+ end
+
before do
devicegraph_stub(scenario)
end
@@ -34,12 +40,8 @@
let(:architecture) { :x86_64 } # bcache is only supported on x86_64
- let(:scenario) { "bcache1.xml" }
-
let(:device) { Y2Storage::BlkDevice.find_by_name(device_graph, device_name) }
- let(:device_name) { "/dev/bcache1" }
-
let(:device_graph) { Y2Partitioner::DeviceGraphs.instance.current }
describe "#run" do
@@ -49,88 +51,156 @@
let(:accept) { nil }
- context "when deleting probed bcache which share cache with other bcache" do
- let(:device_name) { "/dev/bcache1" }
-
- it "shows error popup" do
- expect(Yast2::Popup).to receive(:show).with(anything, headline: :error)
- subject.run
- end
-
+ shared_examples "not delete bcache" do
it "does not delete the bcache" do
subject.run
+
expect(Y2Storage::BlkDevice.find_by_name(device_graph, device_name)).to_not be_nil
end
it "returns :back" do
- expect(subject.run).to eq :back
+ expect(subject.run).to eq(:back)
end
end
- context "when deleting a bcache without associated devices" do
- let(:device_name) { "/dev/bcache1" }
+ shared_examples "confirm and delete bcache" do
+ context "when the bcache is not being used (e.g., partitioned)" do
+ before do
+ device.remove_descendants
+ end
- it "shows a confirm message" do
- device_graph.remove_bcache(Y2Storage::BlkDevice.find_by_name(device_graph, "/dev/bcache2"))
- device_graph.remove_bcache(Y2Storage::BlkDevice.find_by_name(device_graph, "/dev/bcache0"))
- expect(Yast2::Popup).to receive(:show)
- subject.run
+ it "shows a simple confirm message" do
+ expect(Yast2::Popup).to receive(:show).with(/Really delete/, anything)
+
+ subject.run
+ end
end
- it "adds note that also cset will be deleted if the bcache is only user of it" do
- device_graph.remove_bcache(Y2Storage::BlkDevice.find_by_name(device_graph, "/dev/bcache2"))
- device_graph.remove_bcache(Y2Storage::BlkDevice.find_by_name(device_graph, "/dev/bcache0"))
+ context "when the bcache is being used (e.g., partitioned)" do
+ before do
+ device.remove_descendants
- expect(Yast2::Popup).to receive(:show).with(/only one using its caching set/, anything)
- subject.run
+ device.create_partition_table(Y2Storage::PartitionTables::Type::GPT)
+ slot = device.partition_table.unused_partition_slots.first
+ device.partition_table.create_partition(slot.name,
+ slot.region, Y2Storage::PartitionType::PRIMARY)
+ end
+
+ it "shows a specific confirm message for recursive delete" do
+ expect(subject).to receive(:confirm_recursive_delete).and_call_original
+
+ subject.run
+ end
+ end
+
+ context "when the confirm message is not accepted" do
+ let(:accept) { :no }
+
+ include_examples "not delete bcache"
+ end
+
+ context "when the confirm message is accepted" do
+ let(:accept) { :yes }
+
+ it "deletes the bcache" do
+ subject.run
+
+ expect(device_graph.find_by_name(device_name)).to be_nil
+ end
+
+ it "returns :finish" do
+ expect(subject.run).to eq(:finish)
+ end
end
end
- context "when deleting a bcache with associated devices" do
- let(:device_name) { "/dev/bcache2" }
+ context "when the device is a Flash-only bcache" do
+ let(:scenario) { "bcache2.xml" }
- it "shows a specific confirm message for recursive delete" do
- device_graph.remove_bcache(Y2Storage::BlkDevice.find_by_name(device_graph, "/dev/bcache1"))
- device_graph.remove_bcache(Y2Storage::BlkDevice.find_by_name(device_graph, "/dev/bcache0"))
- expect(subject).to receive(:confirm_recursive_delete)
- .and_call_original
+ let(:device_name) { "/dev/bcache1" }
+
+ it "shows an error message" do
+ expect(Yast2::Popup).to receive(:show).with(/is a Flash-only/, headline: :error)
subject.run
end
+
+ include_examples "not delete bcache"
end
- context "when the confirm message is not accepted" do
- let(:accept) { :no }
+ context "when the bcache already exists on disk" do
+ let(:scenario) { "bcache1.xml" }
- it "does not delete the bcache" do
- device_graph.remove_bcache(Y2Storage::BlkDevice.find_by_name(device_graph, "/dev/bcache2"))
- device_graph.remove_bcache(Y2Storage::BlkDevice.find_by_name(device_graph, "/dev/bcache0"))
- subject.run
- expect(Y2Storage::BlkDevice.find_by_name(device_graph, device_name)).to_not be_nil
+ let(:device_name) { "/dev/bcache1" }
+
+ let(:system_device) { Y2Partitioner::DeviceGraphs.instance.system.find_device(device.sid) }
+
+ context "and it had a caching set on disk" do
+ before do
+ # Only to ensure the pre-condition is fulfilled
+ expect(system_device.bcache_cset).to_not be_nil
+ end
+
+ context "and its caching set was shared with other bcaches" do
+ before do
+ # Only to ensure the pre-condition is fulfilled
+ expect(system_device.bcache_cset.bcaches.size).to be > 1
+ end
+
+ it "shows an error message" do
+ expect(Yast2::Popup).to receive(:show).with(/Detaching is required/, headline: :error)
+
+ subject.run
+ end
+
+ include_examples "not delete bcache"
+ end
+
+ context "and its caching set was not shared" do
+ before do
+ bcache_cset_only_for(system_device)
+ end
+
+ include_examples "confirm and delete bcache"
+ end
end
- it "returns :back" do
- device_graph.remove_bcache(Y2Storage::BlkDevice.find_by_name(device_graph, "/dev/bcache2"))
- device_graph.remove_bcache(Y2Storage::BlkDevice.find_by_name(device_graph, "/dev/bcache0"))
- expect(subject.run).to eq(:back)
+ context "and it had no caching set on disk" do
+ before do
+ system_device.remove_bcache_cset
+ end
+
+ context "and currently it has not caching set either" do
+ before do
+ device.remove_bcache_cset
+ end
+
+ include_examples "confirm and delete bcache"
+ end
+
+ context "and currently it has a caching set" do
+ before do
+ # Only to ensure the pre-condition is fulfilled
+ expect(device.bcache_cset).to_not be_nil
+ end
+
+ include_examples "confirm and delete bcache"
+ end
end
end
- context "when the confirm message is accepted" do
- let(:accept) { :yes }
+ context "when the bcache does not exist on disk" do
+ let(:scenario) { "bcache1.xml" }
- it "deletes the bcache" do
- device_graph.remove_bcache(Y2Storage::BlkDevice.find_by_name(device_graph, "/dev/bcache2"))
- device_graph.remove_bcache(Y2Storage::BlkDevice.find_by_name(device_graph, "/dev/bcache0"))
- subject.run
- expect(Y2Storage::BlkDevice.find_by_name(device_graph, device_name)).to be_nil
- end
+ let(:device_name) { "/dev/bcache99" }
+
+ before do
+ vda1 = device_graph.find_by_name("/dev/vda1")
- it "returns :finish" do
- device_graph.remove_bcache(Y2Storage::BlkDevice.find_by_name(device_graph, "/dev/bcache2"))
- device_graph.remove_bcache(Y2Storage::BlkDevice.find_by_name(device_graph, "/dev/bcache0"))
- expect(subject.run).to eq(:finish)
+ vda1.create_bcache(device_name)
end
+
+ include_examples "confirm and delete bcache"
end
end
end
From 58ccc1f0fc20f042647659655f05e839429acab3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jos=C3=A9=20Iv=C3=A1n=20L=C3=B3pez=20Gonz=C3=A1lez?=
Date: Fri, 15 Feb 2019 16:22:42 +0000
Subject: [PATCH 10/25] Add action for editing a bcache
---
src/lib/y2partitioner/actions/edit_bcache.rb | 112 ++++++++
.../y2partitioner/actions/edit_bcache_test.rb | 253 ++++++++++++++++++
2 files changed, 365 insertions(+)
create mode 100644 src/lib/y2partitioner/actions/edit_bcache.rb
create mode 100644 test/y2partitioner/actions/edit_bcache_test.rb
diff --git a/src/lib/y2partitioner/actions/edit_bcache.rb b/src/lib/y2partitioner/actions/edit_bcache.rb
new file mode 100644
index 0000000000..a9b4c9be9f
--- /dev/null
+++ b/src/lib/y2partitioner/actions/edit_bcache.rb
@@ -0,0 +1,112 @@
+# encoding: utf-8
+
+# Copyright (c) [2019] 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"
+require "y2partitioner/actions/base"
+require "y2partitioner/actions/controllers/bcache"
+require "y2partitioner/dialogs/bcache"
+
+module Y2Partitioner
+ module Actions
+ # Action for editing a bcache device, see {Actions::Base}
+ class EditBcache < Base
+ # Constructor
+ #
+ # @param bcache [Y2Storage::Bcache]
+ def initialize(bcache)
+ super()
+
+ textdomain "storage"
+
+ @controller = Controllers::Bcache.new(bcache)
+ end
+
+ private
+
+ # @return [Controllers::Bcache]
+ attr_reader :controller
+
+ # List of errors that avoid to edit a Bcache
+ #
+ # @see Actions::Base#errors
+ #
+ # @return [Array]
+ def errors
+ (super + [flash_only_error, non_editable_error]).compact
+ end
+
+ # Error when the bcache is Flash-only
+ #
+ # @return [String, nil] nil if the bcache is not Flash-only.
+ def flash_only_error
+ return nil unless flash_only_bcache?
+
+ # TRANSLATORS: error message, %{name} is replaced by a bcache name (e.g., /dev/bcache0)
+ format(
+ _("The device %{name} is a Flash-only Bcache and its caching cannot be modified."),
+ name: controller.bcache.name
+ )
+ end
+
+ # Error when the caching device cannot be modified, see {#editable_bcache_cset?}
+ #
+ # @return [String, nil] nil if the caching device can be modified.
+ def non_editable_error
+ return nil if editable_bcache_cset?
+
+ # TRANSLATORS: error message, %{name} is replaced by a bcache name (e.g., /dev/bcache0)
+ format(
+ _("The Bcache %{name} is already created on disk and its caching\n" \
+ "cannot be modified. To modify the caching device, remove the Bcache\n" \
+ "and create it again."),
+ name: controller.bcache.name
+ )
+ end
+
+ # Opens a dialog to edit a Bcache
+ #
+ # The Bcache is updated only if the dialog is accepted.
+ #
+ # @see Actions::Base#perform_action
+ def perform_action
+ dialog = Dialogs::Bcache.new(controller)
+
+ return unless dialog.run == :next
+
+ controller.update_bcache(dialog.caching_device, dialog.options)
+ end
+
+ # Whether the bcache is Flash-only
+ #
+ # @return [Boolean]
+ def flash_only_bcache?
+ controller.bcache.flash_only?
+ end
+
+ # Whether the caching set can be modified
+ #
+ # @return [Boolean]
+ def editable_bcache_cset?
+ !controller.committed_bcache? || !controller.committed_bcache_cset?
+ end
+ end
+ end
+end
diff --git a/test/y2partitioner/actions/edit_bcache_test.rb b/test/y2partitioner/actions/edit_bcache_test.rb
new file mode 100644
index 0000000000..9ef27e736d
--- /dev/null
+++ b/test/y2partitioner/actions/edit_bcache_test.rb
@@ -0,0 +1,253 @@
+#!/usr/bin/env rspec
+# encoding: utf-8
+
+# Copyright (c) [2019] 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 "../test_helper"
+
+require "cwm/rspec"
+require "y2partitioner/actions/edit_bcache"
+
+describe Y2Partitioner::Actions::EditBcache do
+ subject { described_class.new(device) }
+
+ before do
+ devicegraph_stub(scenario)
+
+ allow_any_instance_of(Y2Partitioner::Dialogs::Bcache).to receive(:run)
+ .and_return(dialog_result)
+
+ allow_any_instance_of(Y2Partitioner::Dialogs::Bcache).to receive(:caching_device)
+ .and_return(selected_caching)
+
+ allow_any_instance_of(Y2Partitioner::Dialogs::Bcache).to receive(:options)
+ .and_return(selected_options)
+ end
+
+ let(:dialog_result) { nil }
+
+ let(:selected_caching) { nil }
+
+ let(:selected_options) { { cache_mode: Y2Storage::CacheMode::WRITEBACK } }
+
+ let(:device) { device_graph.find_by_name(device_name) }
+
+ let(:device_graph) { Y2Partitioner::DeviceGraphs.instance.current }
+
+ describe "#run" do
+ before do
+ allow(Yast2::Popup).to receive(:show)
+ end
+
+ shared_examples "not edit device" do
+ it "does not modify the caching device" do
+ bcache_cset = device.bcache_cset
+
+ subject.run
+
+ expect(device.bcache_cset).to eq(bcache_cset)
+ end
+
+ it "does not modify the cache mode" do
+ cache_mode = device.cache_mode
+
+ subject.run
+
+ expect(device.cache_mode).to eq(cache_mode)
+ end
+ end
+
+ shared_examples "not edit action" do
+ it "does not open a dialog to edit a bcache device" do
+ expect(Y2Partitioner::Dialogs::Bcache).to_not receive(:new)
+
+ subject.run
+ end
+
+ include_examples "not edit device"
+
+ it "returns :back" do
+ expect(subject.run).to eq(:back)
+ end
+ end
+
+ shared_examples "edit action" do
+ it "does not show an error popup" do
+ expect(Yast2::Popup).to_not receive(:show)
+
+ subject.run
+ end
+
+ it "opens a dialog to edit the bcache device" do
+ expect(Y2Partitioner::Dialogs::Bcache).to receive(:new).and_call_original
+
+ subject.run
+ end
+
+ context "when the dialog is accepted" do
+ let(:dialog_result) { :next }
+
+ context "and a caching device was selected in the dialog" do
+ before do
+ # Only to ensure the pre-condition is fulfilled
+ expect(selected_caching).to_not be_nil
+ end
+
+ it "attaches the selected caching device" do
+ subject.run
+
+ expect(device.bcache_cset).to_not be_nil
+ expect(device.bcache_cset.blk_devices.first).to eq(selected_caching)
+ end
+
+ it "sets the selected cache mode" do
+ subject.run
+
+ expect(device.cache_mode).to eq(selected_options[:cache_mode])
+ end
+
+ it "returns :finish" do
+ expect(subject.run).to eq :finish
+ end
+ end
+
+ context "when no caching device was selected in the dialog" do
+ let(:selected_caching) { nil }
+
+ it "does not attach a caching device" do
+ subject.run
+
+ expect(device.bcache_cset).to be_nil
+ end
+
+ it "sets the selected cache mode" do
+ subject.run
+
+ expect(device.cache_mode).to eq(selected_options[:cache_mode])
+ end
+
+ it "returns :finish" do
+ expect(subject.run).to eq :finish
+ end
+ end
+ end
+
+ context "when the dialog is discarded" do
+ let(:dialog_result) { :back }
+
+ include_examples "not edit device"
+
+ it "returns :finish" do
+ expect(subject.run).to eq :finish
+ end
+ end
+ end
+
+ context "when the device is a Flash-only bcache" do
+ let(:scenario) { "bcache2.xml" }
+
+ let(:device_name) { "/dev/bcache1" }
+
+ before do
+ # Only to ensure the pre-condition is fulfilled
+ expect(device.flash_only?).to eq(true)
+ end
+
+ it "shows an error message" do
+ expect(Yast2::Popup).to receive(:show).with(/is a Flash-only/, headline: :error)
+
+ subject.run
+ end
+
+ include_examples "not edit action"
+ end
+
+ context "when the bcache already exists on disk" do
+ let(:system_device) { Y2Partitioner::DeviceGraphs.instance.system.find_device(device.sid) }
+
+ let(:scenario) { "bcache1.xml" }
+
+ let(:device_name) { "/dev/bcache1" }
+
+ # Preparing a value for examples that need it (see shared examples "edit bcache")
+ let(:selected_caching) { device_graph.find_by_name("/dev/vda2") }
+
+ before do
+ # Only to ensure the pre-condition is fulfilled
+ expect(system_device).to_not be_nil
+ end
+
+ context "and it had a caching set on disk" do
+ before do
+ # Only to ensure the pre-condition is fulfilled
+ expect(system_device.bcache_cset).to_not be_nil
+ end
+
+ it "shows an error message" do
+ expect(Yast2::Popup).to receive(:show).with(/already created/, headline: :error)
+
+ subject.run
+ end
+
+ include_examples "not edit action"
+ end
+
+ context "and it did not have a caching set on disk" do
+ before do
+ system_device.remove_bcache_cset
+ end
+
+ context "and it currently has no caching set either" do
+ before do
+ device.remove_bcache_cset
+ end
+
+ include_examples "edit action"
+ end
+
+ context "and it currently has a caching set" do
+ before do
+ # Only to ensure the pre-condition is fulfilled
+ expect(device.bcache_cset).to_not be_nil
+ end
+
+ include_examples "edit action"
+ end
+ end
+ end
+
+ context "when the bcache does not exist on disk" do
+ let(:scenario) { "bcache1.xml" }
+
+ before do
+ vda1 = device_graph.find_by_name("/dev/vda1")
+
+ vda1.create_bcache(device_name)
+ end
+
+ let(:device_name) { "/dev/bcache99" }
+
+ # Preparing a value for examples that need it (see shared examples "edit bcache")
+ let(:selected_caching) { device_graph.find_by_name("/dev/vda2") }
+
+ include_examples "edit action"
+ end
+ end
+end
From 753a3ce5ae151c71adef20ff6cbcd21f5cf5b1a0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jos=C3=A9=20Iv=C3=A1n=20L=C3=B3pez=20Gonz=C3=A1lez?=
Date: Fri, 15 Feb 2019 16:25:26 +0000
Subject: [PATCH 11/25] Add buttons for editing a bcache
---
.../widgets/bcache_edit_button.rb | 53 ++++++++++++++++
.../widgets/bcache_modify_button.rb | 8 ++-
.../widgets/bcache_edit_button_test.rb | 62 +++++++++++++++++++
.../widgets/bcache_modify_button_test.rb | 19 +++++-
4 files changed, 139 insertions(+), 3 deletions(-)
create mode 100644 src/lib/y2partitioner/widgets/bcache_edit_button.rb
create mode 100644 test/y2partitioner/widgets/bcache_edit_button_test.rb
diff --git a/src/lib/y2partitioner/widgets/bcache_edit_button.rb b/src/lib/y2partitioner/widgets/bcache_edit_button.rb
new file mode 100644
index 0000000000..f1b4c6b273
--- /dev/null
+++ b/src/lib/y2partitioner/widgets/bcache_edit_button.rb
@@ -0,0 +1,53 @@
+# encoding: utf-8
+
+# Copyright (c) [2019] 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"
+require "y2partitioner/widgets/device_button"
+require "y2partitioner/actions/edit_bcache"
+
+Yast.import "Popup"
+
+module Y2Partitioner
+ module Widgets
+ # Button for editing a bcache
+ class BcacheEditButton < DeviceButton
+ def initialize(*args)
+ super
+ textdomain "storage"
+ end
+
+ # @macro seeAbstractWidget
+ def label
+ # TRANSLATORS: label for button to edit a bcache
+ _("Change Caching...")
+ end
+
+ private
+
+ # Returns the proper Actions class to edit the bcache
+ #
+ # @see Actions::EditBcache
+ def actions_class
+ Actions::EditBcache
+ end
+ end
+ end
+end
diff --git a/src/lib/y2partitioner/widgets/bcache_modify_button.rb b/src/lib/y2partitioner/widgets/bcache_modify_button.rb
index 77e5aa119a..bd83b85c19 100644
--- a/src/lib/y2partitioner/widgets/bcache_modify_button.rb
+++ b/src/lib/y2partitioner/widgets/bcache_modify_button.rb
@@ -1,6 +1,6 @@
# encoding: utf-8
-# Copyright (c) [2018] SUSE LLC
+# Copyright (c) [2018-2019] SUSE LLC
#
# All Rights Reserved.
#
@@ -22,6 +22,7 @@
require "yast"
require "y2partitioner/widgets/device_menu_button"
require "y2partitioner/actions/edit_blk_device"
+require "y2partitioner/actions/edit_bcache"
require "y2partitioner/actions/create_partition_table"
module Y2Partitioner
@@ -50,6 +51,11 @@ def actions
label: _("Edit Bcache..."),
class: Actions::EditBlkDevice
},
+ {
+ id: :caching,
+ label: _("Change Caching..."),
+ class: Actions::EditBcache
+ },
{
id: :ptable,
label: _("Create New Partition Table..."),
diff --git a/test/y2partitioner/widgets/bcache_edit_button_test.rb b/test/y2partitioner/widgets/bcache_edit_button_test.rb
new file mode 100644
index 0000000000..312f61d1d0
--- /dev/null
+++ b/test/y2partitioner/widgets/bcache_edit_button_test.rb
@@ -0,0 +1,62 @@
+#!/usr/bin/env rspec
+# encoding: utf-8
+
+# Copyright (c) [2019] 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 "../test_helper"
+
+require "cwm/rspec"
+require "y2partitioner/widgets/bcache_edit_button"
+
+describe Y2Partitioner::Widgets::BcacheEditButton do
+ before do
+ devicegraph_stub(scenario)
+
+ allow(Y2Partitioner::Actions::EditBcache).to receive(:new).and_return(action)
+ end
+
+ let(:action) { instance_double(Y2Partitioner::Actions::EditBcache, run: :finish) }
+
+ subject(:button) { described_class.new(device: device) }
+
+ let(:device) { device_graph.find_by_name(device_name) }
+
+ let(:device_graph) { Y2Partitioner::DeviceGraphs.instance.current }
+
+ let(:scenario) { "bcache1.xml" }
+
+ let(:device_name) { "/dev/bcache0" }
+
+ include_examples "CWM::PushButton"
+
+ describe "#handle" do
+ it "returns :redraw if the action was successful" do
+ allow(action).to receive(:run).and_return(:finish)
+
+ expect(button.handle).to eq(:redraw)
+ end
+
+ it "returns nil if the action was not successful" do
+ allow(action).to receive(:run).and_return(:back)
+
+ expect(button.handle).to be_nil
+ end
+ end
+end
diff --git a/test/y2partitioner/widgets/bcache_modify_button_test.rb b/test/y2partitioner/widgets/bcache_modify_button_test.rb
index 94f6d3bfff..f9db6bcd3e 100644
--- a/test/y2partitioner/widgets/bcache_modify_button_test.rb
+++ b/test/y2partitioner/widgets/bcache_modify_button_test.rb
@@ -1,6 +1,6 @@
#!/usr/bin/env rspec
# encoding: utf-8
-# Copyright (c) [2018] SUSE LLC
+# Copyright (c) [2018-2019] SUSE LLC
#
# All Rights Reserved.
#
@@ -63,7 +63,7 @@
end
end
- context "when the option for editing the disk is selected" do
+ context "when the option for editing the bcache is selected" do
let(:selected_option) { :"#{widget_id}_edit" }
before do
@@ -78,6 +78,21 @@
include_examples "handle bcache action result"
end
+ context "when the option for changing the caching is selected" do
+ let(:selected_option) { :"#{widget_id}_caching" }
+
+ before do
+ allow(Y2Partitioner::Actions::EditBcache).to receive(:new).and_return action
+ end
+
+ it "opens the workflow for changing the caching options" do
+ expect(Y2Partitioner::Actions::EditBcache).to receive(:new)
+ button.handle(event)
+ end
+
+ include_examples "handle bcache action result"
+ end
+
context "when the option for creating a partition table is selected" do
let(:selected_option) { :"#{widget_id}_ptable" }
From cf49c68a82f66a36832d7712dffd983a42037634 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jos=C3=A9=20Iv=C3=A1n=20L=C3=B3pez=20Gonz=C3=A1lez?=
Date: Fri, 15 Feb 2019 16:29:37 +0000
Subject: [PATCH 12/25] Show delete button even for Flash-only bcaches
---
.../widgets/device_buttons_set.rb | 10 +--
src/lib/y2partitioner/widgets/pages/bcache.rb | 15 ++---
.../widgets/device_buttons_set_test.rb | 67 ++++---------------
.../widgets/pages/bcache_test.rb | 28 ++++----
4 files changed, 37 insertions(+), 83 deletions(-)
diff --git a/src/lib/y2partitioner/widgets/device_buttons_set.rb b/src/lib/y2partitioner/widgets/device_buttons_set.rb
index 9b4ee373c5..0a1dc85272 100644
--- a/src/lib/y2partitioner/widgets/device_buttons_set.rb
+++ b/src/lib/y2partitioner/widgets/device_buttons_set.rb
@@ -130,15 +130,11 @@ def software_raid_buttons
# Buttons to display if {#device} is a bcache device
def bcache_buttons
- buttons = [
+ [
BcacheModifyButton.new(device),
- PartitionsButton.new(device, pager)
+ PartitionsButton.new(device, pager),
+ DeviceDeleteButton.new(pager: pager, device: device)
]
-
- # TODO: Allow to delete flash-only bcache devices
- buttons << DeviceDeleteButton.new(pager: pager, device: device) unless device.flash_only?
-
- buttons
end
# Buttons to display if {#device} is a disk device
diff --git a/src/lib/y2partitioner/widgets/pages/bcache.rb b/src/lib/y2partitioner/widgets/pages/bcache.rb
index 15ea2f7576..96bf64e738 100644
--- a/src/lib/y2partitioner/widgets/pages/bcache.rb
+++ b/src/lib/y2partitioner/widgets/pages/bcache.rb
@@ -23,6 +23,7 @@
require "y2partitioner/icons"
require "y2partitioner/widgets/bcache_device_description"
require "y2partitioner/widgets/blk_device_edit_button"
+require "y2partitioner/widgets/bcache_edit_button"
require "y2partitioner/widgets/device_delete_button"
require "y2partitioner/widgets/partition_table_add_button"
require "y2partitioner/widgets/partitions_tab"
@@ -102,14 +103,12 @@ def contents
# @return [Array]
def buttons
- buttons = [BlkDeviceEditButton.new(device: @bcache)]
-
- # TODO: Allow to delete flash-only bcache devices
- buttons << DeviceDeleteButton.new(device: @bcache) unless @bcache.flash_only?
-
- buttons << PartitionTableAddButton.new(device: @bcache)
-
- buttons
+ [
+ BlkDeviceEditButton.new(device: @bcache),
+ BcacheEditButton.new(device: @bcache),
+ DeviceDeleteButton.new(device: @bcache),
+ PartitionTableAddButton.new(device: @bcache)
+ ]
end
end
end
diff --git a/test/y2partitioner/widgets/device_buttons_set_test.rb b/test/y2partitioner/widgets/device_buttons_set_test.rb
index 49e639227d..d6b230c880 100644
--- a/test/y2partitioner/widgets/device_buttons_set_test.rb
+++ b/test/y2partitioner/widgets/device_buttons_set_test.rb
@@ -1,7 +1,7 @@
#!/usr/bin/env rspec
# encoding: utf-8
-# Copyright (c) [2018] SUSE LLC
+# Copyright (c) [2018-2019] SUSE LLC
#
# All Rights Reserved.
#
@@ -101,63 +101,20 @@
context "when targeting a Bcache device" do
let(:scenario) { "bcache2.xml" }
+ let(:device) { device_graph.find_by_name("/dev/bcache0") }
- let(:device) { device_graph.find_by_name(device_name) }
-
- context "and the device is not a flash-only bcache" do
- let(:device_name) { "/dev/bcache0" }
-
- it "replaces the content with buttons to modify and to manage partitions" do
- expect(widget).to receive(:replace) do |content|
- widgets = Yast::CWM.widgets_in_contents([content])
- expect(widgets.map(&:class)).to include(
- Y2Partitioner::Widgets::DeviceButtonsSet::ButtonsBox,
- Y2Partitioner::Widgets::BcacheModifyButton,
- Y2Partitioner::Widgets::PartitionsButton
- )
- end
-
- widget.device = device
- end
-
- it "includes a button to delete the device" do
- expect(widget).to receive(:replace) do |content|
- widgets = Yast::CWM.widgets_in_contents([content])
- expect(widgets.map(&:class)).to include(
- Y2Partitioner::Widgets::DeviceDeleteButton
- )
- end
-
- widget.device = device
- end
- end
-
- context "and the device is a flash-only bcache" do
- let(:device_name) { "/dev/bcache1" }
-
- it "replaces the content with buttons to modify and to manage partitions" do
- expect(widget).to receive(:replace) do |content|
- widgets = Yast::CWM.widgets_in_contents([content])
- expect(widgets.map(&:class)).to contain_exactly(
- Y2Partitioner::Widgets::DeviceButtonsSet::ButtonsBox,
- Y2Partitioner::Widgets::BcacheModifyButton,
- Y2Partitioner::Widgets::PartitionsButton
- )
- end
-
- widget.device = device
+ it "replaces the content with buttons to modify, to delete and to manage partitions" do
+ expect(widget).to receive(:replace) do |content|
+ widgets = Yast::CWM.widgets_in_contents([content])
+ expect(widgets.map(&:class)).to contain_exactly(
+ Y2Partitioner::Widgets::DeviceButtonsSet::ButtonsBox,
+ Y2Partitioner::Widgets::BcacheModifyButton,
+ Y2Partitioner::Widgets::DeviceDeleteButton,
+ Y2Partitioner::Widgets::PartitionsButton
+ )
end
- it "does not include a button to delete the device" do
- expect(widget).to receive(:replace) do |content|
- widgets = Yast::CWM.widgets_in_contents([content])
- expect(widgets.map(&:class)).to_not include(
- Y2Partitioner::Widgets::DeviceDeleteButton
- )
- end
-
- widget.device = device
- end
+ widget.device = device
end
end
diff --git a/test/y2partitioner/widgets/pages/bcache_test.rb b/test/y2partitioner/widgets/pages/bcache_test.rb
index 134826cc68..c794095c64 100644
--- a/test/y2partitioner/widgets/pages/bcache_test.rb
+++ b/test/y2partitioner/widgets/pages/bcache_test.rb
@@ -1,7 +1,7 @@
#!/usr/bin/env rspec
# encoding: utf-8
-# Copyright (c) [2017] SUSE LLC
+# Copyright (c) [2017-2019] SUSE LLC
#
# All Rights Reserved.
#
@@ -73,22 +73,24 @@
expect(description).to_not be_nil
end
- context "when the device is not a flash-only bcache" do
- let(:device_name) { "/dev/bcache0" }
+ it "shows a button for editing the device" do
+ button = widgets.detect { |i| i.is_a?(Y2Partitioner::Widgets::BlkDeviceEditButton) }
+ expect(button).to_not be_nil
+ end
- it "shows a button for deleting the device" do
- button = widgets.detect { |i| i.is_a?(Y2Partitioner::Widgets::DeviceDeleteButton) }
- expect(button).to_not be_nil
- end
+ it "shows a button for changing the caching options" do
+ button = widgets.detect { |i| i.is_a?(Y2Partitioner::Widgets::BcacheEditButton) }
+ expect(button).to_not be_nil
end
- context "when the device is a flash-only bcache" do
- let(:device_name) { "/dev/bcache1" }
+ it "shows a button for deleting the device" do
+ button = widgets.detect { |i| i.is_a?(Y2Partitioner::Widgets::DeviceDeleteButton) }
+ expect(button).to_not be_nil
+ end
- it "does not show a button for deleting the device" do
- button = widgets.detect { |i| i.is_a?(Y2Partitioner::Widgets::DeviceDeleteButton) }
- expect(button).to be_nil
- end
+ it "shows a button for configuring the partition table" do
+ button = widgets.detect { |i| i.is_a?(Y2Partitioner::Widgets::PartitionTableAddButton) }
+ expect(button).to_not be_nil
end
end
end
From 87778302f10fd48863230d6c3510017ddc861afc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jos=C3=A9=20Iv=C3=A1n=20L=C3=B3pez=20Gonz=C3=A1lez?=
Date: Fri, 15 Feb 2019 16:30:27 +0000
Subject: [PATCH 13/25] Fix 'go back' for bcache
---
src/lib/y2partitioner/ui_state.rb | 11 ++++++
src/lib/y2partitioner/widgets/pages.rb | 3 +-
.../y2partitioner/widgets/pages/bcaches.rb | 3 +-
test/y2partitioner/ui_state_test.rb | 36 +++++++++++++++++--
4 files changed, 48 insertions(+), 5 deletions(-)
diff --git a/src/lib/y2partitioner/ui_state.rb b/src/lib/y2partitioner/ui_state.rb
index 80f7be520c..e657c1b629 100644
--- a/src/lib/y2partitioner/ui_state.rb
+++ b/src/lib/y2partitioner/ui_state.rb
@@ -55,6 +55,15 @@ def lvm_label
_("Volume Management")
end
+ # Title of the Bcache section
+ #
+ # @note See note on {.md_raids_label} about why this looks misplaced.
+ #
+ # @return [String]
+ def bcache_label
+ _("Bcache")
+ end
+
# @return [Integer, nil] if a row must be selected in a table with devices,
# this returns the sid of the associated device
attr_reader :row_sid
@@ -156,6 +165,8 @@ def device_page_candidates(page)
[device.sid, device.lvm_vg.sid]
elsif device.is?(:lvm_vg)
[device.sid, lvm_label]
+ elsif device.is?(:bcache)
+ [device.sid, bcache_label]
else
[device.sid]
end
diff --git a/src/lib/y2partitioner/widgets/pages.rb b/src/lib/y2partitioner/widgets/pages.rb
index 407050809d..0ae5b52ede 100644
--- a/src/lib/y2partitioner/widgets/pages.rb
+++ b/src/lib/y2partitioner/widgets/pages.rb
@@ -1,6 +1,6 @@
# encoding: utf-8
-# Copyright (c) [2017] SUSE LLC
+# Copyright (c) [2017-2019] SUSE LLC
#
# All Rights Reserved.
#
@@ -44,4 +44,5 @@ module Pages
require "y2partitioner/widgets/pages/device_graph.rb"
require "y2partitioner/widgets/pages/summary.rb"
require "y2partitioner/widgets/pages/settings.rb"
+require "y2partitioner/widgets/pages/bcache.rb"
require "y2partitioner/widgets/pages/bcaches.rb"
diff --git a/src/lib/y2partitioner/widgets/pages/bcaches.rb b/src/lib/y2partitioner/widgets/pages/bcaches.rb
index f124dc158e..5e59182413 100644
--- a/src/lib/y2partitioner/widgets/pages/bcaches.rb
+++ b/src/lib/y2partitioner/widgets/pages/bcaches.rb
@@ -20,6 +20,7 @@
# find current contact information at www.suse.com.
require "y2partitioner/icons"
+require "y2partitioner/ui_state"
require "y2partitioner/widgets/pages/devices_table"
require "y2partitioner/widgets/bcache_add_button"
@@ -43,7 +44,7 @@ def initialize(bcaches, pager)
# @macro seeAbstractWidget
def label
- _("Bcache")
+ UIState.instance.bcache_label
end
private
diff --git a/test/y2partitioner/ui_state_test.rb b/test/y2partitioner/ui_state_test.rb
index f640347488..fe3f34eb02 100644
--- a/test/y2partitioner/ui_state_test.rb
+++ b/test/y2partitioner/ui_state_test.rb
@@ -1,7 +1,7 @@
#!/usr/bin/env rspec
# encoding: utf-8
-# Copyright (c) [2017] SUSE LLC
+# Copyright (c) [2017-2019] SUSE LLC
#
# All Rights Reserved.
#
@@ -27,7 +27,9 @@
describe Y2Partitioner::UIState do
subject(:ui_state) { described_class.instance }
- before { devicegraph_stub("complex-lvm-encrypt.yml") }
+ before { devicegraph_stub(scenario) }
+
+ let(:scenario) { "complex-lvm-encrypt.yml" }
let(:device) { Y2Storage::BlkDevice.find_by_name(fake_devicegraph, device_name) }
@@ -64,9 +66,10 @@
let(:disks_page) { Y2Partitioner::Widgets::Pages::Disks.new(disks, pager) }
let(:md_raids_page) { Y2Partitioner::Widgets::Pages::MdRaids.new(pager) }
let(:lvm_page) { Y2Partitioner::Widgets::Pages::Lvm.new(pager) }
+ let(:bcaches_page) { Y2Partitioner::Widgets::Pages::Bcaches.new([], pager) }
let(:btrfs_page) { Y2Partitioner::Widgets::Pages::Btrfs.new(pager) }
- let(:pages) { [system_page, disks_page, md_raids_page, lvm_page, btrfs_page] }
+ let(:pages) { [system_page, disks_page, md_raids_page, lvm_page, bcaches_page, btrfs_page] }
context "if the user has still not visited any node" do
before { described_class.create_instance }
@@ -218,6 +221,33 @@
end
end
end
+
+ context "when the user has opened a Bcache page" do
+ let(:scenario) { "bcache1.xml" }
+ let(:device) { fake_devicegraph.find_by_name("/dev/bcache0") }
+ let(:another_bcache) { fake_devicegraph.find_by_name("/dev/bcache1") }
+
+ let(:page) { Y2Partitioner::Widgets::Pages::Bcache.new(device, pager) }
+ let(:another_bcache_page) { Y2Partitioner::Widgets::Pages::Bcache.new(another_bcache, pager) }
+
+ before { ui_state.go_to_tree_node(page) }
+
+ context "if the Bcache is still there after redrawing" do
+ before { pages.concat [page, another_bcache_page] }
+
+ it "selects the correct Bcache page" do
+ expect(ui_state.find_tree_node(pages)).to eq page
+ end
+ end
+
+ context "if the Bcache is not longer there after redrawing" do
+ before { pages << another_bcache_page }
+
+ it "selects the general Bcache page" do
+ expect(ui_state.find_tree_node(pages)).to eq bcaches_page
+ end
+ end
+ end
end
describe "#find_tab" do
From 4ffa1ca4fdbe3012bcd9de0911a9d65e087ef464 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jos=C3=A9=20Iv=C3=A1n=20L=C3=B3pez=20Gonz=C3=A1lez?=
Date: Mon, 18 Feb 2019 15:18:45 +0000
Subject: [PATCH 14/25] Remove backing device content when needed
---
.../actions/controllers/bcache.rb | 36 +++++++++++++++++--
.../actions/controllers/bcache_test.rb | 35 ++++++++++++++++++
2 files changed, 68 insertions(+), 3 deletions(-)
diff --git a/src/lib/y2partitioner/actions/controllers/bcache.rb b/src/lib/y2partitioner/actions/controllers/bcache.rb
index 18d9b753b3..b066147832 100644
--- a/src/lib/y2partitioner/actions/controllers/bcache.rb
+++ b/src/lib/y2partitioner/actions/controllers/bcache.rb
@@ -71,6 +71,8 @@ def create_bcache(backing_device, caching_device, options)
BlkDeviceRestorer.new(backing_device).update_checkpoint
+ backing_device.remove_descendants if remove_backing_device_content?(backing_device)
+
@bcache = backing_device.create_bcache(Y2Storage::Bcache.find_free_name(current_graph))
apply_options(options)
@@ -244,7 +246,7 @@ def create_bcache_cset(caching_device)
caching_device.create_bcache_cset
end
- # Whether the caching set can be removed
+ # Whether the caching set should be removed
#
# @param bcache_cset [Y2Storage::BcacheCset]
def remove_bcache_cset?(bcache_cset)
@@ -264,6 +266,18 @@ def remove_bcache_cset(bcache_cset)
BlkDeviceRestorer.new(caching_device).restore_from_checkpoint
end
+ # Whether the content of the backing device should be removed
+ #
+ # The content of the backing device should be removed when the backing device
+ # already contains something on the disk (e.g., a filesystem).
+ #
+ # @return [Boolean]
+ def remove_backing_device_content?(backing_device)
+ return false unless committed_device?(backing_device)
+
+ backing_device.descendants.any? { |d| committed_device?(d) }
+ end
+
# Bcache existing on disk
#
# @return [Y2Storage::Bcache, nil] nil if the bcache is being created or
@@ -271,7 +285,7 @@ def remove_bcache_cset(bcache_cset)
def committed_bcache
return nil unless bcache
- system_graph.find_device(bcache.sid)
+ committed_device(bcache)
end
# Caching set of the bcache existing on disk
@@ -279,11 +293,27 @@ def committed_bcache
# @return [Y2Storage::BcacheCset, nil] nil if the bcache does not exist
# on disk or it has no caching set.
def committed_bcache_cset
- return nil unless committed_bcache
+ return nil unless committed_bcache?
committed_bcache.bcache_cset
end
+ # Whether the device already exists on disk
+ #
+ # @param device [Y2Storage::Device]
+ # @return [Boolean]
+ def committed_device?(device)
+ !committed_device(device).nil?
+ end
+
+ # System version of the given device
+ #
+ # @param device [Y2Storage::Device]
+ # @return [Y2Storage::Device, nil] nil if the device does not exist on disk.
+ def committed_device(device)
+ system_graph.find_device(device.sid)
+ end
+
# Current devicegraph in which the action operates on
#
# @return [Y2Storage::Devicegraph]
diff --git a/test/y2partitioner/actions/controllers/bcache_test.rb b/test/y2partitioner/actions/controllers/bcache_test.rb
index 0d10e94e0f..1b3b23824f 100644
--- a/test/y2partitioner/actions/controllers/bcache_test.rb
+++ b/test/y2partitioner/actions/controllers/bcache_test.rb
@@ -233,6 +233,10 @@ def name_of_devices
let(:options) { { cache_mode: Y2Storage::CacheMode::WRITEBACK } }
+ let(:system_backing_device) { system_graph.find_by_name(backing_device.name) }
+
+ let(:system_graph) { Y2Partitioner::DeviceGraphs.instance.system }
+
it "creates a new bcache over the given backing device" do
expect(current_graph.find_by_name("/dev/bcache3")).to be_nil
@@ -255,6 +259,37 @@ def name_of_devices
expect(bcache.cache_mode).to eq(options[:cache_mode])
end
+ context "when the given backing device has some content on disk" do
+ it "creates a new bcache without the content of the backing device" do
+ expect(system_backing_device.descendants).to_not be_empty
+
+ subject.create_bcache(backing_device, caching_device, options)
+
+ bcache = current_graph.find_by_name("/dev/bcache3")
+
+ expect(bcache.descendants).to be_empty
+ end
+ end
+
+ context "when the given backing device has content only in memory" do
+ before do
+ backing_device.remove_descendants
+ backing_device.create_filesystem(Y2Storage::Filesystems::Type::EXT4)
+ end
+
+ it "creates a new bcache with the content of the backing device" do
+ content_before = backing_device.descendants
+ expect(content_before).to_not be_empty
+
+ subject.create_bcache(backing_device, caching_device, options)
+
+ bcache = current_graph.find_by_name("/dev/bcache3")
+
+ expect(bcache.descendants).to_not be_empty
+ expect(bcache.descendants).to eq(content_before)
+ end
+ end
+
context "when non caching device is given" do
let(:caching_device) { nil }
From b639f547942a88bd2248b57e2eb91c1f54ee8d0f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jos=C3=A9=20Iv=C3=A1n=20L=C3=B3pez=20Gonz=C3=A1lez?=
Date: Mon, 18 Feb 2019 16:23:38 +0000
Subject: [PATCH 15/25] Update libstorage-ng dependency
---
package/yast2-storage-ng.spec | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/package/yast2-storage-ng.spec b/package/yast2-storage-ng.spec
index 586822cb7b..06e3a30794 100644
--- a/package/yast2-storage-ng.spec
+++ b/package/yast2-storage-ng.spec
@@ -26,8 +26,8 @@ Source: %{name}-%{version}.tar.bz2
Requires: yast2 >= 4.1.11
# for AbortException and handle direct abort
Requires: yast2-ruby-bindings >= 4.0.6
-# Probing Flash-only Bcache devices
-Requires: libstorage-ng-ruby >= 4.1.81
+# Bcache#remove_bcache_cset
+Requires: libstorage-ng-ruby >= 4.1.89
# communicate with udisks
Requires: rubygem(ruby-dbus)
# Y2Packager::Repository
@@ -36,8 +36,8 @@ Requires: yast2-packager >= 3.3.7
Requires: findutils
BuildRequires: update-desktop-files
-# Probing Flash-only Bcache devices
-BuildRequires: libstorage-ng-ruby >= 4.1.81
+# Bcache#remove_bcache_cset
+BuildRequires: libstorage-ng-ruby >= 4.1.89
BuildRequires: yast2-ruby-bindings
BuildRequires: yast2-devtools
# yast2-xml dependency is added by yast2 but ignored in the
From 7fb96370dd275aec8dfc31e1d6068c79a9fb5e86 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jos=C3=A9=20Iv=C3=A1n=20L=C3=B3pez=20Gonz=C3=A1lez?=
Date: Mon, 18 Feb 2019 16:26:37 +0000
Subject: [PATCH 16/25] Update version and changelog
---
package/yast2-storage-ng.changes | 6 ++++++
package/yast2-storage-ng.spec | 2 +-
2 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/package/yast2-storage-ng.changes b/package/yast2-storage-ng.changes
index 1e3a083fcc..81d83abe37 100644
--- a/package/yast2-storage-ng.changes
+++ b/package/yast2-storage-ng.changes
@@ -1,3 +1,9 @@
+-------------------------------------------------------------------
+Tue Feb 19 14:15:16 UTC 2019 - jlopez@suse.com
+
+- Partitioner: allow to edit bcache devices (part of fate#325346).
+- 4.1.62
+
-------------------------------------------------------------------
Tue Feb 19 13:39:49 UTC 2019 - Stefan Hundhammer
diff --git a/package/yast2-storage-ng.spec b/package/yast2-storage-ng.spec
index 06e3a30794..254459931b 100644
--- a/package/yast2-storage-ng.spec
+++ b/package/yast2-storage-ng.spec
@@ -16,7 +16,7 @@
#
Name: yast2-storage-ng
-Version: 4.1.61
+Version: 4.1.62
Release: 0
BuildRoot: %{_tmppath}/%{name}-%{version}-build
From 3e3502285378557f8c81590cd4052fce72aea9d9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jos=C3=A9=20Iv=C3=A1n=20L=C3=B3pez=20Gonz=C3=A1lez?=
Date: Tue, 19 Feb 2019 16:20:07 +0000
Subject: [PATCH 17/25] Fix row selection for bcache
---
src/lib/y2partitioner/actions/add_bcache.rb | 2 ++
src/lib/y2partitioner/actions/controllers/bcache.rb | 3 ---
src/lib/y2partitioner/actions/delete_bcache.rb | 2 ++
src/lib/y2partitioner/actions/edit_bcache.rb | 2 ++
4 files changed, 6 insertions(+), 3 deletions(-)
diff --git a/src/lib/y2partitioner/actions/add_bcache.rb b/src/lib/y2partitioner/actions/add_bcache.rb
index 3a37c750d4..06a0711646 100644
--- a/src/lib/y2partitioner/actions/add_bcache.rb
+++ b/src/lib/y2partitioner/actions/add_bcache.rb
@@ -23,6 +23,7 @@
require "y2partitioner/actions/base"
require "y2partitioner/actions/controllers/bcache"
require "y2partitioner/dialogs/bcache"
+require "y2partitioner/ui_state"
module Y2Partitioner
module Actions
@@ -71,6 +72,7 @@ def perform_action
return unless dialog.run == :next
controller.create_bcache(dialog.backing_device, dialog.caching_device, dialog.options)
+ UIState.instance.select_row(controller.bcache)
end
# Whether there is suitable backing devices
diff --git a/src/lib/y2partitioner/actions/controllers/bcache.rb b/src/lib/y2partitioner/actions/controllers/bcache.rb
index b066147832..b30c8c485b 100644
--- a/src/lib/y2partitioner/actions/controllers/bcache.rb
+++ b/src/lib/y2partitioner/actions/controllers/bcache.rb
@@ -22,7 +22,6 @@
require "yast"
require "y2storage/bcache"
require "y2partitioner/device_graphs"
-require "y2partitioner/ui_state"
require "y2partitioner/blk_device_restorer"
module Y2Partitioner
@@ -39,8 +38,6 @@ class Bcache
# @param bcache [Y2Storage::Bcache, nil] nil if a new bcache is being created.
def initialize(bcache = nil)
@bcache = bcache
-
- UIState.instance.select_row(bcache) if bcache
end
# Suitable devices to be used as backing device
diff --git a/src/lib/y2partitioner/actions/delete_bcache.rb b/src/lib/y2partitioner/actions/delete_bcache.rb
index 6d3c42a272..91066647a4 100644
--- a/src/lib/y2partitioner/actions/delete_bcache.rb
+++ b/src/lib/y2partitioner/actions/delete_bcache.rb
@@ -22,6 +22,7 @@
require "yast"
require "y2partitioner/actions/delete_device"
require "y2partitioner/actions/controllers/bcache"
+require "y2partitioner/ui_state"
module Y2Partitioner
module Actions
@@ -36,6 +37,7 @@ def initialize(bcache)
textdomain "storage"
@bcache_controller = Controllers::Bcache.new(bcache)
+ UIState.instance.select_row(bcache)
end
private
diff --git a/src/lib/y2partitioner/actions/edit_bcache.rb b/src/lib/y2partitioner/actions/edit_bcache.rb
index a9b4c9be9f..8296ef0d2b 100644
--- a/src/lib/y2partitioner/actions/edit_bcache.rb
+++ b/src/lib/y2partitioner/actions/edit_bcache.rb
@@ -23,6 +23,7 @@
require "y2partitioner/actions/base"
require "y2partitioner/actions/controllers/bcache"
require "y2partitioner/dialogs/bcache"
+require "y2partitioner/ui_state"
module Y2Partitioner
module Actions
@@ -37,6 +38,7 @@ def initialize(bcache)
textdomain "storage"
@controller = Controllers::Bcache.new(bcache)
+ UIState.instance.select_row(bcache)
end
private
From 7b45ea2a10da11498f0e410786e4333b096bd14d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jos=C3=A9=20Iv=C3=A1n=20L=C3=B3pez=20Gonz=C3=A1lez?=
Date: Tue, 19 Feb 2019 16:21:21 +0000
Subject: [PATCH 18/25] Fix messages text
---
src/lib/y2partitioner/actions/delete_bcache.rb | 4 ++--
src/lib/y2partitioner/actions/edit_bcache.rb | 6 +++---
test/y2partitioner/actions/delete_bcache_test.rb | 2 +-
3 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/src/lib/y2partitioner/actions/delete_bcache.rb b/src/lib/y2partitioner/actions/delete_bcache.rb
index 91066647a4..6967e025ea 100644
--- a/src/lib/y2partitioner/actions/delete_bcache.rb
+++ b/src/lib/y2partitioner/actions/delete_bcache.rb
@@ -75,8 +75,8 @@ def unsafe_detach_error
# TRANSLATORS: Error message when detach is not a safe action
_(
"The bcache cannot be deleted because it shares its cache set with other devices.\n" \
- "Detaching is required to avoid possible unreachable space, but detaching action\n" \
- "could take a very long time in some situations."
+ "Deleting it without detaching the device first can result in unreachable space.\n" \
+ "Unfortunately detaching can take a very long time in some situations."
)
end
diff --git a/src/lib/y2partitioner/actions/edit_bcache.rb b/src/lib/y2partitioner/actions/edit_bcache.rb
index 8296ef0d2b..61ac453e71 100644
--- a/src/lib/y2partitioner/actions/edit_bcache.rb
+++ b/src/lib/y2partitioner/actions/edit_bcache.rb
@@ -76,9 +76,9 @@ def non_editable_error
# TRANSLATORS: error message, %{name} is replaced by a bcache name (e.g., /dev/bcache0)
format(
- _("The Bcache %{name} is already created on disk and its caching\n" \
- "cannot be modified. To modify the caching device, remove the Bcache\n" \
- "and create it again."),
+ _("The Bcache %{name} is already created on disk. Such device cannot be modified\n" \
+ "because that might imply a detaching operation. Unfortunately detaching can take\n" \
+ "a very long time in some situations."),
name: controller.bcache.name
)
end
diff --git a/test/y2partitioner/actions/delete_bcache_test.rb b/test/y2partitioner/actions/delete_bcache_test.rb
index fd6436c098..cc5e5551d2 100644
--- a/test/y2partitioner/actions/delete_bcache_test.rb
+++ b/test/y2partitioner/actions/delete_bcache_test.rb
@@ -148,7 +148,7 @@ def bcache_cset_only_for(bcache)
end
it "shows an error message" do
- expect(Yast2::Popup).to receive(:show).with(/Detaching is required/, headline: :error)
+ expect(Yast2::Popup).to receive(:show).with(/cannot be deleted/, headline: :error)
subject.run
end
From 0cce77686eaf5e5d83b8dfa032ca10e326fd1d5e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jos=C3=A9=20Iv=C3=A1n=20L=C3=B3pez=20Gonz=C3=A1lez?=
Date: Tue, 19 Feb 2019 16:21:47 +0000
Subject: [PATCH 19/25] Add missing documentation
---
src/lib/y2storage/bcache.rb | 6 ++++++
src/lib/y2storage/devicegraph.rb | 6 +++++-
2 files changed, 11 insertions(+), 1 deletion(-)
diff --git a/src/lib/y2storage/bcache.rb b/src/lib/y2storage/bcache.rb
index 784f320ce3..6be87a96aa 100644
--- a/src/lib/y2storage/bcache.rb
+++ b/src/lib/y2storage/bcache.rb
@@ -63,6 +63,12 @@ class Bcache < Partitionable
# @param set [BcacheCset] set to attach
storage_forward :add_bcache_cset
+ # @!method remove_bcache_cset
+ # This method does not make sense for Flash-only Bcache devices.
+ #
+ # @raise [storage::Exception] if detaching failed
+ # @raise [storage::LogicException] for a Flash-only Bcache device or when
+ # the Bcache device has no caching set.
storage_forward :remove_bcache_cset
# @!attribute cache_mode
diff --git a/src/lib/y2storage/devicegraph.rb b/src/lib/y2storage/devicegraph.rb
index 2fb341d6fe..9836a97d7e 100644
--- a/src/lib/y2storage/devicegraph.rb
+++ b/src/lib/y2storage/devicegraph.rb
@@ -381,12 +381,16 @@ def remove_bcache(bcache)
remove_with_dependants(bcache_cset) if bcache_cset && bcache_cset.bcaches.empty?
end
+ # Removes a caching set
+ #
+ # Bcache devices using this caching set are not removed.
+ #
+ # @raise [ArgumentError] if the caching set does not exist in the devicegraph
def remove_bcache_cset(bcache_cset)
if !(bcache_cset && bcache_cset.is?(:bcache_cset))
raise(ArgumentError, "Incorrect device #{bcache_cset.inspect}")
end
- # Bcaches using this caching set are not removed
remove_device(bcache_cset)
end
From 019a65f1f2a2f5f6ad3ed56568c06f2a71f397c3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jos=C3=A9=20Iv=C3=A1n=20L=C3=B3pez=20Gonz=C3=A1lez?=
Date: Tue, 19 Feb 2019 16:23:27 +0000
Subject: [PATCH 20/25] Add help for bcache attributes
---
.../widgets/bcache_device_description.rb | 35 +++++++++++++++----
.../widgets/disk_device_description.rb | 2 +-
src/lib/y2partitioner/widgets/help.rb | 14 +++++++-
3 files changed, 43 insertions(+), 8 deletions(-)
diff --git a/src/lib/y2partitioner/widgets/bcache_device_description.rb b/src/lib/y2partitioner/widgets/bcache_device_description.rb
index d9a6d84f8c..403c8d7f06 100644
--- a/src/lib/y2partitioner/widgets/bcache_device_description.rb
+++ b/src/lib/y2partitioner/widgets/bcache_device_description.rb
@@ -44,16 +44,30 @@ def device_description
# @return [String]
def bcache_description
output = Yast::HTML.Heading(_("Bcache Devices:"))
- output << Yast::HTML.List([
- format(_("Backing Device: %s"), backing_device),
- format(_("Caching UUID: %s"), uuid),
- format(_("Caching Device: %s"), caching_device),
- format(_("Cache mode: %s"), cache_mode)
- ])
+ output << Yast::HTML.List(bcache_attributes)
+ end
+
+ # Fields to show in help
+ #
+ # @return [Array]
+ def help_fields
+ super + bcache_help_fields
end
private
+ # Attributes for describing a bcache device
+ #
+ # @return [Array]
+ def bcache_attributes
+ [
+ format(_("Backing Device: %s"), backing_device),
+ format(_("Caching UUID: %s"), uuid),
+ format(_("Caching Device: %s"), caching_device),
+ format(_("Cache Mode: %s"), cache_mode)
+ ]
+ end
+
def uuid
device.bcache_cset ? device.bcache_cset.uuid : ""
end
@@ -79,6 +93,15 @@ def cache_mode
device.cache_mode.to_human_string
end
+
+ BCACHE_HELP_FIELDS = [:backing_device, :caching_uuid, :caching_device, :cache_mode].freeze
+
+ # Help fields for a bcache device
+ #
+ # @return [Array]
+ def bcache_help_fields
+ BCACHE_HELP_FIELDS.dup
+ end
end
end
end
diff --git a/src/lib/y2partitioner/widgets/disk_device_description.rb b/src/lib/y2partitioner/widgets/disk_device_description.rb
index 58c7a34970..f7fa1f0048 100644
--- a/src/lib/y2partitioner/widgets/disk_device_description.rb
+++ b/src/lib/y2partitioner/widgets/disk_device_description.rb
@@ -70,7 +70,7 @@ def disk_attributes
#
# @return [Array]
def help_fields
- blk_device_help_fields + disk_help_fields
+ blk_device_help_fields + disk_help_fields + filesystem_help_fields
end
DISK_HELP_FIELDS = [:vendor, :model, :bus, :sectors, :sector_size, :disk_label].freeze
diff --git a/src/lib/y2partitioner/widgets/help.rb b/src/lib/y2partitioner/widgets/help.rb
index d1e3028834..e3b93a3470 100644
--- a/src/lib/y2partitioner/widgets/help.rb
+++ b/src/lib/y2partitioner/widgets/help.rb
@@ -102,7 +102,19 @@ def included(_target)
uuid: N_("UUID shows the Universally Unique\nIdentifier of the file " \
"system."),
- vendor: N_("Vendor shows the device vendor.")
+ vendor: N_("Vendor shows the device vendor."),
+
+ backing_device: N_("Backing Device shows the device used as backing device " \
+ "for bcache."),
+
+ caching_uuid: N_("Caching UUID shows the UUID of the used caching set. This " \
+ "field is empty if no caching is used."),
+
+ caching_device: N_("Caching Device shows the device used for caching. This field " \
+ "is empty if no caching is used."),
+
+ cache_mode: N_("Cache Mode shows the operating mode for bcache. Currently there " \
+ "are four supported modes: Writethrough, Writeback, Writearound and None.")
}.freeze
# help texts that are appended to the common help only in Mode.normal
From 132e2784878ac3d091cbba7be884dff7f95beda7 Mon Sep 17 00:00:00 2001
From: Ancor Gonzalez Sosa
Date: Fri, 15 Feb 2019 17:49:11 +0100
Subject: [PATCH 21/25] Partitioner: button to activate crypt devices
---
src/lib/y2partitioner/widgets/configure.rb | 20 +++-
src/lib/y2partitioner/widgets/reprobe.rb | 22 ++--
test/support/partitioner_reprobe_examples.rb | 12 +++
test/y2partitioner/widgets/configure_test.rb | 102 ++++++++++++-------
4 files changed, 111 insertions(+), 45 deletions(-)
diff --git a/src/lib/y2partitioner/widgets/configure.rb b/src/lib/y2partitioner/widgets/configure.rb
index 1378657324..b77ba18d9b 100644
--- a/src/lib/y2partitioner/widgets/configure.rb
+++ b/src/lib/y2partitioner/widgets/configure.rb
@@ -66,8 +66,8 @@ def handle(event)
return nil unless action
return nil unless warning_accepted?(action) && availability_ensured?(action)
- Yast::WFM.call(action.client)
- reprobe
+ Yast::WFM.call(action.client) if action.client
+ reprobe(activate: action.activate)
:redraw
end
@@ -183,6 +183,8 @@ def initialize(id, label, icon, client, pkgs)
# Sorted list of actions
ALL = [
+ new(:crypt, N_("Provide Crypt &Passwords..."), "yast-encrypted", nil,
+ ["cryptsetup"]),
new(:iscsi, N_("Configure &iSCSI..."), "yast-iscsi-client", "iscsi-client",
["yast2-iscsi-client"]),
new(:fcoe, N_("Configure &FCoE..."), "fcoe", "fcoe-client",
@@ -202,6 +204,10 @@ def initialize(id, label, icon, client, pkgs)
# are indexed in this constant in order to reuse the existing
# translations from yast2-storage
WARNING_TEXTS = {
+ crypt: N_(
+ "Rescanning crypt devices cancels all current changes.\n" \
+ "Really activate crypt devices?"
+ ),
iscsi: N_(
"Calling iSCSI configuration cancels all current changes.\n" \
"Really call iSCSI configuration?"
@@ -275,6 +281,16 @@ def warning_text
def supported?
S390_IDS.include?(id) ? Yast::Arch.s390 : true
end
+
+ # Value for the 'activate' argument of {Reprobe#reprobe}
+ #
+ # For most cases this returns nil, which implies simply honoring the
+ # default behavior.
+ #
+ # @return [Boolean, nil]
+ def activate
+ id == :crypt ? true : nil
+ end
end
end
end
diff --git a/src/lib/y2partitioner/widgets/reprobe.rb b/src/lib/y2partitioner/widgets/reprobe.rb
index 4075dd4770..5a4eeed4cf 100644
--- a/src/lib/y2partitioner/widgets/reprobe.rb
+++ b/src/lib/y2partitioner/widgets/reprobe.rb
@@ -41,10 +41,19 @@ module Reprobe
# @raise [Y2Partitioner::ForcedAbortError] When there is an error during probing
# and the user decides to abort, or probed devicegraph contains errors and the
# user decides to not sanitize.
- def reprobe
+ #
+ # @param activate [Boolean, nil] whether to perform an activation, if nil
+ # the (re)activation will be done only during installation
+ def reprobe(activate: nil)
textdomain "storage"
+
+ # By default, (re)activation is only done during installation.
+ # In installed systems, activation is only triggered for actions that
+ # explicitly force it.
+ activate = !!Yast::Stage.initial if activate.nil?
+
Yast::Popup.Feedback("", _("Rescanning disks...")) do
- raise Y2Partitioner::ForcedAbortError unless activate_and_probe?
+ raise Y2Partitioner::ForcedAbortError unless activate_and_probe?(activate)
probed = storage_manager.probed
staging = storage_manager.staging
@@ -59,13 +68,12 @@ def storage_manager
# Performs storage reactivation (if needed) and reprobing
#
- # @note Activation is only done during installation, never in an already
- # installed system
- #
+ # @param activate [Boolean] whether to perform a reactivation of devices
+ # before the reprobing
# @return [Boolean] false if something went wrong
- def activate_and_probe?
+ def activate_and_probe?(activate)
success = true
- success &&= storage_manager.activate if Yast::Stage.initial
+ success &&= storage_manager.activate if activate
success &&= storage_manager.probe
success
end
diff --git a/test/support/partitioner_reprobe_examples.rb b/test/support/partitioner_reprobe_examples.rb
index 22ad788cc2..0f80ca55e2 100644
--- a/test/support/partitioner_reprobe_examples.rb
+++ b/test/support/partitioner_reprobe_examples.rb
@@ -51,3 +51,15 @@
end
end
end
+
+RSpec.shared_examples "activation" do
+ it "runs activation (again)" do
+ expect(manager).to receive(:activate).and_return true
+ subject.handle(*handle_args)
+ end
+
+ it "raises an exception if activation fails" do
+ allow(manager).to receive(:activate).and_return false
+ expect { subject.handle(*handle_args) }.to raise_error(Y2Partitioner::ForcedAbortError)
+ end
+end
diff --git a/test/y2partitioner/widgets/configure_test.rb b/test/y2partitioner/widgets/configure_test.rb
index b5163c68fc..c85de3ea86 100644
--- a/test/y2partitioner/widgets/configure_test.rb
+++ b/test/y2partitioner/widgets/configure_test.rb
@@ -64,10 +64,11 @@ def menu_button_item_ids(button)
context "if all the possible clients are available" do
let(:missing_clients) { [] }
- it "returns a menu button with buttons for iSCI, FCoE, DASD, zFCP and XPRAM" do
+ it "returns a menu button with buttons for crypt, iSCI, FCoE, DASD, zFCP and XPRAM" do
term = widget.contents
expect(term.value).to eq :MenuButton
- expect(menu_button_item_ids(term)).to contain_exactly(:iscsi, :fcoe, :dasd, :zfcp, :xpram)
+ expect(menu_button_item_ids(term))
+ .to contain_exactly(:crypt, :iscsi, :fcoe, :dasd, :zfcp, :xpram)
end
end
@@ -77,7 +78,7 @@ def menu_button_item_ids(button)
it "returns a menu button with buttons only for the available clients" do
term = widget.contents
expect(term.value).to eq :MenuButton
- expect(menu_button_item_ids(term)).to contain_exactly(:fcoe, :zfcp, :xpram)
+ expect(menu_button_item_ids(term)).to contain_exactly(:crypt, :fcoe, :zfcp, :xpram)
expect(menu_button_item_ids(term)).to_not include(:iscsi, :dasd)
end
end
@@ -85,9 +86,10 @@ def menu_button_item_ids(button)
context "if no client is available" do
let(:missing_clients) { all_clients }
- it "returns an empty term" do
+ it "returns a menu button with 'Crypt Passwords' as the only option" do
term = widget.contents
- expect(term.value).to eq :Empty
+ expect(term.value).to eq :MenuButton
+ expect(menu_button_item_ids(term)).to eq [:crypt]
end
end
end
@@ -98,10 +100,10 @@ def menu_button_item_ids(button)
context "if all the possible clients are available" do
let(:missing_clients) { [] }
- it "returns a menu button with buttons for iSCI and FCoE" do
+ it "returns a menu button with buttons for crypt, iSCI and FCoE" do
term = widget.contents
expect(term.value).to eq :MenuButton
- expect(menu_button_item_ids(term)).to contain_exactly(:iscsi, :fcoe)
+ expect(menu_button_item_ids(term)).to contain_exactly(:crypt, :iscsi, :fcoe)
end
end
@@ -111,7 +113,7 @@ def menu_button_item_ids(button)
it "returns a menu button with buttons only for the available clients" do
term = widget.contents
expect(term.value).to eq :MenuButton
- expect(menu_button_item_ids(term)).to eq [:fcoe]
+ expect(menu_button_item_ids(term)).to eq [:crypt, :fcoe]
expect(menu_button_item_ids(term)).to_not include(:iscsi)
end
end
@@ -119,9 +121,10 @@ def menu_button_item_ids(button)
context "if no client is available" do
let(:missing_clients) { all_clients }
- it "returns an empty term" do
+ it "returns a menu button with 'Crypt Passwords' as the only option" do
term = widget.contents
- expect(term.value).to eq :Empty
+ expect(term.value).to eq :MenuButton
+ expect(menu_button_item_ids(term)).to eq [:crypt]
end
end
end
@@ -136,20 +139,22 @@ def menu_button_item_ids(button)
context "if all the possible clients are available" do
let(:missing_clients) { [] }
- it "returns a menu button with buttons for all clients (iSCI, FCoE, DASD, zFCP and XPRAM)" do
+ it "returns a menu button with buttons for all actions" do
term = widget.contents
expect(term.value).to eq :MenuButton
- expect(menu_button_item_ids(term)).to contain_exactly(:iscsi, :fcoe, :dasd, :zfcp, :xpram)
+ expect(menu_button_item_ids(term))
+ .to contain_exactly(:crypt, :iscsi, :fcoe, :dasd, :zfcp, :xpram)
end
end
context "if some clients are not available" do
let(:missing_clients) { ["iscsi-client", "dasd"] }
- it "returns a menu button with buttons for all clients (iSCI, FCoE, DASD, zFCP and XPRAM)" do
+ it "returns a menu button with buttons for all actions" do
term = widget.contents
expect(term.value).to eq :MenuButton
- expect(menu_button_item_ids(term)).to contain_exactly(:iscsi, :fcoe, :dasd, :zfcp, :xpram)
+ expect(menu_button_item_ids(term))
+ .to contain_exactly(:crypt, :iscsi, :fcoe, :dasd, :zfcp, :xpram)
end
end
end
@@ -160,20 +165,20 @@ def menu_button_item_ids(button)
context "if all the possible clients are available" do
let(:missing_clients) { [] }
- it "returns a menu button with buttons for all supported clients (iSCI and FCoE)" do
+ it "returns a menu button with buttons for all supported actions (crypt, iSCI and FCoE)" do
term = widget.contents
expect(term.value).to eq :MenuButton
- expect(menu_button_item_ids(term)).to contain_exactly(:iscsi, :fcoe)
+ expect(menu_button_item_ids(term)).to contain_exactly(:crypt, :iscsi, :fcoe)
end
end
context "if some clients are not available" do
let(:missing_clients) { ["iscsi-client"] }
- it "returns a menu button with buttons for all supported clients (iSCI and FCoE)" do
+ it "returns a menu button with buttons for all supported actions (crypt, iSCI and FCoE)" do
term = widget.contents
expect(term.value).to eq :MenuButton
- expect(menu_button_item_ids(term)).to contain_exactly(:iscsi, :fcoe)
+ expect(menu_button_item_ids(term)).to contain_exactly(:crypt, :iscsi, :fcoe)
end
end
end
@@ -240,27 +245,35 @@ def event_for(id)
context "if the user accepts the warning" do
let(:accepted) { true }
- it "calls the corresponding YaST client" do
- expect(Yast::WFM).to receive(:call).with("iscsi-client")
- widget.handle(event)
- end
+ context "for an action performed via a separate client" do
+ let(:event) { event_for(:iscsi) }
- include_examples "reprobing"
+ it "calls the corresponding YaST client" do
+ expect(Yast::WFM).to receive(:call).with("iscsi-client")
+ widget.handle(event)
+ end
- it "runs activation again" do
- expect(manager).to receive(:activate).and_return true
- widget.handle(event)
+ include_examples "reprobing"
+ include_examples "activation"
end
- it "raises an exception if activation fails" do
- allow(manager).to receive(:activate).and_return false
- expect { subject.handle(event) }.to raise_error(Y2Partitioner::ForcedAbortError)
+ context "for activation of crypt devices" do
+ let(:event) { event_for(:crypt) }
+
+ it "does not call any additional YaST client" do
+ expect(Yast::WFM).to_not receive(:call)
+ widget.handle(event)
+ end
+
+ include_examples "reprobing"
+ include_examples "activation"
end
end
end
context "in an already installed system" do
let(:install) { false }
+ let(:handle_args) { [event] }
include_examples "show configure warning"
@@ -292,16 +305,33 @@ def event_for(id)
context "if the packages were installed or already there" do
let(:installed_pkgs) { true }
- it "calls the corresponding YaST client" do
- expect(Yast::WFM).to receive(:call).with("iscsi-client")
- widget.handle(event)
+ context "for an action performed via a separate client" do
+ let(:event) { event_for(:iscsi) }
+
+ it "calls the corresponding YaST client" do
+ expect(Yast::WFM).to receive(:call).with("iscsi-client")
+ widget.handle(event)
+ end
+
+ include_examples "reprobing"
+
+ it "does not run activation" do
+ expect(manager).to_not receive(:activate)
+ widget.handle(event)
+ end
end
- include_examples "reprobing"
+ context "for activation of crypt devices" do
+ let(:event) { event_for(:crypt) }
+ before { allow(manager).to receive(:activate).and_return true }
- it "does not run activation" do
- expect(manager).to_not receive(:activate)
- widget.handle(event)
+ it "does not call any additional YaST client" do
+ expect(Yast::WFM).to_not receive(:call)
+ widget.handle(event)
+ end
+
+ include_examples "reprobing"
+ include_examples "activation"
end
end
end
From 889a2852e3a001e161eebdfd4c490115c2fa6eaa Mon Sep 17 00:00:00 2001
From: Ancor Gonzalez Sosa
Date: Mon, 18 Feb 2019 18:01:21 +0100
Subject: [PATCH 22/25] Configure button: use inheritance to define the actions
---
src/lib/y2partitioner/widgets/configure.rb | 281 ++++++++++++-------
test/y2partitioner/widgets/configure_test.rb | 63 +++--
2 files changed, 221 insertions(+), 123 deletions(-)
diff --git a/src/lib/y2partitioner/widgets/configure.rb b/src/lib/y2partitioner/widgets/configure.rb
index b77ba18d9b..354b7e4454 100644
--- a/src/lib/y2partitioner/widgets/configure.rb
+++ b/src/lib/y2partitioner/widgets/configure.rb
@@ -61,7 +61,7 @@ def contents
# @return [:redraw, nil] :redraw when some configuration client was
# executed; nil otherwise.
def handle(event)
- action = Action.find(event["ID"])
+ action = find_action(event["ID"])
return nil unless action
return nil unless warning_accepted?(action) && availability_ensured?(action)
@@ -108,11 +108,11 @@ def actions
@actions ||=
if Yast::Stage.initial
# In the inst-sys, check which clients are available
- Action.supported.select { |action| Yast::WFM.ClientExists(action.client) }
+ supported_actions.reject(&:client_missing?)
else
# In the installed system, we don't care if the client is there or not
# as the user will be prompted to install the pkg anyway (in #handle).
- Action.supported
+ supported_actions
end
end
@@ -156,130 +156,82 @@ def check_and_install_pkgs?(action)
ret
end
+ # Sorted list of actions
+ def supported_actions
+ @supported_actions ||= [
+ CryptAction.new(_("Provide Crypt &Passwords..."), "yast-encrypted"),
+ IscsiAction.new(_("Configure &iSCSI..."), "yast-iscsi-client"),
+ FcoeAction.new(_("Configure &FCoE..."), "fcoe"),
+ DasdAction.new(_("Configure &DASD..."), "yast-dasd"),
+ ZfcpAction.new(_("Configure &zFCP..."), "yast-zfcp"),
+ XpramAction.new(_("Configure &XPRAM..."), "yast-xpram")
+ ].select(&:supported?)
+ end
+
+ # Action with the given id
+ #
+ # @param id [Symbol]
+ # @return [Action]
+ def find_action(id)
+ supported_actions.find { |action| action.id == id }
+ end
+
# Each one of the configuration actions offered by the widget and that
- # corresponds to a YaST client
+ # (usually) corresponds to a YaST client
class Action
include Yast::I18n
- extend Yast::I18n
-
- textdomain "storage"
# Constructor
#
- # @param id [Symbol] see {#id}
- # @param label [String] string marked for translation to be used by {#label}
+ # @param label [String] see {#label}
# @param icon [String] see {#icon}
- # @param client [String] see {#client}
- # @param pkgs [Array] see {#pkgs}
- def initialize(id, label, icon, client, pkgs)
+ def initialize(label, icon)
textdomain "storage"
- @id = id
@label = label
@icon = icon
- @client = client
- @pkgs = pkgs
- end
-
- # Sorted list of actions
- ALL = [
- new(:crypt, N_("Provide Crypt &Passwords..."), "yast-encrypted", nil,
- ["cryptsetup"]),
- new(:iscsi, N_("Configure &iSCSI..."), "yast-iscsi-client", "iscsi-client",
- ["yast2-iscsi-client"]),
- new(:fcoe, N_("Configure &FCoE..."), "fcoe", "fcoe-client",
- ["yast2-fcoe-client"]),
- new(:dasd, N_("Configure &DASD..."), "yast-dasd", "dasd",
- ["yast2-s390"]),
- new(:zfcp, N_("Configure &zFCP..."), "yast-zfcp", "zfcp",
- ["yast2-s390"]),
- new(:xpram, N_("Configure &XPRAM..."), "yast-xpram", "xpram",
- ["yast2-s390"])
- ].freeze
- private_constant :ALL
-
- # Texts for {#warning_text}
- #
- # Although all texts are almost identical, the whole literal strings
- # are indexed in this constant in order to reuse the existing
- # translations from yast2-storage
- WARNING_TEXTS = {
- crypt: N_(
- "Rescanning crypt devices cancels all current changes.\n" \
- "Really activate crypt devices?"
- ),
- iscsi: N_(
- "Calling iSCSI configuration cancels all current changes.\n" \
- "Really call iSCSI configuration?"
- ),
- fcoe: N_(
- "Calling FCoE configuration cancels all current changes.\n" \
- "Really call FCoE configuration?"
- ),
- dasd: N_(
- "Calling DASD configuration cancels all current changes.\n" \
- "Really call DASD configuration?"
- ),
- fzcp: N_(
- "Calling zFCP configuration cancels all current changes.\n" \
- "Really call zFCP configuration?"
- ),
- xpram: N_(
- "Calling XPRAM configuration cancels all current changes.\n" \
- "Really call XPRAM configuration?"
- )
- }
-
- # Actions that can only be executed on s390 systems
- S390_IDS = [:dasd, :zfcp, :xpram].freeze
- private_constant :S390_IDS
-
- # Action with the given id
- #
- # @param id [Symbol]
- # @return [Action]
- def self.find(id)
- ALL.find { |action| action.id == id }
end
- # Actions that are supported in the current system
- #
- # @return [Array]
- def self.supported
- ALL.select(&:supported?)
+ # @return [Symbol] identifier for the action to use in the UI
+ def id
+ @id ||= self.class.name.split("::").last.to_sym
end
- # @return [Symbol] identifier for the action
- attr_reader :id
+ # @return [String] Internationalized label
+ attr_reader :label
# @return [String] name of the icon to display next to the label
attr_reader :icon
- # @return [Symbol] name of the YaST client implementing the action
- attr_reader :client
-
- # @return [Array] name of the packages needed to run the action
- attr_reader :pkgs
-
- # Internationalized label
+ # Internationalized text to be displayed as a warning before executing the action
+ #
+ # Although all texts are almost identical, the whole literal strings are used
+ # on each subclass in order to reuse the existing translations from yast2-storage
#
# @return [String]
- def label
- _(@label)
+ def warning_text
+ ""
end
- # Internationalized text to be displayed as a warning before executing the action
+ # Name of the YaST client implementing the action
#
- # @return [String]
- def warning_text
- _(WARNING_TEXTS[id])
+ # @return [Symbol, nil] nil if no separate client needs to be called
+ def client
+ nil
+ end
+
+ # Names of the packages needed to run the action
+ #
+ # @return [Array]
+ def pkgs
+ []
end
# Whether the action is supported in the current system
#
# @return [Boolean]
def supported?
- S390_IDS.include?(id) ? Yast::Arch.s390 : true
+ true
end
# Value for the 'activate' argument of {Reprobe#reprobe}
@@ -289,7 +241,140 @@ def supported?
#
# @return [Boolean, nil]
def activate
- id == :crypt ? true : nil
+ nil
+ end
+
+ # Whether the client needed to run the action is missing
+ #
+ # @return [Boolean]
+ def client_missing?
+ return false unless client
+
+ !Yast::WFM.ClientExists(client)
+ end
+ end
+
+ # Specific class for the activation action
+ class CryptAction < Action
+ # @see Action#warning_text
+ def warning_text
+ _(
+ "Rescanning crypt devices cancels all current changes.\n" \
+ "Really activate crypt devices?"
+ )
+ end
+
+ # @see Action#pkgs
+ def pkgs
+ ["cryptsetup"]
+ end
+
+ # @see Action#activate
+ def activate
+ true
+ end
+ end
+
+ # Specific action for running the iSCSI configuration client
+ class IscsiAction < Action
+ # @see Action#warning_text
+ def warning_text
+ _(
+ "Calling iSCSI configuration cancels all current changes.\n" \
+ "Really call iSCSI configuration?"
+ )
+ end
+
+ # @see Action#client
+ def client
+ "iscsi-client"
+ end
+
+ # @see Action#pkgs
+ def pkgs
+ ["yast2-iscsi-client"]
+ end
+ end
+
+ # Specific action for running the FCoE configuration client
+ class FcoeAction < Action
+ # @see Action#warning_text
+ def warning_text
+ _(
+ "Calling FCoE configuration cancels all current changes.\n" \
+ "Really call FCoE configuration?"
+ )
+ end
+
+ # @see Action#client
+ def client
+ "fcoe-client"
+ end
+
+ # @see Action#pkgs
+ def pkgs
+ ["yast2-fcoe-client"]
+ end
+ end
+
+ # Common base class for all the actions that are specific for S390
+ class S390Action < Action
+ # @see Action#pkgs
+ def pkgs
+ ["yast2-s390"]
+ end
+
+ # @see Action#supported?
+ def supported?
+ Yast::Arch.s390
+ end
+ end
+
+ # Specific action for running the DASD activation client
+ class DasdAction < S390Action
+ # @see Action#warning_text
+ def warning_text
+ _(
+ "Calling DASD configuration cancels all current changes.\n" \
+ "Really call DASD configuration?"
+ )
+ end
+
+ # @see Action#client
+ def client
+ "dasd"
+ end
+ end
+
+ # Specific action for running the zFCP configuration client
+ class ZfcpAction < S390Action
+ # @see Action#warning_text
+ def warning_text
+ _(
+ "Calling zFCP configuration cancels all current changes.\n" \
+ "Really call zFCP configuration?"
+ )
+ end
+
+ # @see Action#client
+ def client
+ "zfcp"
+ end
+ end
+
+ # Specific action for running the XPRAM configuration client
+ class XpramAction < S390Action
+ # @see Action#warning_text
+ def warning_text
+ _(
+ "Calling XPRAM configuration cancels all current changes.\n" \
+ "Really call XPRAM configuration?"
+ )
+ end
+
+ # @see Action#client
+ def client
+ "xpram"
end
end
end
diff --git a/test/y2partitioner/widgets/configure_test.rb b/test/y2partitioner/widgets/configure_test.rb
index c85de3ea86..4cb9bfd02b 100644
--- a/test/y2partitioner/widgets/configure_test.rb
+++ b/test/y2partitioner/widgets/configure_test.rb
@@ -67,8 +67,9 @@ def menu_button_item_ids(button)
it "returns a menu button with buttons for crypt, iSCI, FCoE, DASD, zFCP and XPRAM" do
term = widget.contents
expect(term.value).to eq :MenuButton
- expect(menu_button_item_ids(term))
- .to contain_exactly(:crypt, :iscsi, :fcoe, :dasd, :zfcp, :xpram)
+ expect(menu_button_item_ids(term)) .to contain_exactly(
+ :CryptAction, :IscsiAction, :FcoeAction, :DasdAction, :ZfcpAction, :XpramAction
+ )
end
end
@@ -78,8 +79,10 @@ def menu_button_item_ids(button)
it "returns a menu button with buttons only for the available clients" do
term = widget.contents
expect(term.value).to eq :MenuButton
- expect(menu_button_item_ids(term)).to contain_exactly(:crypt, :fcoe, :zfcp, :xpram)
- expect(menu_button_item_ids(term)).to_not include(:iscsi, :dasd)
+ expect(menu_button_item_ids(term)).to contain_exactly(
+ :CryptAction, :FcoeAction, :ZfcpAction, :XpramAction
+ )
+ expect(menu_button_item_ids(term)).to_not include(:IscsiAction, :DasdAction)
end
end
@@ -89,7 +92,7 @@ def menu_button_item_ids(button)
it "returns a menu button with 'Crypt Passwords' as the only option" do
term = widget.contents
expect(term.value).to eq :MenuButton
- expect(menu_button_item_ids(term)).to eq [:crypt]
+ expect(menu_button_item_ids(term)).to eq [:CryptAction]
end
end
end
@@ -103,7 +106,9 @@ def menu_button_item_ids(button)
it "returns a menu button with buttons for crypt, iSCI and FCoE" do
term = widget.contents
expect(term.value).to eq :MenuButton
- expect(menu_button_item_ids(term)).to contain_exactly(:crypt, :iscsi, :fcoe)
+ expect(menu_button_item_ids(term)).to contain_exactly(
+ :CryptAction, :IscsiAction, :FcoeAction
+ )
end
end
@@ -113,8 +118,8 @@ def menu_button_item_ids(button)
it "returns a menu button with buttons only for the available clients" do
term = widget.contents
expect(term.value).to eq :MenuButton
- expect(menu_button_item_ids(term)).to eq [:crypt, :fcoe]
- expect(menu_button_item_ids(term)).to_not include(:iscsi)
+ expect(menu_button_item_ids(term)).to eq [:CryptAction, :FcoeAction]
+ expect(menu_button_item_ids(term)).to_not include(:IscsiAction)
end
end
@@ -124,7 +129,7 @@ def menu_button_item_ids(button)
it "returns a menu button with 'Crypt Passwords' as the only option" do
term = widget.contents
expect(term.value).to eq :MenuButton
- expect(menu_button_item_ids(term)).to eq [:crypt]
+ expect(menu_button_item_ids(term)).to eq [:CryptAction]
end
end
end
@@ -142,8 +147,9 @@ def menu_button_item_ids(button)
it "returns a menu button with buttons for all actions" do
term = widget.contents
expect(term.value).to eq :MenuButton
- expect(menu_button_item_ids(term))
- .to contain_exactly(:crypt, :iscsi, :fcoe, :dasd, :zfcp, :xpram)
+ expect(menu_button_item_ids(term)).to contain_exactly(
+ :CryptAction, :IscsiAction, :FcoeAction, :DasdAction, :ZfcpAction, :XpramAction
+ )
end
end
@@ -153,8 +159,9 @@ def menu_button_item_ids(button)
it "returns a menu button with buttons for all actions" do
term = widget.contents
expect(term.value).to eq :MenuButton
- expect(menu_button_item_ids(term))
- .to contain_exactly(:crypt, :iscsi, :fcoe, :dasd, :zfcp, :xpram)
+ expect(menu_button_item_ids(term)).to contain_exactly(
+ :CryptAction, :IscsiAction, :FcoeAction, :DasdAction, :ZfcpAction, :XpramAction
+ )
end
end
end
@@ -168,7 +175,9 @@ def menu_button_item_ids(button)
it "returns a menu button with buttons for all supported actions (crypt, iSCI and FCoE)" do
term = widget.contents
expect(term.value).to eq :MenuButton
- expect(menu_button_item_ids(term)).to contain_exactly(:crypt, :iscsi, :fcoe)
+ expect(menu_button_item_ids(term)).to contain_exactly(
+ :CryptAction, :IscsiAction, :FcoeAction
+ )
end
end
@@ -178,7 +187,9 @@ def menu_button_item_ids(button)
it "returns a menu button with buttons for all supported actions (crypt, iSCI and FCoE)" do
term = widget.contents
expect(term.value).to eq :MenuButton
- expect(menu_button_item_ids(term)).to contain_exactly(:crypt, :iscsi, :fcoe)
+ expect(menu_button_item_ids(term)).to contain_exactly(
+ :CryptAction, :IscsiAction, :FcoeAction
+ )
end
end
end
@@ -196,9 +207,9 @@ def event_for(id)
end
let(:accepted) { false }
- let(:handle_args) { [event_for(:fcoe)] }
+ let(:handle_args) { [event_for(:FcoeAction)] }
let(:manager) { Y2Storage::StorageManager.instance }
- let(:event) { event_for(:iscsi) }
+ let(:event) { event_for(:IscsiAction) }
RSpec.shared_examples "configure nothing" do
it "returns nil" do
@@ -225,8 +236,8 @@ def event_for(id)
it "displays the corresponding warning message" do
expect(Yast::Popup).to receive(:YesNo).with(/FCoE/).ordered
expect(Yast::Popup).to receive(:YesNo).with(/iSCSI/).ordered
- widget.handle(event_for(:fcoe))
- widget.handle(event_for(:iscsi))
+ widget.handle(event_for(:FcoeAction))
+ widget.handle(event_for(:IscsiAction))
end
context "if the user rejects the warning" do
@@ -246,7 +257,7 @@ def event_for(id)
let(:accepted) { true }
context "for an action performed via a separate client" do
- let(:event) { event_for(:iscsi) }
+ let(:event) { event_for(:IscsiAction) }
it "calls the corresponding YaST client" do
expect(Yast::WFM).to receive(:call).with("iscsi-client")
@@ -258,7 +269,7 @@ def event_for(id)
end
context "for activation of crypt devices" do
- let(:event) { event_for(:crypt) }
+ let(:event) { event_for(:CryptAction) }
it "does not call any additional YaST client" do
expect(Yast::WFM).to_not receive(:call)
@@ -274,6 +285,8 @@ def event_for(id)
context "in an already installed system" do
let(:install) { false }
let(:handle_args) { [event] }
+ # Ensure all actions are available
+ before { allow(Yast::Arch).to receive(:s390).and_return true }
include_examples "show configure warning"
@@ -292,8 +305,8 @@ def event_for(id)
.to receive(:CheckAndInstallPackages).with(["yast2-s390"]).ordered
expect(Yast::PackageSystem)
.to receive(:CheckAndInstallPackages).with(["yast2-fcoe-client"]).ordered
- widget.handle(event_for(:dasd))
- widget.handle(event_for(:fcoe))
+ widget.handle(event_for(:DasdAction))
+ widget.handle(event_for(:FcoeAction))
end
context "if the packages were not installed" do
@@ -306,7 +319,7 @@ def event_for(id)
let(:installed_pkgs) { true }
context "for an action performed via a separate client" do
- let(:event) { event_for(:iscsi) }
+ let(:event) { event_for(:IscsiAction) }
it "calls the corresponding YaST client" do
expect(Yast::WFM).to receive(:call).with("iscsi-client")
@@ -322,7 +335,7 @@ def event_for(id)
end
context "for activation of crypt devices" do
- let(:event) { event_for(:crypt) }
+ let(:event) { event_for(:CryptAction) }
before { allow(manager).to receive(:activate).and_return true }
it "does not call any additional YaST client" do
From fa698374eb489a81aec4baabf9e328cbe4ed87ed Mon Sep 17 00:00:00 2001
From: Ancor Gonzalez Sosa
Date: Tue, 19 Feb 2019 09:45:37 +0100
Subject: [PATCH 23/25] Version and changelog
---
package/yast2-storage-ng.changes | 6 ++++++
package/yast2-storage-ng.spec | 2 +-
2 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/package/yast2-storage-ng.changes b/package/yast2-storage-ng.changes
index 81d83abe37..1dff502f4f 100644
--- a/package/yast2-storage-ng.changes
+++ b/package/yast2-storage-ng.changes
@@ -1,3 +1,9 @@
+-------------------------------------------------------------------
+Tue Feb 19 14:40:11 UTC 2019 - ancor@suse.com
+
+- Partitioner: new option "Provide Crypt Passwords" (bsc#1113515).
+- 4.1.63
+
-------------------------------------------------------------------
Tue Feb 19 14:15:16 UTC 2019 - jlopez@suse.com
diff --git a/package/yast2-storage-ng.spec b/package/yast2-storage-ng.spec
index 254459931b..c50ccc768a 100644
--- a/package/yast2-storage-ng.spec
+++ b/package/yast2-storage-ng.spec
@@ -16,7 +16,7 @@
#
Name: yast2-storage-ng
-Version: 4.1.62
+Version: 4.1.63
Release: 0
BuildRoot: %{_tmppath}/%{name}-%{version}-build
From c1d6033079311b8d1b8660c2af2d52b3145c188d Mon Sep 17 00:00:00 2001
From: Ancor Gonzalez Sosa
Date: Tue, 19 Feb 2019 14:00:30 +0100
Subject: [PATCH 24/25] Partitioner: help text for Configure button
---
src/lib/y2partitioner/widgets/configure.rb | 14 ++++++++++++++
.../y2partitioner/widgets/rescan_devices_button.rb | 9 +++++++++
2 files changed, 23 insertions(+)
diff --git a/src/lib/y2partitioner/widgets/configure.rb b/src/lib/y2partitioner/widgets/configure.rb
index 354b7e4454..bb406b56c7 100644
--- a/src/lib/y2partitioner/widgets/configure.rb
+++ b/src/lib/y2partitioner/widgets/configure.rb
@@ -71,6 +71,20 @@ def handle(event)
:redraw
end
+ # @macro seeAbstractWidget
+ def help
+ # TRANSLATORS: help text for the Partitioner
+ _(
+ "The Configure button offers several options to activate devices " \
+ "that were not detected by the initial system analysis. After activating the " \
+ "devices of the choosen technology, the system will be rescanned and all the " \
+ "information about storage devices will be refreshed. " \
+ "Thus, the Provide Crypt Passwords option is also useful when no " \
+ "encryption is involved, to activate devices of other technologies like LVM " \
+ "or Multipath.
"
+ )
+ end
+
private
# @return [Array]
diff --git a/src/lib/y2partitioner/widgets/rescan_devices_button.rb b/src/lib/y2partitioner/widgets/rescan_devices_button.rb
index 0e7c00c48a..f9e2032a3e 100644
--- a/src/lib/y2partitioner/widgets/rescan_devices_button.rb
+++ b/src/lib/y2partitioner/widgets/rescan_devices_button.rb
@@ -52,6 +52,15 @@ def handle
:redraw
end
+ # @macro seeAbstractWidget
+ def help
+ # TRANSLATORS: help text for the Partitioner
+ _(
+ "The Rescan Devices button refreshes the information about storage " \
+ "devices.
"
+ )
+ end
+
private
def continue?
From 487f879d25b7ee1569f600e4b62c401291f6a40f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jos=C3=A9=20Iv=C3=A1n=20L=C3=B3pez=20Gonz=C3=A1lez?=
Date: Wed, 20 Feb 2019 08:44:54 +0000
Subject: [PATCH 25/25] Add missing arch mocking for bcache tests
---
test/y2partitioner/actions/controllers/bcache_test.rb | 3 +++
test/y2partitioner/actions/edit_bcache_test.rb | 3 +++
test/y2partitioner/ui_state_test.rb | 3 +++
test/y2partitioner/widgets/bcache_edit_button_test.rb | 3 +++
test/y2storage/devicegraph_test.rb | 3 +++
5 files changed, 15 insertions(+)
diff --git a/test/y2partitioner/actions/controllers/bcache_test.rb b/test/y2partitioner/actions/controllers/bcache_test.rb
index 1b3b23824f..e290206307 100644
--- a/test/y2partitioner/actions/controllers/bcache_test.rb
+++ b/test/y2partitioner/actions/controllers/bcache_test.rb
@@ -30,6 +30,9 @@
devicegraph_stub(scenario)
end
+ # Bcache is only supported on x86
+ let(:architecture) { :x86_64 }
+
subject(:controller) { described_class.new(device) }
let(:device) { nil }
diff --git a/test/y2partitioner/actions/edit_bcache_test.rb b/test/y2partitioner/actions/edit_bcache_test.rb
index 9ef27e736d..78f10a2a17 100644
--- a/test/y2partitioner/actions/edit_bcache_test.rb
+++ b/test/y2partitioner/actions/edit_bcache_test.rb
@@ -41,6 +41,9 @@
.and_return(selected_options)
end
+ # Bcache is only supported on x86
+ let(:architecture) { :x86_64 }
+
let(:dialog_result) { nil }
let(:selected_caching) { nil }
diff --git a/test/y2partitioner/ui_state_test.rb b/test/y2partitioner/ui_state_test.rb
index fe3f34eb02..1082617b07 100644
--- a/test/y2partitioner/ui_state_test.rb
+++ b/test/y2partitioner/ui_state_test.rb
@@ -223,6 +223,9 @@
end
context "when the user has opened a Bcache page" do
+ # Bcache is only supported on x86
+ let(:architecture) { :x86_64 }
+
let(:scenario) { "bcache1.xml" }
let(:device) { fake_devicegraph.find_by_name("/dev/bcache0") }
let(:another_bcache) { fake_devicegraph.find_by_name("/dev/bcache1") }
diff --git a/test/y2partitioner/widgets/bcache_edit_button_test.rb b/test/y2partitioner/widgets/bcache_edit_button_test.rb
index 312f61d1d0..0999209e94 100644
--- a/test/y2partitioner/widgets/bcache_edit_button_test.rb
+++ b/test/y2partitioner/widgets/bcache_edit_button_test.rb
@@ -32,6 +32,9 @@
allow(Y2Partitioner::Actions::EditBcache).to receive(:new).and_return(action)
end
+ # Bcache is only supported on x86
+ let(:architecture) { :x86_64 }
+
let(:action) { instance_double(Y2Partitioner::Actions::EditBcache, run: :finish) }
subject(:button) { described_class.new(device: device) }
diff --git a/test/y2storage/devicegraph_test.rb b/test/y2storage/devicegraph_test.rb
index eac82388f9..c5055b5a7a 100644
--- a/test/y2storage/devicegraph_test.rb
+++ b/test/y2storage/devicegraph_test.rb
@@ -735,6 +735,9 @@ def with_sda2_deleted(initial_graph)
fake_scenario("bcache1.xml")
end
+ # Bcache is only supported on x86
+ let(:architecture) { :x86_64 }
+
it "removes the given caching set device" do
bcache_cset = Y2Storage::BcacheCset.all(devicegraph).first
expect(bcache_cset).to_not be_nil