Merge lp:~trapnine/maas/fix-1513085-1.9 into lp:maas/1.9

Proposed by Jeffrey C Jones
Status: Merged
Approved by: Lee Trager
Approved revision: no longer in the source branch.
Merged at revision: 4501
Proposed branch: lp:~trapnine/maas/fix-1513085-1.9
Merge into: lp:maas/1.9
Diff against target: 1347 lines (+256/-192)
21 files modified
src/maasserver/api/tests/test_raid.py (+6/-12)
src/maasserver/api/tests/test_volume_groups.py (+13/-4)
src/maasserver/forms.py (+2/-1)
src/maasserver/models/blockdevice.py (+1/-1)
src/maasserver/models/partition.py (+7/-7)
src/maasserver/models/partitiontable.py (+21/-17)
src/maasserver/models/tests/test_blockdevice.py (+4/-2)
src/maasserver/models/tests/test_filesystemgroup.py (+27/-33)
src/maasserver/models/tests/test_partition.py (+9/-8)
src/maasserver/models/tests/test_partitiontable.py (+27/-18)
src/maasserver/models/virtualblockdevice.py (+21/-11)
src/maasserver/testing/factory.py (+1/-3)
src/maasserver/tests/test_forms_blockdevice.py (+5/-1)
src/maasserver/tests/test_forms_partition.py (+5/-5)
src/maasserver/tests/test_forms_raid.py (+5/-9)
src/maasserver/tests/test_forms_volume_group.py (+7/-2)
src/maasserver/tests/test_preseed_storage.py (+14/-14)
src/maasserver/tests/test_storage_layouts.py (+43/-32)
src/maasserver/utils/converters.py (+5/-3)
src/maasserver/utils/tests/test_converters.py (+22/-6)
src/maasserver/websockets/handlers/tests/test_node.py (+11/-3)
To merge this branch: bzr merge lp:~trapnine/maas/fix-1513085-1.9
Reviewer Review Type Date Requested Status
Mike Pontillo (community) Approve
Review via email: mp+277771@code.launchpad.net

Commit message

Align partitions and logical volumes to 4MiB.

To post a comment you must log in.
Revision history for this message
Mike Pontillo (mpontillo) wrote :

