From 33e361056dea5cf0542e2d919fb8fa93292134fe Mon Sep 17 00:00:00 2001 From: Michael Hudson-Doyle Date: Mon, 28 Aug 2017 11:33:20 +1200 Subject: [PATCH 1/5] very start of a guided partitioning view --- subiquity/controllers/filesystem.py | 23 +++++++++-- subiquity/core.py | 6 +-- subiquity/ui/views/__init__.py | 3 +- subiquity/ui/views/filesystem/__init__.py | 1 + subiquity/ui/views/filesystem/guided.py | 47 +++++++++++++++++++++++ 5 files changed, 72 insertions(+), 8 deletions(-) create mode 100644 subiquity/ui/views/filesystem/guided.py diff --git a/subiquity/controllers/filesystem.py b/subiquity/controllers/filesystem.py index e468fe16..7a65259f 100644 --- a/subiquity/controllers/filesystem.py +++ b/subiquity/controllers/filesystem.py @@ -26,10 +26,17 @@ from subiquity.curtin import ( ) from subiquity.models import (FilesystemModel, RaidModel) from subiquity.models.filesystem import humanize_size -from subiquity.ui.views import (DiskPartitionView, AddPartitionView, - AddFormatView, FilesystemView, - DiskInfoView, RaidView, BcacheView, - LVMVolumeGroupView) +from subiquity.ui.views import ( + AddFormatView, + AddPartitionView, + BcacheView, + DiskInfoView, + DiskPartitionView, + FilesystemView, + GuidedFilesystemView, + LVMVolumeGroupView, + RaidView, + ) log = logging.getLogger("subiquitycore.controller.filesystem") @@ -54,6 +61,14 @@ class FilesystemController(BaseController): log.info("Resetting Filesystem model") self.model.reset() + title = "Filesystem setup" + footer = ("XXX") + self.ui.set_header(title) + self.ui.set_footer(footer, 30) + self.ui.set_body(GuidedFilesystemView(self.model, self)) + + def manual(self): + # FIXME: Is this the best way to zero out this list for a reset? title = "Filesystem setup" footer = ("Select available disks to format and mount") self.ui.set_header(title) diff --git a/subiquity/core.py b/subiquity/core.py index 1c55af4c..aacb2460 100644 --- a/subiquity/core.py +++ b/subiquity/core.py @@ -24,9 +24,9 @@ class Subiquity(Application): project = "subiquity" controllers = [ - "Welcome", - "Installpath", - "Network", +# "Welcome", +# "Installpath", +# "Network", "Filesystem", "Identity", "InstallProgress", diff --git a/subiquity/ui/views/__init__.py b/subiquity/ui/views/__init__.py index de274b03..8c7ae3c7 100644 --- a/subiquity/ui/views/__init__.py +++ b/subiquity/ui/views/__init__.py @@ -17,7 +17,8 @@ from .filesystem import (FilesystemView, # NOQA AddPartitionView, AddFormatView, DiskPartitionView, - DiskInfoView) + DiskInfoView, + GuidedFilesystemView) from .bcache import BcacheView # NOQA from .raid import RaidView # NOQA from .ceph import CephDiskView # NOQA diff --git a/subiquity/ui/views/filesystem/__init__.py b/subiquity/ui/views/filesystem/__init__.py index aa929b98..b5cd381f 100644 --- a/subiquity/ui/views/filesystem/__init__.py +++ b/subiquity/ui/views/filesystem/__init__.py @@ -25,3 +25,4 @@ from .add_partition import AddPartitionView from .disk_info import DiskInfoView from .disk_partition import DiskPartitionView from .filesystem import FilesystemView +from .guided import GuidedFilesystemView diff --git a/subiquity/ui/views/filesystem/guided.py b/subiquity/ui/views/filesystem/guided.py new file mode 100644 index 00000000..bd43f0b8 --- /dev/null +++ b/subiquity/ui/views/filesystem/guided.py @@ -0,0 +1,47 @@ +# Copyright 2017 Canonical, Ltd. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + +from urwid import ( + connect_signal, + Text, + ) + +from subiquitycore.ui.buttons import ( + PlainButton, + ) +from subiquitycore.ui.container import ListBox +from subiquitycore.view import BaseView + +text = """The installer can guide you through partitioning a disk or, if +you prefer, you can do it manually. If you choose guided partitioning you +will still have a chance to review and modify the results.""" + + +class GuidedFilesystemView(BaseView): + + def __init__(self, model, controller): + self.controller = controller + guided = PlainButton(label="Guided") + connect_signal(guided, 'click', self.guided) + manual = PlainButton(label="Manual") + connect_signal(manual, 'click', self.manual) + lb = ListBox([Text(text), guided, manual]) + super().__init__(lb) + + def manual(self, btn): + self.controller.manual() + + def guided(self, btn): + self.controller.guided() From 60561fdf232526b8684ac85daa96abcdfafafde3 Mon Sep 17 00:00:00 2001 From: Michael Hudson-Doyle Date: Mon, 28 Aug 2017 11:41:23 +1200 Subject: [PATCH 2/5] slightly better formatting --- subiquity/ui/views/filesystem/guided.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/subiquity/ui/views/filesystem/guided.py b/subiquity/ui/views/filesystem/guided.py index bd43f0b8..984697ad 100644 --- a/subiquity/ui/views/filesystem/guided.py +++ b/subiquity/ui/views/filesystem/guided.py @@ -18,14 +18,16 @@ from urwid import ( Text, ) +from subiquitycore.ui.utils import Padding, Color + from subiquitycore.ui.buttons import ( PlainButton, ) from subiquitycore.ui.container import ListBox from subiquitycore.view import BaseView -text = """The installer can guide you through partitioning a disk or, if -you prefer, you can do it manually. If you choose guided partitioning you +text = """The installer can guide you through partitioning a disk or, if \ +you prefer, you can do it manually. If you choose guided partitioning you \ will still have a chance to review and modify the results.""" @@ -37,7 +39,11 @@ class GuidedFilesystemView(BaseView): connect_signal(guided, 'click', self.guided) manual = PlainButton(label="Manual") connect_signal(manual, 'click', self.manual) - lb = ListBox([Text(text), guided, manual]) + lb = ListBox([ + Padding.center_70(Text(text)), + Padding.center_70(Text("")), + Padding.center_10(Color.button(guided)), + Padding.center_10(Color.button(manual))]) super().__init__(lb) def manual(self, btn): From 2874fd56bd646ff744833ec43a5f93d0540014aa Mon Sep 17 00:00:00 2001 From: Michael Hudson-Doyle Date: Mon, 28 Aug 2017 21:00:20 +1200 Subject: [PATCH 3/5] present a list of disks to choose from --- subiquity/controllers/filesystem.py | 14 +++++- subiquity/ui/views/__init__.py | 1 + subiquity/ui/views/filesystem/__init__.py | 2 +- .../ui/views/filesystem/add_partition.py | 1 - subiquity/ui/views/filesystem/filesystem.py | 5 ++- subiquity/ui/views/filesystem/guided.py | 44 +++++++++++++++++-- 6 files changed, 59 insertions(+), 8 deletions(-) diff --git a/subiquity/controllers/filesystem.py b/subiquity/controllers/filesystem.py index 7a65259f..a0d656d7 100644 --- a/subiquity/controllers/filesystem.py +++ b/subiquity/controllers/filesystem.py @@ -33,6 +33,7 @@ from subiquity.ui.views import ( DiskInfoView, DiskPartitionView, FilesystemView, + GuidedDiskSelectionView, GuidedFilesystemView, LVMVolumeGroupView, RaidView, @@ -68,13 +69,19 @@ class FilesystemController(BaseController): self.ui.set_body(GuidedFilesystemView(self.model, self)) def manual(self): - # FIXME: Is this the best way to zero out this list for a reset? title = "Filesystem setup" footer = ("Select available disks to format and mount") self.ui.set_header(title) self.ui.set_footer(footer, 30) self.ui.set_body(FilesystemView(self.model, self)) + def guided(self): + title = "Filesystem setup" + footer = ("Select available disks to format and mount") + self.ui.set_header(title) + self.ui.set_footer(footer, 30) + self.ui.set_body(GuidedDiskSelectionView(self.model, self)) + def reset(self): log.info("Resetting Filesystem model") self.model.reset() @@ -144,7 +151,7 @@ class FilesystemController(BaseController): adp_view = AddPartitionView(self.model, self, disk) self.ui.set_body(adp_view) - def add_disk_partition_handler(self, disk, spec): + def do_add_disk_partition(self, disk, spec): log.debug('spec: {}'.format(spec)) log.debug('disk.freespace: {}'.format(disk.free)) @@ -177,6 +184,9 @@ class FilesystemController(BaseController): self.model.add_mount(fs, spec['mountpoint']) log.info("Successfully added partition") + + def add_disk_partition_handler(self, disk, spec): + self.do_add_disk_partition(disk, spec) self.partition_disk(disk) def add_format_handler(self, volume, spec, back): diff --git a/subiquity/ui/views/__init__.py b/subiquity/ui/views/__init__.py index 8c7ae3c7..27245771 100644 --- a/subiquity/ui/views/__init__.py +++ b/subiquity/ui/views/__init__.py @@ -18,6 +18,7 @@ from .filesystem import (FilesystemView, # NOQA AddFormatView, DiskPartitionView, DiskInfoView, + GuidedDiskSelectionView, GuidedFilesystemView) from .bcache import BcacheView # NOQA from .raid import RaidView # NOQA diff --git a/subiquity/ui/views/filesystem/__init__.py b/subiquity/ui/views/filesystem/__init__.py index b5cd381f..d72baac8 100644 --- a/subiquity/ui/views/filesystem/__init__.py +++ b/subiquity/ui/views/filesystem/__init__.py @@ -25,4 +25,4 @@ from .add_partition import AddPartitionView from .disk_info import DiskInfoView from .disk_partition import DiskPartitionView from .filesystem import FilesystemView -from .guided import GuidedFilesystemView +from .guided import GuidedDiskSelectionView, GuidedFilesystemView diff --git a/subiquity/ui/views/filesystem/add_partition.py b/subiquity/ui/views/filesystem/add_partition.py index 532d2c5d..f3632b8b 100644 --- a/subiquity/ui/views/filesystem/add_partition.py +++ b/subiquity/ui/views/filesystem/add_partition.py @@ -131,7 +131,6 @@ class AddPartitionView(BaseView): result = { "partnum": self.form.partnum.value, - "raw_size": self.form.size.value, "bytes": size, "fstype": fstype.label, "mountpoint": mount, diff --git a/subiquity/ui/views/filesystem/filesystem.py b/subiquity/ui/views/filesystem/filesystem.py index 5154d04d..50ebeda9 100644 --- a/subiquity/ui/views/filesystem/filesystem.py +++ b/subiquity/ui/views/filesystem/filesystem.py @@ -94,7 +94,10 @@ class FilesystemView(BaseView): #Text(""), Padding.fixed_10(self._build_buttons()), ] - super().__init__(Padding.center_90(ListBox(self.body))) + w = ListBox(self.body) + if self.model.can_install(): + w.set_focus_path([len(self.body)-1, 0]) + super().__init__(Padding.center_90(w)) log.debug('FileSystemView init complete()') def _build_used_disks(self): diff --git a/subiquity/ui/views/filesystem/guided.py b/subiquity/ui/views/filesystem/guided.py index 984697ad..fb480512 100644 --- a/subiquity/ui/views/filesystem/guided.py +++ b/subiquity/ui/views/filesystem/guided.py @@ -21,11 +21,15 @@ from urwid import ( from subiquitycore.ui.utils import Padding, Color from subiquitycore.ui.buttons import ( + menu_btn, PlainButton, ) -from subiquitycore.ui.container import ListBox +from subiquitycore.ui.container import ListBox, Pile from subiquitycore.view import BaseView +from subiquity.models.filesystem import humanize_size + + text = """The installer can guide you through partitioning a disk or, if \ you prefer, you can do it manually. If you choose guided partitioning you \ will still have a chance to review and modify the results.""" @@ -42,8 +46,8 @@ class GuidedFilesystemView(BaseView): lb = ListBox([ Padding.center_70(Text(text)), Padding.center_70(Text("")), - Padding.center_10(Color.button(guided)), - Padding.center_10(Color.button(manual))]) + Padding.fixed_10(Color.button(guided)), + Padding.fixed_10(Color.button(manual))]) super().__init__(lb) def manual(self, btn): @@ -51,3 +55,37 @@ class GuidedFilesystemView(BaseView): def guided(self, btn): self.controller.guided() + +class GuidedDiskSelectionView(BaseView): + + def __init__(self, model, controller): + self.model = model + self.controller = controller + cancel = PlainButton(label="Cancel") + connect_signal(cancel, 'click', self.cancel) + disks = [] + for disk in self.model.all_disks(): + if disk.available: + disk_btn = menu_btn("%-40s %s"%(disk.serial, humanize_size(disk.size).rjust(9))) + connect_signal(disk_btn, 'click', self.choose_disk, disk) + disks.append(Color.menu_button(disk_btn)) + lb = ListBox([ + Padding.center_70(Text("Choose the disk to install to:")), + Padding.center_70(Text("")), + Padding.center_70(Pile(disks)), + Padding.center_70(Text("")), + Padding.fixed_10(Color.button(cancel))]) + super().__init__(lb) + + def cancel(self, btn): + self.controller.default() + + def choose_disk(self, btn, disk): + result = { + "partnum": 1, + "bytes": disk.free, + "fstype": "ext4", + "mountpoint": "/", + } + self.controller.do_add_disk_partition(disk, result) + self.controller.manual() From fc80887f312e8598cba5f300900bb3418d8acfa2 Mon Sep 17 00:00:00 2001 From: Michael Hudson-Doyle Date: Mon, 28 Aug 2017 22:28:31 +1200 Subject: [PATCH 4/5] self-review --- subiquity/controllers/filesystem.py | 4 ++-- subiquity/core.py | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/subiquity/controllers/filesystem.py b/subiquity/controllers/filesystem.py index a0d656d7..91981abd 100644 --- a/subiquity/controllers/filesystem.py +++ b/subiquity/controllers/filesystem.py @@ -63,7 +63,7 @@ class FilesystemController(BaseController): self.model.reset() title = "Filesystem setup" - footer = ("XXX") + footer = ("Choose guided or manual partitioning") self.ui.set_header(title) self.ui.set_footer(footer, 30) self.ui.set_body(GuidedFilesystemView(self.model, self)) @@ -77,7 +77,7 @@ class FilesystemController(BaseController): def guided(self): title = "Filesystem setup" - footer = ("Select available disks to format and mount") + footer = ("Choose the installation target") self.ui.set_header(title) self.ui.set_footer(footer, 30) self.ui.set_body(GuidedDiskSelectionView(self.model, self)) diff --git a/subiquity/core.py b/subiquity/core.py index aacb2460..1c55af4c 100644 --- a/subiquity/core.py +++ b/subiquity/core.py @@ -24,9 +24,9 @@ class Subiquity(Application): project = "subiquity" controllers = [ -# "Welcome", -# "Installpath", -# "Network", + "Welcome", + "Installpath", + "Network", "Filesystem", "Identity", "InstallProgress", From 641f437fd7e0e169f9e9bcc78c1670eb77f9e19c Mon Sep 17 00:00:00 2001 From: Michael Hudson-Doyle Date: Tue, 29 Aug 2017 09:24:29 +1200 Subject: [PATCH 5/5] do not ask guided/manual on re-entering config screen if any configuration has been done --- subiquity/controllers/filesystem.py | 14 ++++++++------ subiquity/models/filesystem.py | 3 +++ subiquitycore/ui/views/network.py | 2 +- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/subiquity/controllers/filesystem.py b/subiquity/controllers/filesystem.py index 91981abd..725d44a7 100644 --- a/subiquity/controllers/filesystem.py +++ b/subiquity/controllers/filesystem.py @@ -61,12 +61,14 @@ class FilesystemController(BaseController): if reset: log.info("Resetting Filesystem model") self.model.reset() - - title = "Filesystem setup" - footer = ("Choose guided or manual partitioning") - self.ui.set_header(title) - self.ui.set_footer(footer, 30) - self.ui.set_body(GuidedFilesystemView(self.model, self)) + if self.model.any_configuration_done(): + self.manual() + else: + title = "Filesystem setup" + footer = ("Choose guided or manual partitioning") + self.ui.set_header(title) + self.ui.set_footer(footer, 30) + self.ui.set_body(GuidedFilesystemView(self.model, self)) def manual(self): title = "Filesystem setup" diff --git a/subiquity/models/filesystem.py b/subiquity/models/filesystem.py index 712cb33c..139f8c6a 100644 --- a/subiquity/models/filesystem.py +++ b/subiquity/models/filesystem.py @@ -363,6 +363,9 @@ class FilesystemModel(object): r[m.path] = m.device.volume.path return r + def any_configuration_done(self): + return len(self._disks) > 0 + def can_install(self): # 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() diff --git a/subiquitycore/ui/views/network.py b/subiquitycore/ui/views/network.py index 13204395..b22abb12 100644 --- a/subiquitycore/ui/views/network.py +++ b/subiquitycore/ui/views/network.py @@ -125,7 +125,7 @@ class NetworkView(BaseView): ] # FIXME determine which UX widget should have focus self.lb = ListBox(self.body) - self.lb.set_focus(4) # _build_buttons + self.lb.set_focus_path([6, 0]) # _build_buttons super().__init__(self.lb) def _build_buttons(self):