diff --git a/subiquity/ui/views/filesystem/partition.py b/subiquity/ui/views/filesystem/partition.py index 1e7cd7f0..eb0743b6 100644 --- a/subiquity/ui/views/filesystem/partition.py +++ b/subiquity/ui/views/filesystem/partition.py @@ -21,6 +21,7 @@ configuration. """ import logging import re +from typing import Optional from urwid import Text, connect_signal @@ -89,6 +90,7 @@ class FSTypeField(FormField): class SizeWidget(StringEditor): def __init__(self, form): self.form = form + self.accurate_value: Optional[int] = None super().__init__() def lost_focus(self): @@ -114,6 +116,9 @@ class SizeWidget(StringEditor): ), ) ) + # This will invoke self.form.clean_size() and it is expected that + # size_str (and therefore self.value) are propertly aligned. + self.accurate_value = self.form.size else: aligned_sz = align_up(sz, self.form.alignment) aligned_sz_str = humanize_size(aligned_sz) @@ -125,6 +130,7 @@ class SizeWidget(StringEditor): _("Rounded size up to {size}").format(size=aligned_sz_str), ) ) + self.accurate_value = aligned_sz class SizeField(FormField): diff --git a/subiquity/ui/views/filesystem/tests/test_partition.py b/subiquity/ui/views/filesystem/tests/test_partition.py index ab5363aa..8189b9a6 100644 --- a/subiquity/ui/views/filesystem/tests/test_partition.py +++ b/subiquity/ui/views/filesystem/tests/test_partition.py @@ -5,7 +5,7 @@ import urwid from subiquity.client.controllers.filesystem import FilesystemController from subiquity.common.filesystem import gaps -from subiquity.models.filesystem import dehumanize_size +from subiquity.models.filesystem import MiB, dehumanize_size from subiquity.models.tests.test_filesystem import make_model_and_disk from subiquity.ui.views.filesystem.partition import ( FormatEntireStretchy, @@ -58,6 +58,7 @@ class PartitionViewTests(unittest.TestCase): gap = gaps.Gap(device=disk, offset=1 << 20, size=99 << 30) view, stretchy = make_partition_view(model, disk, gap=gap) view_helpers.enter_data(stretchy.form, valid_data) + stretchy.form.size.widget.lost_focus() view_helpers.click(stretchy.form.done_btn.base_widget) valid_data["mount"] = "/" valid_data["size"] = dehumanize_size(valid_data["size"]) @@ -77,6 +78,7 @@ class PartitionViewTests(unittest.TestCase): view, stretchy = make_partition_view(model, disk, partition=partition) self.assertTrue(stretchy.form.done_btn.enabled) view_helpers.enter_data(stretchy.form, form_data) + stretchy.form.size.widget.lost_focus() view_helpers.click(stretchy.form.done_btn.base_widget) expected_data = { "size": dehumanize_size(form_data["size"]), @@ -111,6 +113,7 @@ class PartitionViewTests(unittest.TestCase): self.assertFalse(stretchy.form.size.enabled) self.assertTrue(stretchy.form.done_btn.enabled) view_helpers.enter_data(stretchy.form, form_data) + stretchy.form.size.widget.lost_focus() view_helpers.click(stretchy.form.done_btn.base_widget) expected_data = { "fstype": "xfs", @@ -177,6 +180,7 @@ class PartitionViewTests(unittest.TestCase): self.assertEqual(stretchy.form.mount.value, "/boot/efi") view_helpers.enter_data(stretchy.form, form_data) + stretchy.form.size.widget.lost_focus() view_helpers.click(stretchy.form.done_btn.base_widget) expected_data = { "size": dehumanize_size(form_data["size"]), @@ -246,3 +250,26 @@ class PartitionViewTests(unittest.TestCase): model._orig_config = model._render_actions() view, stretchy = make_format_entire_view(model, disk) self.assertEqual(stretchy.form.fstype.value, None) + + def test_create_partition_unaligned_size(self): + # In LP: #2013201, the user would type in 1.1G and the partition + # created would not be aligned to a MiB boundary. + unaligned_data = { + "size": "1.1G", # Corresponds to 1181116006.4 bytes (not an int) + "fstype": "ext4", + } + valid_data = { + "mount": "/", + "size": 1127 * MiB, # ~1.10058 GiB + "use_swap": False, + "fstype": "ext4", + } + model, disk = make_model_and_disk() + gap = gaps.Gap(device=disk, offset=1 << 20, size=99 << 30) + view, stretchy = make_partition_view(model, disk, gap=gap) + view_helpers.enter_data(stretchy.form, unaligned_data) + stretchy.form.size.widget.lost_focus() + view_helpers.click(stretchy.form.done_btn.base_widget) + view.controller.partition_disk_handler.assert_called_once_with( + stretchy.disk, valid_data, partition=None, gap=gap + ) diff --git a/subiquitycore/ui/form.py b/subiquitycore/ui/form.py index ea73c588..ad248dad 100644 --- a/subiquitycore/ui/form.py +++ b/subiquitycore/ui/form.py @@ -531,7 +531,11 @@ class Form(object, metaclass=MetaForm): data = {} for field in self._fields: if field.enabled: - data[field.field.name] = field.value + accurate_value = getattr(field.widget, "accurate_value", None) + if accurate_value is not None: + data[field.field.name] = accurate_value + else: + data[field.field.name] = field.value return data