commit
ab31a3b206
|
@ -70,7 +70,7 @@ parts:
|
||||||
|
|
||||||
source: https://git.launchpad.net/curtin
|
source: https://git.launchpad.net/curtin
|
||||||
source-type: git
|
source-type: git
|
||||||
source-commit: a349105809af6188cb394e300a99846df3d117f0
|
source-commit: 1997a1614e774cbd152fa33059d53417a641dbd6
|
||||||
|
|
||||||
override-pull: |
|
override-pull: |
|
||||||
craftctl default
|
craftctl default
|
||||||
|
|
|
@ -145,7 +145,7 @@ class FilesystemManipulator:
|
||||||
if key:
|
if key:
|
||||||
device = self.model.add_dm_crypt(
|
device = self.model.add_dm_crypt(
|
||||||
device,
|
device,
|
||||||
key,
|
key=key,
|
||||||
recovery_key=spec.get("recovery-key"),
|
recovery_key=spec.get("recovery-key"),
|
||||||
)
|
)
|
||||||
devices.add(device)
|
devices.add(device)
|
||||||
|
@ -177,6 +177,15 @@ class FilesystemManipulator:
|
||||||
|
|
||||||
delete_lvm_partition = delete_logical_volume
|
delete_lvm_partition = delete_logical_volume
|
||||||
|
|
||||||
|
def create_cryptoswap(self, device):
|
||||||
|
dmc = self.model.add_dm_crypt(
|
||||||
|
device,
|
||||||
|
keyfile="/dev/urandom",
|
||||||
|
options=["swap", "initramfs"],
|
||||||
|
)
|
||||||
|
self.create_filesystem(dmc, dict(fstype="swap"))
|
||||||
|
return dmc
|
||||||
|
|
||||||
def create_zpool(self, device, pool, mountpoint, boot=False, canmount="on"):
|
def create_zpool(self, device, pool, mountpoint, boot=False, canmount="on"):
|
||||||
fs_properties = dict(
|
fs_properties = dict(
|
||||||
atime=None,
|
atime=None,
|
||||||
|
@ -341,7 +350,7 @@ class FilesystemManipulator:
|
||||||
if key:
|
if key:
|
||||||
d = self.model.add_dm_crypt(
|
d = self.model.add_dm_crypt(
|
||||||
d,
|
d,
|
||||||
key,
|
key=key,
|
||||||
recovery_key=spec.get("recovery-key"),
|
recovery_key=spec.get("recovery-key"),
|
||||||
)
|
)
|
||||||
d._constructed_device = existing
|
d._constructed_device = existing
|
||||||
|
|
|
@ -347,6 +347,7 @@ class GuidedCapability(enum.Enum):
|
||||||
LVM = enum.auto()
|
LVM = enum.auto()
|
||||||
LVM_LUKS = enum.auto()
|
LVM_LUKS = enum.auto()
|
||||||
ZFS = enum.auto()
|
ZFS = enum.auto()
|
||||||
|
ZFS_LUKS = enum.auto()
|
||||||
|
|
||||||
CORE_BOOT_ENCRYPTED = enum.auto()
|
CORE_BOOT_ENCRYPTED = enum.auto()
|
||||||
CORE_BOOT_UNENCRYPTED = enum.auto()
|
CORE_BOOT_UNENCRYPTED = enum.auto()
|
||||||
|
@ -381,7 +382,10 @@ class GuidedCapability(enum.Enum):
|
||||||
]
|
]
|
||||||
|
|
||||||
def is_zfs(self) -> bool:
|
def is_zfs(self) -> bool:
|
||||||
return self in [GuidedCapability.ZFS]
|
return self in [
|
||||||
|
GuidedCapability.ZFS,
|
||||||
|
GuidedCapability.ZFS_LUKS,
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class GuidedDisallowedCapabilityReason(enum.Enum):
|
class GuidedDisallowedCapabilityReason(enum.Enum):
|
||||||
|
|
|
@ -1068,10 +1068,11 @@ LUKS_OVERHEAD = 16 * (2**20)
|
||||||
|
|
||||||
|
|
||||||
@fsobj("dm_crypt")
|
@fsobj("dm_crypt")
|
||||||
class DM_Crypt:
|
class DM_Crypt(_Formattable):
|
||||||
volume: _Formattable = attributes.ref(backlink="_constructed_device")
|
volume: _Formattable = attributes.ref(backlink="_constructed_device")
|
||||||
key: Optional[str] = attr.ib(metadata={"redact": True}, default=None)
|
key: Optional[str] = attr.ib(metadata={"redact": True}, default=None)
|
||||||
keyfile: Optional[str] = None
|
keyfile: Optional[str] = None
|
||||||
|
options: Optional[List[str]] = None
|
||||||
recovery_key: Optional[RecoveryKeyHandler] = None
|
recovery_key: Optional[RecoveryKeyHandler] = None
|
||||||
_recovery_keyfile: Optional[str] = None
|
_recovery_keyfile: Optional[str] = None
|
||||||
_recovery_live_location: Optional[str] = None
|
_recovery_live_location: Optional[str] = None
|
||||||
|
@ -1142,6 +1143,29 @@ class DM_Crypt:
|
||||||
def size(self):
|
def size(self):
|
||||||
return self.volume.size - LUKS_OVERHEAD
|
return self.volume.size - LUKS_OVERHEAD
|
||||||
|
|
||||||
|
def available(self):
|
||||||
|
if self._is_in_use:
|
||||||
|
return False
|
||||||
|
if self._constructed_device is not None:
|
||||||
|
return False
|
||||||
|
if self._fs is None:
|
||||||
|
return True
|
||||||
|
return self._fs._available()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def ok_for_raid(self):
|
||||||
|
if self._fs is not None:
|
||||||
|
if self._fs.preserve:
|
||||||
|
return self._fs._mount is None
|
||||||
|
return False
|
||||||
|
if self._constructed_device is not None:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
@property
|
||||||
|
def ok_for_lvm_vg(self):
|
||||||
|
return self.ok_for_raid and self.size > LVM_OVERHEAD
|
||||||
|
|
||||||
|
|
||||||
@fsobj("device")
|
@fsobj("device")
|
||||||
class ArbitraryDevice(_Device):
|
class ArbitraryDevice(_Device):
|
||||||
|
@ -2081,9 +2105,11 @@ class FilesystemModel:
|
||||||
def add_dm_crypt(
|
def add_dm_crypt(
|
||||||
self,
|
self,
|
||||||
volume,
|
volume,
|
||||||
key,
|
|
||||||
*,
|
*,
|
||||||
recovery_key: Optional[RecoveryKeyHandler],
|
key: Optional[str] = None,
|
||||||
|
keyfile: Optional[str] = None,
|
||||||
|
options: Optional[List[str]] = None,
|
||||||
|
recovery_key: Optional[RecoveryKeyHandler] = None,
|
||||||
root: Optional[pathlib.Path] = None,
|
root: Optional[pathlib.Path] = None,
|
||||||
):
|
):
|
||||||
if not volume.available:
|
if not volume.available:
|
||||||
|
@ -2093,6 +2119,8 @@ class FilesystemModel:
|
||||||
m=self,
|
m=self,
|
||||||
volume=volume,
|
volume=volume,
|
||||||
key=key,
|
key=key,
|
||||||
|
keyfile=keyfile,
|
||||||
|
options=options,
|
||||||
recovery_key=recovery_key,
|
recovery_key=recovery_key,
|
||||||
)
|
)
|
||||||
self._actions.append(dm_crypt)
|
self._actions.append(dm_crypt)
|
||||||
|
|
|
@ -216,6 +216,7 @@ class VariationInfo:
|
||||||
GuidedCapability.LVM,
|
GuidedCapability.LVM,
|
||||||
GuidedCapability.LVM_LUKS,
|
GuidedCapability.LVM_LUKS,
|
||||||
GuidedCapability.ZFS,
|
GuidedCapability.ZFS,
|
||||||
|
GuidedCapability.ZFS_LUKS,
|
||||||
]
|
]
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
@ -563,13 +564,17 @@ class FilesystemController(SubiquityController, FilesystemManipulator):
|
||||||
bootfs_size = align_up(sizes.get_bootfs_size(gap.size), part_align)
|
bootfs_size = align_up(sizes.get_bootfs_size(gap.size), part_align)
|
||||||
gap_boot, gap_rest = gap.split(bootfs_size)
|
gap_boot, gap_rest = gap.split(bootfs_size)
|
||||||
bpart = self.create_partition(device, gap_boot, dict(fstype=None))
|
bpart = self.create_partition(device, gap_boot, dict(fstype=None))
|
||||||
|
encrypted = choice.password is not None
|
||||||
|
|
||||||
avail = gap_rest.size - self._info.min_size
|
avail = gap_rest.size - self._info.min_size
|
||||||
swap_size = align_down(swap.suggested_swapsize(avail=avail), part_align)
|
swap_size = align_down(swap.suggested_swapsize(avail=avail), part_align)
|
||||||
if swap_size > 0:
|
if swap_size > 0:
|
||||||
gap_swap, gap_rootfs = gap_rest.split(swap_size)
|
gap_swap, gap = gap_rest.split(swap_size)
|
||||||
|
if encrypted:
|
||||||
|
part = self.create_partition(device, gap_swap, {})
|
||||||
|
self.create_cryptoswap(part)
|
||||||
|
else:
|
||||||
self.create_partition(device, gap_swap, dict(fstype="swap"))
|
self.create_partition(device, gap_swap, dict(fstype="swap"))
|
||||||
gap = gap_rootfs
|
|
||||||
else:
|
else:
|
||||||
gap = gap_rest
|
gap = gap_rest
|
||||||
rpart = self.create_partition(device, gap, dict(fstype=None))
|
rpart = self.create_partition(device, gap, dict(fstype=None))
|
||||||
|
@ -1386,6 +1391,9 @@ class FilesystemController(SubiquityController, FilesystemManipulator):
|
||||||
capability = GuidedCapability.DD
|
capability = GuidedCapability.DD
|
||||||
assert mode == "reformat_disk"
|
assert mode == "reformat_disk"
|
||||||
elif name == "zfs":
|
elif name == "zfs":
|
||||||
|
if password is not None:
|
||||||
|
capability = GuidedCapability.ZFS_LUKS
|
||||||
|
else:
|
||||||
capability = GuidedCapability.ZFS
|
capability = GuidedCapability.ZFS
|
||||||
else:
|
else:
|
||||||
capability = GuidedCapability.DIRECT
|
capability = GuidedCapability.DIRECT
|
||||||
|
|
|
@ -75,6 +75,7 @@ default_capabilities = [
|
||||||
GuidedCapability.LVM,
|
GuidedCapability.LVM,
|
||||||
GuidedCapability.LVM_LUKS,
|
GuidedCapability.LVM_LUKS,
|
||||||
GuidedCapability.ZFS,
|
GuidedCapability.ZFS,
|
||||||
|
GuidedCapability.ZFS_LUKS,
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@ -567,6 +568,43 @@ class TestGuided(IsolatedAsyncioTestCase):
|
||||||
zfs_boot = self.model._mount_for_path("/boot")
|
zfs_boot = self.model._mount_for_path("/boot")
|
||||||
self.assertEqual("zfs", zfs_boot.type)
|
self.assertEqual("zfs", zfs_boot.type)
|
||||||
|
|
||||||
|
@parameterized.expand(boot_expectations)
|
||||||
|
async def test_guided_zfs_luks(self, bootloader, ptable, p1mnt):
|
||||||
|
await self._guided_setup(bootloader, ptable)
|
||||||
|
target = GuidedStorageTargetReformat(
|
||||||
|
disk_id=self.d1.id, allowed=default_capabilities
|
||||||
|
)
|
||||||
|
await self.controller.guided(
|
||||||
|
GuidedChoiceV2(
|
||||||
|
target=target,
|
||||||
|
capability=GuidedCapability.ZFS_LUKS,
|
||||||
|
password="passw0rd",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
[firmware, boot, swap, root] = self.d1.partitions()
|
||||||
|
self.assertEqual(p1mnt, firmware.mount)
|
||||||
|
self.assertIsNone(boot.mount)
|
||||||
|
self.assertIsNone(root.mount)
|
||||||
|
self.assertFalse(firmware.preserve)
|
||||||
|
self.assertFalse(boot.preserve)
|
||||||
|
self.assertFalse(swap.preserve)
|
||||||
|
self.assertFalse(root.preserve)
|
||||||
|
self.assertIsNone(swap.fs())
|
||||||
|
[dmc] = self.model.all_dm_crypts()
|
||||||
|
self.assertEqual("/dev/urandom", dmc.keyfile)
|
||||||
|
self.assertEqual(["swap", "initramfs"], dmc.options)
|
||||||
|
self.assertEqual("swap", dmc.fs().fstype)
|
||||||
|
[rpool] = self.model._all(type="zpool", pool="rpool")
|
||||||
|
self.assertIsNone(rpool.path)
|
||||||
|
self.assertEqual([root], rpool.vdevs)
|
||||||
|
[bpool] = self.model._all(type="zpool", pool="bpool")
|
||||||
|
self.assertIsNone(bpool.path)
|
||||||
|
self.assertEqual([boot], bpool.vdevs)
|
||||||
|
zfs_rootfs = self.model._mount_for_path("/")
|
||||||
|
self.assertEqual("zfs", zfs_rootfs.type)
|
||||||
|
zfs_boot = self.model._mount_for_path("/boot")
|
||||||
|
self.assertEqual("zfs", zfs_boot.type)
|
||||||
|
|
||||||
async def test_guided_zfs_BIOS_MSDOS(self):
|
async def test_guided_zfs_BIOS_MSDOS(self):
|
||||||
await self._guided_setup(Bootloader.BIOS, "msdos")
|
await self._guided_setup(Bootloader.BIOS, "msdos")
|
||||||
target = GuidedStorageTargetReformat(
|
target = GuidedStorageTargetReformat(
|
||||||
|
|
Loading…
Reference in New Issue