convert AddPartitionView and add_disk_partition_handler to new world order

This commit is contained in:
Michael Hudson-Doyle 2017-03-10 12:55:59 +13:00
parent 2a250effef
commit f9ebcb3e25
5 changed files with 84 additions and 76 deletions

View File

@ -125,62 +125,38 @@ class FilesystemController(BaseController):
self.ui.set_body(adp_view) self.ui.set_body(adp_view)
def add_disk_partition_handler(self, disk, spec): def add_disk_partition_handler(self, disk, spec):
current_disk = self.model.get_disk(disk)
log.debug('spec: {}'.format(spec)) log.debug('spec: {}'.format(spec))
log.debug('disk.freespace: {}'.format(current_disk.freespace)) log.debug('disk.freespace: {}'.format(disk.free))
try: system_bootable = self.model.bootable()
''' create a gpt boot partition if one doesn't exist, only log.debug('model has bootable device? {}'.format(system_bootable))
one one disk''' if not system_bootable and len(disk._partitions) == 0:
if self.is_uefi():
system_bootable = self.model.bootable() log.debug('Adding EFI partition first')
log.debug('model has bootable device? {}'.format(system_bootable)) part = self.model.add_partition(disk=disk, partnum=1, size=UEFI_GRUB_SIZE_BYTES, flag='bios_grub')
if system_bootable is False and \ fs = self.model.add_filesystem(part, 'fat32')
current_disk.parttype == 'gpt' and \ self.model.add_mount(fs, '/boot/efi')
len(current_disk.disk.partitions) == 0:
if self.is_uefi():
log.debug('Adding EFI partition first')
size_added = \
current_disk.add_partition(partnum=1,
size=UEFI_GRUB_SIZE_BYTES,
flag='bios_grub',
fstype='fat32',
mountpoint='/boot/efi')
else:
log.debug('Adding grub_bios gpt partition first')
size_added = \
current_disk.add_partition(partnum=1,
size=BIOS_GRUB_SIZE_BYTES,
fstype=None,
flag='bios_grub')
current_disk.set_tag('(boot)')
# adjust downward the partition size to accommodate
# the offset and bios/grub partition
log.debug("Adjusting request down:" +
"{} - {} = {}".format(spec['bytes'], size_added,
spec['bytes'] - size_added))
spec['bytes'] -= size_added
spec['partnum'] = 2
if spec["fstype"] in ["swap"]:
current_disk.add_partition(partnum=spec["partnum"],
size=spec["bytes"],
fstype=spec["fstype"])
else: else:
current_disk.add_partition(partnum=spec["partnum"], log.debug('Adding grub_bios gpt partition first')
size=spec["bytes"], part = self.model.add_partition(disk=disk, partnum=1, size=BIOS_GRUB_SIZE_BYTES, flag='bios_grub')
fstype=spec["fstype"], disk.grub_device = True
mountpoint=spec["mountpoint"])
except Exception: # adjust downward the partition size to accommodate
log.exception('Failed to add disk partition') # the offset and bios/grub partition
log.debug('Returning to add-disk-partition') # XXX should probably only do this if the partition is now too big to fit on the disk?
# FIXME: on failure, we should repopulate input values log.debug("Adjusting request down:" +
self.add_disk_partition(disk) "{} - {} = {}".format(spec['bytes'], part.size,
spec['bytes'] - part.size))
spec['bytes'] -= part.size
spec['partnum'] = 2
part = self.model.add_partition(disk=disk, partnum=spec["partnum"], size=spec["bytes"])
if spec['fstype'] is not None:
fs = self.model.add_filesystem(part, spec['fstype'])
if spec['mountpoint']:
self.model.add_mount(fs, spec['mountpoint'])
log.info("Successfully added partition") log.info("Successfully added partition")
log.debug("FS Table: {}".format(current_disk.get_fs_table()))
self.prev_view() self.prev_view()
def add_disk_format_handler(self, disk, spec): def add_disk_format_handler(self, disk, spec):

View File

