Merge lp:~wesley-wiedenmeier/curtin/1618429 into lp:~curtin-dev/curtin/trunk

Proposed by Wesley Wiedenmeier
Status: Merged
Merged at revision: 424
Proposed branch: lp:~wesley-wiedenmeier/curtin/1618429
Merge into: lp:~curtin-dev/curtin/trunk
Diff against target: 177 lines (+64/-30)
4 files modified
curtin/block/clear_holders.py (+10/-2)
curtin/block/mdadm.py (+18/-5)
tests/unittests/test_block_mdadm.py (+28/-23)
tests/unittests/test_clear_holders.py (+8/-0)
To merge this branch: bzr merge lp:~wesley-wiedenmeier/curtin/1618429
Reviewer Review Type Date Requested Status
Server Team CI bot continuous-integration Approve
Ryan Harper (community) Approve
Review via email: mp+304424@code.launchpad.net

Description of the change

Before clear_holders runs, it starts a mdadm --assemble in order to detect mdadm devices on the system and remove them cleanly. However, if part of a mdadm device is present, but not enough to assemble it, then this may fail. Therefore, ignore any errors encountered running mdadm --assemble for device wipe purposes.

To post a comment you must log in.
Revision history for this message
Wesley Wiedenmeier (wesley-wiedenmeier) wrote :
Revision history for this message
Wesley Wiedenmeier (wesley-wiedenmeier) wrote :
Revision history for this message
Ryan Harper (raharper) wrote :

