Merge ~raharper/curtin:fix/clear-holders-bcache-partitions-lp1811117 into curtin:master

Proposed by Ryan Harper
Status: Merged
Approved by: Ryan Harper
Approved revision: f451985cf2c56c58a7a20b0198f541763f27d578
Merge reported by: Server Team CI bot
Merged at revision: not available
Proposed branch: ~raharper/curtin:fix/clear-holders-bcache-partitions-lp1811117
Merge into: curtin:master
Diff against target: 303 lines (+160/-17)
9 files modified
curtin/block/__init__.py (+1/-1)
curtin/block/clear_holders.py (+6/-2)
curtin/commands/block_meta.py (+5/-4)
curtin/commands/unmount.py (+1/-6)
curtin/util.py (+5/-0)
examples/tests/bcache-partitions.yaml (+97/-0)
tests/unittests/test_commands_block_meta.py (+5/-3)
tests/vmtests/test_bcache_basic.py (+5/-1)
tests/vmtests/test_bcache_partitions.py (+35/-0)
Reviewer Review Type Date Requested Status
Server Team CI bot continuous-integration Approve
Chad Smith Approve
Review via email: mp+361795@code.launchpad.net

Commit message

clear-holders: handle FileNotFound when probing for bcache device slaves

In some cases, when detecting if a bcache has any slave devices which
need removal the path to the sysfs directory may not be found; this is
non-fatal; it indicates that the existing device has been removed by the
kernel. Allow clear-holders to tolerate this failure.

Updated curtin.block.partition_kname to indicate that bcache partitions
have 'p' in the value. This is needed for the vmtest to recreate bcache
partitions.

LP: #1811117

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
Ryan Harper (raharper) wrote :
Revision history for this message
Chad Smith (chad.smith) :
review: Needs Information
Revision history for this message
Ryan Harper (raharper) wrote :

Thanks, I'll fix most changes. Details inline.

Revision history for this message
Chad Smith (chad.smith) wrote :

LGTM +1

review: Approve
339def7... by Ryan Harper

Fix typo and drop 'error' string from debug log message.

Revision history for this message
Server Team CI bot (server-team-bot) wrote :
review: Approve (continuous-integration)
3b33671... by Ryan Harper

bcache-partitions: test XenialHWE and accept failure on 4.4 kernels.

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

vmtests: add expected_failure decorator for known broken Xenial test.

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