Approving this since it is a backport from an approved branch on trunk.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/maasserver/api/tests/test_raid.py'
2--- src/maasserver/api/tests/test_raid.py 2015-10-28 17:32:43 +0000
3+++ src/maasserver/api/tests/test_raid.py 2015-11-17 23:23:01 +0000
4@@ -403,10 +403,8 @@
5 (parsed_block_devices, parsed_partitions,
6 parsed_block_device_spares, parsed_partition_spares) = (
7 get_devices_from_raid(parsed_device))
8- # Size is equivalent to 7 devices of 9 TB each.
9- self.assertEqual(
10- 7 * ((9 * 1000 ** 4) - PARTITION_TABLE_EXTRA_SPACE),
11- parsed_device['size'])
12+ # Size is equivalent to 7 of the smallest device (the partitions).
13+ self.assertEqual(7 * large_partitions[0].size, parsed_device['size'])
14 self.assertItemsEqual(block_devices, parsed_block_devices)
15 self.assertItemsEqual(partitions, parsed_partitions)
16 self.assertItemsEqual(spare_devices, parsed_block_device_spares)
17@@ -450,10 +448,8 @@
18 (parsed_block_devices, parsed_partitions,
19 parsed_block_device_spares, parsed_partition_spares) = (
20 get_devices_from_raid(parsed_device))
21- # Size is equivalent to 6 devices of 9 TB each.
22- self.assertEqual(
23- 6 * ((9 * 1000 ** 4) - PARTITION_TABLE_EXTRA_SPACE),
24- parsed_device['size'])
25+ # Size is equivalent to 6 of the smallest device (the partitions).
26+ self.assertEqual(6 * large_partitions[0].size, parsed_device['size'])
27 self.assertItemsEqual(block_devices, parsed_block_devices)
28 self.assertItemsEqual(partitions, parsed_partitions)
29 self.assertItemsEqual(spare_devices, parsed_block_device_spares)
30@@ -497,10 +493,8 @@
31 (parsed_block_devices, parsed_partitions,
32 parsed_block_device_spares, parsed_partition_spares) = (
33 get_devices_from_raid(parsed_device))
34- # Size is equivalent to 4 devices of 9 TB each.
35- self.assertEqual(
36- 4 * ((9 * 1000 ** 4) - PARTITION_TABLE_EXTRA_SPACE),
37- parsed_device['size'])
38+ # Size is equivalent to 4 of the smallest device (the partitions).
39+ self.assertEqual(4 * large_partitions[0].size, parsed_device['size'])
40 self.assertItemsEqual(block_devices, parsed_block_devices)
41 self.assertItemsEqual(partitions, parsed_partitions)
42 self.assertItemsEqual(spare_devices, parsed_block_device_spares)
43
44=== modified file 'src/maasserver/api/tests/test_volume_groups.py'
45--- src/maasserver/api/tests/test_volume_groups.py 2015-09-24 16:22:12 +0000
46+++ src/maasserver/api/tests/test_volume_groups.py 2015-11-17 23:23:01 +0000
47@@ -26,11 +26,18 @@
48 NODE_STATUS,
49 )
50 from maasserver.models.blockdevice import MIN_BLOCK_DEVICE_SIZE
51+from maasserver.models.partition import (
52+ MIN_PARTITION_SIZE,
53+ PARTITION_ALIGNMENT_SIZE,
54+)
55 from maasserver.models.partitiontable import PARTITION_TABLE_EXTRA_SPACE
56 from maasserver.testing.api import APITestCase
57 from maasserver.testing.factory import factory
58 from maasserver.testing.orm import reload_object
59-from maasserver.utils.converters import human_readable_bytes
60+from maasserver.utils.converters import (
61+ human_readable_bytes,
62+ round_size_to_nearest_block,
63+)
64 from testtools.matchers import (
65 ContainsDict,
66 Equals,
67@@ -132,11 +139,11 @@
68 ]
69 block_device = factory.make_PhysicalBlockDevice(
70 node=node,
71- size=(MIN_BLOCK_DEVICE_SIZE * 3) + PARTITION_TABLE_EXTRA_SPACE)
72+ size=MIN_PARTITION_SIZE * 3 + PARTITION_TABLE_EXTRA_SPACE)
73 partition_table = factory.make_PartitionTable(
74 block_device=block_device)
75 partitions = [
76- partition_table.add_partition(size=MIN_BLOCK_DEVICE_SIZE)
77+ partition_table.add_partition(size=MIN_PARTITION_SIZE)
78 for _ in range(2)
79 ]
80 partition_ids = [
81@@ -411,10 +418,12 @@
82 })
83 self.assertEqual(httplib.OK, response.status_code, response.content)
84 logical_volume = json.loads(response.content)
85+ expected_size = round_size_to_nearest_block(
86+ size, PARTITION_ALIGNMENT_SIZE, False)
87 self.assertThat(logical_volume, ContainsDict({
88 "name": Equals("%s-%s" % (volume_group.name, name)),
89 "uuid": Equals(vguuid),
90- "size": Equals(size),
91+ "size": Equals(expected_size),
92 }))
93
94 def test_delete_logical_volume_204_when_invalid_id(self):
95
96=== modified file 'src/maasserver/forms.py'
97--- src/maasserver/forms.py 2015-11-02 16:32:29 +0000
98+++ src/maasserver/forms.py 2015-11-17 23:23:01 +0000
99@@ -154,6 +154,7 @@
100 nodegroup_fqdn,
101 )
102 from maasserver.models.nodegroup import NODEGROUP_CLUSTER_NAME_TEMPLATE
103+from maasserver.models.partition import MIN_PARTITION_SIZE
104 from maasserver.models.subnet import (
105 create_cidr,
106 Subnet,
107@@ -3253,7 +3254,7 @@
108 This needs to be done on the fly so that we can pass the maximum size.
109 """
110 self.fields['size'] = BytesField(
111- min_value=MIN_BLOCK_DEVICE_SIZE,
112+ min_value=MIN_PARTITION_SIZE,
113 max_value=self.block_device.size,
114 required=True)
115
116
117=== modified file 'src/maasserver/models/blockdevice.py'
118--- src/maasserver/models/blockdevice.py 2015-10-28 01:59:30 +0000
119+++ src/maasserver/models/blockdevice.py 2015-11-17 23:23:01 +0000
120@@ -51,7 +51,7 @@
121 )
122
123
124-MIN_BLOCK_DEVICE_SIZE = 2 * 1024 * 1024 # 2MiB
125+MIN_BLOCK_DEVICE_SIZE = 4 * 1024 * 1024 # 4MiB
126 MIN_BLOCK_DEVICE_BLOCK_SIZE = 512 # A ProDOS block
127
128
129
130=== modified file 'src/maasserver/models/partition.py'
131--- src/maasserver/models/partition.py 2015-10-20 15:02:19 +0000
132+++ src/maasserver/models/partition.py 2015-11-17 23:23:01 +0000
133@@ -32,7 +32,6 @@
134 from django.dispatch import receiver
135 from maasserver import DefaultMeta
136 from maasserver.enum import PARTITION_TABLE_TYPE
137-from maasserver.models.blockdevice import MIN_BLOCK_DEVICE_SIZE
138 from maasserver.models.cleansave import CleanSave
139 from maasserver.models.timestampedmodel import TimestampedModel
140 from maasserver.utils.converters import (
141@@ -45,8 +44,10 @@
142 )
143
144
145-MIN_PARTITION_SIZE = MIN_BLOCK_DEVICE_SIZE
146 MAX_PARTITION_SIZE_FOR_MBR = (((2 ** 32) - 1) * 512) - (1024 ** 2) # 2 TiB
147+# All partitions are aligned down to 4MiB blocks for performance (lp:1513085)
148+PARTITION_ALIGNMENT_SIZE = 4 * 1024 * 1024
149+MIN_PARTITION_SIZE = PARTITION_ALIGNMENT_SIZE
150
151
152 class PartitionManager(Manager):
153@@ -216,17 +217,16 @@
154 bd=self.partition_table.block_device.__unicode__())
155
156 def _round_size(self):
157- """Round the size of this partition to the nearest block."""
158+ """Round the size of this partition down for alignment."""
159 if self.size is not None and self.partition_table is not None:
160 self.size = round_size_to_nearest_block(
161- self.size, self.partition_table.get_block_size())
162+ self.size, PARTITION_ALIGNMENT_SIZE, False)
163
164 @classmethod
165 def _get_mbr_max_for_block_device(self, block_device):
166 """Get the maximum partition size for MBR for this block device."""
167- block_size = block_device.block_size
168- number_of_blocks = MAX_PARTITION_SIZE_FOR_MBR / block_size
169- return block_size * (number_of_blocks - 1)
170+ return round_size_to_nearest_block(
171+ MAX_PARTITION_SIZE_FOR_MBR, PARTITION_ALIGNMENT_SIZE, False)
172
173 def _get_mbr_max_for_partition(self):
174 """Get the maximum partition size for MBR for this partition."""
175
176=== modified file 'src/maasserver/models/partitiontable.py'
177--- src/maasserver/models/partitiontable.py 2015-11-04 04:27:46 +0000
178+++ src/maasserver/models/partitiontable.py 2015-11-17 23:23:01 +0000
179@@ -29,13 +29,17 @@
180 )
181 from maasserver.models.blockdevice import BlockDevice
182 from maasserver.models.cleansave import CleanSave
183-from maasserver.models.partition import Partition
184+from maasserver.models.partition import (
185+ Partition,
186+ PARTITION_ALIGNMENT_SIZE,
187+)
188 from maasserver.models.timestampedmodel import TimestampedModel
189 from maasserver.utils.converters import round_size_to_nearest_block
190
191-# The first partition on the disk must start at 2MiB, as all previous bytes
192-# will be used by the partition table and grub.
193-INITIAL_PARTITION_OFFSET = 2 * 1024 * 1024
194+# The first 2MiB of the device are used by the partition table and grub. We'll
195+# reserve the first 4MiB to make sure all partitions stay aligned to 4MB across
196+# the device.
197+INITIAL_PARTITION_OFFSET = 4 * 1024 * 1024
198
199 # An additional 1MiB of space is left open at the end of the disk to allow for
200 # the extra MBR table.
201@@ -67,11 +71,11 @@
202 return self.block_device.node
203
204 def get_size(self):
205- """Size of partition table."""
206- return (
207- self.block_device.size -
208- round_size_to_nearest_block(
209- PARTITION_TABLE_EXTRA_SPACE, self.get_block_size()))
210+ """Total usable size of partition table."""
211+ return round_size_to_nearest_block(
212+ self.block_device.size - PARTITION_TABLE_EXTRA_SPACE,
213+ PARTITION_ALIGNMENT_SIZE,
214+ False)
215
216 def get_block_size(self):
217 """Block size of partition table."""
218@@ -89,15 +93,15 @@
219 if used_size is None:
220 used_size = 0
221 # The extra space taken by the partition table header is used space.
222- used_size += round_size_to_nearest_block(
223- PARTITION_TABLE_EXTRA_SPACE, self.get_block_size())
224- return round_size_to_nearest_block(
225- used_size, self.get_block_size())
226+ return used_size + PARTITION_TABLE_EXTRA_SPACE
227
228 def get_available_size(self, ignore_partitions=[]):
229 """Return the remaining size available for partitions."""
230 used_size = self.get_used_size(ignore_partitions=ignore_partitions)
231- return self.block_device.size - used_size
232+ # Only report 'alignable' space as available for new partitions
233+ return round_size_to_nearest_block(
234+ self.block_device.size - used_size,
235+ PARTITION_ALIGNMENT_SIZE, False)
236
237 def add_partition(self, size=None, bootable=False, uuid=None):
238 """Adds a partition to this partition table, returns the added
239@@ -105,15 +109,15 @@
240
241 If size is omitted, the partition will extend to the end of the device.
242
243- If size is not a multiple of the device's block size, the size will be
244- rounded up to the next multiple.
245+ All partition sizes will be aligned down to PARTITION_ALIGNMENT_SIZE.
246 """
247 if size is None:
248 size = self.get_available_size()
249 if self.table_type == PARTITION_TABLE_TYPE.MBR:
250 size = min(size, Partition._get_mbr_max_for_block_device(
251 self.block_device))
252- size = round_size_to_nearest_block(size, self.get_block_size())
253+ size = round_size_to_nearest_block(
254+ size, PARTITION_ALIGNMENT_SIZE, False)
255 return Partition.objects.create(
256 partition_table=self, size=size, uuid=uuid, bootable=bootable)
257
258
259=== modified file 'src/maasserver/models/tests/test_blockdevice.py'
260--- src/maasserver/models/tests/test_blockdevice.py 2015-10-28 01:59:30 +0000
261+++ src/maasserver/models/tests/test_blockdevice.py 2015-11-17 23:23:01 +0000
262@@ -34,6 +34,7 @@
263 VirtualBlockDevice,
264 VolumeGroup,
265 )
266+from maasserver.models.partition import PARTITION_ALIGNMENT_SIZE
267 from maasserver.testing.factory import factory
268 from maasserver.testing.orm import reload_object
269 from maasserver.testing.testcase import MAASServerTestCase
270@@ -428,8 +429,9 @@
271 boot_disk = factory.make_PhysicalBlockDevice(node=node)
272 partition = boot_disk.create_partition_if_boot_disk()
273 self.assertIsNotNone(partition)
274- self.assertEquals(
275- boot_disk.get_available_size(), 0,
276+ available_size = boot_disk.get_available_size()
277+ self.assertTrue(
278+ available_size >= 0 and available_size < PARTITION_ALIGNMENT_SIZE,
279 "Should create a partition for the entire disk.")
280
281
282
283=== modified file 'src/maasserver/models/tests/test_filesystemgroup.py'
284--- src/maasserver/models/tests/test_filesystemgroup.py 2015-11-10 16:55:24 +0000
285+++ src/maasserver/models/tests/test_filesystemgroup.py 2015-11-17 23:23:01 +0000
286@@ -43,6 +43,7 @@
287 VolumeGroup,
288 VolumeGroupManager,
289 )
290+from maasserver.models.partition import PARTITION_ALIGNMENT_SIZE
291 from maasserver.models.partitiontable import PARTITION_TABLE_EXTRA_SPACE
292 from maasserver.models.physicalblockdevice import PhysicalBlockDevice
293 from maasserver.models.virtualblockdevice import VirtualBlockDevice
294@@ -52,7 +53,10 @@
295 reload_objects,
296 )
297 from maasserver.testing.testcase import MAASServerTestCase
298-from maasserver.utils.converters import machine_readable_bytes
299+from maasserver.utils.converters import (
300+ machine_readable_bytes,
301+ round_size_to_nearest_block,
302+)
303 from maastesting.matchers import (
304 MockCalledOnceWith,
305 MockNotCalled,
306@@ -327,13 +331,16 @@
307 [filesystem_group.id], result_filesystem_group_ids)
308
309 def test__bcache_on_partitions(self):
310- block_device = factory.make_PhysicalBlockDevice()
311+ device_size = random.randint(
312+ MIN_BLOCK_DEVICE_SIZE * 4, MIN_BLOCK_DEVICE_SIZE * 1024)
313+ block_device = factory.make_PhysicalBlockDevice(
314+ size=device_size + PARTITION_TABLE_EXTRA_SPACE)
315 partition_table = factory.make_PartitionTable(
316 block_device=block_device)
317 partition_one = factory.make_Partition(
318- partition_table=partition_table)
319+ partition_table=partition_table, size=device_size / 2)
320 partition_two = factory.make_Partition(
321- partition_table=partition_table)
322+ partition_table=partition_table, size=device_size / 2)
323 cache_set = factory.make_CacheSet(partition=partition_one)
324 filesystem_backing = factory.make_Filesystem(
325 fstype=FILESYSTEM_TYPE.BCACHE_BACKING, partition=partition_two)
326@@ -1324,9 +1331,11 @@
327 factory.make_VirtualBlockDevice(
328 filesystem_group=fsgroup, size=5 * 1000 ** 3)
329
330- self.assertEqual(40 * 1000 ** 3, fsgroup.get_lvm_allocated_size())
331+ expected_size = round_size_to_nearest_block(
332+ 40 * 1000 ** 3, PARTITION_ALIGNMENT_SIZE, False)
333+ self.assertEqual(expected_size, fsgroup.get_lvm_allocated_size())
334 self.assertEqual(
335- usable_size - (40 * 1000 ** 3), fsgroup.get_lvm_free_space())
336+ usable_size - expected_size, fsgroup.get_lvm_free_space())
337
338 def test_get_virtual_block_device_block_size_returns_backing_for_bc(self):
339 # This test is not included in the scenario below
340@@ -1567,10 +1576,12 @@
341 logical_volume = volume_group.create_logical_volume(
342 name=name, uuid=vguuid, size=size)
343 logical_volume = reload_object(logical_volume)
344+ expected_size = round_size_to_nearest_block(
345+ size, PARTITION_ALIGNMENT_SIZE, False)
346 self.assertThat(logical_volume, MatchesStructure.byEquality(
347 name=name,
348 uuid=vguuid,
349- size=size,
350+ size=expected_size,
351 block_size=volume_group.get_virtual_block_device_block_size(),
352 ))
353
354@@ -1597,8 +1608,6 @@
355 bd.get_partitiontable().add_partition()
356 for bd in block_devices[5:]
357 ]
358- # Partition size will be smaller than the disk, because of overhead.
359- partition_size = device_size - PARTITION_TABLE_EXTRA_SPACE
360 spare_block_device = block_devices[0]
361 spare_partition = partitions[0]
362 uuid = unicode(uuid4())
363@@ -1611,7 +1620,7 @@
364 spare_devices=[spare_block_device],
365 spare_partitions=[spare_partition])
366 self.assertEqual('md0', raid.name)
367- self.assertEqual(6 * partition_size, raid.get_size())
368+ self.assertEqual(6 * partitions[1].size, raid.get_size())
369 self.assertEqual(FILESYSTEM_GROUP_TYPE.RAID_6, raid.group_type)
370 self.assertEqual(uuid, raid.uuid)
371 self.assertEqual(10, raid.filesystems.count())
372@@ -1689,7 +1698,6 @@
373 for bd in block_devices[5:]
374 ]
375 # Partition size will be smaller than the disk, because of overhead.
376- partition_size = device_size - PARTITION_TABLE_EXTRA_SPACE
377 spare_block_device = block_devices[0]
378 spare_partition = partitions[0]
379 uuid = unicode(uuid4())
380@@ -1702,7 +1710,7 @@
381 spare_devices=[spare_block_device],
382 spare_partitions=[spare_partition])
383 self.assertEqual('md0', raid.name)
384- self.assertEqual(partition_size, raid.get_size())
385+ self.assertEqual(partitions[1].size, raid.get_size())
386 self.assertEqual(FILESYSTEM_GROUP_TYPE.RAID_1, raid.group_type)
387 self.assertEqual(uuid, raid.uuid)
388 self.assertEqual(10, raid.filesystems.count())
389@@ -1742,8 +1750,6 @@
390 bd.get_partitiontable().add_partition()
391 for bd in block_devices[5:]
392 ]
393- # Partition size will be smaller than the disk, because of overhead.
394- partition_size = device_size - PARTITION_TABLE_EXTRA_SPACE
395 spare_block_device = block_devices[0]
396 spare_partition = partitions[0]
397 uuid = unicode(uuid4())
398@@ -1756,7 +1762,7 @@
399 spare_devices=[spare_block_device],
400 spare_partitions=[spare_partition])
401 self.assertEqual('md0', raid.name)
402- self.assertEqual(7 * partition_size, raid.get_size())
403+ self.assertEqual(7 * partitions[1].size, raid.get_size())
404 self.assertEqual(FILESYSTEM_GROUP_TYPE.RAID_5, raid.group_type)
405 self.assertEqual(uuid, raid.uuid)
406 self.assertEqual(10, raid.filesystems.count())
407@@ -1906,11 +1912,9 @@
408 partition = factory.make_PartitionTable(
409 block_device=factory.make_PhysicalBlockDevice(
410 node=node, size=device_size)).add_partition()
411- # Partition size will be smaller than the disk, because of overhead.
412- partition_size = device_size - PARTITION_TABLE_EXTRA_SPACE
413 raid.add_partition(partition, FILESYSTEM_TYPE.RAID)
414 self.assertEqual(11, raid.filesystems.count())
415- self.assertEqual(10 * partition_size, raid.get_size())
416+ self.assertEqual(10 * partition.size, raid.get_size())
417
418 def test_add_spare_partition_to_array(self):
419 node = factory.make_Node()
420@@ -1928,11 +1932,9 @@
421 partition = factory.make_PartitionTable(
422 block_device=factory.make_PhysicalBlockDevice(
423 node=node, size=device_size)).add_partition()
424- # Partition size will be smaller than the disk, because of overhead.
425- partition_size = device_size - PARTITION_TABLE_EXTRA_SPACE
426 raid.add_partition(partition, FILESYSTEM_TYPE.RAID_SPARE)
427 self.assertEqual(11, raid.filesystems.count())
428- self.assertEqual(9 * partition_size, raid.get_size())
429+ self.assertEqual(9 * partition.size, raid.get_size())
430
431 def test_add_device_from_another_node_to_array_fails(self):
432 node = factory.make_Node()
433@@ -2054,8 +2056,6 @@
434 node=node, size=device_size)).add_partition()
435 for _ in range(4)
436 ]
437- # Partition size will be smaller than the disk, because of overhead.
438- partition_size = device_size - PARTITION_TABLE_EXTRA_SPACE
439 uuid = unicode(uuid4())
440 raid = RAID.objects.create_raid(
441 name='md0',
442@@ -2070,7 +2070,7 @@
443 "devices and any number of spares.']}")):
444 raid.remove_partition(partitions[0])
445 self.assertEqual(4, raid.filesystems.count())
446- self.assertEqual(2 * partition_size, raid.get_size())
447+ self.assertEqual(2 * partitions[0].size, raid.get_size())
448 # Ensure the filesystems are the exact same before and after.
449 self.assertItemsEqual(
450 fsids_before, [fs.id for fs in raid.filesystems.all()])
451@@ -2102,8 +2102,6 @@
452 node=node, size=device_size)).add_partition()
453 for _ in range(10)
454 ]
455- # Partition size will be smaller than the disk, because of overhead.
456- partition_size = device_size - PARTITION_TABLE_EXTRA_SPACE
457 uuid = unicode(uuid4())
458 raid = RAID.objects.create_raid(
459 name='md0',
460@@ -2113,7 +2111,7 @@
461 spare_partitions=partitions[-2:])
462 raid.remove_partition(partitions[0])
463 self.assertEqual(9, raid.filesystems.count())
464- self.assertEqual(6 * partition_size, raid.get_size())
465+ self.assertEqual(6 * partitions[0].size, raid.get_size())
466
467 def test_remove_invalid_partition_from_array_fails(self):
468 node = factory.make_Node(bios_boot_method="uefi")
469@@ -2125,8 +2123,6 @@
470 node=node, size=device_size)).add_partition()
471 for _ in range(10)
472 ]
473- # Partition size will be smaller than the disk, because of overhead.
474- partition_size = device_size - PARTITION_TABLE_EXTRA_SPACE
475 uuid = unicode(uuid4())
476 raid = RAID.objects.create_raid(
477 name='md0',
478@@ -2142,7 +2138,7 @@
479 block_device=factory.make_PhysicalBlockDevice(
480 node=node, size=device_size)).add_partition())
481 self.assertEqual(10, raid.filesystems.count())
482- self.assertEqual(9 * partition_size, raid.get_size())
483+ self.assertEqual(9 * partitions[0].size, raid.get_size())
484
485 def test_remove_device_from_array_fails(self):
486 node = factory.make_Node()
487@@ -2251,8 +2247,6 @@
488 backing_partition = factory.make_PartitionTable(
489 block_device=factory.make_PhysicalBlockDevice(
490 node=node, size=backing_size)).add_partition()
491- # Partition size will be smaller than the disk, because of overhead.
492- partition_size = backing_size - PARTITION_TABLE_EXTRA_SPACE
493 uuid = unicode(uuid4())
494 bcache = Bcache.objects.create_bcache(
495 name='bcache0',
496@@ -2262,7 +2256,7 @@
497 cache_mode=CACHE_MODE_TYPE.WRITEBACK)
498
499 # Verify the filesystems were properly created on the target devices
500- self.assertEqual(partition_size, bcache.get_size())
501+ self.assertEqual(backing_partition.size, bcache.get_size())
502 self.assertEqual(
503 FILESYSTEM_TYPE.BCACHE_CACHE,
504 cache_partition.get_effective_filesystem().fstype)
505
506=== modified file 'src/maasserver/models/tests/test_partition.py'
507--- src/maasserver/models/tests/test_partition.py 2015-11-04 19:39:51 +0000
508+++ src/maasserver/models/tests/test_partition.py 2015-11-17 23:23:01 +0000
509@@ -29,6 +29,7 @@
510 from maasserver.models.partition import (
511 MIN_PARTITION_SIZE,
512 Partition,
513+ PARTITION_ALIGNMENT_SIZE,
514 )
515 from maasserver.models.partitiontable import PARTITION_TABLE_EXTRA_SPACE
516 from maasserver.testing.factory import factory
517@@ -45,18 +46,18 @@
518 node = factory.make_Node()
519 block_device = factory.make_PhysicalBlockDevice(
520 node=node,
521- size=(MIN_BLOCK_DEVICE_SIZE * 4) + PARTITION_TABLE_EXTRA_SPACE)
522+ size=(MIN_PARTITION_SIZE * 4) + PARTITION_TABLE_EXTRA_SPACE)
523 partition_table = factory.make_PartitionTable(
524 block_device=block_device)
525 free_partitions = [
526- partition_table.add_partition(size=MIN_BLOCK_DEVICE_SIZE)
527+ partition_table.add_partition(size=MIN_PARTITION_SIZE)
528 for _ in range(2)
529 ]
530 # Make used partitions.
531 for _ in range(2):
532 factory.make_Filesystem(
533 partition=partition_table.add_partition(
534- size=MIN_BLOCK_DEVICE_SIZE))
535+ size=MIN_PARTITION_SIZE))
536 self.assertItemsEqual(
537 free_partitions,
538 Partition.objects.get_free_partitions_for_node(node))
539@@ -213,12 +214,12 @@
540 partition.save()
541 self.assertEquals('%s' % uuid, partition.uuid)
542
543- def test_size_is_rounded_to_next_block(self):
544+ def test_size_is_rounded_to_current_block(self):
545 partition = factory.make_Partition()
546- partition.size = partition.get_block_size() * 4096
547+ partition.size = PARTITION_ALIGNMENT_SIZE * 4
548 partition.size += 1
549 partition.save()
550- self.assertEquals(4097, partition.size / partition.get_block_size())
551+ self.assertEquals(PARTITION_ALIGNMENT_SIZE * 4, partition.size)
552
553 def test_validate_enough_space_for_new_partition(self):
554 partition_table = factory.make_PartitionTable()
555@@ -235,7 +236,7 @@
556 def test_validate_enough_space_for_resize_partition(self):
557 partition_table = factory.make_PartitionTable()
558 partition = partition_table.add_partition()
559- partition.size += partition_table.get_block_size() * 2
560+ partition.size += PARTITION_ALIGNMENT_SIZE * 2
561 error = self.assertRaises(ValidationError, partition.save)
562 self.assertEquals({
563 "size": [
564@@ -298,7 +299,7 @@
565 node = factory.make_Node(bios_boot_method="uefi")
566 block_device = factory.make_PhysicalBlockDevice(
567 node=node,
568- size=(MIN_BLOCK_DEVICE_SIZE * 4) + PARTITION_TABLE_EXTRA_SPACE)
569+ size=(MIN_PARTITION_SIZE * 4) + PARTITION_TABLE_EXTRA_SPACE)
570 partition_table = factory.make_PartitionTable(
571 block_device=block_device, table_type=PARTITION_TABLE_TYPE.GPT)
572 partitions = [
573
574=== modified file 'src/maasserver/models/tests/test_partitiontable.py'
575--- src/maasserver/models/tests/test_partitiontable.py 2015-11-04 04:27:46 +0000
576+++ src/maasserver/models/tests/test_partitiontable.py 2015-11-17 23:23:01 +0000
577@@ -23,7 +23,11 @@
578 BlockDevice,
579 MIN_BLOCK_DEVICE_SIZE,
580 )
581-from maasserver.models.partition import MAX_PARTITION_SIZE_FOR_MBR
582+from maasserver.models.partition import (
583+ MAX_PARTITION_SIZE_FOR_MBR,
584+ MIN_PARTITION_SIZE,
585+ PARTITION_ALIGNMENT_SIZE,
586+)
587 from maasserver.models.partitiontable import PARTITION_TABLE_EXTRA_SPACE
588 from maasserver.testing.factory import factory
589 from maasserver.testing.testcase import MAASServerTestCase
590@@ -41,7 +45,11 @@
591 def test_get_size_returns_block_device_size_minus_initial_offset(self):
592 partition_table = factory.make_PartitionTable()
593 self.assertEquals(
594- partition_table.block_device.size - PARTITION_TABLE_EXTRA_SPACE,
595+ round_size_to_nearest_block(
596+ partition_table.block_device.size -
597+ PARTITION_TABLE_EXTRA_SPACE,
598+ PARTITION_ALIGNMENT_SIZE,
599+ False),
600 partition_table.get_size())
601
602 def test_get_block_size_returns_block_device_block_size(self):
603@@ -52,17 +60,17 @@
604
605 def test_add_misaligned_partition(self):
606 """Tests whether a partition size are adjusted according to
607- device block size."""
608+ partition alignment size (4MiB)."""
609 block_size = 4096
610 device = factory.make_BlockDevice(
611- size=MIN_BLOCK_DEVICE_SIZE * 2 + PARTITION_TABLE_EXTRA_SPACE,
612+ size=MIN_PARTITION_SIZE * 2 + PARTITION_TABLE_EXTRA_SPACE,
613 block_size=block_size)
614 partition_table = factory.make_PartitionTable(block_device=device)
615 partition = partition_table.add_partition(
616- size=MIN_BLOCK_DEVICE_SIZE + 54)
617+ size=MIN_PARTITION_SIZE + 54)
618 self.assertEqual(
619 round_size_to_nearest_block(
620- MIN_BLOCK_DEVICE_SIZE + 54, block_size),
621+ MIN_PARTITION_SIZE + 54, PARTITION_ALIGNMENT_SIZE, False),
622 partition.size)
623
624 def test_add_partition_no_size(self):
625@@ -85,9 +93,10 @@
626 partition_table = factory.make_PartitionTable(
627 table_type=PARTITION_TABLE_TYPE.MBR, block_device=device)
628 partition = partition_table.add_partition()
629- number_of_blocks = MAX_PARTITION_SIZE_FOR_MBR / block_size
630 self.assertEqual(
631- partition.size, block_size * (number_of_blocks - 1))
632+ round_size_to_nearest_block(
633+ MAX_PARTITION_SIZE_FOR_MBR, PARTITION_ALIGNMENT_SIZE, False),
634+ partition.size)
635
636 def test_add_second_partition_no_size(self):
637 """Tests whether a second partition with no specified size starts from
638@@ -95,12 +104,12 @@
639 device."""
640 block_size = 4096
641 device = factory.make_BlockDevice(
642- size=MIN_BLOCK_DEVICE_SIZE * 3 + PARTITION_TABLE_EXTRA_SPACE,
643+ size=MIN_PARTITION_SIZE * 3 + PARTITION_TABLE_EXTRA_SPACE,
644 block_size=block_size)
645 partition_table = factory.make_PartitionTable(block_device=device)
646- partition_table.add_partition(size=MIN_BLOCK_DEVICE_SIZE)
647+ partition_table.add_partition(size=MIN_PARTITION_SIZE)
648 partition = partition_table.add_partition()
649- self.assertEqual(MIN_BLOCK_DEVICE_SIZE * 2, partition.size)
650+ self.assertEqual(MIN_PARTITION_SIZE * 2, partition.size)
651
652 def test_add_partition_to_full_device(self):
653 """Tests whether we fail to add a partition to an already full device.
654@@ -117,26 +126,26 @@
655 def test_get_available_size(self):
656 block_size = 4096
657 device = factory.make_BlockDevice(
658- size=MIN_BLOCK_DEVICE_SIZE * 3 + PARTITION_TABLE_EXTRA_SPACE,
659+ size=MIN_PARTITION_SIZE * 3 + PARTITION_TABLE_EXTRA_SPACE,
660 block_size=block_size)
661 partition_table = factory.make_PartitionTable(block_device=device)
662- partition_table.add_partition(size=MIN_BLOCK_DEVICE_SIZE)
663+ partition_table.add_partition(size=MIN_PARTITION_SIZE)
664 self.assertEquals(
665- MIN_BLOCK_DEVICE_SIZE * 2, partition_table.get_available_size())
666+ MIN_PARTITION_SIZE * 2, partition_table.get_available_size())
667
668 def test_get_available_size_skips_partitions(self):
669 block_size = 4096
670 device = factory.make_BlockDevice(
671- size=MIN_BLOCK_DEVICE_SIZE * 3 + PARTITION_TABLE_EXTRA_SPACE,
672+ size=MIN_PARTITION_SIZE * 3 + PARTITION_TABLE_EXTRA_SPACE,
673 block_size=block_size)
674 partition_table = factory.make_PartitionTable(block_device=device)
675 ignore_partitions = [
676- partition_table.add_partition(size=MIN_BLOCK_DEVICE_SIZE)
677+ partition_table.add_partition(size=MIN_PARTITION_SIZE)
678 for _ in range(2)
679 ]
680- partition_table.add_partition(size=MIN_BLOCK_DEVICE_SIZE)
681+ partition_table.add_partition(size=MIN_PARTITION_SIZE)
682 self.assertEquals(
683- MIN_BLOCK_DEVICE_SIZE * 2,
684+ MIN_PARTITION_SIZE * 2,
685 partition_table.get_available_size(
686 ignore_partitions=ignore_partitions))
687
688
689=== modified file 'src/maasserver/models/virtualblockdevice.py'
690--- src/maasserver/models/virtualblockdevice.py 2015-08-14 13:48:59 +0000
691+++ src/maasserver/models/virtualblockdevice.py 2015-11-17 23:23:01 +0000
692@@ -30,7 +30,11 @@
693 )
694 from maasserver.models.filesystemgroup import FilesystemGroup
695 from maasserver.models.node import Node
696-from maasserver.utils.converters import human_readable_bytes
697+from maasserver.models.partition import PARTITION_ALIGNMENT_SIZE
698+from maasserver.utils.converters import (
699+ human_readable_bytes,
700+ round_size_to_nearest_block,
701+)
702 from maasserver.utils.orm import get_one
703
704
705@@ -109,16 +113,22 @@
706
707 # Check if the size of this is not larger than the free size of
708 # its filesystem group if its lvm.
709- if (self.filesystem_group.is_lvm() and
710- self.size > self.filesystem_group.get_lvm_free_space(
711- skip_volumes=[self])):
712- raise ValidationError(
713- "There is not enough free space (%s) "
714- "on volume group %s." % (
715- human_readable_bytes(self.size),
716- self.filesystem_group.name,
717- ))
718- elif not self.filesystem_group.is_lvm():
719+ if self.filesystem_group.is_lvm():
720+
721+ # align virtual partition to partition alignment size
722+ # otherwise on creation it may be rounded up, overfilling group
723+ self.size = round_size_to_nearest_block(
724+ self.size, PARTITION_ALIGNMENT_SIZE, False)
725+
726+ if self.size > self.filesystem_group.get_lvm_free_space(
727+ skip_volumes=[self]):
728+ raise ValidationError(
729+ "There is not enough free space (%s) "
730+ "on volume group %s." % (
731+ human_readable_bytes(self.size),
732+ self.filesystem_group.name,
733+ ))
734+ else:
735 # If not a volume group the size of the virtual block device
736 # must equal the size of the filesystem group.
737 assert self.size == self.filesystem_group.get_size()
738
739=== modified file 'src/maasserver/testing/factory.py'
740--- src/maasserver/testing/factory.py 2015-11-02 22:17:02 +0000
741+++ src/maasserver/testing/factory.py 2015-11-17 23:23:01 +0000
742@@ -1287,9 +1287,7 @@
743 raise ValueError(
744 "Cannot make another partition on partition_table not "
745 "enough free space.")
746- size = round_size_to_nearest_block(
747- random.randint(MIN_PARTITION_SIZE, available_size),
748- partition_table.get_block_size())
749+ size = random.randint(MIN_PARTITION_SIZE, available_size)
750 if bootable is None:
751 bootable = random.choice([True, False])
752 return Partition.objects.create(
753
754=== modified file 'src/maasserver/tests/test_forms_blockdevice.py'
755--- src/maasserver/tests/test_forms_blockdevice.py 2015-09-24 19:54:30 +0000
756+++ src/maasserver/tests/test_forms_blockdevice.py 2015-11-17 23:23:01 +0000
757@@ -31,9 +31,11 @@
758 )
759 from maasserver.models import Filesystem
760 from maasserver.models.blockdevice import MIN_BLOCK_DEVICE_SIZE
761+from maasserver.models.partition import PARTITION_ALIGNMENT_SIZE
762 from maasserver.testing.factory import factory
763 from maasserver.testing.orm import reload_object
764 from maasserver.testing.testcase import MAASServerTestCase
765+from maasserver.utils.converters import round_size_to_nearest_block
766 from maasserver.utils.orm import get_one
767 from testtools.matchers import MatchesStructure
768
769@@ -379,8 +381,10 @@
770 })
771 self.assertTrue(form.is_valid(), form.errors)
772 block_device = form.save()
773+ expected_size = round_size_to_nearest_block(
774+ size, PARTITION_ALIGNMENT_SIZE, False)
775 self.assertThat(block_device, MatchesStructure.byEquality(
776 name=name,
777 uuid=vguuid,
778- size=size,
779+ size=expected_size,
780 ))
781
782=== modified file 'src/maasserver/tests/test_forms_partition.py'
783--- src/maasserver/tests/test_forms_partition.py 2015-09-24 19:54:30 +0000
784+++ src/maasserver/tests/test_forms_partition.py 2015-11-17 23:23:01 +0000
785@@ -26,9 +26,11 @@
786 )
787 from maasserver.models import Filesystem
788 from maasserver.models.blockdevice import MIN_BLOCK_DEVICE_SIZE
789+from maasserver.models.partition import PARTITION_ALIGNMENT_SIZE
790 from maasserver.testing.factory import factory
791 from maasserver.testing.orm import reload_object
792 from maasserver.testing.testcase import MAASServerTestCase
793+from maasserver.utils.converters import round_size_to_nearest_block
794 from maasserver.utils.orm import get_one
795
796
797@@ -84,15 +86,13 @@
798 form.is_valid(),
799 "Should be valid because size is large enough and a string.")
800
801- def test_size_rounded_up_and_placed_on_block_boundry(self):
802+ def test_size_rounded_down_and_placed_on_alignment_boundry(self):
803 block_size = 4096
804 block_device = factory.make_PhysicalBlockDevice(block_size=block_size)
805 k_size = (MIN_BLOCK_DEVICE_SIZE / 1000) + 1
806 size = "%sk" % k_size
807- block_count = (k_size * 1000) / block_size
808- if (k_size * 1000) % block_size > 0:
809- block_count += 1
810- rounded_size = block_count * block_size
811+ rounded_size = round_size_to_nearest_block(
812+ k_size * 1000, PARTITION_ALIGNMENT_SIZE, False)
813 data = {
814 'size': size,
815 }
816
817=== modified file 'src/maasserver/tests/test_forms_raid.py'
818--- src/maasserver/tests/test_forms_raid.py 2015-10-29 16:39:49 +0000
819+++ src/maasserver/tests/test_forms_raid.py 2015-11-17 23:23:01 +0000
820@@ -26,7 +26,6 @@
821 UpdateRaidForm,
822 )
823 from maasserver.models.filesystemgroup import RAID
824-from maasserver.models.partitiontable import PARTITION_TABLE_EXTRA_SPACE
825 from maasserver.testing.factory import factory
826 from maasserver.testing.testcase import MAASServerTestCase
827
828@@ -126,12 +125,11 @@
829 for bd in bds
830 if bd.get_partitiontable() is None
831 ]
832- partitions = [
833- bd.get_partitiontable().add_partition().id
834+ partition_objs = [
835+ bd.get_partitiontable().add_partition()
836 for bd in bds[5:]
837 ]
838- # Partition size will be smaller than the disk, because of overhead.
839- partition_size = device_size - PARTITION_TABLE_EXTRA_SPACE
840+ partitions = [partition.id for partition in partition_objs]
841 form = CreateRaidForm(node=node, data={
842 'name': 'md1',
843 'level': FILESYSTEM_GROUP_TYPE.RAID_6,
844@@ -141,7 +139,7 @@
845 self.assertTrue(form.is_valid(), form.errors)
846 raid = form.save()
847 self.assertEqual('md1', raid.name)
848- self.assertEqual(8 * partition_size, raid.get_size())
849+ self.assertEqual(8 * partition_objs[0].size, raid.get_size())
850 self.assertEqual(FILESYSTEM_GROUP_TYPE.RAID_6, raid.group_type)
851 self.assertItemsEqual(
852 block_devices,
853@@ -183,8 +181,6 @@
854 part.name
855 for part in partitions
856 ]
857- # Partition size will be smaller than the disk, because of overhead.
858- partition_size = device_size - PARTITION_TABLE_EXTRA_SPACE
859 form = CreateRaidForm(node=node, data={
860 'name': 'md1',
861 'level': FILESYSTEM_GROUP_TYPE.RAID_6,
862@@ -194,7 +190,7 @@
863 self.assertTrue(form.is_valid(), form.errors)
864 raid = form.save()
865 self.assertEqual('md1', raid.name)
866- self.assertEqual(8 * partition_size, raid.get_size())
867+ self.assertEqual(8 * partitions[0].size, raid.get_size())
868 self.assertEqual(FILESYSTEM_GROUP_TYPE.RAID_6, raid.group_type)
869 self.assertItemsEqual(
870 block_devices_ids,
871
872=== modified file 'src/maasserver/tests/test_forms_volume_group.py'
873--- src/maasserver/tests/test_forms_volume_group.py 2015-10-28 01:59:30 +0000
874+++ src/maasserver/tests/test_forms_volume_group.py 2015-11-17 23:23:01 +0000
875@@ -24,9 +24,11 @@
876 UpdateVolumeGroupForm,
877 )
878 from maasserver.models.blockdevice import MIN_BLOCK_DEVICE_SIZE
879+from maasserver.models.partition import PARTITION_ALIGNMENT_SIZE
880 from maasserver.models.partitiontable import PARTITION_TABLE_EXTRA_SPACE
881 from maasserver.testing.factory import factory
882 from maasserver.testing.testcase import MAASServerTestCase
883+from maasserver.utils.converters import round_size_to_nearest_block
884 from testtools.matchers import MatchesStructure
885
886
887@@ -512,9 +514,10 @@
888 factory.make_name("lv"),
889 size=volume_group.get_size() - MIN_BLOCK_DEVICE_SIZE - 1)
890 name = factory.make_name("lv")
891+ free_space = volume_group.get_lvm_free_space()
892 data = {
893 'name': name,
894- 'size': MIN_BLOCK_DEVICE_SIZE + 2,
895+ 'size': free_space + 2,
896 }
897 form = CreateLogicalVolumeForm(volume_group, data=data)
898 self.assertFalse(
899@@ -560,9 +563,11 @@
900 form = CreateLogicalVolumeForm(volume_group, data=data)
901 self.assertTrue(form.is_valid(), form._errors)
902 logical_volume = form.save()
903+ expected_size = round_size_to_nearest_block(
904+ size, PARTITION_ALIGNMENT_SIZE, False)
905 self.assertThat(
906 logical_volume, MatchesStructure.byEquality(
907 name=name,
908 uuid=vguuid,
909- size=size,
910+ size=expected_size,
911 ))
912
913=== modified file 'src/maasserver/tests/test_preseed_storage.py'
914--- src/maasserver/tests/test_preseed_storage.py 2015-11-04 04:27:46 +0000
915+++ src/maasserver/tests/test_preseed_storage.py 2015-11-17 23:23:01 +0000
916@@ -83,7 +83,7 @@
917 size: 536870912B
918 device: sda
919 wipe: superblock
920- offset: 2097152B
921+ offset: 4194304B
922 flag: boot
923 - id: sda-part2
924 name: sda-part2
925@@ -99,7 +99,7 @@
926 type: partition
927 number: 3
928 uuid: f74ff260-2a5b-4a36-b1b8-37f746b946bf
929- size: 6976176128B
930+ size: 6970933248B
931 wipe: superblock
932 device: sda
933 - id: sda-part1_format
934@@ -195,7 +195,7 @@
935 size: 536870912B
936 device: sda
937 wipe: superblock
938- offset: 2097152B
939+ offset: 4194304B
940 flag: boot
941 - id: sda-part2
942 name: sda-part2
943@@ -233,7 +233,7 @@
944 type: partition
945 number: 6
946 uuid: 8c365c80-900b-40a1-a8c7-1e445878d19a
947- size: 2144337920B
948+ size: 2139095040B
949 device: sda
950 wipe: superblock
951 flag: logical
952@@ -370,10 +370,10 @@
953 type: partition
954 number: 1
955 uuid: 6efc2c3d-bc9d-4ee5-a7ed-c6e1574d5398
956- size: 8586788864B
957+ size: 8581545984B
958 device: sda
959 wipe: superblock
960- offset: 2097152B
961+ offset: 4194304B
962 - id: sda-part1_format
963 type: format
964 fstype: ext4
965@@ -435,10 +435,10 @@
966 type: partition
967 number: 1
968 uuid: 6efc2c3d-bc9d-4ee5-a7ed-c6e1574d5398
969- size: 8586788864B
970+ size: 8581545984B
971 device: sda
972 wipe: superblock
973- offset: 2097152B
974+ offset: 4194304B
975 - id: sda-part1_format
976 type: format
977 fstype: ext4
978@@ -548,7 +548,7 @@
979 size: 536870912B
980 device: sda
981 wipe: superblock
982- offset: 2097152B
983+ offset: 4194304B
984 flag: boot
985 - id: sda-part2
986 name: sda-part2
987@@ -564,16 +564,16 @@
988 type: partition
989 number: 3
990 uuid: f74ff260-2a5b-4a36-b1b8-37f746b946bf
991- size: 6976176128B
992+ size: 6970933248B
993 device: sda
994 wipe: superblock
995 - id: sdb-part1
996 name: sdb-part1
997 type: partition
998 number: 1
999- offset: 2097152B
1000+ offset: 4194304B
1001 uuid: f3281144-a0b6-46f1-90af-8541f97f7b1f
1002- size: 2144337920B
1003+ size: 2139095040B
1004 wipe: superblock
1005 device: sdb
1006 - id: bcache0
1007@@ -610,9 +610,9 @@
1008 name: md0-part1
1009 type: partition
1010 number: 1
1011- offset: 2097152B
1012+ offset: 4194304B
1013 uuid: 18a6e885-3e6d-4505-8a0d-cf34df11a8b0
1014- size: 2199020109824B
1015+ size: 2199014866944B
1016 wipe: superblock
1017 device: md0
1018 - id: sda-part1_format
1019
1020=== modified file 'src/maasserver/tests/test_storage_layouts.py'
1021--- src/maasserver/tests/test_storage_layouts.py 2015-10-27 20:53:16 +0000
1022+++ src/maasserver/tests/test_storage_layouts.py 2015-11-17 23:23:01 +0000
1023@@ -25,7 +25,10 @@
1024 )
1025 from maasserver.models.blockdevice import MIN_BLOCK_DEVICE_SIZE
1026 from maasserver.models.filesystemgroup import VolumeGroup
1027-from maasserver.models.partition import MAX_PARTITION_SIZE_FOR_MBR
1028+from maasserver.models.partition import (
1029+ MAX_PARTITION_SIZE_FOR_MBR,
1030+ PARTITION_ALIGNMENT_SIZE,
1031+)
1032 from maasserver.models.partitiontable import PARTITION_TABLE_EXTRA_SPACE
1033 from maasserver.storage_layouts import (
1034 BcacheStorageLayout,
1035@@ -46,6 +49,7 @@
1036 )
1037 from maasserver.testing.factory import factory
1038 from maasserver.testing.testcase import MAASServerTestCase
1039+from maasserver.utils.converters import round_size_to_nearest_block
1040 from maastesting.matchers import MockCalledOnceWith
1041 from testtools.matchers import MatchesStructure
1042
1043@@ -53,13 +57,6 @@
1044 LARGE_BLOCK_DEVICE = 10 * 1024 * 1024 * 1024 # 10 GiB
1045
1046
1047-def round_size_by_blocks(size, block_size):
1048- number_of_blocks = size / block_size
1049- if size % block_size > 0:
1050- number_of_blocks += 1
1051- return number_of_blocks * block_size
1052-
1053-
1054 def make_Node_with_uefi_boot_method(*args, **kwargs):
1055 kwargs['bios_boot_method'] = "uefi"
1056 kwargs['with_boot_disk'] = False
1057@@ -435,7 +432,8 @@
1058 def assertEFIPartition(self, partition, boot_disk):
1059 self.assertIsNotNone(partition)
1060 self.assertEquals(
1061- round_size_by_blocks(EFI_PARTITION_SIZE, boot_disk.block_size),
1062+ round_size_to_nearest_block(
1063+ EFI_PARTITION_SIZE, boot_disk.block_size),
1064 partition.size)
1065 self.assertThat(
1066 partition.get_effective_filesystem(), MatchesStructure.byEquality(
1067@@ -474,9 +472,10 @@
1068 root_partition = partitions[0]
1069 self.assertIsNotNone(root_partition)
1070 self.assertEquals(
1071- round_size_by_blocks(
1072+ round_size_to_nearest_block(
1073 boot_disk.size - PARTITION_TABLE_EXTRA_SPACE,
1074- boot_disk.block_size),
1075+ PARTITION_ALIGNMENT_SIZE,
1076+ False),
1077 root_partition.size)
1078 self.assertThat(
1079 root_partition.get_effective_filesystem(),
1080@@ -500,10 +499,12 @@
1081 # Validate root partition.
1082 partitions = partition_table.partitions.order_by('id').all()
1083 root_partition = partitions[0]
1084- number_of_blocks = MAX_PARTITION_SIZE_FOR_MBR / boot_disk.block_size
1085 self.assertIsNotNone(root_partition)
1086 self.assertEquals(
1087- (boot_disk.block_size * (number_of_blocks - 1)),
1088+ round_size_to_nearest_block(
1089+ MAX_PARTITION_SIZE_FOR_MBR,
1090+ PARTITION_ALIGNMENT_SIZE,
1091+ False),
1092 root_partition.size)
1093 self.assertThat(
1094 root_partition.get_effective_filesystem(),
1095@@ -533,10 +534,11 @@
1096 root_partition = partitions[1]
1097 self.assertIsNotNone(root_partition)
1098 self.assertEquals(
1099- round_size_by_blocks(
1100+ round_size_to_nearest_block(
1101 boot_disk.size - EFI_PARTITION_SIZE -
1102 PARTITION_TABLE_EXTRA_SPACE,
1103- boot_disk.block_size),
1104+ PARTITION_ALIGNMENT_SIZE,
1105+ False),
1106 root_partition.size)
1107 self.assertThat(
1108 root_partition.get_effective_filesystem(),
1109@@ -570,8 +572,8 @@
1110 boot_partition = partitions[1]
1111 self.assertIsNotNone(boot_partition)
1112 self.assertEquals(
1113- round_size_by_blocks(
1114- boot_size, boot_disk.block_size),
1115+ round_size_to_nearest_block(
1116+ boot_size, PARTITION_ALIGNMENT_SIZE, False),
1117 boot_partition.size)
1118 self.assertThat(
1119 boot_partition.get_effective_filesystem(),
1120@@ -585,10 +587,11 @@
1121 root_partition = partitions[2]
1122 self.assertIsNotNone(root_partition)
1123 self.assertEquals(
1124- round_size_by_blocks(
1125+ round_size_to_nearest_block(
1126 boot_disk.size - boot_partition.size -
1127 EFI_PARTITION_SIZE - PARTITION_TABLE_EXTRA_SPACE,
1128- boot_disk.block_size),
1129+ PARTITION_ALIGNMENT_SIZE,
1130+ False),
1131 root_partition.size)
1132 self.assertThat(
1133 root_partition.get_effective_filesystem(),
1134@@ -622,7 +625,8 @@
1135 root_partition = partitions[1]
1136 self.assertIsNotNone(root_partition)
1137 self.assertEquals(
1138- round_size_by_blocks(root_size, boot_disk.block_size),
1139+ round_size_to_nearest_block(
1140+ root_size, PARTITION_ALIGNMENT_SIZE, False),
1141 root_partition.size)
1142 self.assertThat(
1143 root_partition.get_effective_filesystem(),
1144@@ -659,8 +663,8 @@
1145 boot_partition = partitions[1]
1146 self.assertIsNotNone(boot_partition)
1147 self.assertEquals(
1148- round_size_by_blocks(
1149- boot_size, boot_disk.block_size),
1150+ round_size_to_nearest_block(
1151+ boot_size, PARTITION_ALIGNMENT_SIZE, False),
1152 boot_partition.size)
1153 self.assertThat(
1154 boot_partition.get_effective_filesystem(),
1155@@ -674,7 +678,8 @@
1156 root_partition = partitions[2]
1157 self.assertIsNotNone(root_partition)
1158 self.assertEquals(
1159- round_size_by_blocks(root_size, boot_disk.block_size),
1160+ round_size_to_nearest_block(
1161+ root_size, PARTITION_ALIGNMENT_SIZE, False),
1162 root_partition.size)
1163 self.assertThat(
1164 root_partition.get_effective_filesystem(),
1165@@ -716,7 +721,8 @@
1166 'id').all()[0]
1167 self.assertIsNotNone(root_partition)
1168 self.assertEquals(
1169- round_size_by_blocks(root_size, root_device.block_size),
1170+ round_size_to_nearest_block(
1171+ root_size, PARTITION_ALIGNMENT_SIZE, False),
1172 root_partition.size)
1173 self.assertThat(
1174 root_partition.get_effective_filesystem(),
1175@@ -980,7 +986,9 @@
1176 1, volume_group.virtual_devices.count(),
1177 "Should have only 1 logical volume.")
1178 logical_volume = volume_group.virtual_devices.first()
1179- self.assertEquals(lv_size, logical_volume.size)
1180+ expected_size = round_size_to_nearest_block(
1181+ lv_size, PARTITION_ALIGNMENT_SIZE, False)
1182+ self.assertEquals(expected_size, logical_volume.size)
1183 self.assertEquals(layout.DEFAULT_LV_NAME, logical_volume.name)
1184 self.assertThat(
1185 logical_volume.get_effective_filesystem(),
1186@@ -1003,14 +1011,13 @@
1187 root_partition = partitions[0]
1188 volume_group = VolumeGroup.objects.get(
1189 filesystems__partition=root_partition)
1190- number_of_blocks = MAX_PARTITION_SIZE_FOR_MBR / boot_disk.block_size
1191 self.assertIsNotNone(volume_group)
1192 self.assertEquals(
1193 4, partition_table.partitions.count(),
1194 "Should have 4 partitions.")
1195- self.assertEquals(
1196- boot_disk.block_size * (number_of_blocks - 1),
1197- root_partition.size)
1198+ expected_size = round_size_to_nearest_block(
1199+ MAX_PARTITION_SIZE_FOR_MBR, PARTITION_ALIGNMENT_SIZE, False)
1200+ self.assertEquals(expected_size, root_partition.size)
1201
1202
1203 class TestBcacheStorageLayoutBase(MAASServerTestCase):
1204@@ -1185,7 +1192,7 @@
1205 ssd = factory.make_PhysicalBlockDevice(
1206 node=node, size=5 * 1024 * 1024 * 1024, block_size=4096,
1207 tags=['ssd'])
1208- cache_size = round_size_by_blocks(
1209+ cache_size = round_size_to_nearest_block(
1210 random.randint(
1211 3 * 1024 * 1024 * 1024, 5 * 1024 * 1024 * 1024),
1212 4096)
1213@@ -1200,7 +1207,10 @@
1214 self.assertIsNotNone(partition_table)
1215 partition = partition_table.partitions.order_by('id').all()[0]
1216 self.assertEquals(partition, cache_device)
1217- self.assertEquals(cache_size, partition.size)
1218+ self.assertEquals(
1219+ round_size_to_nearest_block(
1220+ cache_size, PARTITION_ALIGNMENT_SIZE, False),
1221+ partition.size)
1222
1223 def test_raises_error_when_invalid_cache_device(self):
1224 node = make_Node_with_uefi_boot_method()
1225@@ -1234,7 +1244,8 @@
1226 "Cannot use cache_size and cache_no_part at the same time."],
1227 "cache_no_part": [
1228 "Cannot use cache_size and cache_no_part at the same time."],
1229- }, layout.errors)
1230+ },
1231+ layout.errors)
1232
1233 def test_raises_error_when_precentage_to_low_for_cache_size(self):
1234 node = make_Node_with_uefi_boot_method()
1235
1236=== modified file 'src/maasserver/utils/converters.py'
1237--- src/maasserver/utils/converters.py 2015-10-11 00:26:09 +0000
1238+++ src/maasserver/utils/converters.py 2015-11-17 23:23:01 +0000
1239@@ -100,12 +100,14 @@
1240 return int(humanized)
1241
1242
1243-def round_size_to_nearest_block(size, block_size):
1244+def round_size_to_nearest_block(size, block_size, round_up=True):
1245 """Round the size to the nearest block returning the new size.
1246
1247- :param round_up: Round the size to fill an entire block.
1248+ :param size: The requested size to round.
1249+ :param block_size: The block size to round to.
1250+ :param round_up: If True, will round up to fill current block, else down.
1251 """
1252 number_of_blocks = size / block_size
1253- if size % block_size > 0:
1254+ if round_up and size % block_size > 0:
1255 number_of_blocks += 1
1256 return block_size * number_of_blocks
1257
1258=== modified file 'src/maasserver/utils/tests/test_converters.py'
1259--- src/maasserver/utils/tests/test_converters.py 2015-08-14 13:48:59 +0000
1260+++ src/maasserver/utils/tests/test_converters.py 2015-11-17 23:23:01 +0000
1261@@ -114,18 +114,34 @@
1262
1263 class TestRoundSizeToNearestBlock(MAASTestCase):
1264
1265- def test__adds_extra_block(self):
1266+ def test__round_up_adds_extra_block(self):
1267 block_size = 4096
1268 size = block_size + 1
1269 self.assertEquals(
1270 2 * block_size,
1271- round_size_to_nearest_block(size, block_size),
1272- "Should add another block to the size.")
1273+ round_size_to_nearest_block(size, block_size, True),
1274+ "Should add an extra block to the size.")
1275
1276- def test__doesnt_add_extra_block(self):
1277+ def test__round_up_doesnt_add_extra_block(self):
1278 block_size = 4096
1279 size = block_size
1280 self.assertEquals(
1281 size,
1282- round_size_to_nearest_block(size, block_size),
1283- "Shouldn't add another block to the size.")
1284+ round_size_to_nearest_block(size, block_size, True),
1285+ "Shouldn't add an extra block to the size.")
1286+
1287+ def test__round_down_removes_block(self):
1288+ block_size = 4096
1289+ size = block_size + 1
1290+ self.assertEquals(
1291+ 1 * block_size,
1292+ round_size_to_nearest_block(size, block_size, False),
1293+ "Should remove block from the size.")
1294+
1295+ def test__round_down_doesnt_remove_block(self):
1296+ block_size = 4096
1297+ size = block_size * 2
1298+ self.assertEquals(
1299+ size,
1300+ round_size_to_nearest_block(size, block_size, False),
1301+ "Shouldn't remove a block from the size.")
1302
1303=== modified file 'src/maasserver/websockets/handlers/tests/test_node.py'
1304--- src/maasserver/websockets/handlers/tests/test_node.py 2015-11-10 23:41:49 +0000
1305+++ src/maasserver/websockets/handlers/tests/test_node.py 2015-11-17 23:23:01 +0000
1306@@ -48,7 +48,10 @@
1307 from maasserver.models.interface import Interface
1308 from maasserver.models.node import Node
1309 from maasserver.models.nodeprobeddetails import get_single_probed_details
1310-from maasserver.models.partition import Partition
1311+from maasserver.models.partition import (
1312+ Partition,
1313+ PARTITION_ALIGNMENT_SIZE,
1314+)
1315 from maasserver.node_action import compile_node_actions
1316 from maasserver.rpc.testing.fixtures import MockLiveRegionToClusterRPCFixture
1317 from maasserver.testing.architecture import make_usable_architecture
1318@@ -66,6 +69,7 @@
1319 from maasserver.third_party_drivers import get_third_party_driver
1320 from maasserver.utils.converters import (
1321 human_readable_bytes,
1322+ round_size_to_nearest_block,
1323 XMLToYAML,
1324 )
1325 from maasserver.utils.orm import (
1326@@ -1477,7 +1481,9 @@
1327 self.assertEquals(
1328 1, Partition.objects.count())
1329 self.assertEquals(
1330- human_readable_bytes(size),
1331+ human_readable_bytes(
1332+ round_size_to_nearest_block(
1333+ size, PARTITION_ALIGNMENT_SIZE, False)),
1334 human_readable_bytes(Partition.objects.first().size))
1335
1336 def test_create_partition_with_filesystem(self):
1337@@ -1502,7 +1508,9 @@
1338 self.assertEquals(
1339 1, Partition.objects.count())
1340 self.assertEquals(
1341- human_readable_bytes(size),
1342+ human_readable_bytes(
1343+ round_size_to_nearest_block(
1344+ size, PARTITION_ALIGNMENT_SIZE, False)),
1345 human_readable_bytes(Partition.objects.first().size))
1346 self.assertEquals(
1347 fstype,

Subscribers

People subscribed via source and target branches