sort raid devices consistently when computing size and when serializing

This commit is contained in:
Michael Hudson-Doyle 2019-11-07 13:25:58 +13:00
parent 233965b376
commit fde1c53141
3 changed files with 23 additions and 12 deletions

View File

@ -7,16 +7,13 @@
# raid devices (backed by sparse files in a tmpfs) and comparing their sizes
# with the estimates. It must be run as root.
import atexit
import os
import random
import shutil
import subprocess
import sys
import tempfile
import uuid
import attr
from subiquity.models.filesystem import (
align_down,
@ -25,6 +22,9 @@ from subiquity.models.filesystem import (
humanize_size,
raidlevels,
)
from subiquity.models.tests.test_filesystem import (
FakeDev,
)
tmpdir = tempfile.mkdtemp()
@ -96,11 +96,6 @@ def get_real_raid_size(raid):
stdout=subprocess.PIPE, encoding='ascii').stdout.strip())
@attr.s
class FakeDev:
size = attr.ib()
def verify_size_ok(level, sizes):
r = False
try:

View File

@ -258,10 +258,15 @@ def calculate_data_offset(devsize):
return data_offset
def raid_device_sort(devices):
return sorted(devices, key=lambda d: d.id)
# This this is tested against reality in ./scripts/get-raid-sizes.py
def get_raid_size(level, devices):
if len(devices) == 0:
return 0
devices = raid_device_sort(devices)
data_offset = calculate_data_offset(devices[0].size)
sizes = [align_down(dev.size - data_offset) for dev in devices]
min_size = min(sizes)
@ -893,6 +898,13 @@ class Raid(_Device):
name = attr.ib()
raidlevel = attr.ib(converter=lambda x: raidlevels_by_value[x].value)
devices = attributes.reflist(backlink="_constructed_device")
def serialize_devices(self):
# Surprisingly, the order of devices passed to mdadm --create
# matters (see get_raid_size) so we sort devices here the same
# way get_raid_size does.
return [d.id for d in raid_device_sort(self.devices)]
spare_devices = attributes.reflist(backlink="_constructed_device")
preserve = attr.ib(default=False)

View File

@ -19,6 +19,7 @@ import unittest
import attr
from subiquity.models.filesystem import (
attributes,
Bootloader,
dehumanize_size,
DeviceAction,
@ -108,14 +109,17 @@ class TestDehumanizeSize(unittest.TestCase):
self.assertEqual(expected_error, actual_error)
@attr.s
class FakeDev:
size = attr.ib()
id = attributes.idfield("fakedev")
class TestRoundRaidSize(unittest.TestCase):
def test_lp1816777(self):
@attr.s
class FakeDev:
size = attr.ib()
self.assertLessEqual(
get_raid_size("raid1", [FakeDev(500107862016)]*2),
499972571136)