Testers have confirmed this branch addresses the issue. Landing.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/curtin/block/__init__.py b/curtin/block/__init__.py
2index 490c268..eb56674 100644
3--- a/curtin/block/__init__.py
4+++ b/curtin/block/__init__.py
5@@ -103,7 +103,7 @@ def partition_kname(disk_kname, partition_number):
6 """
7 Add number to disk_kname prepending a 'p' if needed
8 """
9- for dev_type in ['nvme', 'mmcblk', 'cciss', 'mpath', 'dm', 'md']:
10+ for dev_type in ['bcache', 'nvme', 'mmcblk', 'cciss', 'mpath', 'dm', 'md']:
11 if disk_kname.startswith(dev_type):
12 partition_number = "p%s" % partition_number
13 break
14diff --git a/curtin/block/clear_holders.py b/curtin/block/clear_holders.py
15index a05c9ca..05d756c 100644
16--- a/curtin/block/clear_holders.py
17+++ b/curtin/block/clear_holders.py
18@@ -130,8 +130,12 @@ def shutdown_bcache(device):
19 return
20
21 # get slaves [vdb1, vdc], allow for slaves to not have bcache dir
22- slave_paths = [get_bcache_sys_path(k, strict=False) for k in
23- os.listdir(os.path.join(device, 'slaves'))]
24+ try:
25+ slave_paths = [get_bcache_sys_path(k, strict=False) for k in
26+ os.listdir(os.path.join(device, 'slaves'))]
27+ except util.FileMissingError as e:
28+ LOG.debug('Transient race, bcache slave path not found: %s', e)
29+ slave_paths = []
30
31 # stop cacheset if it exists
32 bcache_cache_sysfs = get_bcache_using_dev(device, strict=False)
33diff --git a/curtin/commands/block_meta.py b/curtin/commands/block_meta.py
34index 8decab5..4c3a434 100644
35--- a/curtin/commands/block_meta.py
36+++ b/curtin/commands/block_meta.py
37@@ -692,13 +692,14 @@ def partition_handler(info, storage_config):
38 else:
39 raise ValueError("parent partition has invalid partition table")
40
41+ # ensure partition exists
42+ part_path = block.dev_path(block.partition_kname(disk_kname, partnumber))
43+ block.rescan_block_devices([disk])
44+ udevadm_settle(exists=part_path)
45+
46 # wipe the created partition if needed, superblocks have already been wiped
47 wipe_mode = info.get('wipe', 'superblock')
48 if wipe_mode != 'superblock':
49- part_path = block.dev_path(block.partition_kname(disk_kname,
50- partnumber))
51- block.rescan_block_devices([disk])
52- udevadm_settle(exists=part_path)
53 LOG.debug('Wiping partition %s mode=%s', part_path, wipe_mode)
54 block.wipe_volume(part_path, mode=wipe_mode, exclusive=False)
55
56diff --git a/curtin/commands/unmount.py b/curtin/commands/unmount.py
57index defaae4..602fcb2 100644
58--- a/curtin/commands/unmount.py
59+++ b/curtin/commands/unmount.py
60@@ -6,11 +6,6 @@ from . import populate_one_subcmd
61
62 import os
63
64-try:
65- FileMissingError = FileNotFoundError
66-except NameError:
67- FileMissingError = IOError
68-
69
70 def unmount_main(args):
71 """
72@@ -22,7 +17,7 @@ def unmount_main(args):
73
74 if not os.path.exists(args.target):
75 msg = "Cannot unmount target path %s: it does not exist" % args.target
76- raise FileMissingError(msg)
77+ raise util.FileMissingError(msg)
78
79 LOG.info("Unmounting devices from target path: %s", args.target)
80 recursive_mode = not args.disable_recursive_mounts
81diff --git a/curtin/util.py b/curtin/util.py
82index 238d7c5..35e004f 100644
83--- a/curtin/util.py
84+++ b/curtin/util.py
85@@ -37,6 +37,11 @@ except NameError:
86 # python3 does not have a long type.
87 numeric_types = (int, float)
88
89+try:
90+ FileMissingError = FileNotFoundError
91+except NameError:
92+ FileMissingError = IOError
93+
94 from . import paths
95 from .log import LOG, log_call
96
97diff --git a/examples/tests/bcache-partitions.yaml b/examples/tests/bcache-partitions.yaml
98new file mode 100644
99index 0000000..20ccddc
100--- /dev/null
101+++ b/examples/tests/bcache-partitions.yaml
102@@ -0,0 +1,97 @@
103+showtrace: true
104+
105+storage:
106+ config:
107+ - id: id_rotary0
108+ type: disk
109+ name: rotary0
110+ serial: disk-a
111+ ptable: msdos
112+ wipe: superblock
113+ grub_device: true
114+ - id: id_ssd0
115+ type: disk
116+ name: ssd0
117+ serial: disk-b
118+ wipe: superblock
119+ - id: id_rotary1
120+ type: disk
121+ name: rotary1
122+ serial: disk-c
123+ ptable: gpt
124+ wipe: superblock
125+ - id: id_rotary0_part1
126+ type: partition
127+ name: rotary0-part1
128+ device: id_rotary0
129+ number: 1
130+ offset: 1M
131+ size: 999M
132+ wipe: superblock
133+ - id: id_rotary0_part2
134+ type: partition
135+ name: rotary0-part2
136+ device: id_rotary0
137+ number: 2
138+ size: 9G
139+ wipe: superblock
140+ - id: id_bcache0
141+ type: bcache
142+ name: bcache0
143+ backing_device: id_rotary0_part2
144+ cache_device: id_ssd0
145+ cache_mode: writeback
146+ - id: id_bcache1
147+ type: bcache
148+ name: bcache1
149+ backing_device: id_rotary1
150+ cache_device: id_ssd0
151+ cache_mode: writeback
152+ - id: id_bcache1_disk
153+ type: disk
154+ path: /dev/bcache1
155+ ptable: gpt
156+ - id: id_bcache1_part1
157+ type: partition
158+ device: id_bcache1_disk
159+ number: 1
160+ offset: 1M
161+ size: 1G
162+ wipe: superblock
163+ - id: id_bcache1_part2
164+ type: partition
165+ device: id_bcache1_disk
166+ number: 2
167+ size: 1G
168+ wipe: superblock
169+ - id: id_bcache1_part3
170+ type: partition
171+ device: id_bcache1_disk
172+ number: 3
173+ size: 1G
174+ wipe: superblock
175+ - id: id_bcache1_part4
176+ type: partition
177+ device: id_bcache1_disk
178+ number: 4
179+ size: 1G
180+ wipe: superblock
181+ - id: bootfs
182+ type: format
183+ label: boot-fs
184+ volume: id_rotary0_part1
185+ fstype: ext4
186+ - id: rootfs
187+ type: format
188+ label: root-fs
189+ volume: id_bcache0
190+ fstype: ext4
191+ - id: rootfs_mount
192+ type: mount
193+ path: /
194+ device: rootfs
195+ - id: bootfs_mount
196+ type: mount
197+ path: /boot
198+ device: bootfs
199+ version: 1
200diff --git a/tests/unittests/test_commands_block_meta.py b/tests/unittests/test_commands_block_meta.py
201index 45b9906..acb0d29 100644
202--- a/tests/unittests/test_commands_block_meta.py
203+++ b/tests/unittests/test_commands_block_meta.py
204@@ -146,6 +146,8 @@ class TestBlockMeta(CiTestCase):
205 'mock_block_get_volume_uuid')
206 self.add_patch('curtin.block.zero_file_at_offsets',
207 'mock_block_zero_file')
208+ self.add_patch('curtin.block.rescan_block_devices',
209+ 'mock_block_rescan')
210
211 self.target = "my_target"
212 self.config = {
213@@ -225,9 +227,9 @@ class TestBlockMeta(CiTestCase):
214 part_offset = 2048 * 512
215 self.mock_block_zero_file.assert_called_with(disk_kname, [part_offset],
216 exclusive=False)
217- self.mock_subp.assert_called_with(['parted', disk_kname, '--script',
218- 'mkpart', 'primary', '2048s',
219- '1001471s'], capture=True)
220+ self.mock_subp.assert_has_calls(
221+ [call(['parted', disk_kname, '--script',
222+ 'mkpart', 'primary', '2048s', '1001471s'], capture=True)])
223
224 @patch('curtin.util.write_file')
225 def test_mount_handler_defaults(self, mock_write_file):
226diff --git a/tests/vmtests/test_bcache_basic.py b/tests/vmtests/test_bcache_basic.py
227index a62fb17..b6044d4 100644
228--- a/tests/vmtests/test_bcache_basic.py
229+++ b/tests/vmtests/test_bcache_basic.py
230@@ -1,6 +1,6 @@
231 # This file is part of curtin. See LICENSE file for copyright and license info.
232
233-from . import VMBaseClass
234+from . import VMBaseClass, skip_if_flag
235 from .releases import base_vm_classes as relbase
236
237 import textwrap
238@@ -24,10 +24,12 @@ class TestBcacheBasic(VMBaseClass):
239 exit 0
240 """)]
241
242+ @skip_if_flag('expected_failure')
243 def test_bcache_output_files_exist(self):
244 self.output_files_exist(["bcache_super_vda2", "bcache_ls",
245 "bcache_cache_mode"])
246
247+ @skip_if_flag('expected_failure')
248 def test_bcache_status(self):
249 bcache_cset_uuid = None
250 for line in self.load_collect_file("bcache_super_vda2").splitlines():
251@@ -37,9 +39,11 @@ class TestBcacheBasic(VMBaseClass):
252 self.assertTrue(bcache_cset_uuid in
253 self.load_collect_file("bcache_ls").splitlines())
254
255+ @skip_if_flag('expected_failure')
256 def test_bcache_cachemode(self):
257 self.check_file_regex("bcache_cache_mode", r"\[writeback\]")
258
259+ @skip_if_flag('expected_failure')
260 def test_proc_cmdline_root_by_uuid(self):
261 self.check_file_regex("proc_cmdline", r"root=UUID=")
262
263diff --git a/tests/vmtests/test_bcache_partitions.py b/tests/vmtests/test_bcache_partitions.py
264new file mode 100644
265index 0000000..ff86b51
266--- /dev/null
267+++ b/tests/vmtests/test_bcache_partitions.py
268@@ -0,0 +1,35 @@
269+# This file is part of curtin. See LICENSE file for copyright and license info.
270+
271+from .releases import base_vm_classes as relbase
272+from .test_bcache_basic import TestBcacheBasic
273+
274+
275+class TestBcachePartitions(TestBcacheBasic):
276+ conf_file = "examples/tests/bcache-partitions.yaml"
277+ dirty_disks = True
278+ nr_cpus = 2
279+ extra_disks = ['10G', '10G']
280+
281+
282+class XenialTestBcachePartitions(relbase.xenial, TestBcachePartitions):
283+ # Xenial 4.4 kernel does not support bcache partitions
284+ expected_failure = True
285+ __test__ = True
286+
287+
288+class XenialHWETestBcachePartitions(relbase.xenial_hwe, TestBcachePartitions):
289+ __test__ = True
290+
291+
292+class BionicTestBcachePartitions(relbase.bionic, TestBcachePartitions):
293+ __test__ = True
294+
295+
296+class CosmicTestBcachePartitions(relbase.cosmic, TestBcachePartitions):
297+ __test__ = True
298+
299+
300+class DiscoTestBcachePartitions(relbase.disco, TestBcachePartitions):
301+ __test__ = True
302+
303+# vi: ts=4 expandtab syntax=python

Subscribers

People subscribed via source and target branches