Merge ~raharper/curtin:fix/mpath-partitions-missed-wiping-devices into curtin:master

Proposed by Ryan Harper
Status: Merged
Approved by: Dan Watkins
Approved revision: 410d41920d7c1fdbe08f165bba2b93ddbce1cad6
Merge reported by: Server Team CI bot
Merged at revision: not available
Proposed branch: ~raharper/curtin:fix/mpath-partitions-missed-wiping-devices
Merge into: curtin:master
Diff against target: 115 lines (+90/-3)
2 files modified
curtin/block/clear_holders.py (+4/-3)
tests/unittests/test_clear_holders.py (+86/-0)
Reviewer Review Type Date Requested Status
Dan Watkins (community) Approve
Server Team CI bot continuous-integration Approve
Review via email: mp+378340@code.launchpad.net

Commit message

clear-holders: ensure we wipe device even if multipath enabled not not mp

On Ubuntu releases where multipath is enabled but not in-use some devices
would fail to be wiped due to logic bug. This was found in the
BcacheBasic test. Refactor this logic to ensure that we wipe either
the in-use multipath dm device or the block device value originally
supplied to the wipe function.

To post a comment you must log in.
Revision history for this message
Server Team CI bot (server-team-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
Dan Watkins (oddbloke) wrote :

Do we need a test that would catch a similar regression in future?

Revision history for this message
Ryan Harper (raharper) wrote :

On Thu, Jan 30, 2020 at 10:43 AM Dan Watkins <email address hidden>
wrote:

> Do we need a test that would catch a similar regression in future?
>

Sure, let me add a unittest; vmtests caught it but no reason not to catch
it in unittest.

> --
> https://code.launchpad.net/~raharper/curtin/+git/curtin/+merge/378340
> You are the owner of
> ~raharper/curtin:fix/mpath-partitions-missed-wiping-devices.
>

410d419... by Ryan Harper

clear-holders: add multipath related scenarios

Revision history for this message
Server Team CI bot (server-team-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
Dan Watkins (oddbloke) wrote :

Thanks!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/curtin/block/clear_holders.py b/curtin/block/clear_holders.py
2index 08aa70a..b691841 100644
3--- a/curtin/block/clear_holders.py
4+++ b/curtin/block/clear_holders.py
5@@ -301,9 +301,10 @@ def wipe_superblock(device):
6 # if we don't find a mapping then the mp partition has already been
7 # wiped/removed
8 if mp_dev:
9- _wipe_superblock(mp_dev)
10- else:
11- _wipe_superblock(blockdev)
12+ LOG.debug('Found multipath device over %s, wiping holder %s',
13+ blockdev, mp_dev)
14+
15+ _wipe_superblock(mp_dev if mp_dev else blockdev)
16
17 # if we had partitions, make sure they've been removed
18 if partitions:
19diff --git a/tests/unittests/test_clear_holders.py b/tests/unittests/test_clear_holders.py
20index 0a8f2da..fca5dd3 100644
21--- a/tests/unittests/test_clear_holders.py
22+++ b/tests/unittests/test_clear_holders.py
23@@ -481,6 +481,92 @@ class TestClearHolders(CiTestCase):
24 [mock.call(devices=[self.test_blockdev])] * 2)
25 self.assertEqual(1, m_time.sleep.call_count)
26
27+ @mock.patch('curtin.block.clear_holders.multipath')
28+ @mock.patch('curtin.block.clear_holders.is_swap_device')
29+ @mock.patch('curtin.block.clear_holders.time')
30+ @mock.patch('curtin.block.clear_holders.LOG')
31+ @mock.patch('curtin.block.clear_holders.block')
32+ def test_clear_holders_mp_enabled_not_active_wipes_dev(self, mock_block,
33+ mock_log, m_time,
34+ mock_swap,
35+ mock_mpath):
36+ """wipe_superblock wipes dev with multipath enabled but inactive."""
37+ mock_swap.return_value = False
38+ mock_block.sysfs_to_devpath.return_value = self.test_blockdev
39+ mock_block.is_extended_partition.return_value = False
40+ mock_mpath.multipath_supported.return_value = True
41+ mock_mpath.find_mpath_id_by_path.return_value = None
42+ mock_block.get_blockdev_for_partition.return_value = (
43+ self.test_blockdev, 1)
44+ mock_block.is_zfs_member.return_value = False
45+ mock_block.get_sysfs_partitions.side_effect = iter([
46+ ['p1', 'p2'], # has partitions before wipe
47+ ['p1', 'p2'], # still has partitions after wipe
48+ [], # partitions are now gone
49+ ])
50+ clear_holders.wipe_superblock(self.test_syspath)
51+ mock_block.sysfs_to_devpath.assert_called_with(self.test_syspath)
52+ mock_block.wipe_volume.assert_called_with(
53+ self.test_blockdev, exclusive=True, mode='superblock', strict=True)
54+
55+ @mock.patch('curtin.block.clear_holders.multipath')
56+ @mock.patch('curtin.block.clear_holders.is_swap_device')
57+ @mock.patch('curtin.block.clear_holders.time')
58+ @mock.patch('curtin.block.clear_holders.LOG')
59+ @mock.patch('curtin.block.clear_holders.block')
60+ def test_clear_holders_mp_disabled_wipes_dev(self, mock_block, mock_log,
61+ m_time, mock_swap,
62+ mock_mpath):
63+ """wipe_superblock wipes blockdev with multipath disabled."""
64+ mock_swap.return_value = False
65+ mock_block.sysfs_to_devpath.return_value = self.test_blockdev
66+ mock_block.is_extended_partition.return_value = False
67+ mock_mpath.multipath_supported.return_value = False
68+ mock_block.get_blockdev_for_partition.return_value = (
69+ self.test_blockdev, 1)
70+ mock_block.is_zfs_member.return_value = False
71+ mock_block.get_sysfs_partitions.side_effect = iter([
72+ ['p1', 'p2'], # has partitions before wipe
73+ ['p1', 'p2'], # still has partitions after wipe
74+ [], # partitions are now gone
75+ ])
76+ clear_holders.wipe_superblock(self.test_syspath)
77+ mock_block.sysfs_to_devpath.assert_called_with(self.test_syspath)
78+ mock_block.wipe_volume.assert_called_with(
79+ self.test_blockdev, exclusive=True, mode='superblock', strict=True)
80+
81+ @mock.patch('curtin.block.clear_holders.multipath')
82+ @mock.patch('curtin.block.clear_holders.is_swap_device')
83+ @mock.patch('curtin.block.clear_holders.time')
84+ @mock.patch('curtin.block.clear_holders.LOG')
85+ @mock.patch('curtin.block.clear_holders.block')
86+ def test_clear_holders_mp_enabled_and_active_wipes_dm_dev(self, mock_block,
87+ mock_log, m_time,
88+ mock_swap,
89+ mock_mpath):
90+ """wipe_superblock wipes parent mp_dev and removes from dev mapper."""
91+ mock_swap.return_value = False
92+ mock_block.sysfs_to_devpath.return_value = self.test_blockdev
93+ mock_block.is_zfs_member.return_value = False
94+ mock_block.is_extended_partition.return_value = False
95+ mock_block.get_blockdev_for_partition.return_value = (
96+ self.test_blockdev, 1)
97+
98+ mock_mpath.multipath_supported.return_value = True
99+ mock_mpath.find_mpath_id_by_path.return_value = 'mpath-wark'
100+ mp_dev = '/wark/dm-1'
101+ mock_mpath.find_mpath_id_by_parent.return_value = (
102+ 'mpath-wark', mp_dev)
103+ mock_mpath.is_mpath_partition.return_value = False
104+ mock_block.get_sysfs_partitions.side_effect = iter([
105+ [], # partitions are now gone
106+ ])
107+ clear_holders.wipe_superblock(self.test_syspath)
108+ mock_block.sysfs_to_devpath.assert_called_with(self.test_syspath)
109+ mock_block.wipe_volume.assert_called_with(
110+ mp_dev, exclusive=True, mode='superblock', strict=True)
111+ mock_mpath.remove_partition.assert_called_with(mp_dev)
112+
113 @mock.patch('curtin.block.clear_holders.LOG')
114 @mock.patch('curtin.block.clear_holders.block')
115 @mock.patch('curtin.block.clear_holders.os')

Subscribers

People subscribed via source and target branches