Merge ~dbungert/curtin:resize-no-format-action into curtin:master

Proposed by Dan Bungert
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)
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

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
Michael Hudson-Doyle (mwhudson) :
review: Needs Fixing
1bf15b7... by Dan Bungert

block/v2: combine needs and prepare resize

Revision history for this message
Dan Bungert (dbungert) :
Revision history for this message
Server Team CI bot (server-team-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Michael Hudson-Doyle (mwhudson) wrote :

LGTM

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
1diff --git a/curtin/commands/block_meta_v2.py b/curtin/commands/block_meta_v2.py
2index 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:
143diff --git a/tests/unittests/test_commands_block_meta.py b/tests/unittests/test_commands_block_meta.py
144index 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):

Subscribers

People subscribed via source and target branches