@ -659,7 +659,7 @@ class Disk:
@property @property
def next_partnum(self): def next_partnum(self):
return len(self._partitions) return len(self._partitions) + 1
@property @property
def size(self): def size(self):
@ -698,7 +698,7 @@ class Partition:
@property @property
def path(self): def path(self):
return "%s%s"(self.device.path, self.number) return "%s%s"%(self.device.path, self.number)
def render(self): def render(self):
r = asdict(self) r = asdict(self)
@ -731,6 +731,18 @@ class Mount:
class FilesystemModel(object): class FilesystemModel(object):
supported_filesystems = [
('ext4', True, FS('ext4', True)),
('xfs', True, FS('xfs', True)),
('btrfs', True, FS('btrfs', True)),
('---', False),
('swap', True, FS('swap', False)),
('bcache cache', True, FS('bcache cache', False)),
('bcache store', True, FS('bcache store', False)),
('---', False),
('leave unformatted', True, FS('leave unformatted', False)),
]
def __init__(self, prober, opts): def __init__(self, prober, opts):
self.prober = prober self.prober = prober
self.opts = opts self.opts = opts
@ -796,9 +808,10 @@ class FilesystemModel(object):
def get_disk(self, path): def get_disk(self, path):
return self._available_disks.get(path) return self._available_disks.get(path)
def add_partition(self, disk, partnum, size): def add_partition(self, disk, partnum, size, flag=""):
## XXX check, round, maybe adjust size?
self._use_disk(disk) self._use_disk(disk)
p = Partition(device=disk, number=partnum, size=size) p = Partition(device=disk, number=partnum, size=size, flag=flag)
disk._partitions.append(p) disk._partitions.append(p)
self._partitions.append(p) self._partitions.append(p)
return p return p
@ -830,3 +843,21 @@ class FilesystemModel(object):
def can_install(self): def can_install(self):
# Need to figure out stuff to do with grub & a boot partition # Need to figure out stuff to do with grub & a boot partition
return '/' in self.get_mountpoint_to_devpath_mapping() return '/' in self.get_mountpoint_to_devpath_mapping()
def validate_mount(self, mountpoint):
if mountpoint is None:
return
# /usr/include/linux/limits.h:PATH_MAX
if len(mountpoint) > 4095:
return 'Path exceeds PATH_MAX'
mnts = self.get_mountpoint_to_devpath_mapping()
dev = mnts.get(mountpoint)
if dev is not None:
return "%s is already mounted at %s"%(dev, mountpoint)
def bootable(self):
''' true if one disk has a boot partition '''
for p in self._partitions:
if p.flag == 'bios_grub':
return True
return False

View File

@ -37,7 +37,7 @@ LEAVE_UNMOUNTED = object()
class MountSelector(WidgetWrap): class MountSelector(WidgetWrap):
def __init__(self, model): def __init__(self, model):
mounts = model.get_mounts() mounts = model.get_mountpoint_to_devpath_mapping()
opts = [] opts = []
first_opt = None first_opt = None
max_len = max(map(len, common_mountpoints)) max_len = max(map(len, common_mountpoints))

View File

