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
diff --git a/curtin/block/clear_holders.py b/curtin/block/clear_holders.py
index 08aa70a..b691841 100644
--- a/curtin/block/clear_holders.py
+++ b/curtin/block/clear_holders.py
@@ -301,9 +301,10 @@ def wipe_superblock(device):
301 # if we don't find a mapping then the mp partition has already been301 # if we don't find a mapping then the mp partition has already been
302 # wiped/removed302 # wiped/removed
303 if mp_dev:303 if mp_dev:
304 _wipe_superblock(mp_dev)304 LOG.debug('Found multipath device over %s, wiping holder %s',
305 else:305 blockdev, mp_dev)
306 _wipe_superblock(blockdev)306
307 _wipe_superblock(mp_dev if mp_dev else blockdev)
307308
308 # if we had partitions, make sure they've been removed309 # if we had partitions, make sure they've been removed
309 if partitions:310 if partitions:
diff --git a/tests/unittests/test_clear_holders.py b/tests/unittests/test_clear_holders.py
index 0a8f2da..fca5dd3 100644
--- a/tests/unittests/test_clear_holders.py
+++ b/tests/unittests/test_clear_holders.py
@@ -481,6 +481,92 @@ class TestClearHolders(CiTestCase):
481 [mock.call(devices=[self.test_blockdev])] * 2)481 [mock.call(devices=[self.test_blockdev])] * 2)
482 self.assertEqual(1, m_time.sleep.call_count)482 self.assertEqual(1, m_time.sleep.call_count)
483483
484 @mock.patch('curtin.block.clear_holders.multipath')
485 @mock.patch('curtin.block.clear_holders.is_swap_device')
486 @mock.patch('curtin.block.clear_holders.time')
487 @mock.patch('curtin.block.clear_holders.LOG')
488 @mock.patch('curtin.block.clear_holders.block')
489 def test_clear_holders_mp_enabled_not_active_wipes_dev(self, mock_block,
490 mock_log, m_time,
491 mock_swap,
492 mock_mpath):
493 """wipe_superblock wipes dev with multipath enabled but inactive."""
494 mock_swap.return_value = False
495 mock_block.sysfs_to_devpath.return_value = self.test_blockdev
496 mock_block.is_extended_partition.return_value = False
497 mock_mpath.multipath_supported.return_value = True
498 mock_mpath.find_mpath_id_by_path.return_value = None
499 mock_block.get_blockdev_for_partition.return_value = (
500 self.test_blockdev, 1)
501 mock_block.is_zfs_member.return_value = False
502 mock_block.get_sysfs_partitions.side_effect = iter([
503 ['p1', 'p2'], # has partitions before wipe
504 ['p1', 'p2'], # still has partitions after wipe
505 [], # partitions are now gone
506 ])
507 clear_holders.wipe_superblock(self.test_syspath)
508 mock_block.sysfs_to_devpath.assert_called_with(self.test_syspath)
509 mock_block.wipe_volume.assert_called_with(
510 self.test_blockdev, exclusive=True, mode='superblock', strict=True)
511
512 @mock.patch('curtin.block.clear_holders.multipath')
513 @mock.patch('curtin.block.clear_holders.is_swap_device')
514 @mock.patch('curtin.block.clear_holders.time')
515 @mock.patch('curtin.block.clear_holders.LOG')
516 @mock.patch('curtin.block.clear_holders.block')
517 def test_clear_holders_mp_disabled_wipes_dev(self, mock_block, mock_log,
518 m_time, mock_swap,
519 mock_mpath):
520 """wipe_superblock wipes blockdev with multipath disabled."""
521 mock_swap.return_value = False
522 mock_block.sysfs_to_devpath.return_value = self.test_blockdev
523 mock_block.is_extended_partition.return_value = False
524 mock_mpath.multipath_supported.return_value = False
525 mock_block.get_blockdev_for_partition.return_value = (
526 self.test_blockdev, 1)
527 mock_block.is_zfs_member.return_value = False
528 mock_block.get_sysfs_partitions.side_effect = iter([
529 ['p1', 'p2'], # has partitions before wipe
530 ['p1', 'p2'], # still has partitions after wipe
531 [], # partitions are now gone
532 ])
533 clear_holders.wipe_superblock(self.test_syspath)
534 mock_block.sysfs_to_devpath.assert_called_with(self.test_syspath)
535 mock_block.wipe_volume.assert_called_with(
536 self.test_blockdev, exclusive=True, mode='superblock', strict=True)
537
538 @mock.patch('curtin.block.clear_holders.multipath')
539 @mock.patch('curtin.block.clear_holders.is_swap_device')
540 @mock.patch('curtin.block.clear_holders.time')
541 @mock.patch('curtin.block.clear_holders.LOG')
542 @mock.patch('curtin.block.clear_holders.block')
543 def test_clear_holders_mp_enabled_and_active_wipes_dm_dev(self, mock_block,
544 mock_log, m_time,
545 mock_swap,
546 mock_mpath):
547 """wipe_superblock wipes parent mp_dev and removes from dev mapper."""
548 mock_swap.return_value = False
549 mock_block.sysfs_to_devpath.return_value = self.test_blockdev
550 mock_block.is_zfs_member.return_value = False
551 mock_block.is_extended_partition.return_value = False
552 mock_block.get_blockdev_for_partition.return_value = (
553 self.test_blockdev, 1)
554
555 mock_mpath.multipath_supported.return_value = True
556 mock_mpath.find_mpath_id_by_path.return_value = 'mpath-wark'
557 mp_dev = '/wark/dm-1'
558 mock_mpath.find_mpath_id_by_parent.return_value = (
559 'mpath-wark', mp_dev)
560 mock_mpath.is_mpath_partition.return_value = False
561 mock_block.get_sysfs_partitions.side_effect = iter([
562 [], # partitions are now gone
563 ])
564 clear_holders.wipe_superblock(self.test_syspath)
565 mock_block.sysfs_to_devpath.assert_called_with(self.test_syspath)
566 mock_block.wipe_volume.assert_called_with(
567 mp_dev, exclusive=True, mode='superblock', strict=True)
568 mock_mpath.remove_partition.assert_called_with(mp_dev)
569
484 @mock.patch('curtin.block.clear_holders.LOG')570 @mock.patch('curtin.block.clear_holders.LOG')
485 @mock.patch('curtin.block.clear_holders.block')571 @mock.patch('curtin.block.clear_holders.block')
486 @mock.patch('curtin.block.clear_holders.os')572 @mock.patch('curtin.block.clear_holders.os')

Subscribers

People subscribed via source and target branches