Merge ~dbungert/curtin:resize-no-format-action into curtin:master
- Git
- lp:~dbungert/curtin
- resize-no-format-action
- Merge into master
Status: | Merged |
---|---|
Approved by: | Dan Bungert |
Approved revision: | 1bf15b791368c4acd0f4836b3adb0721c740b566 |
Merge reported by: | Server Team CI bot |
Merged at revision: | not available |
Proposed branch: | ~dbungert/curtin:resize-no-format-action |
Merge into: | curtin:master |
Diff against target: |
261 lines (+114/-51) 2 files modified
curtin/commands/block_meta_v2.py (+49/-43) tests/unittests/test_commands_block_meta.py (+65/-8) |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Server Team CI bot | continuous-integration | Approve | |
Michael Hudson-Doyle | Approve | ||
Review via email: mp+419640@code.launchpad.net |
Commit message
block/v2: handle resize when no format action
Description of the change
Server Team CI bot (server-team-bot) wrote : | # |
Michael Hudson-Doyle (mwhudson) : | # |
- 1bf15b7... by Dan Bungert
-
block/v2: combine needs and prepare resize
Dan Bungert (dbungert) : | # |
Server Team CI bot (server-team-bot) wrote : | # |
FAILED: Continuous integration, rev:92af4dc3ba8
https:/
Executed test runs:
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
Server Team CI bot (server-team-bot) wrote : | # |
PASSED: Continuous integration, rev:1bf15b79136
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
Click here to trigger a rebuild:
https:/
Preview Diff
1 | diff --git a/curtin/commands/block_meta_v2.py b/curtin/commands/block_meta_v2.py |
2 | index 2efff25..cc2639c 100644 |
3 | --- a/curtin/commands/block_meta_v2.py |
4 | +++ b/curtin/commands/block_meta_v2.py |
5 | @@ -64,13 +64,14 @@ def resize_ntfs(path, size): |
6 | util.subp(['ntfsresize', '-s', str(size), path]) |
7 | |
8 | |
9 | -def perform_resize(kname, size, direction): |
10 | +def perform_resize(kname, resize): |
11 | path = block.kname_to_path(kname) |
12 | - fstype = _get_volume_fstype(path) |
13 | - if fstype: |
14 | - LOG.debug('Resizing %s of type %s %s to %s', |
15 | - path, fstype, direction, size) |
16 | - resizers[fstype](path, size) |
17 | + fstype = resize['fstype'] |
18 | + size = resize['size'] |
19 | + direction = resize['direction'] |
20 | + LOG.debug('Resizing %s of type %s %s to %s', |
21 | + path, fstype, direction, size) |
22 | + resizers[fstype](path, size) |
23 | |
24 | |
25 | resizers = { |
26 | @@ -245,47 +246,52 @@ def _wipe_for_action(action): |
27 | return 'superblock' |
28 | |
29 | |
30 | -def _prepare_resize(entry, part_info, table): |
31 | - return { |
32 | - 'start': table.sectors2bytes(part_info['size']), |
33 | - 'end': table.sectors2bytes(entry.size), |
34 | - } |
35 | - |
36 | +def _prepare_resize(storage_config, part_action, table, part_info): |
37 | + if not part_action.get('preserve') or not part_action.get('resize'): |
38 | + return None |
39 | |
40 | -def needs_resize(storage_config, part_action, sfdisk_part_info): |
41 | - if not part_action.get('preserve'): |
42 | - return False |
43 | - if not part_action.get('resize'): |
44 | - return False |
45 | + devpath = os.path.realpath(part_info['node']) |
46 | + fstype = _get_volume_fstype(devpath) |
47 | + if fstype == '': |
48 | + return None |
49 | |
50 | volume = part_action['id'] |
51 | format_actions = select_configs(storage_config, type='format', |
52 | - volume=volume, preserve=True) |
53 | - if len(format_actions) < 1: |
54 | - return False |
55 | + volume=volume) |
56 | if len(format_actions) > 1: |
57 | raise Exception(f'too many format actions for volume {volume}') |
58 | |
59 | - if not format_actions[0].get('preserve'): |
60 | - return False |
61 | + if len(format_actions) == 1: |
62 | + if not format_actions[0].get('preserve'): |
63 | + return None |
64 | |
65 | - devpath = os.path.realpath(sfdisk_part_info['node']) |
66 | - fstype = _get_volume_fstype(devpath) |
67 | - target_fstype = format_actions[0]['fstype'] |
68 | - msg = ( |
69 | - 'Verifying %s format, expecting %s, found %s' % ( |
70 | - devpath, fstype, target_fstype)) |
71 | - LOG.debug(msg) |
72 | - if fstype != target_fstype: |
73 | - raise RuntimeError(msg) |
74 | - |
75 | - if part_action.get('resize'): |
76 | - msg = 'Resize requested for format %s' % (fstype, ) |
77 | + target_fstype = format_actions[0]['fstype'] |
78 | + msg = ( |
79 | + 'Verifying %s format, expecting %s, found %s' % ( |
80 | + devpath, fstype, target_fstype)) |
81 | LOG.debug(msg) |
82 | - if fstype not in resizers: |
83 | - raise RuntimeError(msg + ' is unsupported') |
84 | + if fstype != target_fstype: |
85 | + raise RuntimeError(msg) |
86 | |
87 | - return True |
88 | + msg = 'Resize requested for format %s' % (fstype, ) |
89 | + LOG.debug(msg) |
90 | + if fstype not in resizers: |
91 | + raise RuntimeError(msg + ' is unsupported') |
92 | + |
93 | + start = table.sectors2bytes(part_info['size']) |
94 | + end = int(util.human2bytes(part_action['size'])) |
95 | + if start > end: |
96 | + direction = 'down' |
97 | + elif start < end: |
98 | + direction = 'up' |
99 | + else: |
100 | + return None |
101 | + |
102 | + return { |
103 | + 'fstype': fstype, |
104 | + 'size': end, |
105 | + 'direction': direction, |
106 | + } |
107 | |
108 | |
109 | def verify_offset(devpath, part_action, current_info, table): |
110 | @@ -353,8 +359,8 @@ def disk_handler_v2(info, storage_config, handlers): |
111 | part_info = _find_part_info(sfdisk_info, entry.start) |
112 | partition_verify_sfdisk_v2(action, sfdisk_info['label'], part_info, |
113 | storage_config, table) |
114 | - if needs_resize(storage_config, action, part_info): |
115 | - resizes[entry.start] = _prepare_resize(entry, part_info, table) |
116 | + resizes[entry.start] = _prepare_resize(storage_config, action, |
117 | + table, part_info) |
118 | preserved_offsets.add(entry.start) |
119 | wipe = wipes[entry.start] = _wipe_for_action(action) |
120 | if wipe is not None: |
121 | @@ -375,8 +381,8 @@ def disk_handler_v2(info, storage_config, handlers): |
122 | # Do a superblock wipe of any partitions that are being deleted. |
123 | block.wipe_volume(block.kname_to_path(kname), 'superblock') |
124 | resize = resizes.get(offset_sectors) |
125 | - if resize and size > resize['end']: |
126 | - perform_resize(kname, resize['end'], 'down') |
127 | + if resize and resize['direction'] == 'down': |
128 | + perform_resize(kname, resize) |
129 | |
130 | table.apply(disk) |
131 | |
132 | @@ -387,8 +393,8 @@ def disk_handler_v2(info, storage_config, handlers): |
133 | # Wipe the new partitions as needed. |
134 | block.wipe_volume(block.kname_to_path(kname), mode) |
135 | resize = resizes.get(offset_sectors) |
136 | - if resize and resize['start'] < size: |
137 | - perform_resize(kname, resize['end'], 'up') |
138 | + if resize and resize['direction'] == 'up': |
139 | + perform_resize(kname, resize) |
140 | |
141 | # Make the names if needed |
142 | if 'name' in info: |
143 | diff --git a/tests/unittests/test_commands_block_meta.py b/tests/unittests/test_commands_block_meta.py |
144 | index 3698d32..0d73ab6 100644 |
145 | --- a/tests/unittests/test_commands_block_meta.py |
146 | +++ b/tests/unittests/test_commands_block_meta.py |
147 | @@ -2690,6 +2690,7 @@ class TestPartitionNeedsResize(CiTestCase): |
148 | self.sfdisk_part_info = { |
149 | 'node': self.devpath, |
150 | 'start': (1 << 30) // 512, |
151 | + 'size': (1 << 30) // 512, |
152 | } |
153 | self.format = { |
154 | 'id': 'id-format', |
155 | @@ -2701,6 +2702,39 @@ class TestPartitionNeedsResize(CiTestCase): |
156 | self.partition['id']: self.partition, |
157 | self.format['id']: self.format, |
158 | } |
159 | + self.table = Mock() |
160 | + self.table.sectors2bytes = lambda x: x * 512 |
161 | + |
162 | + def test_partition_resize_happy_path(self): |
163 | + self.partition['preserve'] = True |
164 | + self.partition['resize'] = True |
165 | + self.format['preserve'] = True |
166 | + self.format['fstype'] = 'ext4' |
167 | + self.m_get_volume_fstype.return_value = 'ext4' |
168 | + expected = { |
169 | + 'fstype': 'ext4', |
170 | + 'size': 5 << 30, |
171 | + 'direction': 'up', |
172 | + } |
173 | + actual = block_meta_v2._prepare_resize( |
174 | + self.storage_config, self.partition, self.table, |
175 | + self.sfdisk_part_info) |
176 | + self.assertEqual(expected, actual) |
177 | + |
178 | + def test_partition_resize_no_format_action(self): |
179 | + self.partition['preserve'] = True |
180 | + self.partition['resize'] = True |
181 | + self.storage_config = {self.partition['id']: self.partition} |
182 | + self.m_get_volume_fstype.return_value = 'ext4' |
183 | + expected = { |
184 | + 'fstype': 'ext4', |
185 | + 'size': 5 << 30, |
186 | + 'direction': 'up', |
187 | + } |
188 | + actual = block_meta_v2._prepare_resize( |
189 | + self.storage_config, self.partition, self.table, |
190 | + self.sfdisk_part_info) |
191 | + self.assertEqual(expected, actual) |
192 | |
193 | def test_partition_resize_change_fs(self): |
194 | self.partition['preserve'] = True |
195 | @@ -2709,8 +2743,8 @@ class TestPartitionNeedsResize(CiTestCase): |
196 | self.format['fstype'] = 'ext3' |
197 | self.m_get_volume_fstype.return_value = 'ext4' |
198 | with self.assertRaises(RuntimeError): |
199 | - block_meta_v2.needs_resize( |
200 | - self.storage_config, self.partition, self.sfdisk_part_info) |
201 | + block_meta_v2._prepare_resize(self.storage_config, self.partition, |
202 | + self.table, self.sfdisk_part_info) |
203 | |
204 | def test_partition_resize_unsupported_fs(self): |
205 | self.partition['preserve'] = True |
206 | @@ -2719,8 +2753,8 @@ class TestPartitionNeedsResize(CiTestCase): |
207 | self.format['fstype'] = 'reiserfs' |
208 | self.m_get_volume_fstype.return_value = 'resierfs' |
209 | with self.assertRaises(RuntimeError): |
210 | - block_meta_v2.needs_resize( |
211 | - self.storage_config, self.partition, self.sfdisk_part_info) |
212 | + block_meta_v2._prepare_resize(self.storage_config, self.partition, |
213 | + self.table, self.sfdisk_part_info) |
214 | |
215 | def test_partition_resize_format_preserve_false(self): |
216 | # though the filesystem type is not supported for resize, it's ok |
217 | @@ -2730,8 +2764,9 @@ class TestPartitionNeedsResize(CiTestCase): |
218 | self.format['preserve'] = False |
219 | self.format['fstype'] = 'reiserfs' |
220 | self.m_get_volume_fstype.return_value = 'reiserfs' |
221 | - block_meta_v2.needs_resize( |
222 | - self.storage_config, self.partition, self.sfdisk_part_info) |
223 | + self.assertIsNone( |
224 | + block_meta_v2._prepare_resize(self.storage_config, self.partition, |
225 | + self.table, self.sfdisk_part_info)) |
226 | |
227 | def test_partition_resize_partition_preserve_false(self): |
228 | # not a resize - partition is recreated |
229 | @@ -2740,8 +2775,30 @@ class TestPartitionNeedsResize(CiTestCase): |
230 | self.format['preserve'] = False |
231 | self.format['fstype'] = 'reiserfs' |
232 | self.m_get_volume_fstype.return_value = 'reiserfs' |
233 | - block_meta_v2.needs_resize( |
234 | - self.storage_config, self.partition, self.sfdisk_part_info) |
235 | + self.assertIsNone( |
236 | + block_meta_v2._prepare_resize(self.storage_config, self.partition, |
237 | + self.table, self.sfdisk_part_info)) |
238 | + |
239 | + def test_partition_resize_equal_size(self): |
240 | + # not a resize - the size is the same so leave it alone |
241 | + self.partition['preserve'] = True |
242 | + self.partition['resize'] = True |
243 | + self.partition['size'] = '1GB' |
244 | + self.format['preserve'] = True |
245 | + self.m_get_volume_fstype.return_value = 'ext4' |
246 | + self.assertIsNone( |
247 | + block_meta_v2._prepare_resize(self.storage_config, self.partition, |
248 | + self.table, self.sfdisk_part_info)) |
249 | + |
250 | + def test_partition_resize_unformatted(self): |
251 | + # not a resize - an unformatted partition has nothing to preserve |
252 | + self.partition['preserve'] = True |
253 | + self.partition['resize'] = True |
254 | + self.storage_config = {self.partition['id']: self.partition} |
255 | + self.m_get_volume_fstype.return_value = '' |
256 | + self.assertIsNone( |
257 | + block_meta_v2._prepare_resize(self.storage_config, self.partition, |
258 | + self.table, self.sfdisk_part_info)) |
259 | |
260 | |
261 | class TestPartitionVerifyFdasd(CiTestCase): |
PASSED: Continuous integration, rev:3df9c173b07 3ae683f30184007 a2c4e4c6fa0e3c /jenkins. ubuntu. com/server/ job/curtin- ci/289/ /jenkins. ubuntu. com/server/ job/curtin- ci/nodes= metal-amd64/ 289/ /jenkins. ubuntu. com/server/ job/curtin- ci/nodes= metal-arm64/ 289/ /jenkins. ubuntu. com/server/ job/curtin- ci/nodes= metal-ppc64el/ 289/ /jenkins. ubuntu. com/server/ job/curtin- ci/nodes= metal-s390x/ 289/
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
Click here to trigger a rebuild: /jenkins. ubuntu. com/server/ job/curtin- ci/289/ /rebuild
https:/