From 52127d1997c5b2a8df313ec568e7c3e92783c408 Mon Sep 17 00:00:00 2001 From: Michael Hudson-Doyle Date: Fri, 10 Mar 2017 14:30:48 +1300 Subject: [PATCH] can render actions now --- subiquity/controllers/filesystem.py | 10 +++-- subiquity/curtin.py | 6 +++ subiquity/models/filesystem.py | 44 +++++++++++-------- .../ui/views/filesystem/disk_partition.py | 25 ++++++----- subiquity/ui/views/filesystem/filesystem.py | 15 ++++--- 5 files changed, 62 insertions(+), 38 deletions(-) diff --git a/subiquity/controllers/filesystem.py b/subiquity/controllers/filesystem.py index a28eac4e..735279cf 100644 --- a/subiquity/controllers/filesystem.py +++ b/subiquity/controllers/filesystem.py @@ -45,6 +45,7 @@ class FilesystemController(BaseController): # self.iscsi_model = IscsiDiskModel() # self.ceph_model = CephDiskModel() self.raid_model = RaidModel() + self.model.probe() # probe before we complete @view def default(self, reset=False): @@ -76,17 +77,20 @@ class FilesystemController(BaseController): self.ui.set_footer(footer, 30) self.ui.set_body(ErrorView(self.signal, error_msg)) - def finish(self, actions): + def finish(self): log.info("Rendering curtin config from user choices") try: - curtin_write_storage_actions(actions=actions) + curtin_write_storage_actions(actions=self.model.render()) except PermissionError: log.exception('Failed to write storage actions') self.filesystem_error('curtin_write_storage_actions') return None log.info("Rendering preserved config for post install") - preserved_actions = [preserve_action(a) for a in actions] + preserved_actions = [] + for a in self.model.render(): + a['preserve'] = True + preserved_actions.append(a) try: curtin_write_preserved_actions(actions=preserved_actions) except PermissionError: diff --git a/subiquity/curtin.py b/subiquity/curtin.py index fc701020..5901b093 100644 --- a/subiquity/curtin.py +++ b/subiquity/curtin.py @@ -132,6 +132,12 @@ def curtin_write_storage_actions(actions): conf.write(curtin_config) conf.close() +from collections import OrderedDict +def setup_yaml(): + """ http://stackoverflow.com/a/8661021 """ + represent_dict_order = lambda self, data: self.represent_mapping('tag:yaml.org,2002:map', data.items()) + yaml.add_representer(OrderedDict, represent_dict_order) +setup_yaml() def curtin_write_network_actions(actions): curtin_config = yaml.dump(actions, default_flow_style=False) diff --git a/subiquity/models/filesystem.py b/subiquity/models/filesystem.py index f037101d..43f87fda 100644 --- a/subiquity/models/filesystem.py +++ b/subiquity/models/filesystem.py @@ -620,14 +620,17 @@ def id_factory(name): return r return attr.Factory(factory) -def filter_false(attr, val): - if attr.name.startswith('_'): - return False - return bool(val) - def asdict(inst): - return inst.asdict( - recurse=False, filter=filter_false, dict_factory=collections.OrderedDict) + r = collections.OrderedDict() + for field in attr.fields(type(inst)): + if field.name.startswith('_'): + continue + v = getattr(inst, field.name) + if v: + if hasattr(v, 'id'): + v = v.id + r[field.name] = v + return r @attr.s class Disk: @@ -655,7 +658,7 @@ class Disk: @property def available(self): - return self.used < self.size and self._fs is None + return self.used < self.size @property def next_partnum(self): @@ -678,9 +681,6 @@ class Disk: def free(self): return self.size - self.used - def render(self): - return asdict(self) - @attr.s class Partition: id = attr.ib(default=id_factory("part")) @@ -730,6 +730,11 @@ class Mount: device = attr.ib(default=None) # validator=attr.validators.instance_of((Filesystem, type(None))), path = attr.ib(default=None) + def render(self): + r = asdict(self) + r['device'] = self.device.id + return r + class FilesystemModel(object): @@ -760,13 +765,13 @@ class FilesystemModel(object): def render(self): r = [] for d in self._disks.values(): - r.append(d.render()) + r.append(asdict(d)) for p in self._partitions: - r.append(p.render()) - for f in self._formats: - r.append(f.format()) + r.append(asdict(p)) + for f in self._filesystems: + r.append(asdict(f)) for m in self._mounts: - r.append(m.format()) + r.append(asdict(m)) return r def _get_system_mounted_disks(self): @@ -813,12 +818,15 @@ class FilesystemModel(object): def add_partition(self, disk, partnum, size, flag=""): ## XXX check, round, maybe adjust size? self._use_disk(disk) + if disk._fs is not None: + raise Exception("%s is already formatted" % (disk.path,)) p = Partition(device=disk, number=partnum, size=size, flag=flag) disk._partitions.append(p) self._partitions.append(p) return p def add_filesystem(self, volume, fstype): + log.debug("adding %s to %s", fstype, volume) if not volume.available: raise Exception("%s is not available", volume) if isinstance(volume, Disk): @@ -843,8 +851,8 @@ class FilesystemModel(object): return r def can_install(self): - # Need to figure out stuff to do with grub & a boot partition - return '/' in self.get_mountpoint_to_devpath_mapping() + # Do we need to check that there is a disk with the boot flag? + return '/' in self.get_mountpoint_to_devpath_mapping() and self.bootable() def validate_mount(self, mountpoint): if mountpoint is None: diff --git a/subiquity/ui/views/filesystem/disk_partition.py b/subiquity/ui/views/filesystem/disk_partition.py index 74cb8e9d..f7dbc657 100644 --- a/subiquity/ui/views/filesystem/disk_partition.py +++ b/subiquity/ui/views/filesystem/disk_partition.py @@ -56,7 +56,7 @@ class DiskPartitionView(BaseView): def _build_model_inputs(self): partitioned_disks = [] - for part in self.disk._partitions: + def format_volume(part): path = part.path size = _humanize_size(part.size) if part._fs is None: @@ -68,20 +68,25 @@ class DiskPartitionView(BaseView): else: fstype = part._fs.fstype mountpoint = part._fs._mount.path - partition_column = Columns([ + return Columns([ (15, Text(path)), Text(size), Text(fstype), Text(mountpoint), ], 4) - partitioned_disks.append(partition_column) - free_space = _humanize_size(self.disk.free) - partitioned_disks.append(Columns([ - (15, Text("FREE SPACE")), - Text(free_space), - Text(""), - Text("") - ], 4)) + if self.disk._fs is not None: + partitioned_disks.append(format_volume(self.disk)) + else: + for part in self.disk._partitions: + partitioned_disks.append(format_volume(part)) + if self.disk.free > 0: + free_space = _humanize_size(self.disk.free) + partitioned_disks.append(Columns([ + (15, Text("FREE SPACE")), + Text(free_space), + Text(""), + Text("") + ], 4)) return BoxAdapter(SimpleList(partitioned_disks, is_selectable=False), height=len(partitioned_disks)) diff --git a/subiquity/ui/views/filesystem/filesystem.py b/subiquity/ui/views/filesystem/filesystem.py index 707f4817..2bff585e 100644 --- a/subiquity/ui/views/filesystem/filesystem.py +++ b/subiquity/ui/views/filesystem/filesystem.py @@ -43,7 +43,6 @@ class FilesystemView(BaseView): self.model = model self.controller = controller self.items = [] - self.model.probe() # probe before we complete self.body = [ Padding.center_79(Text("FILE SYSTEM")), Padding.center_79(self._build_filesystem_list()), @@ -88,10 +87,10 @@ class FilesystemView(BaseView): pl = [] for m in mounts: col = Columns([ - (15, m.device.volume.path), - _humanize_size(m.device.volume.size), - m.device.fstype, - m.path, + (15, Text(m.device.volume.path)), + Text(_humanize_size(m.device.volume.size)), + Text(m.device.fstype), + Text(m.path), ], 4) pl.append(col) return Pile(pl) @@ -136,6 +135,9 @@ class FilesystemView(BaseView): inputs.append(Columns([col1, col2])) else: inputs.append(disk_btn) + if len(inputs) == 0: + return Pile([Color.info_minor( + Text("No disks available."))]) return Pile(inputs) def click_disk(self, sender, disk): @@ -172,5 +174,4 @@ class FilesystemView(BaseView): self.controller.reset() def done(self, button): - actions = self.model.get_actions() - self.controller.finish(actions) + self.controller.finish()