Merge pull request #733 from mwhudson/disable-multiple-boot-devices-on-bionic
do not offer resilient boot options pre-focal
This commit is contained in:
commit
905d34daaa
|
@ -26,10 +26,12 @@ from subiquitycore.async_helpers import (
|
|||
schedule_task,
|
||||
SingleInstanceTask,
|
||||
)
|
||||
from subiquitycore.lsb_release import lsb_release
|
||||
from subiquitycore.utils import (
|
||||
run_command,
|
||||
)
|
||||
|
||||
|
||||
from subiquity.controller import SubiquityController
|
||||
from subiquity.controllers.error import ErrorReportKind
|
||||
from subiquity.models.filesystem import (
|
||||
|
@ -80,6 +82,11 @@ class FilesystemController(SubiquityController):
|
|||
self._probe_once, propagate_errors=False)
|
||||
self._probe_task = SingleInstanceTask(
|
||||
self._probe, propagate_errors=False)
|
||||
if self.model.bootloader == Bootloader.PREP:
|
||||
self.supports_resilient_boot = False
|
||||
else:
|
||||
release = lsb_release()['release']
|
||||
self.supports_resilient_boot = release >= '20.04'
|
||||
|
||||
def load_autoinstall_data(self, data):
|
||||
log.debug("load_autoinstall_data %s", data)
|
||||
|
@ -679,7 +686,7 @@ class FilesystemController(SubiquityController):
|
|||
|
||||
def add_boot_disk(self, new_boot_disk):
|
||||
bootloader = self.model.bootloader
|
||||
if bootloader == Bootloader.PREP:
|
||||
if not self.supports_resilient_boot:
|
||||
for disk in self.model.all_disks():
|
||||
if disk._is_boot_device():
|
||||
self.remove_boot_disk(disk)
|
||||
|
|
|
@ -89,52 +89,6 @@ class TestFilesystemController(unittest.TestCase):
|
|||
"add_boot_disk(disk) did not make _can_TOGGLE_BOOT false "
|
||||
"with bootloader {}".format(bl))
|
||||
|
||||
def test_make_boot_disk_BIOS(self):
|
||||
controller = make_controller(Bootloader.BIOS)
|
||||
disk1 = make_disk(controller.model, preserve=False)
|
||||
|
||||
controller.add_boot_disk(disk1)
|
||||
self.assertEqual(len(disk1.partitions()), 1)
|
||||
self.assertEqual(disk1.partitions()[0].flag, "bios_grub")
|
||||
self.assertTrue(disk1.grub_device)
|
||||
|
||||
controller.remove_boot_disk(disk1)
|
||||
self.assertEqual(len(disk1.partitions()), 0)
|
||||
self.assertFalse(disk1.grub_device)
|
||||
|
||||
disk2 = make_disk(controller.model, preserve=False)
|
||||
disk2p1 = controller.model.add_partition(
|
||||
disk2, size=disk2.free_for_partitions)
|
||||
size_before = disk2p1.size
|
||||
controller.add_boot_disk(disk2)
|
||||
self.assertEqual(len(disk2.partitions()), 2)
|
||||
self.assertEqual(disk2.partitions()[1], disk2p1)
|
||||
self.assertEqual(
|
||||
disk2.partitions()[0].size + disk2p1.size, size_before)
|
||||
self.assertEqual(disk2.partitions()[0].flag, "bios_grub")
|
||||
self.assertTrue(disk2.grub_device)
|
||||
|
||||
controller.remove_boot_disk(disk2)
|
||||
self.assertEqual(disk2.partitions(), [disk2p1])
|
||||
self.assertEqual(disk2p1.size, size_before)
|
||||
self.assertFalse(disk2.grub_device)
|
||||
|
||||
def test_make_boot_disk_BIOS_existing(self):
|
||||
controller = make_controller(Bootloader.BIOS)
|
||||
disk1 = make_disk(controller.model, preserve=True)
|
||||
disk1p1 = controller.model.add_partition(
|
||||
disk1, size=1 << 20, flag="bios_grub")
|
||||
disk1p1.preserve = True
|
||||
|
||||
self.assertEqual(disk1.partitions(), [disk1p1])
|
||||
self.assertFalse(disk1.grub_device)
|
||||
controller.add_boot_disk(disk1)
|
||||
self.assertEqual(disk1.partitions(), [disk1p1])
|
||||
self.assertTrue(disk1.grub_device)
|
||||
controller.remove_boot_disk(disk1)
|
||||
self.assertEqual(disk1.partitions(), [disk1p1])
|
||||
self.assertFalse(disk1.grub_device)
|
||||
|
||||
def assertIsMountedAtBootEFI(self, device):
|
||||
efi_mnts = device._m._all(type="mount", path="/boot/efi")
|
||||
self.assertEqual(len(efi_mnts), 1)
|
||||
|
@ -144,103 +98,137 @@ class TestFilesystemController(unittest.TestCase):
|
|||
if device.fs():
|
||||
self.assertIs(device.fs().mount(), None)
|
||||
|
||||
def test_make_boot_disk_UEFI(self):
|
||||
controller = make_controller(Bootloader.UEFI)
|
||||
def add_existing_boot_partition(self, controller, disk):
|
||||
if controller.model.bootloader == Bootloader.BIOS:
|
||||
part = controller.model.add_partition(
|
||||
disk, size=1 << 20, flag="bios_grub")
|
||||
elif controller.model.bootloader == Bootloader.UEFI:
|
||||
part = controller.model.add_partition(
|
||||
disk, size=512 << 20, flag="boot")
|
||||
elif controller.model.bootloader == Bootloader.PREP:
|
||||
part = controller.model.add_partition(
|
||||
disk, size=8 << 20, flag="prep")
|
||||
part.preserve = True
|
||||
return part
|
||||
|
||||
def assertIsBootDisk(self, controller, disk):
|
||||
if controller.model.bootloader == Bootloader.BIOS:
|
||||
self.assertTrue(disk.grub_device)
|
||||
self.assertEqual(disk.partitions()[0].flag, "bios_grub")
|
||||
elif controller.model.bootloader == Bootloader.UEFI:
|
||||
for part in disk.partitions():
|
||||
if part.flag == "boot" and part.grub_device:
|
||||
return
|
||||
self.fail("{} is not a boot disk".format(disk))
|
||||
elif controller.model.bootloader == Bootloader.PREP:
|
||||
for part in disk.partitions():
|
||||
if part.flag == "prep" and part.grub_device:
|
||||
self.assertEqual(part.wipe, 'zero')
|
||||
return
|
||||
self.fail("{} is not a boot disk".format(disk))
|
||||
|
||||
def assertIsNotBootDisk(self, controller, disk):
|
||||
if controller.model.bootloader == Bootloader.BIOS:
|
||||
self.assertFalse(disk.grub_device)
|
||||
elif controller.model.bootloader == Bootloader.UEFI:
|
||||
for part in disk.partitions():
|
||||
if part.flag == "boot" and part.grub_device:
|
||||
self.fail("{} is a boot disk".format(disk))
|
||||
elif controller.model.bootloader == Bootloader.PREP:
|
||||
for part in disk.partitions():
|
||||
if part.flag == "prep" and part.grub_device:
|
||||
self.fail("{} is a boot disk".format(disk))
|
||||
|
||||
def test_boot_disk_resilient(self):
|
||||
for bl in Bootloader:
|
||||
if bl == Bootloader.NONE:
|
||||
continue
|
||||
controller = make_controller(bl)
|
||||
controller.supports_resilient_boot = True
|
||||
|
||||
disk1 = make_disk(controller.model, preserve=False)
|
||||
disk2 = make_disk(controller.model, preserve=False)
|
||||
disk2p1 = controller.model.add_partition(
|
||||
disk2, size=disk2.free_for_partitions)
|
||||
|
||||
controller.add_boot_disk(disk1)
|
||||
self.assertEqual(len(disk1.partitions()), 1)
|
||||
disk1esp = disk1.partitions()[0]
|
||||
self.assertEqual(disk1esp.flag, "boot")
|
||||
self.assertEqual(disk1esp.fs().fstype, "fat32")
|
||||
self.assertTrue(disk1esp.grub_device)
|
||||
self.assertIsMountedAtBootEFI(disk1esp)
|
||||
self.assertIsBootDisk(controller, disk1)
|
||||
if bl == Bootloader.UEFI:
|
||||
self.assertIsMountedAtBootEFI(disk1.partitions()[0])
|
||||
|
||||
size_before = disk2p1.size
|
||||
controller.add_boot_disk(disk2)
|
||||
self.assertEqual(len(disk2.partitions()), 2)
|
||||
self.assertEqual(disk2.partitions()[1], disk2p1)
|
||||
disk2esp = disk2.partitions()[0]
|
||||
self.assertEqual(disk2esp.size + disk2p1.size, size_before)
|
||||
self.assertEqual(disk2esp.flag, "boot")
|
||||
self.assertTrue(disk2esp.grub_device)
|
||||
self.assertIsMountedAtBootEFI(disk1esp)
|
||||
self.assertNotMounted(disk2esp)
|
||||
|
||||
controller.remove_boot_disk(disk1)
|
||||
self.assertIsMountedAtBootEFI(disk2esp)
|
||||
self.assertEqual(len(disk1.partitions()), 0)
|
||||
|
||||
controller.remove_boot_disk(disk2)
|
||||
self.assertEqual(len(disk2.partitions()), 1)
|
||||
self.assertEqual(disk2p1.size, size_before)
|
||||
|
||||
def test_make_boot_disk_UEFI_existing(self):
|
||||
controller = make_controller(Bootloader.UEFI)
|
||||
disk1 = make_disk(controller.model, preserve=True)
|
||||
disk1p1 = controller.model.add_partition(
|
||||
disk1, size=512 << 20, flag="boot")
|
||||
disk1p1.preserve = True
|
||||
disk2 = make_disk(controller.model, preserve=True)
|
||||
|
||||
self.assertEqual(disk1.partitions(), [disk1p1])
|
||||
efi_mnt = controller.model._mount_for_path("/boot/efi")
|
||||
self.assertEqual(efi_mnt, None)
|
||||
controller.add_boot_disk(disk1)
|
||||
self.assertEqual(disk1.partitions(), [disk1p1])
|
||||
self.assertTrue(disk1p1.grub_device)
|
||||
self.assertIsMountedAtBootEFI(disk1p1)
|
||||
self.assertEqual(disk1p1.fs().fstype, "fat32")
|
||||
|
||||
controller.add_boot_disk(disk2)
|
||||
self.assertEqual(disk1.partitions(), [disk1p1])
|
||||
self.assertTrue(disk1p1.grub_device)
|
||||
self.assertIsMountedAtBootEFI(disk1p1)
|
||||
|
||||
def test_make_boot_disk_PREP(self):
|
||||
controller = make_controller(Bootloader.PREP)
|
||||
disk1 = make_disk(controller.model, preserve=False)
|
||||
disk2 = make_disk(controller.model, preserve=False)
|
||||
disk2p1 = controller.model.add_partition(
|
||||
disk2, size=disk2.free_for_partitions)
|
||||
|
||||
controller.add_boot_disk(disk1)
|
||||
self.assertEqual(len(disk1.partitions()), 1)
|
||||
self.assertEqual(disk1.partitions()[0].flag, "prep")
|
||||
self.assertEqual(disk1.partitions()[0].wipe, "zero")
|
||||
self.assertTrue(disk1.partitions()[0].grub_device)
|
||||
|
||||
size_before = disk2p1.size
|
||||
controller.add_boot_disk(disk2)
|
||||
self.assertEqual(len(disk1.partitions()), 0)
|
||||
self.assertIsBootDisk(controller, disk1)
|
||||
self.assertIsBootDisk(controller, disk2)
|
||||
if bl == Bootloader.UEFI:
|
||||
self.assertIsMountedAtBootEFI(disk1.partitions()[0])
|
||||
self.assertNotMounted(disk2.partitions()[0])
|
||||
self.assertEqual(len(disk2.partitions()), 2)
|
||||
self.assertEqual(disk2.partitions()[1], disk2p1)
|
||||
self.assertEqual(
|
||||
disk2.partitions()[0].size + disk2p1.size, size_before)
|
||||
self.assertEqual(disk2.partitions()[0].flag, "prep")
|
||||
self.assertEqual(disk2.partitions()[0].wipe, "zero")
|
||||
|
||||
def test_make_boot_disk_PREP_existing(self):
|
||||
controller = make_controller(Bootloader.PREP)
|
||||
disk1 = make_disk(controller.model, preserve=True)
|
||||
disk1p1 = controller.model.add_partition(
|
||||
disk1, size=8 << 20, flag="prep")
|
||||
disk1p1.preserve = True
|
||||
|
||||
self.assertEqual(disk1.partitions(), [disk1p1])
|
||||
self.assertFalse(disk1p1.grub_device)
|
||||
controller.add_boot_disk(disk1)
|
||||
self.assertEqual(disk1.partitions(), [disk1p1])
|
||||
self.assertTrue(disk1p1.grub_device)
|
||||
self.assertEqual(disk1p1.wipe, 'zero')
|
||||
|
||||
controller.remove_boot_disk(disk1)
|
||||
self.assertEqual(disk1.partitions(), [disk1p1])
|
||||
self.assertFalse(disk1p1.grub_device)
|
||||
self.assertEqual(disk1p1.wipe, None)
|
||||
self.assertIsNotBootDisk(controller, disk1)
|
||||
self.assertIsBootDisk(controller, disk2)
|
||||
if bl == Bootloader.UEFI:
|
||||
self.assertIsMountedAtBootEFI(disk2.partitions()[0])
|
||||
self.assertEqual(len(disk1.partitions()), 0)
|
||||
|
||||
controller.remove_boot_disk(disk2)
|
||||
self.assertIsNotBootDisk(controller, disk2)
|
||||
self.assertEqual(len(disk2.partitions()), 1)
|
||||
self.assertEqual(disk2p1.size, size_before)
|
||||
|
||||
def test_boot_disk_no_resilient(self):
|
||||
for bl in Bootloader:
|
||||
if bl == Bootloader.NONE:
|
||||
continue
|
||||
controller = make_controller(bl)
|
||||
controller.supports_resilient_boot = False
|
||||
|
||||
disk1 = make_disk(controller.model, preserve=False)
|
||||
disk2 = make_disk(controller.model, preserve=False)
|
||||
disk2p1 = controller.model.add_partition(
|
||||
disk2, size=disk2.free_for_partitions)
|
||||
|
||||
controller.add_boot_disk(disk1)
|
||||
self.assertIsBootDisk(controller, disk1)
|
||||
if bl == Bootloader.UEFI:
|
||||
self.assertIsMountedAtBootEFI(disk1.partitions()[0])
|
||||
|
||||
size_before = disk2p1.size
|
||||
controller.add_boot_disk(disk2)
|
||||
self.assertIsNotBootDisk(controller, disk1)
|
||||
self.assertIsBootDisk(controller, disk2)
|
||||
if bl == Bootloader.UEFI:
|
||||
self.assertIsMountedAtBootEFI(disk2.partitions()[0])
|
||||
self.assertEqual(len(disk2.partitions()), 2)
|
||||
self.assertEqual(disk2.partitions()[1], disk2p1)
|
||||
self.assertEqual(
|
||||
disk2.partitions()[0].size + disk2p1.size, size_before)
|
||||
|
||||
def test_boot_disk_existing(self):
|
||||
for bl in Bootloader:
|
||||
if bl == Bootloader.NONE:
|
||||
continue
|
||||
controller = make_controller(bl)
|
||||
|
||||
disk1 = make_disk(controller.model, preserve=True)
|
||||
part = self.add_existing_boot_partition(controller, disk1)
|
||||
|
||||
wipe_before = part.wipe
|
||||
controller.add_boot_disk(disk1)
|
||||
self.assertIsBootDisk(controller, disk1)
|
||||
if bl == Bootloader.UEFI:
|
||||
self.assertIsMountedAtBootEFI(part)
|
||||
|
||||
controller.remove_boot_disk(disk1)
|
||||
self.assertIsNotBootDisk(controller, disk1)
|
||||
self.assertEqual(len(disk1.partitions()), 1)
|
||||
self.assertEqual(part.wipe, wipe_before)
|
||||
if bl == Bootloader.UEFI:
|
||||
self.assertNotMounted(part)
|
||||
|
||||
def test_mounting_partition_makes_boot_disk(self):
|
||||
controller = make_controller(Bootloader.UEFI)
|
||||
|
|
|
@ -61,7 +61,6 @@ from subiquitycore.ui.utils import (
|
|||
from subiquitycore.view import BaseView
|
||||
|
||||
from subiquity.models.filesystem import (
|
||||
Bootloader,
|
||||
DeviceAction,
|
||||
humanize_size,
|
||||
)
|
||||
|
@ -330,7 +329,7 @@ class DeviceList(WidgetWrap):
|
|||
if device._is_boot_device():
|
||||
return _("Stop Using As Boot Device")
|
||||
else:
|
||||
if self.parent.model.bootloader != Bootloader.PREP:
|
||||
if self.parent.controller.supports_resilient_boot:
|
||||
for other in self.parent.model.all_disks():
|
||||
if other._is_boot_device():
|
||||
return _("Add As Another Boot Device")
|
||||
|
|
Loading…
Reference in New Issue