Merge pull request #476 from mwhudson/fstype-defensiveness

rework how we handle filesystem types a bit
This commit is contained in:
Michael Hudson-Doyle 2019-05-10 12:09:13 +12:00 committed by GitHub
commit ab4ef05a62
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 62 additions and 88 deletions

View File

@ -160,9 +160,6 @@ class FilesystemController(BaseController):
return dev
raise Exception("could not resolve {}".format(id))
def _action_clean_fstype(self, fstype):
return self.model.fs_by_name[fstype]
def _action_clean_devices_raid(self, devices):
return {
self._action_get(d): v
@ -268,15 +265,15 @@ class FilesystemController(BaseController):
self.model.remove_mount(mount)
def create_filesystem(self, volume, spec):
if spec['fstype'] is None or spec['fstype'].label is None:
if spec['fstype'] is None:
return
fs = self.model.add_filesystem(volume, spec['fstype'].label)
fs = self.model.add_filesystem(volume, spec['fstype'])
if isinstance(volume, Partition):
if spec['fstype'].label == "swap":
if spec['fstype'] == "swap":
volume.flag = "swap"
elif volume.flag == "swap":
volume.flag = ""
if spec['fstype'].label == "swap":
if spec['fstype'] == "swap":
self.model.add_mount(fs, "")
self.create_mount(fs, spec)
return fs
@ -304,19 +301,13 @@ class FilesystemController(BaseController):
log.debug('Adding EFI partition first')
part = self.create_partition(
disk,
dict(
size=part_size,
fstype=self.model.fs_by_name['fat32'],
mount='/boot/efi'),
dict(size=part_size, fstype='fat32', mount='/boot/efi'),
flag="boot")
elif self.is_prep():
log.debug('Adding PReP gpt partition first')
part = self.create_partition(
disk,
dict(
size=PREP_GRUB_SIZE_BYTES,
fstype=None,
mount=None),
dict(size=PREP_GRUB_SIZE_BYTES, fstype=None, mount=None),
# must be wiped or grub-install will fail
wipe='zero',
flag='prep')
@ -324,10 +315,7 @@ class FilesystemController(BaseController):
log.debug('Adding grub_bios gpt partition first')
part = self.create_partition(
disk,
dict(
size=BIOS_GRUB_SIZE_BYTES,
fstype=None,
mount=None),
dict(size=BIOS_GRUB_SIZE_BYTES, fstype=None, mount=None),
flag='bios_grub')
# should _not_ specify grub device for prep
if not self.is_prep():

View File

@ -84,12 +84,6 @@ def dependencies(obj):
yield from v
@attr.s(cmp=False)
class FS:
label = attr.ib()
is_mounted = attr.ib()
@attr.s(cmp=False)
class RaidLevel:
name = attr.ib()
@ -823,8 +817,7 @@ class Filesystem:
def _available(self):
# False if mounted or if fs does not require a mount, True otherwise.
if self._mount is None:
fs_obj = FilesystemModel.fs_by_name[self.fstype]
return fs_obj.is_mounted
return FilesystemModel.is_mounted_filesystem(self.fstype)
else:
return False
@ -862,26 +855,12 @@ class FilesystemModel(object):
lower_size_limit = 128 * (1 << 20)
supported_filesystems = [
('ext4', True, FS('ext4', True)),
('xfs', True, FS('xfs', True)),
('btrfs', True, FS('btrfs', True)),
('---', False),
('swap', True, FS('swap', False)),
('---', False),
('leave unformatted', True, FS(None, False)),
]
fs_by_name = {}
longest_fs_name = 0
for t in supported_filesystems:
if len(t) > 2:
fs = t[2]
if fs.label is not None:
if len(fs.label) > longest_fs_name:
longest_fs_name = len(fs.label)
fs_by_name[fs.label] = fs
fs_by_name['fat32'] = FS('fat32', True)
@classmethod
def is_mounted_filesystem(self, fstype):
if fstype in [None, 'swap']:
return False
else:
return True
def __init__(self):
self._disk_info = []

View File

@ -148,7 +148,7 @@ class GuidedDiskSelectionView(BaseView):
if self.method == "direct":
result = {
"size": disk.free_for_partitions,
"fstype": self.model.fs_by_name["ext4"],
"fstype": "ext4",
"mount": "/",
}
self.controller.partition_disk_handler(disk, None, result)
@ -158,7 +158,7 @@ class GuidedDiskSelectionView(BaseView):
self.controller.create_partition(
device=disk, spec=dict(
size=dehumanize_size('1G'),
fstype=self.model.fs_by_name['ext4'],
fstype="ext4",
mount='/boot'
))
part = self.controller.create_partition(
@ -175,7 +175,7 @@ class GuidedDiskSelectionView(BaseView):
vg=vg, spec=dict(
size=dehumanize_size("4G"),
name="ubuntu-lv",
fstype=self.model.fs_by_name['ext4'],
fstype="ext4",
mount="/",
))
else:

View File

@ -38,7 +38,6 @@ from subiquitycore.ui.stretchy import Stretchy
from subiquity.models.filesystem import (
align_up,
Disk,
FilesystemModel,
HUMAN_UNITS,
dehumanize_size,
humanize_size,
@ -55,7 +54,20 @@ class FSTypeField(FormField):
takes_default_style = False
def _make_widget(self, form):
return Selector(opts=FilesystemModel.supported_filesystems)
# This will need to do something different for editing an
# existing partition that is already formatted.
options = [
('ext4', True),
('xfs', True),
('btrfs', True),
('---', False),
('swap', True),
('---', False),
('leave unformatted', True, None),
]
sel = Selector(opts=options)
sel.value = None
return sel
class SizeWidget(StringEditor):
@ -116,9 +128,13 @@ LVNameField = simple_field(LVNameEditor)
class PartitionForm(Form):
def __init__(self, mountpoints, max_size, initial, ok_for_slash_boot,
def __init__(self, model, max_size, initial, ok_for_slash_boot,
lvm_names):
self.mountpoints = mountpoints
self.model = model
initial_path = initial.get('mount')
self.mountpoints = {
m.path: m.device.volume for m in self.model.all_mounts()
if m.path != initial_path}
self.ok_for_slash_boot = ok_for_slash_boot
self.max_size = max_size
if max_size is not None:
@ -131,8 +147,8 @@ class PartitionForm(Form):
connect_signal(self.fstype.widget, 'select', self.select_fstype)
self.select_fstype(None, self.fstype.widget.value)
def select_fstype(self, sender, fs):
self.mount.enabled = fs.is_mounted
def select_fstype(self, sender, fstype):
self.mount.enabled = self.model.is_mounted_filesystem(fstype)
name = LVNameField(_("Name: "))
size = SizeField()
@ -151,7 +167,7 @@ class PartitionForm(Form):
return dehumanize_size(val)
def clean_mount(self, val):
if self.fstype.value.is_mounted:
if self.model.is_mounted_filesystem(self.fstype):
return val
else:
return None
@ -218,15 +234,12 @@ prep_partition_description = _(
class PartitionStretchy(Stretchy):
def __init__(self, parent, disk, partition=None):
self.disk = disk
self.partition = partition
self.model = parent.model
self.controller = parent.controller
self.parent = parent
max_size = disk.free_for_partitions
mountpoints = {
m.path: m.device.volume for m in self.model.all_mounts()}
initial = {}
label = _("Create")
@ -245,29 +258,28 @@ class PartitionStretchy(Stretchy):
fs = self.partition.fs()
if fs is not None:
if partition.flag != "boot":
initial['fstype'] = self.model.fs_by_name[fs.fstype]
initial['fstype'] = fs.fstype
mount = fs.mount()
if mount is not None:
initial['mount'] = mount.path
del mountpoints[mount.path]
else:
initial['mount'] = None
else:
initial['fstype'] = self.model.fs_by_name[None]
if isinstance(disk, LVM_VolGroup):
initial['name'] = partition.name
lvm_names.remove(partition.name)
elif isinstance(disk, LVM_VolGroup):
x = 0
while True:
name = 'lv-{}'.format(x)
if name not in lvm_names:
break
x += 1
initial['name'] = name
else:
initial['fstype'] = 'ext4'
if isinstance(disk, LVM_VolGroup):
x = 0
while True:
name = 'lv-{}'.format(x)
if name not in lvm_names:
break
x += 1
initial['name'] = name
self.form = PartitionForm(
mountpoints, max_size, initial, isinstance(disk, Disk), lvm_names)
self.model, max_size, initial, isinstance(disk, Disk), lvm_names)
if not isinstance(disk, LVM_VolGroup):
self.form.remove_field('name')
@ -280,9 +292,7 @@ class PartitionStretchy(Stretchy):
if partition is not None:
if partition.flag == "boot":
opts = [
Option(("fat32", True, self.model.fs_by_name["fat32"])),
]
opts = [Option(("fat32", True))]
self.form.fstype.widget.options = opts
self.form.fstype.widget.index = 0
self.form.mount.enabled = False
@ -344,7 +354,7 @@ class PartitionStretchy(Stretchy):
log.debug("Add Partition Result: {}".format(form.as_data()))
data = form.as_data()
if self.partition is not None and self.partition.flag == "boot":
data['fstype'] = self.model.fs_by_name[self.partition.fs().fstype]
data['fstype'] = self.partition.fs().fstype
data['mount'] = self.partition.fs().mount().path
if isinstance(self.disk, LVM_VolGroup):
handler = self.controller.logical_volume_handler
@ -363,20 +373,17 @@ class FormatEntireStretchy(Stretchy):
self.model = parent.model
self.controller = parent.controller
self.parent = parent
mountpoints = {
m.path: m.device.volume for m in self.model.all_mounts()}
initial = {}
fs = device.fs()
if fs is not None:
initial['fstype'] = self.model.fs_by_name[fs.fstype]
initial['fstype'] = fs.fstype
mount = fs.mount()
if mount is not None:
initial['mount'] = mount.path
del mountpoints[mount.path]
else:
initial['fstype'] = self.model.fs_by_name[None]
self.form = PartitionForm(mountpoints, 0, initial, False, {})
elif not isinstance(device, Disk):
initial['fstype'] = 'ext4'
self.form = PartitionForm(self.model, 0, initial, False, None)
self.form.remove_field('size')
self.form.remove_field('name')

View File

@ -54,7 +54,7 @@ class PartitionViewTests(unittest.TestCase):
def test_create_partition(self):
valid_data = {
'size': "1M",
'fstype': FilesystemModel.fs_by_name["ext4"],
'fstype': "ext4",
}
model, disk = make_model_and_disk()
view, stretchy = make_view(model, disk)
@ -68,7 +68,7 @@ class PartitionViewTests(unittest.TestCase):
def test_edit_partition(self):
form_data = {
'size': "256M",
'fstype': FilesystemModel.fs_by_name['xfs'],
'fstype': "xfs",
}
model, disk = make_model_and_disk()
partition = model.add_partition(disk, 512*(2**20))
@ -79,7 +79,7 @@ class PartitionViewTests(unittest.TestCase):
view_helpers.click(stretchy.form.done_btn.base_widget)
expected_data = {
'size': dehumanize_size(form_data['size']),
'fstype': FilesystemModel.fs_by_name['xfs'],
'fstype': 'xfs',
'mount': None,
}
view.controller.partition_disk_handler.assert_called_once_with(
@ -98,7 +98,7 @@ class PartitionViewTests(unittest.TestCase):
view_helpers.click(stretchy.form.done_btn.base_widget)
expected_data = {
'size': dehumanize_size(form_data['size']),
'fstype': FilesystemModel.fs_by_name["fat32"],
'fstype': "fat32",
'mount': '/boot/efi',
}
view.controller.partition_disk_handler.assert_called_once_with(