@ -54,13 +54,17 @@ class FSTypeField(FormField):
class AddPartitionForm(Form): class AddPartitionForm(Form):
def __init__(self, model, disk_obj): def __init__(self, model, disk):
self.model = model self.model = model
self.disk_obj = disk_obj self.disk = disk
self.size_str = _humanize_size(disk_obj.freespace) self.size_str = _humanize_size(disk.free)
super().__init__() super().__init__()
self.size.caption = "Size (max {})".format(self.size_str) self.size.caption = "Size (max {})".format(self.size_str)
self.partnum.value = str(self.disk_obj.lastpartnumber + 1) self.partnum.value = self.disk.next_partnum
connect_signal(self.fstype.widget, 'select', self.select_fstype)
def select_fstype(self, sender, fs):
self.mount.enabled = fs.is_mounted
partnum = IntegerField("Partition number") partnum = IntegerField("Partition number")
size = StringField() size = StringField()
@ -81,7 +85,7 @@ class AddPartitionForm(Form):
v += unit v += unit
self.size.value = v self.size.value = v
sz = _dehumanize_size(v) sz = _dehumanize_size(v)
if sz > self.disk_obj.freespace: if sz > self.disk.free:
self.size.value = self.size_str self.size.value = self.size_str
self.size.show_extra(Color.info_minor(Text("Capped partition size at %s"%(self.size_str,), align="center"))) self.size.show_extra(Color.info_minor(Text("Capped partition size at %s"%(self.size_str,), align="center")))
@ -91,24 +95,22 @@ class AddPartitionForm(Form):
class AddPartitionView(BaseView): class AddPartitionView(BaseView):
def __init__(self, model, controller, selected_disk): def __init__(self, model, controller, disk):
log.debug('AddPartitionView: selected_disk=[{}]'.format(selected_disk)) log.debug('AddPartitionView: selected_disk=[{}]'.format(disk.path))
self.model = model self.model = model
self.controller = controller self.controller = controller
self.selected_disk = selected_disk self.disk = disk
self.disk_obj = self.model.get_disk(selected_disk)
self.form = AddPartitionForm(model, self.disk_obj) self.form = AddPartitionForm(model, self.disk)
connect_signal(self.form, 'submit', self.done) connect_signal(self.form, 'submit', self.done)
connect_signal(self.form, 'cancel', self.cancel) connect_signal(self.form, 'cancel', self.cancel)
connect_signal(self.form.fstype.widget, 'select', self.select_fstype)
body = [ body = [
Columns( Columns(
[ [
("weight", 0.2, Text("Adding partition to {}".format( ("weight", 0.2, Text("Adding partition to {}".format(
self.disk_obj.devpath), align="right")), self.disk.path), align="right")),
("weight", 0.3, Text("")) ("weight", 0.3, Text(""))
] ]
), ),
@ -120,9 +122,6 @@ class AddPartitionView(BaseView):
partition_box = Padding.center_50(ListBox(body)) partition_box = Padding.center_50(ListBox(body))
super().__init__(partition_box) super().__init__(partition_box)
def select_fstype(self, sender, fs):
self.form.mount.enabled = fs.is_mounted
def cancel(self, button): def cancel(self, button):
self.controller.prev_view() self.controller.prev_view()
@ -137,10 +136,10 @@ class AddPartitionView(BaseView):
if self.form.size.value: if self.form.size.value:
size = _dehumanize_size(self.form.size.value) size = _dehumanize_size(self.form.size.value)
if size > self.disk_obj.freespace: if size > self.disk.free:
size = self.disk_obj.freespace size = self.disk.free
else: else:
size = self.disk_obj.freespace size = self.disk.free
result = { result = {
"partnum": self.form.partnum.value, "partnum": self.form.partnum.value,
@ -151,4 +150,4 @@ class AddPartitionView(BaseView):
} }
log.debug("Add Partition Result: {}".format(result)) log.debug("Add Partition Result: {}".format(result))
self.controller.add_disk_partition_handler(self.disk_obj.devpath, result) self.controller.add_disk_partition_handler(self.disk, result)

View File

@ -67,7 +67,7 @@ class DiskPartitionView(BaseView):
mountpoint = '-' mountpoint = '-'
else: else:
fstype = part._fs.fstype fstype = part._fs.fstype
mountpoint = part._fs.path mountpoint = part._fs._mount.path
partition_column = Columns([ partition_column = Columns([
(15, Text(path)), (15, Text(path)),
Text(size), Text(size),
@ -124,6 +124,8 @@ class DiskPartitionView(BaseView):
""" Handles presenting the add partition widget button """ Handles presenting the add partition widget button
depending on if partitions exist already or not. depending on if partitions exist already or not.
""" """
if not self.disk.available:
return None
text = "Add first partition" text = "Add first partition"
if len(self.disk._partitions) > 0: if len(self.disk._partitions) > 0:
text = "Add partition (max size {})".format( text = "Add partition (max size {})".format(