Thanks!

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

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'curtin/block/clear_holders.py'
--- curtin/block/clear_holders.py 2016-08-11 20:41:40 +0000
+++ curtin/block/clear_holders.py 2016-09-14 19:52:48 +0000
@@ -360,8 +360,16 @@
360 prepare system for clear holders to be able to scan old devices360 prepare system for clear holders to be able to scan old devices
361 """361 """
362 # a mdadm scan has to be started in case there is a md device that needs to362 # a mdadm scan has to be started in case there is a md device that needs to
363 # be detected363 # be detected. if the scan fails, it is either because there are no mdadm
364 block.mdadm.mdadm_assemble(scan=True)364 # devices on the system, or because there is a mdadm device in a damaged
365 # state that could not be started. due to the nature of mdadm tools, it is
366 # difficult to know which is the case. if any errors did occur, then ignore
367 # them, since no action needs to be taken if there were no mdadm devices on
368 # the system, and in the case where there is some mdadm metadata on a disk,
369 # but there was not enough to start the array, the call to wipe_volume on
370 # all disks and partitions should be sufficient to remove the mdadm
371 # metadata
372 block.mdadm.mdadm_assemble(scan=True, ignore_errors=True)
365 # the bcache module needs to be present to properly detect bcache devs373 # the bcache module needs to be present to properly detect bcache devs
366 # on some systems (precise without hwe kernel) it may not be possible to374 # on some systems (precise without hwe kernel) it may not be possible to
367 # lad the bcache module bcause it is not present in the kernel. if this375 # lad the bcache module bcause it is not present in the kernel. if this
368376
=== modified file 'curtin/block/mdadm.py'
--- curtin/block/mdadm.py 2016-04-14 01:45:54 +0000
+++ curtin/block/mdadm.py 2016-09-14 19:52:48 +0000
@@ -28,7 +28,7 @@
28from subprocess import CalledProcessError28from subprocess import CalledProcessError
2929
30from curtin.block import (dev_short, dev_path, is_valid_device, sys_block_path)30from curtin.block import (dev_short, dev_path, is_valid_device, sys_block_path)
31from curtin import util31from curtin import (util, udev)
32from curtin.log import LOG32from curtin.log import LOG
3333
34NOSPARE_RAID_LEVELS = [34NOSPARE_RAID_LEVELS = [
@@ -117,21 +117,34 @@
117#117#
118118
119119
120def mdadm_assemble(md_devname=None, devices=[], spares=[], scan=False):120def mdadm_assemble(md_devname=None, devices=[], spares=[], scan=False,
121 ignore_errors=False):
121 # md_devname is a /dev/XXXX122 # md_devname is a /dev/XXXX
122 # devices is non-empty list of /dev/xxx123 # devices is non-empty list of /dev/xxx
123 # if spares is non-empt list append of /dev/xxx124 # if spares is non-empt list append of /dev/xxx
124 cmd = ["mdadm", "--assemble"]125 cmd = ["mdadm", "--assemble"]
125 if scan:126 if scan:
126 cmd += ['--scan']127 cmd += ['--scan', '-v']
127 else:128 else:
128 valid_mdname(md_devname)129 valid_mdname(md_devname)
129 cmd += [md_devname, "--run"] + devices130 cmd += [md_devname, "--run"] + devices
130 if spares:131 if spares:
131 cmd += spares132 cmd += spares
132133
133 util.subp(cmd, capture=True, rcs=[0, 1, 2])134 try:
134 util.subp(["udevadm", "settle"])135 # mdadm assemble returns 1 when no arrays are found. this might not be
136 # an error depending on the situation this function was called in, so
137 # accept a return code of 1
138 # mdadm assemble returns 2 when called on an array that is already
139 # assembled. this is not an error, so accept return code of 2
140 # all other return codes can be accepted with ignore_error set to true
141 util.subp(cmd, capture=True, rcs=[0, 1, 2])
142 except util.ProcessExecutionError:
143 LOG.warning("mdadm_assemble had unexpected return code")
144 if not ignore_errors:
145 raise
146
147 udev.udevadm_settle()
135148
136149
137def mdadm_create(md_devname, raidlevel, devices, spares=None, md_name=""):150def mdadm_create(md_devname, raidlevel, devices, spares=None, md_name=""):
138151
=== modified file 'tests/unittests/test_block_mdadm.py'
--- tests/unittests/test_block_mdadm.py 2016-04-14 01:45:54 +0000
+++ tests/unittests/test_block_mdadm.py 2016-09-14 19:52:48 +0000
@@ -2,6 +2,7 @@
2from mock import call, patch2from mock import call, patch
3from curtin.block import dev_short3from curtin.block import dev_short
4from curtin.block import mdadm4from curtin.block import mdadm
5from curtin import util
5import os6import os
6import subprocess7import subprocess
78
@@ -24,34 +25,27 @@
24 super(TestBlockMdadmAssemble, self).setUp()25 super(TestBlockMdadmAssemble, self).setUp()
25 self.add_patch('curtin.block.mdadm.util', 'mock_util')26 self.add_patch('curtin.block.mdadm.util', 'mock_util')
26 self.add_patch('curtin.block.mdadm.is_valid_device', 'mock_valid')27 self.add_patch('curtin.block.mdadm.is_valid_device', 'mock_valid')
28 self.add_patch('curtin.block.mdadm.udev', 'mock_udev')
2729
28 # Common mock settings30 # Common mock settings
29 self.mock_valid.return_value = True31 self.mock_valid.return_value = True
30 self.mock_util.lsb_release.return_value = {'codename': 'precise'}32 self.mock_util.lsb_release.return_value = {'codename': 'precise'}
31 self.mock_util.subp.side_effect = [33 self.mock_util.subp.return_value = ('', '')
32 ("", ""), # mdadm assemble
33 ("", ""), # udevadm settle
34 ]
3534
36 def test_mdadm_assemble_scan(self):35 def test_mdadm_assemble_scan(self):
37 mdadm.mdadm_assemble(scan=True)36 mdadm.mdadm_assemble(scan=True)
38 expected_calls = [37 self.mock_util.subp.assert_called_with(
39 call(["mdadm", "--assemble", "--scan"], capture=True,38 ["mdadm", "--assemble", "--scan", "-v"], capture=True,
40 rcs=[0, 1, 2]),39 rcs=[0, 1, 2])
41 call(["udevadm", "settle"]),40 self.assertTrue(self.mock_udev.udevadm_settle.called)
42 ]
43 self.mock_util.subp.assert_has_calls(expected_calls)
4441
45 def test_mdadm_assemble_md_devname(self):42 def test_mdadm_assemble_md_devname(self):
46 md_devname = "/dev/md0"43 md_devname = "/dev/md0"
47 mdadm.mdadm_assemble(md_devname=md_devname)44 mdadm.mdadm_assemble(md_devname=md_devname)
4845 self.mock_util.subp.assert_called_with(
49 expected_calls = [46 ["mdadm", "--assemble", md_devname, "--run"], capture=True,
50 call(["mdadm", "--assemble", md_devname, "--run"], capture=True,47 rcs=[0, 1, 2])
51 rcs=[0, 1, 2]),48 self.assertTrue(self.mock_udev.udevadm_settle.called)
52 call(["udevadm", "settle"]),
53 ]
54 self.mock_util.subp.assert_has_calls(expected_calls)
5549
56 def test_mdadm_assemble_md_devname_short(self):50 def test_mdadm_assemble_md_devname_short(self):
57 with self.assertRaises(ValueError):51 with self.assertRaises(ValueError):
@@ -67,12 +61,23 @@
67 md_devname = "/dev/md0"61 md_devname = "/dev/md0"
68 devices = ["/dev/vdc1", "/dev/vdd1"]62 devices = ["/dev/vdc1", "/dev/vdd1"]
69 mdadm.mdadm_assemble(md_devname=md_devname, devices=devices)63 mdadm.mdadm_assemble(md_devname=md_devname, devices=devices)
70 expected_calls = [64 self.mock_util.subp.assert_called_with(
71 call(["mdadm", "--assemble", md_devname, "--run"] + devices,65 ["mdadm", "--assemble", md_devname, "--run"] + devices,
72 capture=True, rcs=[0, 1, 2]),66 capture=True, rcs=[0, 1, 2])
73 call(["udevadm", "settle"]),67 self.assertTrue(self.mock_udev.udevadm_settle.called)
74 ]68
75 self.mock_util.subp.assert_has_calls(expected_calls)69 def test_mdadm_assemble_exec_error(self):
70
71 def _raise_pexec_error(*args, **kwargs):
72 raise util.ProcessExecutionError()
73
74 self.mock_util.ProcessExecutionError = util.ProcessExecutionError
75 self.mock_util.subp.side_effect = _raise_pexec_error
76 with self.assertRaises(util.ProcessExecutionError):
77 mdadm.mdadm_assemble(scan=True, ignore_errors=False)
78 self.mock_util.subp.assert_called_with(
79 ['mdadm', '--assemble', '--scan', '-v'], capture=True,
80 rcs=[0, 1, 2])
7681
7782
78class TestBlockMdadmCreate(MdadmTestBase):83class TestBlockMdadmCreate(MdadmTestBase):
7984
=== modified file 'tests/unittests/test_clear_holders.py'
--- tests/unittests/test_clear_holders.py 2016-08-11 20:30:27 +0000
+++ tests/unittests/test_clear_holders.py 2016-09-14 19:52:48 +0000
@@ -319,3 +319,11 @@
319 mock_gen_holders_tree.assert_called_with(device)319 mock_gen_holders_tree.assert_called_with(device)
320 mock_gen_holders_tree.return_value = self.example_holders_trees[1][1]320 mock_gen_holders_tree.return_value = self.example_holders_trees[1][1]
321 clear_holders.assert_clear(device)321 clear_holders.assert_clear(device)
322
323 @mock.patch('curtin.block.clear_holders.block.mdadm')
324 @mock.patch('curtin.block.clear_holders.util')
325 def test_start_clear_holders_deps(self, mock_util, mock_mdadm):
326 clear_holders.start_clear_holders_deps()
327 mock_mdadm.mdadm_assemble.assert_called_with(
328 scan=True, ignore_errors=True)
329 mock_util.subp.assert_called_with(['modprobe', 'bcache'], rcs=[0, 1])

Subscribers

People subscribed via source and target branches